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;
86 static char *rb1regs[] = {
87 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
90 static void saveRBank (int, iCode *, bool);
92 #define RESULTONSTACK(x) \
93 (IC_RESULT(x) && IC_RESULT(x)->aop && \
94 IC_RESULT(x)->aop->type == AOP_STK )
96 #define MOVA(x) _movA(x)
97 #define MOVB(x) _movB(x)
99 #define CLRC emitcode("clr","c")
100 #define SETC emitcode("setb","c")
102 // A scratch register which will be used to hold
103 // result bytes from operands in far space via DPTR2.
104 #define DP2_RESULT_REG "_ap"
106 static lineNode *lineHead = NULL;
107 static lineNode *lineCurr = NULL;
109 static unsigned char SLMask[] =
110 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
111 0xE0, 0xC0, 0x80, 0x00};
112 static unsigned char SRMask[] =
113 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
114 0x07, 0x03, 0x01, 0x00};
120 #define PROTECT_SP {if (options.protect_sp_update) { \
121 symbol *lbl = newiTempLabel(NULL); \
122 emitcode ("setb","F1"); \
123 emitcode ("jbc","EA,!tlabel",lbl->key+100); \
124 emitcode ("clr","F1"); \
125 emitcode ("","!tlabeldef",lbl->key+100); \
127 #define UNPROTECT_SP { if (options.protect_sp_update) { \
128 symbol *lbl = newiTempLabel(NULL); \
129 emitcode ("jnb","F1,!tlabel",lbl->key+100); \
130 emitcode ("setb","EA"); \
131 emitcode ("","!tlabeldef",lbl->key+100); \
134 static int _currentDPS; /* Current processor DPS. */
135 static int _desiredDPS; /* DPS value compiler thinks we should be using. */
136 static int _lazyDPS = 0; /* if non-zero, we are doing lazy evaluation of DPS changes. */
138 /*-----------------------------------------------------------------*/
139 /* emitcode - writes the code into a file : for now it is simple */
140 /*-----------------------------------------------------------------*/
142 emitcode (char *inst, char *fmt,...)
145 char lb[INITIAL_INLINEASM];
154 SNPRINTF (lb, sizeof(lb), "%s\t", inst);
158 SNPRINTF (lb, sizeof(lb), "%s", inst);
161 tvsprintf (lb + strlen(lb), sizeof(lb) - strlen(lb),
166 tvsprintf (lb, sizeof(lb), fmt, ap);
170 while (isspace (*lbp))
177 lineCurr = (lineCurr ?
178 connectLine (lineCurr, newLineNode (lb)) :
179 (lineHead = newLineNode (lb)));
182 lineCurr->isInline = _G.inLine;
183 lineCurr->isDebug = _G.debugLine;
184 lineCurr->ic = _G.current_iCode;
185 lineCurr->aln = ds390newAsmLineNode(_currentDPS);
190 // Move the passed value into A unless it is already there.
195 if (strcmp(s,"a") && strcmp(s,"acc"))
197 emitcode("mov","a,%s",s);
202 // Move the passed value into B unless it is already there.
209 emitcode("mov","b,%s",s);
213 /*-----------------------------------------------------------------*/
214 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
215 /*-----------------------------------------------------------------*/
217 getFreePtr (iCode * ic, asmop ** aopp, bool result)
222 /* the logic: if r0 & r1 used in the instruction
223 then we are in trouble otherwise */
225 /* first check if r0 & r1 are used by this
226 instruction, in which case we are in trouble */
227 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
228 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
233 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
234 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
236 /* if no usage of r0 then return it */
239 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
240 (*aopp)->type = AOP_R0;
242 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
245 /* if no usage of r1 then return it */
248 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
249 (*aopp)->type = AOP_R1;
251 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
254 /* now we know they both have usage */
255 /* if r0 not used in this instruction */
258 /* push it if not already pushed */
261 emitcode ("push", "%s",
262 ds390_regWithIdx (R0_IDX)->dname);
266 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
267 (*aopp)->type = AOP_R0;
269 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
272 /* if r1 not used then */
276 /* push it if not already pushed */
279 emitcode ("push", "%s",
280 ds390_regWithIdx (R1_IDX)->dname);
284 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
285 (*aopp)->type = AOP_R1;
286 return ds390_regWithIdx (R1_IDX);
290 /* I said end of world but not quite end of world yet */
291 /* if this is a result then we can push it on the stack */
294 (*aopp)->type = AOP_STK;
298 /* other wise this is true end of the world */
299 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
300 "getFreePtr should never reach here");
303 return NULL; // notreached, but makes compiler happy.
306 /*-----------------------------------------------------------------*/
307 /* newAsmop - creates a new asmOp */
308 /*-----------------------------------------------------------------*/
310 newAsmop (short type)
314 aop = Safe_calloc (1, sizeof (asmop));
320 /*-----------------------------------------------------------------*/
321 /* genSetDPTR: generate code to select which DPTR is in use (zero */
322 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390 */
323 /* alternate DPTR (DPL1/DPH1/DPX1). */
324 /*-----------------------------------------------------------------*/
329 /* If we are doing lazy evaluation, simply note the desired
330 * change, but don't emit any code yet.
340 emitcode ("mov", "dps,#0");
345 emitcode ("mov", "dps,#1");
349 /*-----------------------------------------------------------------*/
350 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
352 /* Any code that operates on DPTR (NB: not on the individual */
353 /* components, like DPH) *must* call _flushLazyDPS() before using */
354 /* DPTR within a lazy DPS evaluation block. */
356 /* Note that aopPut and aopGet already contain the proper calls to */
357 /* _flushLazyDPS, so it is safe to use these calls within a lazy */
358 /* DPS evaluation block. */
360 /* Also, _flushLazyDPS must be called before any flow control */
361 /* operations that could potentially branch out of the block. */
363 /* Lazy DPS evaluation is simply an optimization (though an */
364 /* important one), so if in doubt, leave it out. */
365 /*-----------------------------------------------------------------*/
367 _startLazyDPSEvaluation (void)
371 #ifdef BETTER_LITERAL_SHIFT
378 /*-----------------------------------------------------------------*/
379 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
380 /* desired one. Call before using DPTR within a lazy DPS evaluation */
382 /*-----------------------------------------------------------------*/
392 if (_desiredDPS != _currentDPS)
396 emitcode ("inc", "dps");
400 emitcode ("dec", "dps");
402 _currentDPS = _desiredDPS;
406 /*-----------------------------------------------------------------*/
407 /* _endLazyDPSEvaluation: end lazy DPS evaluation block. */
409 /* Forces us back to the safe state (standard DPTR selected). */
410 /*-----------------------------------------------------------------*/
412 _endLazyDPSEvaluation (void)
414 #ifdef BETTER_LITERAL_SHIFT
433 /*-----------------------------------------------------------------*/
434 /* pointerCode - returns the code for a pointer type */
435 /*-----------------------------------------------------------------*/
437 pointerCode (sym_link * etype)
440 return PTR_TYPE (SPEC_OCLS (etype));
444 /*-----------------------------------------------------------------*/
445 /* leftRightUseAcc - returns size of accumulator use by operands */
446 /*-----------------------------------------------------------------*/
448 leftRightUseAcc(iCode *ic)
457 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
458 "null iCode pointer");
465 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
468 size = getSize (OP_SYMBOL (op)->type);
473 else if (ic->op == JUMPTABLE)
476 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
479 size = getSize (OP_SYMBOL (op)->type);
487 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
490 size = getSize (OP_SYMBOL (op)->type);
495 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
498 size = getSize (OP_SYMBOL (op)->type);
510 /*-----------------------------------------------------------------*/
511 /* aopForSym - for a true symbol */
512 /*-----------------------------------------------------------------*/
514 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
517 memmap *space = SPEC_OCLS (sym->etype);
518 int accuse = leftRightUseAcc (ic);
520 /* if already has one */
523 if ((sym->aop->type == AOP_DPTR && useDP2)
524 || (sym->aop->type == AOP_DPTR2 && !useDP2))
530 /* assign depending on the storage class */
531 /* if it is on the stack or indirectly addressable */
532 /* space we need to assign either r0 or r1 to it */
533 if ((sym->onStack && !options.stack10bit) || sym->iaccess)
535 sym->aop = aop = newAsmop (0);
536 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
537 aop->size = getSize (sym->type);
539 /* now assign the address of the variable to
540 the pointer register */
541 if (aop->type != AOP_STK)
546 if (_G.accInUse || accuse)
547 emitcode ("push", "acc");
549 if (_G.bInUse || (accuse>1))
550 emitcode ("push", "b");
552 emitcode ("mov", "a,_bp");
553 emitcode ("add", "a,#!constbyte",
555 ((char) (sym->stack - _G.nRegsSaved)) :
556 ((char) sym->stack)) & 0xff);
557 emitcode ("mov", "%s,a",
558 aop->aopu.aop_ptr->name);
560 if (_G.bInUse || (accuse>1))
561 emitcode ("pop", "b");
563 if (_G.accInUse || accuse)
564 emitcode ("pop", "acc");
567 emitcode ("mov", "%s,#%s",
568 aop->aopu.aop_ptr->name,
570 aop->paged = space->paged;
573 aop->aopu.aop_stk = sym->stack;
577 if (sym->onStack && options.stack10bit)
579 short stack_val = -((sym->stack < 0) ?
580 ((short) (sym->stack - _G.nRegsSaved)) :
581 ((short) sym->stack)) ;
582 if (useDP2 && _G.dptr1InUse) {
583 emitcode ("push","dpl1");
584 emitcode ("push","dph1");
585 emitcode ("push","dpx1");
586 } else if (_G.dptrInUse ) {
587 emitcode ("push","dpl");
588 emitcode ("push","dph");
589 emitcode ("push","dpx");
591 /* It's on the 10 bit stack, which is located in
594 if (stack_val < 0 && stack_val > -5) { /* between -5 & -1 */
596 if (options.model == MODEL_FLAT24)
598 emitcode ("mov", "dpx1,#!constbyte",
599 (options.stack_loc >> 16) & 0xff);
601 emitcode ("mov", "dph1,_bpx+1");
603 emitcode ("mov", "dpl1,_bpx");
604 emitcode ("mov","dps,#1");
606 if (options.model == MODEL_FLAT24)
608 emitcode ("mov", "dpx,#!constbyte",
609 (options.stack_loc >> 16) & 0xff);
611 emitcode ("mov", "dph,_bpx+1");
612 emitcode ("mov", "dpl,_bpx");
614 stack_val = -stack_val;
615 while (stack_val--) {
616 emitcode ("inc","dptr");
619 emitcode("mov","dps,#0");
622 if (_G.accInUse || accuse)
623 emitcode ("push", "acc");
625 if (_G.bInUse || (accuse>1))
626 emitcode ("push", "b");
628 emitcode ("mov", "a,_bpx");
629 emitcode ("clr","c");
630 emitcode ("subb", "a,#!constbyte", stack_val & 0xff);
631 emitcode ("mov","b,a");
632 emitcode ("mov","a,_bpx+1");
633 emitcode ("subb","a,#!constbyte",(stack_val >> 8) & 0xff);
635 if (options.model == MODEL_FLAT24)
637 emitcode ("mov", "dpx1,#!constbyte",
638 (options.stack_loc >> 16) & 0xff);
640 emitcode ("mov", "dph1,a");
641 emitcode ("mov", "dpl1,b");
643 if (options.model == MODEL_FLAT24)
645 emitcode ("mov", "dpx,#!constbyte",
646 (options.stack_loc >> 16) & 0xff);
648 emitcode ("mov", "dph,a");
649 emitcode ("mov", "dpl,b");
652 if (_G.bInUse || (accuse>1))
653 emitcode ("pop", "b");
655 if (_G.accInUse || accuse)
656 emitcode ("pop", "acc");
658 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
659 aop->size = getSize (sym->type);
663 /* if in bit space */
664 if (IN_BITSPACE (space))
666 sym->aop = aop = newAsmop (AOP_CRY);
667 aop->aopu.aop_dir = sym->rname;
668 aop->size = getSize (sym->type);
671 /* if it is in direct space */
672 if (IN_DIRSPACE (space))
674 sym->aop = aop = newAsmop (AOP_DIR);
675 aop->aopu.aop_dir = sym->rname;
676 aop->size = getSize (sym->type);
680 /* special case for a function */
681 if (IS_FUNC (sym->type) && !(sym->isitmp))
683 sym->aop = aop = newAsmop (AOP_IMMD);
684 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
685 aop->size = FPTRSIZE;
689 /* only remaining is far space */
690 /* in which case DPTR gets the address */
691 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
696 emitcode ("mov", "dptr,#%s", sym->rname);
701 emitcode ("mov", "dptr,#%s", sym->rname);
703 aop->size = getSize (sym->type);
705 /* if it is in code space */
706 if (IN_CODESPACE (space))
712 /*-----------------------------------------------------------------*/
713 /* aopForRemat - rematerialzes an object */
714 /*-----------------------------------------------------------------*/
716 aopForRemat (symbol * sym)
718 iCode *ic = sym->rematiCode;
719 asmop *aop = newAsmop (AOP_IMMD);
726 val += (int) operandLitValue (IC_RIGHT (ic));
727 else if (ic->op == '-')
728 val -= (int) operandLitValue (IC_RIGHT (ic));
729 else if (IS_CAST_ICODE(ic)) {
730 sym_link *from_type = operandType(IC_RIGHT(ic));
731 aop->aopu.aop_immd.from_cast_remat = 1;
732 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
733 ptr_type = DCL_TYPE(from_type);
734 if (ptr_type == IPOINTER) {
741 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
746 SNPRINTF (buffer, sizeof(buffer),
748 OP_SYMBOL (IC_LEFT (ic))->rname,
749 val >= 0 ? '+' : '-',
750 abs (val) & 0xffffff);
754 if (IS_ASSIGN_ICODE(ic) && isOperandLiteral(IC_RIGHT(ic)))
756 SNPRINTF(buffer, sizeof(buffer),
757 "0x%x",(int) operandLitValue (IC_RIGHT (ic)));
761 strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
765 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);
766 /* set immd2 field if required */
767 if (aop->aopu.aop_immd.from_cast_remat)
769 tsprintf(buffer, sizeof(buffer), "#!constbyte",ptr_type);
770 aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
776 /*-----------------------------------------------------------------*/
777 /* aopHasRegs - returns true if aop has regs between from-to */
778 /*-----------------------------------------------------------------*/
779 static int aopHasRegs(asmop *aop, int from, int to)
783 if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
785 for (; size < aop->size ; size++) {
787 for (reg = from ; reg <= to ; reg++)
788 if (aop->aopu.aop_reg[size] == ds390_regWithIdx(reg)) return 1;
793 /*-----------------------------------------------------------------*/
794 /* regsInCommon - two operands have some registers in common */
795 /*-----------------------------------------------------------------*/
797 regsInCommon (operand * op1, operand * op2)
802 /* if they have registers in common */
803 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
806 sym1 = OP_SYMBOL (op1);
807 sym2 = OP_SYMBOL (op2);
809 if (sym1->nRegs == 0 || sym2->nRegs == 0)
812 for (i = 0; i < sym1->nRegs; i++)
818 for (j = 0; j < sym2->nRegs; j++)
823 if (sym2->regs[j] == sym1->regs[i])
831 /*-----------------------------------------------------------------*/
832 /* operandsEqu - equivalent */
833 /*-----------------------------------------------------------------*/
835 operandsEqu (operand * op1, operand * op2)
839 /* if they not symbols */
840 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
843 sym1 = OP_SYMBOL (op1);
844 sym2 = OP_SYMBOL (op2);
846 /* if both are itemps & one is spilt
847 and the other is not then false */
848 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
849 sym1->isspilt != sym2->isspilt)
852 /* if they are the same */
856 if (strcmp (sym1->rname, sym2->rname) == 0)
860 /* if left is a tmp & right is not */
861 if (IS_ITEMP (op1) &&
864 (sym1->usl.spillLoc == sym2))
867 if (IS_ITEMP (op2) &&
871 (sym2->usl.spillLoc == sym1))
874 /* are they spilt to the same location */
875 if (IS_ITEMP (op2) &&
879 (sym1->usl.spillLoc == sym2->usl.spillLoc))
885 /*-----------------------------------------------------------------*/
886 /* sameRegs - two asmops have the same registers */
887 /*-----------------------------------------------------------------*/
889 sameRegs (asmop * aop1, asmop * aop2)
895 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
902 if (aop1->type != AOP_REG ||
903 aop2->type != AOP_REG)
906 if (aop1->size != aop2->size)
909 for (i = 0; i < aop1->size; i++)
910 if (aop1->aopu.aop_reg[i] !=
911 aop2->aopu.aop_reg[i])
917 /*-----------------------------------------------------------------*/
918 /* aopOp - allocates an asmop for an operand : */
919 /*-----------------------------------------------------------------*/
921 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
930 /* if this a literal */
931 if (IS_OP_LITERAL (op))
933 op->aop = aop = newAsmop (AOP_LIT);
934 aop->aopu.aop_lit = op->operand.valOperand;
935 aop->size = getSize (operandType (op));
939 /* if already has a asmop then continue */
942 if ((op->aop->type == AOP_DPTR && useDP2)
943 || (op->aop->type == AOP_DPTR2 && !useDP2))
949 /* if the underlying symbol has a aop */
950 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
952 op->aop = OP_SYMBOL (op)->aop;
953 if ((op->aop->type == AOP_DPTR && useDP2)
954 || (op->aop->type == AOP_DPTR2 && !useDP2))
960 /* if this is a true symbol */
961 if (IS_TRUE_SYMOP (op))
963 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
967 /* this is a temporary : this has
973 e) can be a return use only */
975 sym = OP_SYMBOL (op);
978 /* if the type is a conditional */
979 if (sym->regType == REG_CND)
981 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
986 /* if it is spilt then two situations
988 b) has a spill location */
989 if (sym->isspilt || sym->nRegs == 0)
992 /* rematerialize it NOW */
995 sym->aop = op->aop = aop =
997 aop->size = getSize (sym->type);
1004 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
1005 aop->size = getSize (sym->type);
1006 for (i = 0; i < 2; i++)
1007 aop->aopu.aop_str[i] = accUse[i];
1017 /* a AOP_STR uses DPTR, but DPTR is already in use;
1020 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"AOP_STR with DPTR in use!");
1023 aop = op->aop = sym->aop = newAsmop (AOP_STR);
1024 aop->size = getSize (sym->type);
1025 for (i = 0; i < (int) fReturnSizeDS390; i++)
1026 aop->aopu.aop_str[i] = fReturn[i];
1030 if (sym->dptr) { /* has been allocated to a DPTRn */
1031 aop = op->aop = sym->aop = newAsmop (AOP_DPTRn);
1032 aop->size = getSize (sym->type);
1033 aop->aopu.dptr = sym->dptr;
1037 if (sym->usl.spillLoc)
1039 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1041 /* force a new aop if sizes differ */
1042 sym->usl.spillLoc->aop = NULL;
1044 sym->aop = op->aop = aop =
1045 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
1046 aop->size = getSize (sym->type);
1050 /* else must be a dummy iTemp */
1051 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1052 aop->size = getSize (sym->type);
1056 /* must be in a register */
1057 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1058 aop->size = sym->nRegs;
1059 for (i = 0; i < sym->nRegs; i++)
1060 aop->aopu.aop_reg[i] = sym->regs[i];
1063 /*-----------------------------------------------------------------*/
1064 /* freeAsmop - free up the asmop given to an operand */
1065 /*----------------------------------------------------------------*/
1067 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1084 /* depending on the asmop type only three cases need work AOP_RO
1085 , AOP_R1 && AOP_STK */
1093 emitcode ("pop", "ar0");
1097 bitVectUnSetBit (ic->rUsed, R0_IDX);
1105 emitcode ("pop", "ar1");
1109 bitVectUnSetBit (ic->rUsed, R1_IDX);
1115 int stk = aop->aopu.aop_stk + aop->size;
1116 bitVectUnSetBit (ic->rUsed, R0_IDX);
1117 bitVectUnSetBit (ic->rUsed, R1_IDX);
1119 getFreePtr (ic, &aop, FALSE);
1121 if (options.stack10bit)
1123 /* I'm not sure what to do here yet... */
1126 "*** Warning: probably generating bad code for "
1127 "10 bit stack mode.\n");
1132 emitcode ("mov", "a,_bp");
1133 emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
1134 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1138 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1143 emitcode ("pop", "acc");
1144 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1147 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1150 freeAsmop (op, NULL, ic, TRUE);
1153 emitcode ("pop", "ar0");
1159 emitcode ("pop", "ar1");
1164 if (_G.dptr1InUse) {
1165 emitcode ("pop","dpx1");
1166 emitcode ("pop","dph1");
1167 emitcode ("pop","dpl1");
1172 emitcode ("pop","dpx");
1173 emitcode ("pop","dph");
1174 emitcode ("pop","dpl");
1179 /* all other cases just dealloc */
1185 OP_SYMBOL (op)->aop = NULL;
1186 /* if the symbol has a spill */
1188 SPIL_LOC (op)->aop = NULL;
1193 #define DEFAULT_ACC_WARNING 0
1194 static int saveAccWarn = DEFAULT_ACC_WARNING;
1196 /*-------------------------------------------------------------------*/
1197 /* aopGet - for fetching value of the aop */
1199 /* Set saveAcc to NULL if you are sure it is OK to clobber the value */
1200 /* in the accumulator. Set it to the name of a free register */
1201 /* if acc must be preserved; the register will be used to preserve */
1202 /* acc temporarily and to return the result byte. */
1203 /*-------------------------------------------------------------------*/
1212 /* offset is greater than
1214 if (offset > (aop->size - 1) &&
1215 aop->type != AOP_LIT)
1218 /* depending on type */
1226 /* if we need to increment it */
1227 while (offset > aop->coff)
1229 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1233 while (offset < aop->coff)
1235 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1242 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1243 return (dname ? "acc" : "a");
1245 SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1246 return Safe_strdup(buffer);
1249 assert(offset <= 3);
1250 return dptrn[aop->aopu.dptr][offset];
1255 if (aop->type == AOP_DPTR2)
1263 // if (aop->type != AOP_DPTR2)
1265 // if (saveAccWarn) { fprintf(stderr, "saveAcc for DPTR...\n"); }
1266 // emitcode(";", "spanky: saveAcc for DPTR");
1269 emitcode ("xch", "a, %s", saveAcc);
1274 while (offset > aop->coff)
1276 emitcode ("inc", "dptr");
1280 while (offset < aop->coff)
1282 emitcode ("lcall", "__decdptr");
1289 emitcode ("clr", "a");
1290 emitcode ("movc", "a,@a+dptr");
1294 emitcode ("movx", "a,@dptr");
1297 if (aop->type == AOP_DPTR2)
1305 emitcode ("xch", "a, %s", saveAcc);
1306 // if (strcmp(saveAcc, "_ap"))
1308 // emitcode(";", "spiffy: non _ap return from aopGet.");
1313 return (dname ? "acc" : "a");
1316 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1318 SNPRINTF(buffer, sizeof(buffer),
1319 "%s",aop->aopu.aop_immd.aop_immd2);
1323 SNPRINTF(buffer, sizeof(buffer),
1324 "#%s", aop->aopu.aop_immd.aop_immd1);
1330 tsprintf(buffer, sizeof(buffer),
1331 "#!his",aop->aopu.aop_immd.aop_immd1);
1334 tsprintf(buffer, sizeof(buffer),
1335 "#!hihis",aop->aopu.aop_immd.aop_immd1);
1338 tsprintf(buffer, sizeof(buffer),
1339 "#!hihihis",aop->aopu.aop_immd.aop_immd1);
1341 default: /* should not need this (just in case) */
1342 SNPRINTF (buffer, sizeof(buffer),
1344 aop->aopu.aop_immd.aop_immd1,
1350 SNPRINTF (buffer, sizeof(buffer),
1351 "#%s", aop->aopu.aop_immd.aop_immd1);
1353 return Safe_strdup(buffer);
1358 SNPRINTF (buffer, sizeof(buffer),
1365 SNPRINTF(buffer, sizeof(buffer),
1366 "%s", aop->aopu.aop_dir);
1369 return Safe_strdup(buffer);
1373 return aop->aopu.aop_reg[offset]->dname;
1375 return aop->aopu.aop_reg[offset]->name;
1378 emitcode ("clr", "a");
1379 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1380 emitcode ("rlc", "a");
1381 return (dname ? "acc" : "a");
1384 if (!offset && dname)
1386 return aop->aopu.aop_str[offset];
1389 return aopLiteral (aop->aopu.aop_lit, offset);
1393 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1397 return aop->aopu.aop_str[offset];
1401 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1402 "aopget got unsupported aop->type");
1405 return NULL; // not reached, but makes compiler happy.
1407 /*-----------------------------------------------------------------*/
1408 /* aopPut - puts a string for a aop */
1409 /*-----------------------------------------------------------------*/
1411 aopPut (asmop * aop, char *s, int offset)
1413 if (aop->size && offset > (aop->size - 1))
1415 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1416 "aopPut got offset > aop->size");
1420 /* will assign value to value */
1421 /* depending on where it is ofcourse */
1425 MOVA (s); /* read s in case it was volatile */
1431 SNPRINTF (buffer, sizeof(buffer),
1433 aop->aopu.aop_dir, offset);
1437 SNPRINTF (buffer, sizeof(buffer),
1438 "%s", aop->aopu.aop_dir);
1442 if (strcmp (buffer, s))
1444 emitcode ("mov", "%s,%s", buffer, s);
1449 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1450 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1453 strcmp (s, "r0") == 0 ||
1454 strcmp (s, "r1") == 0 ||
1455 strcmp (s, "r2") == 0 ||
1456 strcmp (s, "r3") == 0 ||
1457 strcmp (s, "r4") == 0 ||
1458 strcmp (s, "r5") == 0 ||
1459 strcmp (s, "r6") == 0 ||
1460 strcmp (s, "r7") == 0)
1462 emitcode ("mov", "%s,%s",
1463 aop->aopu.aop_reg[offset]->dname, s);
1467 emitcode ("mov", "%s,%s",
1468 aop->aopu.aop_reg[offset]->name, s);
1474 emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1480 if (aop->type == AOP_DPTR2)
1488 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1489 "aopPut writting to code space");
1493 while (offset > aop->coff)
1496 emitcode ("inc", "dptr");
1499 while (offset < aop->coff)
1502 emitcode ("lcall", "__decdptr");
1507 /* if not in accumulater */
1510 emitcode ("movx", "@dptr,a");
1512 if (aop->type == AOP_DPTR2)
1520 while (offset > aop->coff)
1523 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1525 while (offset < aop->coff)
1528 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1535 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1541 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1543 else if (strcmp (s, "r0") == 0 ||
1544 strcmp (s, "r1") == 0 ||
1545 strcmp (s, "r2") == 0 ||
1546 strcmp (s, "r3") == 0 ||
1547 strcmp (s, "r4") == 0 ||
1548 strcmp (s, "r5") == 0 ||
1549 strcmp (s, "r6") == 0 ||
1550 strcmp (s, "r7") == 0)
1553 SNPRINTF(buff, sizeof(buff),
1555 emitcode ("mov", "@%s,%s",
1556 aop->aopu.aop_ptr->name, buff);
1560 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1565 if (strcmp (s, "a") == 0)
1566 emitcode ("push", "acc");
1570 emitcode ("push", "acc");
1572 emitcode ("push", s);
1578 /* if bit variable */
1579 if (!aop->aopu.aop_dir)
1581 emitcode ("clr", "a");
1582 emitcode ("rlc", "a");
1587 emitcode ("clr", "%s", aop->aopu.aop_dir);
1589 emitcode ("setb", "%s", aop->aopu.aop_dir);
1590 else if (!strcmp (s, "c"))
1591 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1594 if (strcmp (s, "a"))
1599 /* set C, if a >= 1 */
1600 emitcode ("add", "a,#!constbyte",0xff);
1601 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1609 if (strcmp (aop->aopu.aop_str[offset], s))
1610 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1615 if (!offset && (strcmp (s, "acc") == 0))
1618 if (strcmp (aop->aopu.aop_str[offset], s))
1619 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1623 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1624 "aopPut got unsupported aop->type");
1631 /*--------------------------------------------------------------------*/
1632 /* reAdjustPreg - points a register back to where it should (coff==0) */
1633 /*--------------------------------------------------------------------*/
1635 reAdjustPreg (asmop * aop)
1637 if ((aop->coff==0) || (aop->size <= 1)) {
1646 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1650 if (aop->type == AOP_DPTR2)
1657 emitcode ("lcall", "__decdptr");
1660 if (aop->type == AOP_DPTR2)
1670 #define AOP(op) op->aop
1671 #define AOP_TYPE(op) AOP(op)->type
1672 #define AOP_SIZE(op) AOP(op)->size
1673 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1674 AOP_TYPE(x) == AOP_R0))
1676 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1677 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1680 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1681 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1682 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1683 #define AOP_INDPTRn(x) (AOP_TYPE(x) == AOP_DPTRn)
1684 #define AOP_USESDPTR(x) ((AOP_TYPE(x) == AOP_DPTR) || (AOP_TYPE(x) == AOP_STR))
1685 #define AOP_USESDPTR2(x) ((AOP_TYPE(x) == AOP_DPTR2) || (AOP_TYPE(x) == AOP_DPTRn))
1687 // The following two macros can be used even if the aop has not yet been aopOp'd.
1688 #define AOP_IS_STR(x) (IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
1689 #define AOP_IS_DPTRn(x) (IS_SYMOP(x) && OP_SYMBOL(x)->dptr)
1691 /* Workaround for DS80C390 bug: div ab may return bogus results
1692 * if A is accessed in instruction immediately before the div.
1694 * Will be fixed in B4 rev of processor, Dallas claims.
1697 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1698 if (!AOP_NEEDSACC(RIGHT)) \
1700 /* We can load A first, then B, since \
1701 * B (the RIGHT operand) won't clobber A, \
1702 * thus avoiding touching A right before the div. \
1704 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1705 L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL); \
1707 L = aopGet(AOP(RIGHT),0,FALSE,FALSE,"b"); \
1712 /* Just stuff in a nop after loading A. */ \
1713 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,NULL));\
1714 L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL); \
1716 emitcode("nop", "; workaround for DS80C390 div bug."); \
1720 /*-----------------------------------------------------------------*/
1721 /* opIsGptr: returns non-zero if the passed operand is */
1722 /* a generic pointer type. */
1723 /*-----------------------------------------------------------------*/
1725 opIsGptr (operand * op)
1727 sym_link *type = operandType (op);
1729 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1736 /*-----------------------------------------------------------------*/
1737 /* getDataSize - get the operand data size */
1738 /*-----------------------------------------------------------------*/
1740 getDataSize (operand * op)
1743 size = AOP_SIZE (op);
1744 if (size == GPTRSIZE)
1746 sym_link *type = operandType (op);
1747 if (IS_GENPTR (type))
1749 /* generic pointer; arithmetic operations
1750 * should ignore the high byte (pointer type).
1758 /*-----------------------------------------------------------------*/
1759 /* outAcc - output Acc */
1760 /*-----------------------------------------------------------------*/
1762 outAcc (operand * result)
1765 size = getDataSize (result);
1768 aopPut (AOP (result), "a", 0);
1771 /* unsigned or positive */
1774 aopPut (AOP (result), zero, offset++);
1779 /*-----------------------------------------------------------------*/
1780 /* outBitC - output a bit C */
1781 /*-----------------------------------------------------------------*/
1783 outBitC (operand * result)
1785 /* if the result is bit */
1786 if (AOP_TYPE (result) == AOP_CRY)
1788 aopPut (AOP (result), "c", 0);
1792 emitcode ("clr", "a");
1793 emitcode ("rlc", "a");
1798 /*-----------------------------------------------------------------*/
1799 /* toBoolean - emit code for orl a,operator(sizeop) */
1800 /*-----------------------------------------------------------------*/
1802 toBoolean (operand * oper)
1804 int size = AOP_SIZE (oper) - 1;
1808 /* The generic part of a generic pointer should
1809 * not participate in it's truth value.
1811 * i.e. 0x10000000 is zero.
1813 if (opIsGptr (oper))
1815 D (emitcode (";", "toBoolean: generic ptr special case."););
1819 _startLazyDPSEvaluation ();
1820 if (AOP_NEEDSACC (oper) && size)
1825 emitcode ("push", "b");
1827 MOVB (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1831 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1838 emitcode ("orl", "b,%s",
1839 aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1843 emitcode ("orl", "a,%s",
1844 aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1847 _endLazyDPSEvaluation ();
1851 emitcode ("mov", "a,b");
1854 emitcode ("pop", "b");
1861 /*-----------------------------------------------------------------*/
1862 /* genNot - generate code for ! operation */
1863 /*-----------------------------------------------------------------*/
1869 D (emitcode (";", "genNot "););
1871 /* assign asmOps to operand & result */
1872 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1873 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1875 /* if in bit space then a special case */
1876 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1878 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1879 emitcode ("cpl", "c");
1880 outBitC (IC_RESULT (ic));
1884 toBoolean (IC_LEFT (ic));
1886 tlbl = newiTempLabel (NULL);
1887 emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1888 emitcode ("", "!tlabeldef", tlbl->key + 100);
1889 outBitC (IC_RESULT (ic));
1892 /* release the aops */
1893 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1894 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1898 /*-----------------------------------------------------------------*/
1899 /* genCpl - generate code for complement */
1900 /*-----------------------------------------------------------------*/
1908 D (emitcode (";", "genCpl "););
1911 /* assign asmOps to operand & result */
1912 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1913 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1915 /* special case if in bit space */
1916 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1917 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1918 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1919 emitcode ("cpl", "c");
1920 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1923 tlbl=newiTempLabel(NULL);
1924 emitcode ("cjne", "%s,#0x01,%05d$",
1925 aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE,NULL), tlbl->key+100);
1926 emitcode ("", "%05d$:", tlbl->key+100);
1927 outBitC (IC_RESULT(ic));
1931 size = AOP_SIZE (IC_RESULT (ic));
1932 _startLazyDPSEvaluation ();
1935 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
1936 emitcode ("cpl", "a");
1937 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1939 _endLazyDPSEvaluation ();
1943 /* release the aops */
1944 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1945 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1948 /*-----------------------------------------------------------------*/
1949 /* genUminusFloat - unary minus for floating points */
1950 /*-----------------------------------------------------------------*/
1952 genUminusFloat (operand * op, operand * result)
1954 int size, offset = 0;
1956 D(emitcode (";", "genUminusFloat"););
1958 /* for this we just copy and then flip the bit */
1960 _startLazyDPSEvaluation ();
1961 size = AOP_SIZE (op) - 1;
1965 aopPut (AOP (result),
1966 aopGet (AOP (op), offset, FALSE, FALSE, NULL),
1971 MOVA(aopGet (AOP (op), offset, FALSE, FALSE, NULL));
1973 emitcode ("cpl", "acc.7");
1974 aopPut (AOP (result), "a", offset);
1975 _endLazyDPSEvaluation ();
1978 /*-----------------------------------------------------------------*/
1979 /* genUminus - unary minus code generation */
1980 /*-----------------------------------------------------------------*/
1982 genUminus (iCode * ic)
1987 D (emitcode (";", "genUminus "););
1990 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1991 aopOp (IC_RESULT (ic), ic, TRUE, (AOP_TYPE(IC_LEFT (ic)) == AOP_DPTR));
1993 /* if both in bit space then special
1995 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1996 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1999 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2000 emitcode ("cpl", "c");
2001 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2005 optype = operandType (IC_LEFT (ic));
2007 /* if float then do float stuff */
2008 if (IS_FLOAT (optype))
2010 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2014 /* otherwise subtract from zero */
2015 size = AOP_SIZE (IC_LEFT (ic));
2017 _startLazyDPSEvaluation ();
2020 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL);
2021 if (!strcmp (l, "a"))
2025 emitcode ("cpl", "a");
2026 emitcode ("addc", "a,#0");
2032 emitcode ("clr", "a");
2033 emitcode ("subb", "a,%s", l);
2035 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2037 _endLazyDPSEvaluation ();
2039 /* if any remaining bytes in the result */
2040 /* we just need to propagate the sign */
2041 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic)))) != 0)
2043 emitcode ("rlc", "a");
2044 emitcode ("subb", "a,acc");
2046 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2050 /* release the aops */
2051 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2052 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2055 /*-----------------------------------------------------------------*/
2056 /* savermask - saves registers in the mask */
2057 /*-----------------------------------------------------------------*/
2058 static void savermask(bitVect *rs_mask)
2061 if (options.useXstack) {
2062 if (bitVectBitValue (rs_mask, R0_IDX))
2063 emitcode ("mov", "b,r0");
2064 emitcode ("mov", "r0,%s", spname);
2065 for (i = 0; i < ds390_nRegs; i++) {
2066 if (bitVectBitValue (rs_mask, i)) {
2068 emitcode ("mov", "a,b");
2070 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
2071 emitcode ("movx", "@r0,a");
2072 emitcode ("inc", "r0");
2075 emitcode ("mov", "%s,r0", spname);
2076 if (bitVectBitValue (rs_mask, R0_IDX))
2077 emitcode ("mov", "r0,b");
2079 for (i = 0; i < ds390_nRegs; i++) {
2080 if (bitVectBitValue (rs_mask, i))
2081 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2086 /*-----------------------------------------------------------------*/
2087 /* saveRegisters - will look for a call and save the registers */
2088 /*-----------------------------------------------------------------*/
2090 saveRegisters (iCode * lic)
2096 for (ic = lic; ic; ic = ic->next)
2097 if (ic->op == CALL || ic->op == PCALL)
2102 fprintf (stderr, "found parameter push with no function call\n");
2106 /* if the registers have been saved already then
2109 || (IS_SYMOP(IC_LEFT(ic)) && IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))) && !TARGET_IS_DS400) )
2112 /* special case if DPTR alive across a function call then must save it
2113 even though callee saves */
2114 if (IS_SYMOP(IC_LEFT(ic)) &&
2115 IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2117 rsave = newBitVect(ic->rMask->size);
2118 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2119 if (bitVectBitValue(ic->rMask,i))
2120 rsave = bitVectSetBit(rsave,i);
2122 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2124 /* safe the registers in use at this time but skip the
2125 ones for the result */
2126 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2127 ds390_rUmaskForOp (IC_RESULT(ic)));
2133 /*-----------------------------------------------------------------*/
2134 /* usavermask - restore registers with mask */
2135 /*-----------------------------------------------------------------*/
2136 static void unsavermask(bitVect *rs_mask)
2139 if (options.useXstack) {
2140 emitcode ("mov", "r0,%s", spname);
2141 for (i = ds390_nRegs; i >= 0; i--) {
2142 if (bitVectBitValue (rs_mask, i)) {
2143 emitcode ("dec", "r0");
2144 emitcode ("movx", "a,@r0");
2146 emitcode ("mov", "b,a");
2148 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
2151 emitcode ("mov", "%s,r0", spname);
2152 if (bitVectBitValue (rs_mask, R0_IDX))
2153 emitcode ("mov", "r0,b");
2155 for (i = ds390_nRegs; i >= 0; i--) {
2156 if (bitVectBitValue (rs_mask, i))
2157 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2162 /*-----------------------------------------------------------------*/
2163 /* unsaveRegisters - pop the pushed registers */
2164 /*-----------------------------------------------------------------*/
2166 unsaveRegisters (iCode * ic)
2170 if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2172 rsave = newBitVect(ic->rMask->size);
2173 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2174 if (bitVectBitValue(ic->rMask,i))
2175 rsave = bitVectSetBit(rsave,i);
2177 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2179 /* restore the registers in use at this time but skip the
2180 ones for the result */
2181 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2182 ds390_rUmaskForOp (IC_RESULT(ic)));
2188 /*-----------------------------------------------------------------*/
2190 /*-----------------------------------------------------------------*/
2192 pushSide (operand * oper, int size)
2195 _startLazyDPSEvaluation ();
2198 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, NULL);
2199 if (AOP_TYPE (oper) != AOP_REG &&
2200 AOP_TYPE (oper) != AOP_DIR &&
2203 emitcode ("mov", "a,%s", l);
2204 emitcode ("push", "acc");
2207 emitcode ("push", "%s", l);
2209 _endLazyDPSEvaluation ();
2212 /*-----------------------------------------------------------------*/
2213 /* assignResultValue - */
2214 /*-----------------------------------------------------------------*/
2216 assignResultValue (operand * oper)
2219 int size = AOP_SIZE (oper);
2220 bool pushedAcc = FALSE;
2222 if (size == fReturnSizeDS390)
2224 /* I don't think this case can ever happen... */
2225 /* ACC is the last part of this. If writing the result
2226 * uses AC, we must preserve it.
2228 if (AOP_NEEDSACC(oper))
2230 emitcode(";", "assignResultValue special case for ACC.");
2231 emitcode("push", "acc");
2238 _startLazyDPSEvaluation ();
2241 aopPut (AOP (oper), fReturn[offset], offset);
2244 _endLazyDPSEvaluation ();
2248 emitcode("pop", "acc");
2249 aopPut(AOP(oper), "a", offset);
2254 /*-----------------------------------------------------------------*/
2255 /* genXpush - pushes onto the external stack */
2256 /*-----------------------------------------------------------------*/
2258 genXpush (iCode * ic)
2260 asmop *aop = newAsmop (0);
2262 int size, offset = 0;
2264 D (emitcode (";", "genXpush ");
2267 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2268 r = getFreePtr (ic, &aop, FALSE);
2271 emitcode ("mov", "%s,_spx", r->name);
2273 size = AOP_SIZE (IC_LEFT (ic));
2274 _startLazyDPSEvaluation ();
2278 MOVA (aopGet (AOP (IC_LEFT (ic)),
2279 offset++, FALSE, FALSE, NULL));
2280 emitcode ("movx", "@%s,a", r->name);
2281 emitcode ("inc", "%s", r->name);
2284 _endLazyDPSEvaluation ();
2287 emitcode ("mov", "_spx,%s", r->name);
2289 freeAsmop (NULL, aop, ic, TRUE);
2290 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2293 /*-----------------------------------------------------------------*/
2294 /* genIpush - generate code for pushing this gets a little complex */
2295 /*-----------------------------------------------------------------*/
2297 genIpush (iCode * ic)
2299 int size, offset = 0;
2302 D (emitcode (";", "genIpush ");
2305 /* if this is not a parm push : ie. it is spill push
2306 and spill push is always done on the local stack */
2310 /* and the item is spilt then do nothing */
2311 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2314 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2315 size = AOP_SIZE (IC_LEFT (ic));
2316 /* push it on the stack */
2317 _startLazyDPSEvaluation ();
2320 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2326 emitcode ("push", "%s", l);
2328 _endLazyDPSEvaluation ();
2332 /* this is a paramter push: in this case we call
2333 the routine to find the call and save those
2334 registers that need to be saved */
2337 /* if use external stack then call the external
2338 stack pushing routine */
2339 if (options.useXstack)
2345 /* then do the push */
2346 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2348 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2349 size = AOP_SIZE (IC_LEFT (ic));
2351 _startLazyDPSEvaluation ();
2354 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2355 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2356 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2359 emitcode ("mov", "a,%s", l);
2360 emitcode ("push", "acc");
2364 emitcode ("push", "%s", l);
2367 _endLazyDPSEvaluation ();
2369 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2372 /*-----------------------------------------------------------------*/
2373 /* genIpop - recover the registers: can happen only for spilling */
2374 /*-----------------------------------------------------------------*/
2376 genIpop (iCode * ic)
2380 D (emitcode (";", "genIpop ");
2384 /* if the temp was not pushed then */
2385 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2388 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2389 size = AOP_SIZE (IC_LEFT (ic));
2390 offset = (size - 1);
2391 _startLazyDPSEvaluation ();
2394 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2395 FALSE, TRUE, NULL));
2397 _endLazyDPSEvaluation ();
2399 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2402 /*-----------------------------------------------------------------*/
2403 /* unsaveRBank - restores the resgister bank from stack */
2404 /*-----------------------------------------------------------------*/
2406 unsaveRBank (int bank, iCode * ic, bool popPsw)
2412 if (options.useXstack)
2416 /* Assume r0 is available for use. */
2417 r = ds390_regWithIdx (R0_IDX);;
2422 r = getFreePtr (ic, &aop, FALSE);
2424 emitcode ("mov", "%s,_spx", r->name);
2429 if (options.useXstack)
2431 emitcode ("movx", "a,@%s", r->name);
2432 emitcode ("mov", "psw,a");
2433 emitcode ("dec", "%s", r->name);
2437 emitcode ("pop", "psw");
2441 for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2443 if (options.useXstack)
2445 emitcode ("movx", "a,@%s", r->name);
2446 emitcode ("mov", "(%s+%d),a",
2447 regs390[i].base, 8 * bank + regs390[i].offset);
2448 emitcode ("dec", "%s", r->name);
2452 emitcode ("pop", "(%s+%d)",
2453 regs390[i].base, 8 * bank + regs390[i].offset);
2456 if (options.useXstack)
2458 emitcode ("mov", "_spx,%s", r->name);
2463 freeAsmop (NULL, aop, ic, TRUE);
2467 /*-----------------------------------------------------------------*/
2468 /* saveRBank - saves an entire register bank on the stack */
2469 /*-----------------------------------------------------------------*/
2471 saveRBank (int bank, iCode * ic, bool pushPsw)
2477 if (options.useXstack)
2481 /* Assume r0 is available for use. */
2482 r = ds390_regWithIdx (R0_IDX);;
2487 r = getFreePtr (ic, &aop, FALSE);
2489 emitcode ("mov", "%s,_spx", r->name);
2492 for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2494 if (options.useXstack)
2496 emitcode ("inc", "%s", r->name);
2497 emitcode ("mov", "a,(%s+%d)",
2498 regs390[i].base, 8 * bank + regs390[i].offset);
2499 emitcode ("movx", "@%s,a", r->name);
2502 emitcode ("push", "(%s+%d)",
2503 regs390[i].base, 8 * bank + regs390[i].offset);
2508 if (options.useXstack)
2510 emitcode ("mov", "a,psw");
2511 emitcode ("movx", "@%s,a", r->name);
2512 emitcode ("inc", "%s", r->name);
2513 emitcode ("mov", "_spx,%s", r->name);
2517 emitcode ("push", "psw");
2520 emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2525 freeAsmop (NULL, aop, ic, TRUE);
2534 /*-----------------------------------------------------------------*/
2535 /* genSend - gen code for SEND */
2536 /*-----------------------------------------------------------------*/
2537 static void genSend(set *sendSet)
2541 static int rb1_count = 0;
2543 for (sic = setFirstItem (sendSet); sic;
2544 sic = setNextItem (sendSet)) {
2545 int size, offset = 0;
2547 size=getSize(operandType(IC_LEFT(sic)));
2548 D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2549 if (sendCount == 0) { /* first parameter */
2550 // we know that dpl(hxb) is the result, so
2552 _startLazyDPSEvaluation ();
2554 aopOp (IC_LEFT (sic), sic, FALSE,
2555 (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2557 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2560 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2561 FALSE, FALSE, NULL);
2562 if (strcmp (l, fReturn[offset])) {
2563 emitcode ("mov", "%s,%s",
2569 _endLazyDPSEvaluation ();
2570 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2572 } else { /* if more parameter in registers */
2573 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2575 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
2576 FALSE, FALSE, NULL));
2578 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2585 adjustEsp(const char *reg)
2587 emitcode ("anl","%s,#3", reg);
2588 if (TARGET_IS_DS400)
2590 emitcode ("orl","%s,#!constbyte",
2592 (options.stack_loc >> 8) & 0xff);
2596 /*-----------------------------------------------------------------*/
2597 /* genCall - generates a call statement */
2598 /*-----------------------------------------------------------------*/
2600 genCall (iCode * ic)
2603 bool restoreBank = FALSE;
2604 bool swapBanks = FALSE;
2606 D (emitcode (";", "genCall "););
2608 /* if we are calling a not _naked function that is not using
2609 the same register bank then we need to save the
2610 destination registers on the stack */
2611 dtype = operandType (IC_LEFT (ic));
2612 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2613 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2614 IFFUNC_ISISR (currFunc->type))
2618 /* This is unexpected; the bank should have been saved in
2621 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2627 /* if caller saves & we have not saved then */
2631 /* if send set is not empty the assign */
2632 /* We've saved all the registers we care about;
2633 * therefore, we may clobber any register not used
2634 * in the calling convention (i.e. anything not in
2639 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2640 genSend(reverseSet(_G.sendSet));
2642 genSend(_G.sendSet);
2649 emitcode ("mov", "psw,#!constbyte",
2650 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2654 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2655 OP_SYMBOL (IC_LEFT (ic))->rname :
2656 OP_SYMBOL (IC_LEFT (ic))->name));
2660 emitcode ("mov", "psw,#!constbyte",
2661 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2664 /* if we need assign a result value */
2665 if ((IS_ITEMP (IC_RESULT (ic)) &&
2666 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2667 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2668 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2669 IS_TRUE_SYMOP (IC_RESULT (ic)))
2671 if (isOperandInFarSpace (IC_RESULT (ic))
2672 && getSize (operandType (IC_RESULT (ic))) <= 2)
2674 int size = getSize (operandType (IC_RESULT (ic)));
2676 /* Special case for 1 or 2 byte return in far space. */
2680 emitcode ("mov", "b,%s", fReturn[1]);
2685 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2691 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2695 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2697 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2702 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2705 assignResultValue (IC_RESULT (ic));
2707 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2711 /* adjust the stack for parameters if
2713 if (ic->parmBytes) {
2715 if (options.stack10bit) {
2716 if (ic->parmBytes <= 10) {
2717 emitcode(";","stack adjustment for parms");
2718 for (i=0; i < ic->parmBytes ; i++) {
2719 emitcode("pop","acc");
2723 emitcode ("clr","c");
2724 emitcode ("mov","a,sp");
2725 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2726 emitcode ("mov","sp,a");
2727 emitcode ("mov","a,esp");
2729 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2730 emitcode ("mov","esp,a");
2734 if (ic->parmBytes > 3) {
2735 emitcode ("mov", "a,%s", spname);
2736 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2737 emitcode ("mov", "%s,a", spname);
2739 for (i = 0; i < ic->parmBytes; i++)
2740 emitcode ("dec", "%s", spname);
2744 /* if we hade saved some registers then unsave them */
2746 unsaveRegisters (ic);
2748 /* if register bank was saved then pop them */
2750 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2753 /*-----------------------------------------------------------------*/
2754 /* genPcall - generates a call by pointer statement */
2755 /*-----------------------------------------------------------------*/
2757 genPcall (iCode * ic)
2760 symbol *rlbl = newiTempLabel (NULL);
2761 bool restoreBank=FALSE;
2763 D (emitcode (";", "genPcall ");
2767 /* if caller saves & we have not saved then */
2771 /* if we are calling a function that is not using
2772 the same register bank then we need to save the
2773 destination registers on the stack */
2774 dtype = operandType (IC_LEFT (ic));
2775 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2776 IFFUNC_ISISR (currFunc->type) &&
2777 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2778 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2782 /* push the return address on to the stack */
2783 emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2784 emitcode ("push", "acc");
2785 emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2786 emitcode ("push", "acc");
2788 if (options.model == MODEL_FLAT24)
2790 emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2791 emitcode ("push", "acc");
2794 /* now push the calling address */
2795 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2797 pushSide (IC_LEFT (ic), FPTRSIZE);
2799 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2801 /* if send set is not empty the assign */
2804 genSend(reverseSet(_G.sendSet));
2808 emitcode ("ret", "");
2809 emitcode ("", "!tlabeldef", (rlbl->key + 100));
2812 /* if we need assign a result value */
2813 if ((IS_ITEMP (IC_RESULT (ic)) &&
2814 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2815 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2816 IS_TRUE_SYMOP (IC_RESULT (ic)))
2820 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2823 assignResultValue (IC_RESULT (ic));
2825 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2828 /* adjust the stack for parameters if
2833 if (options.stack10bit) {
2834 if (ic->parmBytes <= 10) {
2835 emitcode(";","stack adjustment for parms");
2836 for (i=0; i < ic->parmBytes ; i++) {
2837 emitcode("pop","acc");
2841 emitcode ("clr","c");
2842 emitcode ("mov","a,sp");
2843 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2844 emitcode ("mov","sp,a");
2845 emitcode ("mov","a,esp");
2847 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2848 emitcode ("mov","esp,a");
2852 if (ic->parmBytes > 3) {
2853 emitcode ("mov", "a,%s", spname);
2854 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2855 emitcode ("mov", "%s,a", spname);
2858 for (i = 0; i < ic->parmBytes; i++)
2859 emitcode ("dec", "%s", spname);
2863 /* if register bank was saved then unsave them */
2865 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2867 /* if we hade saved some registers then
2870 unsaveRegisters (ic);
2874 /*-----------------------------------------------------------------*/
2875 /* resultRemat - result is rematerializable */
2876 /*-----------------------------------------------------------------*/
2878 resultRemat (iCode * ic)
2880 if (SKIP_IC (ic) || ic->op == IFX)
2883 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2885 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2886 if (sym->remat && !POINTER_SET (ic))
2893 #if defined(__BORLANDC__) || defined(_MSC_VER)
2894 #define STRCASECMP stricmp
2896 #define STRCASECMP strcasecmp
2899 /*-----------------------------------------------------------------*/
2900 /* inExcludeList - return 1 if the string is in exclude Reg list */
2901 /*-----------------------------------------------------------------*/
2903 regsCmp(void *p1, void *p2)
2905 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2909 inExcludeList (char *s)
2911 const char *p = setFirstItem(options.excludeRegsSet);
2913 if (p == NULL || STRCASECMP(p, "none") == 0)
2917 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2920 /*-----------------------------------------------------------------*/
2921 /* genFunction - generated code for function entry */
2922 /*-----------------------------------------------------------------*/
2924 genFunction (iCode * ic)
2928 bool switchedPSW = FALSE;
2930 D (emitcode (";", "genFunction "););
2933 /* create the function header */
2934 emitcode (";", "-----------------------------------------");
2935 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2936 emitcode (";", "-----------------------------------------");
2938 emitcode ("", "%s:", sym->rname);
2939 ftype = operandType (IC_LEFT (ic));
2941 if (IFFUNC_ISNAKED(ftype))
2943 emitcode(";", "naked function: no prologue.");
2947 if (options.stack_probe)
2948 emitcode ("lcall","__stack_probe");
2950 /* here we need to generate the equates for the
2951 register bank if required */
2952 if (FUNC_REGBANK (ftype) != rbank)
2956 rbank = FUNC_REGBANK (ftype);
2957 for (i = 0; i < ds390_nRegs; i++)
2959 if (regs390[i].print) {
2960 if (strcmp (regs390[i].base, "0") == 0)
2961 emitcode ("", "%s !equ !constbyte",
2963 8 * rbank + regs390[i].offset);
2965 emitcode ("", "%s !equ %s + !constbyte",
2968 8 * rbank + regs390[i].offset);
2973 /* if this is an interrupt service routine then
2974 save acc, b, dpl, dph */
2975 if (IFFUNC_ISISR (sym->type))
2977 if (!inExcludeList ("acc"))
2978 emitcode ("push", "acc");
2979 if (!inExcludeList ("b"))
2980 emitcode ("push", "b");
2981 if (!inExcludeList ("dpl"))
2982 emitcode ("push", "dpl");
2983 if (!inExcludeList ("dph"))
2984 emitcode ("push", "dph");
2985 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2987 emitcode ("push", "dpx");
2988 /* Make sure we're using standard DPTR */
2989 emitcode ("push", "dps");
2990 emitcode ("mov", "dps,#0");
2991 if (options.stack10bit)
2993 /* This ISR could conceivably use DPTR2. Better save it. */
2994 emitcode ("push", "dpl1");
2995 emitcode ("push", "dph1");
2996 emitcode ("push", "dpx1");
2997 emitcode ("push", DP2_RESULT_REG);
3000 /* if this isr has no bank i.e. is going to
3001 run with bank 0 , then we need to save more
3003 if (!FUNC_REGBANK (sym->type))
3007 /* if this function does not call any other
3008 function then we can be economical and
3009 save only those registers that are used */
3010 if (!IFFUNC_HASFCALL(sym->type))
3013 /* if any registers used */
3016 /* save the registers used */
3017 for (i = 0; i < sym->regsUsed->size; i++)
3019 if (bitVectBitValue (sym->regsUsed, i) ||
3020 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3021 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3024 else if (ds390_ptrRegReq)
3026 emitcode ("push", "%s", ds390_regWithIdx (R0_IDX)->dname);
3027 emitcode ("push", "%s", ds390_regWithIdx (R1_IDX)->dname);
3033 /* this function has a function call cannot
3034 determines register usage so we will have to push the
3036 saveRBank (0, ic, FALSE);
3037 if (options.parms_in_bank1) {
3038 for (i=0; i < 8 ; i++ ) {
3039 emitcode ("push","%s",rb1regs[i]);
3046 /* This ISR uses a non-zero bank.
3048 * We assume that the bank is available for our
3051 * However, if this ISR calls a function which uses some
3052 * other bank, we must save that bank entirely.
3054 unsigned long banksToSave = 0;
3056 if (IFFUNC_HASFCALL(sym->type))
3059 #define MAX_REGISTER_BANKS 4
3064 for (i = ic; i; i = i->next)
3066 if (i->op == ENDFUNCTION)
3068 /* we got to the end OK. */
3076 dtype = operandType (IC_LEFT(i));
3078 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3080 /* Mark this bank for saving. */
3081 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3083 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3087 banksToSave |= (1 << FUNC_REGBANK(dtype));
3090 /* And note that we don't need to do it in
3098 /* This is a mess; we have no idea what
3099 * register bank the called function might
3102 * The only thing I can think of to do is
3103 * throw a warning and hope.
3105 werror(W_FUNCPTR_IN_USING_ISR);
3109 if (banksToSave && options.useXstack)
3111 /* Since we aren't passing it an ic,
3112 * saveRBank will assume r0 is available to abuse.
3114 * So switch to our (trashable) bank now, so
3115 * the caller's R0 isn't trashed.
3117 emitcode ("push", "psw");
3118 emitcode ("mov", "psw,#!constbyte",
3119 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3123 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3125 if (banksToSave & (1 << ix))
3127 saveRBank(ix, NULL, FALSE);
3131 // TODO: this needs a closer look
3132 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3137 /* if callee-save to be used for this function
3138 then save the registers being used in this function */
3139 if (IFFUNC_CALLEESAVES(sym->type))
3143 /* if any registers used */
3146 /* save the registers used */
3147 for (i = 0; i < sym->regsUsed->size; i++)
3149 if (bitVectBitValue (sym->regsUsed, i) ||
3150 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3152 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3157 else if (ds390_ptrRegReq)
3159 emitcode ("push", "%s", ds390_regWithIdx (R0_IDX)->dname);
3160 emitcode ("push", "%s", ds390_regWithIdx (R1_IDX)->dname);
3166 /* set the register bank to the desired value */
3167 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3170 emitcode ("push", "psw");
3171 emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3174 if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3175 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3176 if (options.stack10bit) {
3177 emitcode ("push","_bpx");
3178 emitcode ("push","_bpx+1");
3179 emitcode ("mov","_bpx,%s",spname);
3180 emitcode ("mov","_bpx+1,esp");
3181 adjustEsp("_bpx+1");
3183 if (options.useXstack) {
3184 emitcode ("mov", "r0,%s", spname);
3185 emitcode ("mov", "a,_bp");
3186 emitcode ("movx", "@r0,a");
3187 emitcode ("inc", "%s", spname);
3189 /* set up the stack */
3190 emitcode ("push", "_bp"); /* save the callers stack */
3192 emitcode ("mov", "_bp,%s", spname);
3196 /* adjust the stack for the function */
3199 if (options.stack10bit) {
3200 if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
3201 assert (sym->recvSize <= 4);
3202 if (sym->stack <= 8) {
3203 while (i--) emitcode ("push","acc");
3206 emitcode ("mov","a,sp");
3207 emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3208 emitcode ("mov","sp,a");
3209 emitcode ("mov","a,esp");
3211 emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3212 emitcode ("mov","esp,a");
3217 werror (W_STACK_OVERFLOW, sym->name);
3219 if (i > 3 && sym->recvSize < 4) {
3221 emitcode ("mov", "a,sp");
3222 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3223 emitcode ("mov", "sp,a");
3227 emitcode ("inc", "sp");
3234 emitcode ("mov", "a,_spx");
3235 emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3236 emitcode ("mov", "_spx,a");
3239 /* if critical function then turn interrupts off */
3240 if (IFFUNC_ISCRITICAL (ftype))
3242 symbol *tlbl = newiTempLabel (NULL);
3243 emitcode ("setb", "c");
3244 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3245 emitcode ("clr", "c");
3246 emitcode ("", "%05d$:", (tlbl->key + 100));
3247 emitcode ("push", "psw"); /* save old ea via c in psw */
3252 /*-----------------------------------------------------------------*/
3253 /* genEndFunction - generates epilogue for functions */
3254 /*-----------------------------------------------------------------*/
3256 genEndFunction (iCode * ic)
3258 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3259 lineNode *lnp = lineCurr;
3261 bitVect *regsUsedPrologue;
3262 bitVect *regsUnneeded;
3265 D (emitcode (";", "genEndFunction "););
3267 if (IFFUNC_ISNAKED(sym->type))
3269 emitcode(";", "naked function: no epilogue.");
3273 if (IFFUNC_ISCRITICAL (sym->type))
3275 emitcode ("pop", "psw"); /* restore ea via c in psw */
3276 emitcode ("mov", "ea,c");
3279 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3280 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3282 if (options.stack10bit) {
3284 emitcode ("mov", "sp,_bpx", spname);
3285 emitcode ("mov", "esp,_bpx+1", spname);
3288 emitcode ("mov", "%s,_bp", spname);
3292 /* if use external stack but some variables were
3293 added to the local stack then decrement the
3295 if (options.useXstack && sym->stack) {
3296 emitcode ("mov", "a,sp");
3297 emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3298 emitcode ("mov", "sp,a");
3302 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3303 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3305 if (options.useXstack) {
3306 emitcode ("mov", "r0,%s", spname);
3307 emitcode ("movx", "a,@r0");
3308 emitcode ("mov", "_bp,a");
3309 emitcode ("dec", "%s", spname);
3311 if (options.stack10bit) {
3312 emitcode ("pop", "_bpx+1");
3313 emitcode ("pop", "_bpx");
3315 emitcode ("pop", "_bp");
3320 /* restore the register bank */
3321 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3323 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3324 || !options.useXstack)
3326 /* Special case of ISR using non-zero bank with useXstack
3329 emitcode ("pop", "psw");
3333 if (IFFUNC_ISISR (sym->type))
3336 /* now we need to restore the registers */
3337 /* if this isr has no bank i.e. is going to
3338 run with bank 0 , then we need to save more
3340 if (!FUNC_REGBANK (sym->type))
3343 /* if this function does not call any other
3344 function then we can be economical and
3345 save only those registers that are used */
3346 if (!IFFUNC_HASFCALL(sym->type))
3349 /* if any registers used */
3352 /* save the registers used */
3353 for (i = sym->regsUsed->size; i >= 0; i--)
3355 if (bitVectBitValue (sym->regsUsed, i) ||
3356 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3357 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3360 else if (ds390_ptrRegReq)
3362 emitcode ("pop", "%s", ds390_regWithIdx (R1_IDX)->dname);
3363 emitcode ("pop", "%s", ds390_regWithIdx (R0_IDX)->dname);
3369 /* this function has a function call cannot
3370 determines register usage so we will have to pop the
3372 if (options.parms_in_bank1) {
3373 for (i = 7 ; i >= 0 ; i-- ) {
3374 emitcode ("pop","%s",rb1regs[i]);
3377 unsaveRBank (0, ic, FALSE);
3382 /* This ISR uses a non-zero bank.
3384 * Restore any register banks saved by genFunction
3387 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3390 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3392 if (savedBanks & (1 << ix))
3394 unsaveRBank(ix, NULL, FALSE);
3398 if (options.useXstack)
3400 /* Restore bank AFTER calling unsaveRBank,
3401 * since it can trash r0.
3403 emitcode ("pop", "psw");
3407 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3409 if (options.stack10bit)
3411 emitcode ("pop", DP2_RESULT_REG);
3412 emitcode ("pop", "dpx1");
3413 emitcode ("pop", "dph1");
3414 emitcode ("pop", "dpl1");
3416 emitcode ("pop", "dps");
3417 emitcode ("pop", "dpx");
3419 if (!inExcludeList ("dph"))
3420 emitcode ("pop", "dph");
3421 if (!inExcludeList ("dpl"))
3422 emitcode ("pop", "dpl");
3423 if (!inExcludeList ("b"))
3424 emitcode ("pop", "b");
3425 if (!inExcludeList ("acc"))
3426 emitcode ("pop", "acc");
3428 /* if debug then send end of function */
3429 if (options.debug && currFunc) {
3431 emitcode ("", "C$%s$%d$%d$%d ==.",
3432 FileBaseName (ic->filename), currFunc->lastLine,
3433 ic->level, ic->block);
3434 if (IS_STATIC (currFunc->etype))
3435 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3437 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3441 emitcode ("reti", "");
3445 if (IFFUNC_CALLEESAVES(sym->type))
3449 /* if any registers used */
3452 /* save the registers used */
3453 for (i = sym->regsUsed->size; i >= 0; i--)
3455 if (bitVectBitValue (sym->regsUsed, i) ||
3456 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3457 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3460 else if (ds390_ptrRegReq)
3462 emitcode ("pop", "%s", ds390_regWithIdx (R1_IDX)->dname);
3463 emitcode ("pop", "%s", ds390_regWithIdx (R0_IDX)->dname);
3468 /* if debug then send end of function */
3469 if (options.debug && currFunc)
3472 emitcode ("", "C$%s$%d$%d$%d ==.",
3473 FileBaseName (ic->filename), currFunc->lastLine,
3474 ic->level, ic->block);
3475 if (IS_STATIC (currFunc->etype))
3476 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3478 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3482 emitcode ("ret", "");
3485 if (!port->peep.getRegsRead || !port->peep.getRegsWritten)
3488 /* If this was an interrupt handler using bank 0 that called another */
3489 /* function, then all registers must be saved; nothing to optimized. */
3490 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3491 && !FUNC_REGBANK(sym->type))
3494 /* Compute the registers actually used */
3495 regsUsed = newBitVect (ds390_nRegs);
3496 regsUsedPrologue = newBitVect (ds390_nRegs);
3499 if (lnp->ic && lnp->ic->op == FUNCTION)
3500 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3502 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3504 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3505 && lnp->prev->ic && lnp->prev->ic->op != FUNCTION)
3512 if (bitVectBitValue (regsUsedPrologue, DPS_IDX)
3513 && !bitVectBitValue (regsUsed, DPS_IDX))
3515 bitVectUnSetBit (regsUsedPrologue, DPS_IDX);
3518 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3519 && !bitVectBitValue (regsUsed, CND_IDX))
3521 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3522 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK(sym->type)
3524 bitVectUnSetBit (regsUsed, CND_IDX);
3527 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3529 /* If this was an interrupt handler that called another function */
3530 /* function, then assume working registers may be modified by it. */
3531 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3533 regsUsed = bitVectSetBit (regsUsed, AP_IDX);
3534 regsUsed = bitVectSetBit (regsUsed, DPX1_IDX);
3535 regsUsed = bitVectSetBit (regsUsed, DPL1_IDX);
3536 regsUsed = bitVectSetBit (regsUsed, DPH1_IDX);
3537 regsUsed = bitVectSetBit (regsUsed, DPX_IDX);
3538 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3539 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3540 regsUsed = bitVectSetBit (regsUsed, DPS_IDX);
3541 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3542 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3543 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3546 /* Remove the unneeded push/pops */
3547 regsUnneeded = newBitVect (ds390_nRegs);
3550 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3552 if (!strncmp(lnp->line, "push", 4))
3554 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3555 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3557 connectLine (lnp->prev, lnp->next);
3558 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3561 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3563 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3564 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3566 connectLine (lnp->prev, lnp->next);
3567 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3574 for (idx = 0; idx < regsUnneeded->size; idx++)
3575 if (bitVectBitValue (regsUnneeded, idx))
3576 emitcode ("", ";\teliminated unneeded push/pop %s", ds390_regWithIdx (idx)->dname);
3578 freeBitVect (regsUnneeded);
3579 freeBitVect (regsUsed);
3580 freeBitVect (regsUsedPrologue);
3583 /*-----------------------------------------------------------------*/
3584 /* genJavaNativeRet - generate code for return JavaNative */
3585 /*-----------------------------------------------------------------*/
3586 static void genJavaNativeRet(iCode *ic)
3590 aopOp (IC_LEFT (ic), ic, FALSE,
3591 AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
3592 size = AOP_SIZE (IC_LEFT (ic));
3596 /* it is assigned to GPR0-R3 then push them */
3597 if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3598 aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3599 for (i = 0 ; i < size ; i++ ) {
3600 emitcode ("push","%s",
3601 aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3603 for (i = (size-1) ; i >= 0 ; i--) {
3604 emitcode ("pop","a%s",javaRet[i]);
3607 for (i = 0 ; i < size ; i++)
3608 emitcode ("mov","%s,%s",javaRet[i],
3609 aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3611 for (i = size ; i < 4 ; i++ )
3612 emitcode ("mov","%s,#0",javaRet[i]);
3616 /*-----------------------------------------------------------------*/
3617 /* genRet - generate code for return statement */
3618 /*-----------------------------------------------------------------*/
3622 int size, offset = 0, pushed = 0;
3624 D (emitcode (";", "genRet "););
3626 /* if we have no return value then
3627 just generate the "ret" */
3631 /* if this is a JavaNative function then return
3632 value in different register */
3633 if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3634 genJavaNativeRet(ic);
3637 /* we have something to return then
3638 move the return value into place */
3639 aopOp (IC_LEFT (ic), ic, FALSE,
3640 (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
3641 size = AOP_SIZE (IC_LEFT (ic));
3643 _startLazyDPSEvaluation ();
3647 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3649 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3651 emitcode ("push", "%s", l);
3656 /* Since A is the last element of fReturn,
3657 * is is OK to clobber it in the aopGet.
3659 l = aopGet (AOP (IC_LEFT (ic)), offset,
3660 FALSE, FALSE, NULL);
3661 if (strcmp (fReturn[offset], l))
3662 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3665 _endLazyDPSEvaluation ();
3672 if (strcmp (fReturn[pushed], "a"))
3673 emitcode ("pop", fReturn[pushed]);
3675 emitcode ("pop", "acc");
3678 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3681 /* generate a jump to the return label
3682 if the next is not the return statement */
3683 if (!(ic->next && ic->next->op == LABEL &&
3684 IC_LABEL (ic->next) == returnLabel))
3686 emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3690 /*-----------------------------------------------------------------*/
3691 /* genLabel - generates a label */
3692 /*-----------------------------------------------------------------*/
3694 genLabel (iCode * ic)
3696 /* special case never generate */
3697 if (IC_LABEL (ic) == entryLabel)
3700 D (emitcode (";", "genLabel ");
3703 emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3706 /*-----------------------------------------------------------------*/
3707 /* genGoto - generates a ljmp */
3708 /*-----------------------------------------------------------------*/
3710 genGoto (iCode * ic)
3712 D (emitcode (";", "genGoto ");
3714 emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3717 /*-----------------------------------------------------------------*/
3718 /* findLabelBackwards: walks back through the iCode chain looking */
3719 /* for the given label. Returns number of iCode instructions */
3720 /* between that label and given ic. */
3721 /* Returns zero if label not found. */
3722 /*-----------------------------------------------------------------*/
3724 findLabelBackwards (iCode * ic, int key)
3733 /* If we have any pushes or pops, we cannot predict the distance.
3734 I don't like this at all, this should be dealt with in the
3736 if (ic->op == IPUSH || ic->op == IPOP) {
3740 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3742 /* printf("findLabelBackwards = %d\n", count); */
3750 /*-----------------------------------------------------------------*/
3751 /* genPlusIncr :- does addition with increment if possible */
3752 /*-----------------------------------------------------------------*/
3754 genPlusIncr (iCode * ic)
3756 unsigned int icount;
3757 unsigned int size = getDataSize (IC_RESULT (ic));
3759 /* will try to generate an increment */
3760 /* if the right side is not a literal
3762 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3765 /* if the literal value of the right hand side
3766 is greater than 4 then it is not worth it */
3767 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3770 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3771 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3773 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
3777 /* if increment 16 bits in register */
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))) &&
3790 /* If the next instruction is a goto and the goto target
3791 * is <= 5 instructions previous to this, we can generate
3792 * jumps straight to that target.
3794 if (ic->next && ic->next->op == GOTO
3795 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3798 D(emitcode (";", "tail increment optimized (range %d)", labelRange););
3799 tlbl = IC_LABEL (ic->next);
3804 tlbl = newiTempLabel (NULL);
3808 l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
3809 emitcode ("inc", "%s", l);
3811 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3812 IS_AOP_PREG (IC_RESULT (ic)))
3814 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3818 emitcode ("clr", "a");
3819 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3822 l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
3823 emitcode ("inc", "%s", l);
3826 if (!strcmp(l, "acc"))
3828 emitcode("jnz", "!tlabel", tlbl->key + 100);
3830 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3831 IS_AOP_PREG (IC_RESULT (ic)))
3833 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3837 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3840 l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
3841 emitcode ("inc", "%s", l);
3845 if (!strcmp(l, "acc"))
3847 emitcode("jnz", "!tlabel", tlbl->key + 100);
3849 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3850 IS_AOP_PREG (IC_RESULT (ic)))
3852 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3856 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3859 l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
3860 emitcode ("inc", "%s", l); }
3864 emitcode ("", "!tlabeldef", tlbl->key + 100);
3869 if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3870 !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 &&
3871 options.model == MODEL_FLAT24 ) {
3875 emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, NULL));
3877 emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, NULL));
3879 emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3882 while (icount--) emitcode ("inc","dptr");
3886 if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3887 AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3889 emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3890 while (icount--) emitcode ("inc","dptr");
3891 emitcode ("mov","dps,#0");
3895 /* if the sizes are greater than 1 then we cannot */
3896 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3897 AOP_SIZE (IC_LEFT (ic)) > 1)
3900 /* we can if the aops of the left & result match or
3901 if they are in registers and the registers are the
3904 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3905 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3906 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3911 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3912 emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3913 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3918 _startLazyDPSEvaluation ();
3921 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3923 _endLazyDPSEvaluation ();
3932 /*-----------------------------------------------------------------*/
3933 /* outBitAcc - output a bit in acc */
3934 /*-----------------------------------------------------------------*/
3936 outBitAcc (operand * result)
3938 symbol *tlbl = newiTempLabel (NULL);
3939 /* if the result is a bit */
3940 if (AOP_TYPE (result) == AOP_CRY)
3942 aopPut (AOP (result), "a", 0);
3946 emitcode ("jz", "!tlabel", tlbl->key + 100);
3947 emitcode ("mov", "a,%s", one);
3948 emitcode ("", "!tlabeldef", tlbl->key + 100);
3953 /*-----------------------------------------------------------------*/
3954 /* genPlusBits - generates code for addition of two bits */
3955 /*-----------------------------------------------------------------*/
3957 genPlusBits (iCode * ic)
3959 D (emitcode (";", "genPlusBits "););
3961 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3963 symbol *lbl = newiTempLabel (NULL);
3964 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3965 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3966 emitcode ("cpl", "c");
3967 emitcode ("", "!tlabeldef", (lbl->key + 100));
3968 outBitC (IC_RESULT (ic));
3972 emitcode ("clr", "a");
3973 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3974 emitcode ("rlc", "a");
3975 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3976 emitcode ("addc", "a,#0");
3977 outAcc (IC_RESULT (ic));
3982 adjustArithmeticResult (iCode * ic)
3984 if (opIsGptr (IC_RESULT (ic)) &&
3985 opIsGptr (IC_LEFT (ic)) &&
3986 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3988 aopPut (AOP (IC_RESULT (ic)),
3989 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3993 if (opIsGptr (IC_RESULT (ic)) &&
3994 opIsGptr (IC_RIGHT (ic)) &&
3995 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3997 aopPut (AOP (IC_RESULT (ic)),
3998 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
4002 if (opIsGptr (IC_RESULT (ic)) &&
4003 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4004 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4005 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4006 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4009 SNPRINTF (buff, sizeof(buff),
4010 "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
4011 aopPut (AOP (IC_RESULT (ic)), buff, GPTRSIZE - 1);
4015 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
4016 // generates the result if possible. If result is generated, returns TRUE; otherwise
4017 // returns false and caller must deal with fact that result isn't aopOp'd.
4018 bool aopOp3(iCode * ic)
4020 bool dp1InUse, dp2InUse;
4023 // First, generate the right opcode. DPTR may be used if neither left nor result are
4026 // D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
4027 // AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
4028 // AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
4029 // AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
4031 // D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
4032 // AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
4033 // AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
4034 // AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
4037 // Right uses DPTR unless left or result is an AOP_STR; however,
4038 // if right is an AOP_STR, it must use DPTR regardless.
4039 if ((AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)))
4040 && !AOP_IS_STR(IC_RIGHT(ic)))
4049 aopOp (IC_RIGHT(ic),ic,FALSE, useDp2);
4051 // if the right used DPTR, left MUST use DPTR2.
4052 // if the right used DPTR2, left MUST use DPTR.
4053 // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
4054 // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
4055 // enabling us to assign DPTR to result.
4057 if (AOP_USESDPTR(IC_RIGHT(ic)))
4061 else if (AOP_USESDPTR2(IC_RIGHT(ic)))
4067 if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
4077 aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
4080 // We've op'd the left & right. So, if left or right are the same operand as result,
4081 // we know aopOp will succeed, and we can just do it & bail.
4082 if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)))
4084 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4087 if (isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
4089 // D(emitcode(";", "aopOp3: (left | right) & result equal"););
4090 aopOp(IC_RESULT(ic),ic,TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4094 // Operands may be equivalent (but not equal) if they share a spill location. If
4095 // so, use the same DPTR or DPTR2.
4096 if (operandsEqu (IC_LEFT(ic), IC_RESULT(ic)))
4098 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4101 if (operandsEqu (IC_RIGHT(ic), IC_RESULT(ic)))
4103 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4107 // Note which dptrs are currently in use.
4108 dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
4109 dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
4111 // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot
4113 if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
4118 // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
4119 if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
4124 // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck
4125 if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
4130 aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
4132 // Some sanity checking...
4133 if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
4136 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
4137 __FILE__, __LINE__, ic->filename, ic->lineno);
4138 emitcode(";", ">>> unexpected DPTR here.");
4141 if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
4144 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
4145 __FILE__, __LINE__, ic->filename, ic->lineno);
4146 emitcode(";", ">>> unexpected DPTR2 here.");
4152 // Macro to aopOp all three operands of an ic. If this cannot be done,
4153 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
4154 // will be set TRUE. The caller must then handle the case specially, noting
4155 // that the IC_RESULT operand is not aopOp'd.
4157 #define AOP_OP_3_NOFATAL(ic, rc) \
4158 do { rc = !aopOp3(ic); } while (0)
4160 // aopOp the left & right operands of an ic.
4161 #define AOP_OP_2(ic) \
4162 aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
4163 aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
4165 // convienience macro.
4166 #define AOP_SET_LOCALS(ic) \
4167 left = IC_LEFT(ic); \
4168 right = IC_RIGHT(ic); \
4169 result = IC_RESULT(ic);
4172 // Given an integer value of pushedSize bytes on the stack,
4173 // adjust it to be resultSize bytes, either by discarding
4174 // the most significant bytes or by zero-padding.
4176 // On exit from this macro, pushedSize will have been adjusted to
4177 // equal resultSize, and ACC may be trashed.
4178 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
4179 /* If the pushed data is bigger than the result, \
4180 * simply discard unused bytes. Icky, but works. \
4182 while (pushedSize > resultSize) \
4184 D (emitcode (";", "discarding unused result byte."););\
4185 emitcode ("pop", "acc"); \
4188 if (pushedSize < resultSize) \
4190 emitcode ("clr", "a"); \
4191 /* Conversly, we haven't pushed enough here. \
4192 * just zero-pad, and all is well. \
4194 while (pushedSize < resultSize) \
4196 emitcode("push", "acc"); \
4200 assert(pushedSize == resultSize);
4202 /*-----------------------------------------------------------------*/
4203 /* genPlus - generates code for addition */
4204 /*-----------------------------------------------------------------*/
4206 genPlus (iCode * ic)
4208 int size, offset = 0;
4212 D (emitcode (";", "genPlus "););
4214 /* special cases :- */
4215 if ( AOP_IS_STR(IC_LEFT(ic)) &&
4216 isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
4217 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
4218 size = (int)floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
4220 while (size--) emitcode ("inc","dptr");
4222 emitcode ("mov","a,dpl");
4223 emitcode ("add","a,#!constbyte",size & 0xff);
4224 emitcode ("mov","dpl,a");
4225 emitcode ("mov","a,dph");
4226 emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
4227 emitcode ("mov","dph,a");
4228 emitcode ("mov","a,dpx");
4229 emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
4230 emitcode ("mov","dpx,a");
4232 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
4235 if ( IS_SYMOP(IC_LEFT(ic)) &&
4236 OP_SYMBOL(IC_LEFT(ic))->remat &&
4237 isOperandInFarSpace(IC_RIGHT(ic))) {
4238 operand *op = IC_RIGHT(ic);
4239 IC_RIGHT(ic) = IC_LEFT(ic);
4243 AOP_OP_3_NOFATAL (ic, pushResult);
4247 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
4252 /* if literal, literal on the right or
4253 if left requires ACC or right is already
4255 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4256 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
4257 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4259 operand *t = IC_RIGHT (ic);
4260 IC_RIGHT (ic) = IC_LEFT (ic);
4262 emitcode (";", "Swapped plus args.");
4265 /* if both left & right are in bit
4267 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4268 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4274 /* if left in bit space & right literal */
4275 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4276 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4278 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4279 /* if result in bit space */
4280 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4282 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4283 emitcode ("cpl", "c");
4284 outBitC (IC_RESULT (ic));
4288 size = getDataSize (IC_RESULT (ic));
4289 _startLazyDPSEvaluation ();
4292 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4293 emitcode ("addc", "a,#0");
4294 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4296 _endLazyDPSEvaluation ();
4301 /* if I can do an increment instead
4302 of add then GOOD for ME */
4303 if (genPlusIncr (ic) == TRUE)
4305 emitcode (";", "did genPlusIncr");
4310 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4312 _startLazyDPSEvaluation ();
4315 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4317 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4319 emitcode ("add", "a,%s",
4320 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4322 emitcode ("addc", "a,%s",
4323 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4327 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4329 /* right is going to use ACC or we would have taken the
4332 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4334 D(emitcode(";", "+ AOP_ACC special case."););
4335 emitcode("xch", "a, %s", DP2_RESULT_REG);
4337 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4340 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4343 emitcode("add", "a, %s", DP2_RESULT_REG);
4347 emitcode ("add", "a,%s",
4348 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE,
4354 emitcode ("addc", "a,%s",
4355 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE,
4361 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4365 emitcode ("push", "acc");
4369 _endLazyDPSEvaluation ();
4373 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4375 size = getDataSize (IC_LEFT (ic));
4376 rSize = getDataSize (IC_RESULT (ic));
4378 ADJUST_PUSHED_RESULT(size, rSize);
4380 _startLazyDPSEvaluation ();
4383 emitcode ("pop", "acc");
4384 aopPut (AOP (IC_RESULT (ic)), "a", size);
4386 _endLazyDPSEvaluation ();
4389 adjustArithmeticResult (ic);
4392 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4393 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4394 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4397 /*-----------------------------------------------------------------*/
4398 /* genMinusDec :- does subtraction with deccrement if possible */
4399 /*-----------------------------------------------------------------*/
4401 genMinusDec (iCode * ic)
4403 unsigned int icount;
4404 unsigned int size = getDataSize (IC_RESULT (ic));
4406 /* will try to generate an increment */
4407 /* if the right side is not a literal
4409 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4412 /* if the literal value of the right hand side
4413 is greater than 4 then it is not worth it */
4414 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4417 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4418 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4420 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
4424 /* if decrement 16 bits in register */
4425 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4426 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4427 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4436 /* If the next instruction is a goto and the goto target
4437 * is <= 5 instructions previous to this, we can generate
4438 * jumps straight to that target.
4440 if (ic->next && ic->next->op == GOTO
4441 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4444 emitcode (";", "tail decrement optimized (range %d)", labelRange);
4445 tlbl = IC_LABEL (ic->next);
4450 tlbl = newiTempLabel (NULL);
4454 l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
4455 emitcode ("dec", "%s", l);
4457 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4458 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4459 IS_AOP_PREG (IC_RESULT (ic)))
4461 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4465 emitcode ("mov", "a,#!constbyte",0xff);
4466 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4468 l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
4469 emitcode ("dec", "%s", l);
4472 if (!strcmp(l, "acc"))
4474 emitcode("jnz", "!tlabel", tlbl->key + 100);
4476 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4477 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4478 IS_AOP_PREG (IC_RESULT (ic)))
4480 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4484 emitcode ("mov", "a,#!constbyte",0xff);
4485 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4487 l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
4488 emitcode ("dec", "%s", l);
4492 if (!strcmp(l, "acc"))
4494 emitcode("jnz", "!tlabel", tlbl->key + 100);
4496 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4497 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4498 IS_AOP_PREG (IC_RESULT (ic)))
4500 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4504 emitcode ("mov", "a,#!constbyte",0xff);
4505 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4507 l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
4508 emitcode ("dec", "%s", l);
4512 emitcode ("", "!tlabeldef", tlbl->key + 100);
4517 /* if the sizes are greater than 1 then we cannot */
4518 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4519 AOP_SIZE (IC_LEFT (ic)) > 1)
4522 /* we can if the aops of the left & result match or
4523 if they are in registers and the registers are the
4526 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4527 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4528 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4531 _startLazyDPSEvaluation ();
4534 emitcode ("dec", "%s",
4535 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
4537 _endLazyDPSEvaluation ();
4545 /*-----------------------------------------------------------------*/
4546 /* addSign - complete with sign */
4547 /*-----------------------------------------------------------------*/
4549 addSign (operand * result, int offset, int sign)
4551 int size = (getDataSize (result) - offset);
4554 _startLazyDPSEvaluation();
4557 emitcode ("rlc", "a");
4558 emitcode ("subb", "a,acc");
4561 aopPut (AOP (result), "a", offset++);
4568 aopPut (AOP (result), zero, offset++);
4571 _endLazyDPSEvaluation();
4575 /*-----------------------------------------------------------------*/
4576 /* genMinusBits - generates code for subtraction of two bits */
4577 /*-----------------------------------------------------------------*/
4579 genMinusBits (iCode * ic)
4581 symbol *lbl = newiTempLabel (NULL);
4583 D (emitcode (";", "genMinusBits "););
4585 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4587 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4588 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4589 emitcode ("cpl", "c");
4590 emitcode ("", "!tlabeldef", (lbl->key + 100));
4591 outBitC (IC_RESULT (ic));
4595 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4596 emitcode ("subb", "a,acc");
4597 emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4598 emitcode ("inc", "a");
4599 emitcode ("", "!tlabeldef", (lbl->key + 100));
4600 aopPut (AOP (IC_RESULT (ic)), "a", 0);
4601 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4605 /*-----------------------------------------------------------------*/
4606 /* genMinus - generates code for subtraction */
4607 /*-----------------------------------------------------------------*/
4609 genMinus (iCode * ic)
4611 int size, offset = 0;
4616 D (emitcode (";", "genMinus "););
4618 AOP_OP_3_NOFATAL(ic, pushResult);
4622 /* special cases :- */
4623 /* if both left & right are in bit space */
4624 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4625 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4631 /* if I can do an decrement instead
4632 of subtract then GOOD for ME */
4633 if (genMinusDec (ic) == TRUE)
4638 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4640 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4646 lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4651 /* if literal, add a,#-lit, else normal subb */
4652 _startLazyDPSEvaluation ();
4654 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4655 if (AOP_USESDPTR(IC_RIGHT(ic))) {
4656 emitcode ("mov","b,%s",
4657 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4658 MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4659 emitcode ("subb","a,b");
4661 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4662 emitcode ("subb", "a,%s",
4663 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE,
4667 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4668 /* first add without previous c */
4670 if (!size && lit==-1) {
4671 emitcode ("dec", "a");
4673 emitcode ("add", "a,#!constbyte",
4674 (unsigned int) (lit & 0x0FFL));
4677 emitcode ("addc", "a,#!constbyte",
4678 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4683 emitcode ("push", "acc");
4685 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4689 _endLazyDPSEvaluation ();
4693 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4695 size = getDataSize (IC_LEFT (ic));
4696 rSize = getDataSize (IC_RESULT (ic));
4698 ADJUST_PUSHED_RESULT(size, rSize);
4700 _startLazyDPSEvaluation ();
4703 emitcode ("pop", "acc");
4704 aopPut (AOP (IC_RESULT (ic)), "a", size);
4706 _endLazyDPSEvaluation ();
4709 adjustArithmeticResult (ic);
4712 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4713 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4714 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4718 /*-----------------------------------------------------------------*/
4719 /* genMultbits :- multiplication of bits */
4720 /*-----------------------------------------------------------------*/
4722 genMultbits (operand * left,
4727 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4728 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4729 aopOp(result, ic, TRUE, FALSE);
4734 /*-----------------------------------------------------------------*/
4735 /* genMultOneByte : 8*8=8/16 bit multiplication */
4736 /*-----------------------------------------------------------------*/
4738 genMultOneByte (operand * left,
4745 bool runtimeSign, compiletimeSign;
4746 bool lUnsigned, rUnsigned;
4749 /* (if two literals: the value is computed before) */
4750 /* if one literal, literal on the right */
4751 if (AOP_TYPE (left) == AOP_LIT)
4756 emitcode (";", "swapped left and right");
4759 /* (if two literals: the value is computed before) */
4760 /* if one literal, literal on the right */
4761 if (AOP_TYPE (left) == AOP_LIT)
4766 /* emitcode (";", "swapped left and right"); */
4768 /* if no literal, unsigned on the right: shorter code */
4769 if ( AOP_TYPE (right) != AOP_LIT
4770 && SPEC_USIGN (getSpec (operandType (left))))
4777 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4778 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4780 if ((lUnsigned && rUnsigned)
4781 /* sorry, I don't know how to get size
4782 without calling aopOp (result,...);
4783 see Feature Request */
4784 /* || size == 1 */ ) /* no, this is not a bug; with a 1 byte result there's
4785 no need to take care about the signedness! */
4787 /* just an unsigned 8 * 8 = 8 multiply
4789 /* emitcode (";","unsigned"); */
4790 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4791 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4792 emitcode ("mul", "ab");
4794 _G.accInUse++; _G.bInUse++;
4795 aopOp (result, ic, TRUE, FALSE);
4796 size = AOP_SIZE (result);
4798 if (size < 1 || size > 2)
4800 /* this should never happen */
4801 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4802 size, __FILE__, lineno);
4806 aopPut (AOP (result), "a", 0);
4807 _G.accInUse--; _G.bInUse--;
4809 aopPut (AOP (result), "b", 1);
4813 /* we have to do a signed multiply */
4814 /* emitcode (";", "signed"); */
4816 /* now sign adjust for both left & right */
4818 /* let's see what's needed: */
4819 /* apply negative sign during runtime */
4820 runtimeSign = FALSE;
4821 /* negative sign from literals */
4822 compiletimeSign = FALSE;
4826 if (AOP_TYPE(left) == AOP_LIT)
4828 /* signed literal */
4829 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4831 compiletimeSign = TRUE;
4834 /* signed but not literal */
4840 if (AOP_TYPE(right) == AOP_LIT)
4842 /* signed literal */
4843 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4845 compiletimeSign ^= TRUE;
4848 /* signed but not literal */
4852 /* initialize F0, which stores the runtime sign */
4855 if (compiletimeSign)
4856 emitcode ("setb", "F0"); /* set sign flag */
4858 emitcode ("clr", "F0"); /* reset sign flag */
4861 /* save the signs of the operands */
4862 if (AOP_TYPE(right) == AOP_LIT)
4864 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4866 if (!rUnsigned && val < 0)
4867 emitcode ("mov", "b,#!constbyte", -val);
4869 emitcode ("mov", "b,#!constbyte", (unsigned char) val);
4871 else /* ! literal */
4873 if (rUnsigned) /* emitcode (";", "signed"); */
4874 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4877 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4878 lbl = newiTempLabel (NULL);
4879 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
4880 emitcode ("cpl", "F0"); /* complement sign flag */
4881 emitcode ("cpl", "a"); /* 2's complement */
4882 emitcode ("inc", "a");
4883 emitcode ("", "!tlabeldef", lbl->key + 100);
4884 emitcode ("mov", "b,a");
4888 if (AOP_TYPE(left) == AOP_LIT)
4890 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4892 if (!lUnsigned && val < 0)
4893 emitcode ("mov", "a,#!constbyte", -val);
4895 emitcode ("mov", "a,#!constbyte", (unsigned char) val);
4897 else /* ! literal */
4899 if (lUnsigned) /* emitcode (";", "signed"); */
4901 emitcode ("mov", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4904 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4905 lbl = newiTempLabel (NULL);
4906 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
4907 emitcode ("cpl", "F0"); /* complement sign flag */
4908 emitcode ("cpl", "a"); /* 2's complement */
4909 emitcode ("inc", "a");
4910 emitcode ("", "!tlabeldef", lbl->key + 100);
4914 /* now the multiplication */
4915 emitcode ("mul", "ab");
4916 _G.accInUse++;_G.bInUse++;
4917 aopOp(result, ic, TRUE, FALSE);
4918 size = AOP_SIZE (result);
4920 if (size < 1 || size > 2)
4922 /* this should never happen */
4923 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4924 size, __FILE__, lineno);
4928 if (runtimeSign || compiletimeSign)
4930 lbl = newiTempLabel (NULL);
4932 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
4933 emitcode ("cpl", "a"); /* lsb 2's complement */
4935 emitcode ("inc", "a"); /* inc doesn't set carry flag */
4938 emitcode ("add", "a,#1"); /* this sets carry flag */
4939 emitcode ("xch", "a,b");
4940 emitcode ("cpl", "a"); /* msb 2's complement */
4941 emitcode ("addc", "a,#0");
4942 emitcode ("xch", "a,b");
4944 emitcode ("", "!tlabeldef", lbl->key + 100);
4946 aopPut (AOP (result), "a", 0);
4947 _G.accInUse--;_G.bInUse--;
4949 aopPut (AOP (result), "b", 1);
4952 /*-----------------------------------------------------------------*/
4953 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
4954 /*-----------------------------------------------------------------*/
4955 static void genMultTwoByte (operand *left, operand *right,
4956 operand *result, iCode *ic)
4958 sym_link *retype = getSpec(operandType(right));
4959 sym_link *letype = getSpec(operandType(left));
4960 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4963 if (AOP_TYPE (left) == AOP_LIT) {
4968 /* save EA bit in F1 */
4969 lbl = newiTempLabel(NULL);
4970 emitcode ("setb","F1");
4971 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4972 emitcode ("clr","F1");
4973 emitcode("","!tlabeldef",lbl->key+100);
4975 /* load up MB with right */
4977 emitcode("clr","F0");
4978 if (AOP_TYPE(right) == AOP_LIT) {
4979 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
4981 emitcode("setb","F0");
4984 emitcode ("mov","mb,#!constbyte",val & 0xff);
4985 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4987 lbl = newiTempLabel(NULL);
4988 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4989 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4990 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4991 emitcode ("xch", "a,b");
4992 emitcode ("cpl","a");
4993 emitcode ("add", "a,#1");
4994 emitcode ("xch", "a,b");
4995 emitcode ("cpl", "a"); // msb
4996 emitcode ("addc", "a,#0");
4997 emitcode ("setb","F0");
4998 emitcode ("","!tlabeldef",lbl->key+100);
4999 emitcode ("mov","mb,b");
5000 emitcode ("mov","mb,a");
5003 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5004 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5006 /* load up MA with left */
5008 lbl = newiTempLabel(NULL);
5009 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5010 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5011 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5012 emitcode ("xch", "a,b");
5013 emitcode ("cpl","a");
5014 emitcode ("add", "a,#1");
5015 emitcode ("xch", "a,b");
5016 emitcode ("cpl", "a"); // msb
5017 emitcode ("addc","a,#0");
5018 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5019 emitcode ("setb","F0");
5020 emitcode ("","!tlabeldef",lbl->key+100);
5021 emitcode ("mov","ma,b");
5022 emitcode ("mov","ma,a");
5024 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5025 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5027 /* wait for multiplication to finish */
5028 lbl = newiTempLabel(NULL);
5029 emitcode("","!tlabeldef", lbl->key+100);
5030 emitcode("mov","a,mcnt1");
5031 emitcode("anl","a,#!constbyte",0x80);
5032 emitcode("jnz","!tlabel",lbl->key+100);
5034 freeAsmop (left, NULL, ic, TRUE);
5035 freeAsmop (right, NULL, ic,TRUE);
5036 aopOp(result, ic, TRUE, FALSE);
5038 /* if unsigned then simple */
5040 emitcode ("mov","a,ma");
5041 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
5042 emitcode ("mov","a,ma");
5043 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
5044 aopPut(AOP(result),"ma",1);
5045 aopPut(AOP(result),"ma",0);
5047 emitcode("push","ma");
5048 emitcode("push","ma");
5049 emitcode("push","ma");
5051 /* negate result if needed */
5052 lbl = newiTempLabel(NULL);
5053 emitcode("jnb","F0,!tlabel",lbl->key+100);
5054 emitcode("cpl","a");
5055 emitcode("add","a,#1");
5056 emitcode("","!tlabeldef", lbl->key+100);
5057 if (AOP_TYPE(result) == AOP_ACC)
5059 D(emitcode(";", "ACC special case."););
5060 /* We know result is the only live aop, and
5061 * it's obviously not a DPTR2, so AP is available.
5063 emitcode("mov", "%s,acc", DP2_RESULT_REG);
5067 aopPut(AOP(result),"a",0);
5070 emitcode("pop","acc");
5071 lbl = newiTempLabel(NULL);
5072 emitcode("jnb","F0,!tlabel",lbl->key+100);
5073 emitcode("cpl","a");
5074 emitcode("addc","a,#0");
5075 emitcode("","!tlabeldef", lbl->key+100);
5076 aopPut(AOP(result),"a",1);
5077 emitcode("pop","acc");
5078 if (AOP_SIZE(result) >= 3) {
5079 lbl = newiTempLabel(NULL);
5080 emitcode("jnb","F0,!tlabel",lbl->key+100);
5081 emitcode("cpl","a");
5082 emitcode("addc","a,#0");
5083 emitcode("","!tlabeldef", lbl->key+100);
5084 aopPut(AOP(result),"a",2);
5086 emitcode("pop","acc");
5087 if (AOP_SIZE(result) >= 4) {
5088 lbl = newiTempLabel(NULL);
5089 emitcode("jnb","F0,!tlabel",lbl->key+100);
5090 emitcode("cpl","a");
5091 emitcode("addc","a,#0");
5092 emitcode("","!tlabeldef", lbl->key+100);
5093 aopPut(AOP(result),"a",3);
5095 if (AOP_TYPE(result) == AOP_ACC)
5097 /* We stashed the result away above. */
5098 emitcode("mov", "acc,%s", DP2_RESULT_REG);
5102 freeAsmop (result, NULL, ic, TRUE);
5104 /* restore EA bit in F1 */
5105 lbl = newiTempLabel(NULL);
5106 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5107 emitcode ("setb","EA");
5108 emitcode("","!tlabeldef",lbl->key+100);
5112 /*-----------------------------------------------------------------*/
5113 /* genMult - generates code for multiplication */
5114 /*-----------------------------------------------------------------*/
5116 genMult (iCode * ic)
5118 operand *left = IC_LEFT (ic);
5119 operand *right = IC_RIGHT (ic);
5120 operand *result = IC_RESULT (ic);
5122 D (emitcode (";", "genMult "););
5124 /* assign the amsops */
5127 /* special cases first */
5129 if (AOP_TYPE (left) == AOP_CRY &&
5130 AOP_TYPE (right) == AOP_CRY)
5132 genMultbits (left, right, result, ic);
5136 /* if both are of size == 1 */
5137 if (AOP_SIZE (left) == 1 &&
5138 AOP_SIZE (right) == 1)
5140 genMultOneByte (left, right, result, ic);
5144 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5145 /* use the ds390 ARITHMETIC accel UNIT */
5146 genMultTwoByte (left, right, result, ic);
5149 /* should have been converted to function call */
5153 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5154 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5155 freeAsmop (result, NULL, ic, TRUE);
5158 /*-----------------------------------------------------------------*/
5159 /* genDivbits :- division of bits */
5160 /*-----------------------------------------------------------------*/
5162 genDivbits (operand * left,
5170 /* the result must be bit */
5171 LOAD_AB_FOR_DIV (left, right, l);
5172 emitcode ("div", "ab");
5173 emitcode ("rrc", "a");
5174 aopOp(result, ic, TRUE, FALSE);
5176 aopPut (AOP (result), "c", 0);
5179 /*-----------------------------------------------------------------*/
5180 /* genDivOneByte : 8 bit division */
5181 /*-----------------------------------------------------------------*/
5183 genDivOneByte (operand * left,
5188 bool lUnsigned, rUnsigned;
5189 bool runtimeSign, compiletimeSign;
5195 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5196 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5198 /* signed or unsigned */
5199 if (lUnsigned && rUnsigned)
5201 /* unsigned is easy */
5202 LOAD_AB_FOR_DIV (left, right, l);
5203 emitcode ("div", "ab");
5206 aopOp (result, ic, TRUE, FALSE);
5207 aopPut (AOP (result), "a", 0);
5210 size = AOP_SIZE (result) - 1;
5213 aopPut (AOP (result), zero, offset++);
5217 /* signed is a little bit more difficult */
5219 /* now sign adjust for both left & right */
5221 /* let's see what's needed: */
5222 /* apply negative sign during runtime */
5223 runtimeSign = FALSE;
5224 /* negative sign from literals */
5225 compiletimeSign = FALSE;
5229 if (AOP_TYPE(left) == AOP_LIT)
5231 /* signed literal */
5232 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5234 compiletimeSign = TRUE;
5237 /* signed but not literal */
5243 if (AOP_TYPE(right) == AOP_LIT)
5245 /* signed literal */
5246 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5248 compiletimeSign ^= TRUE;
5251 /* signed but not literal */
5255 /* initialize F0, which stores the runtime sign */
5258 if (compiletimeSign)
5259 emitcode ("setb", "F0"); /* set sign flag */
5261 emitcode ("clr", "F0"); /* reset sign flag */
5264 /* save the signs of the operands */
5265 if (AOP_TYPE(right) == AOP_LIT)
5267 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5269 if (!rUnsigned && val < 0)
5270 emitcode ("mov", "b,#0x%02x", -val);
5272 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5274 else /* ! literal */
5277 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5280 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5281 lbl = newiTempLabel (NULL);
5282 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5283 emitcode ("cpl", "F0"); /* complement sign flag */
5284 emitcode ("cpl", "a"); /* 2's complement */
5285 emitcode ("inc", "a");
5286 emitcode ("", "!tlabeldef", lbl->key + 100);
5287 emitcode ("mov", "b,a");
5291 if (AOP_TYPE(left) == AOP_LIT)
5293 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5295 if (!lUnsigned && val < 0)
5296 emitcode ("mov", "a,#0x%02x", -val);
5298 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5300 else /* ! literal */
5303 emitcode ("mov", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5306 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5307 lbl = newiTempLabel (NULL);
5308 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5309 emitcode ("cpl", "F0"); /* complement sign flag */
5310 emitcode ("cpl", "a"); /* 2's complement */
5311 emitcode ("inc", "a");
5312 emitcode ("", "!tlabeldef", lbl->key + 100);
5316 /* now the division */
5317 emitcode ("nop", "; workaround for DS80C390 div bug.");
5318 emitcode ("div", "ab");
5320 if (runtimeSign || compiletimeSign)
5322 lbl = newiTempLabel (NULL);
5324 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5325 emitcode ("cpl", "a"); /* lsb 2's complement */
5326 emitcode ("inc", "a");
5327 emitcode ("", "!tlabeldef", lbl->key + 100);
5329 _G.accInUse++; _G.bInUse++;
5330 aopOp (result, ic, TRUE, FALSE);
5331 size = AOP_SIZE (result) - 1;
5335 /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
5336 then the result will be in b, a */
5337 emitcode ("mov", "b,a"); /* 1 */
5338 /* msb is 0x00 or 0xff depending on the sign */
5341 emitcode ("mov", "c,F0");
5342 emitcode ("subb", "a,acc");
5343 emitcode ("xch", "a,b"); /* 2 */
5345 aopPut (AOP (result), "b", offset++); /* write msb's */
5347 else /* compiletimeSign */
5349 aopPut (AOP (result), "#0xff", offset++); /* write msb's */
5351 aopPut (AOP (result), "a", 0); /* 3: write lsb */
5355 _G.accInUse++; _G.bInUse++;
5356 aopOp(result, ic, TRUE, FALSE);
5357 size = AOP_SIZE (result) - 1;
5359 aopPut (AOP (result), "a", 0);
5361 aopPut (AOP (result), zero, offset++);
5363 _G.accInUse--; _G.bInUse--;
5367 /*-----------------------------------------------------------------*/
5368 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
5369 /*-----------------------------------------------------------------*/
5370 static void genDivTwoByte (operand *left, operand *right,
5371 operand *result, iCode *ic)
5373 sym_link *retype = getSpec(operandType(right));
5374 sym_link *letype = getSpec(operandType(left));
5375 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5378 /* save EA bit in F1 */
5379 lbl = newiTempLabel(NULL);
5380 emitcode ("setb","F1");
5381 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5382 emitcode ("clr","F1");
5383 emitcode("","!tlabeldef",lbl->key+100);
5385 /* load up MA with left */
5387 emitcode("clr","F0");
5388 lbl = newiTempLabel(NULL);
5389 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5390 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5391 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5392 emitcode ("xch", "a,b");
5393 emitcode ("cpl","a");
5394 emitcode ("add", "a,#1");
5395 emitcode ("xch", "a,b");
5396 emitcode ("cpl", "a"); // msb
5397 emitcode ("addc","a,#0");
5398 emitcode ("setb","F0");
5399 emitcode ("","!tlabeldef",lbl->key+100);
5400 emitcode ("mov","ma,b");
5401 emitcode ("mov","ma,a");
5403 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5404 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5407 /* load up MB with right */
5409 if (AOP_TYPE(right) == AOP_LIT) {
5410 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5412 lbl = newiTempLabel(NULL);
5413 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5414 emitcode("setb","F0");
5415 emitcode ("","!tlabeldef",lbl->key+100);
5418 emitcode ("mov","mb,#!constbyte",val & 0xff);
5419 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5421 lbl = newiTempLabel(NULL);
5422 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5423 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5424 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5425 emitcode ("xch", "a,b");
5426 emitcode ("cpl","a");
5427 emitcode ("add", "a,#1");
5428 emitcode ("xch", "a,b");
5429 emitcode ("cpl", "a"); // msb
5430 emitcode ("addc", "a,#0");
5431 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5432 emitcode ("setb","F0");
5433 emitcode ("","!tlabeldef",lbl->key+100);
5434 emitcode ("mov","mb,b");
5435 emitcode ("mov","mb,a");
5438 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5439 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5442 /* wait for multiplication to finish */
5443 lbl = newiTempLabel(NULL);
5444 emitcode("","!tlabeldef", lbl->key+100);
5445 emitcode("mov","a,mcnt1");
5446 emitcode("anl","a,#!constbyte",0x80);
5447 emitcode("jnz","!tlabel",lbl->key+100);
5449 freeAsmop (left, NULL, ic, TRUE);
5450 freeAsmop (right, NULL, ic,TRUE);
5451 aopOp(result, ic, TRUE, FALSE);
5453 /* if unsigned then simple */
5455 aopPut(AOP(result),"ma",1);
5456 aopPut(AOP(result),"ma",0);
5458 emitcode("push","ma");
5460 /* negate result if needed */
5461 lbl = newiTempLabel(NULL);
5462 emitcode("jnb","F0,!tlabel",lbl->key+100);
5463 emitcode("cpl","a");
5464 emitcode("add","a,#1");
5465 emitcode("","!tlabeldef", lbl->key+100);
5466 aopPut(AOP(result),"a",0);
5467 emitcode("pop","acc");
5468 lbl = newiTempLabel(NULL);
5469 emitcode("jnb","F0,!tlabel",lbl->key+100);
5470 emitcode("cpl","a");
5471 emitcode("addc","a,#0");
5472 emitcode("","!tlabeldef", lbl->key+100);
5473 aopPut(AOP(result),"a",1);
5475 freeAsmop (result, NULL, ic, TRUE);
5476 /* restore EA bit in F1 */
5477 lbl = newiTempLabel(NULL);
5478 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5479 emitcode ("setb","EA");
5480 emitcode("","!tlabeldef",lbl->key+100);
5484 /*-----------------------------------------------------------------*/
5485 /* genDiv - generates code for division */
5486 /*-----------------------------------------------------------------*/
5490 operand *left = IC_LEFT (ic);
5491 operand *right = IC_RIGHT (ic);
5492 operand *result = IC_RESULT (ic);
5494 D (emitcode (";", "genDiv "););
5496 /* assign the amsops */
5499 /* special cases first */
5501 if (AOP_TYPE (left) == AOP_CRY &&
5502 AOP_TYPE (right) == AOP_CRY)
5504 genDivbits (left, right, result, ic);
5508 /* if both are of size == 1 */
5509 if (AOP_SIZE (left) == 1 &&
5510 AOP_SIZE (right) == 1)
5512 genDivOneByte (left, right, result, ic);
5516 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5517 /* use the ds390 ARITHMETIC accel UNIT */
5518 genDivTwoByte (left, right, result, ic);
5521 /* should have been converted to function call */
5524 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5525 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5526 freeAsmop (result, NULL, ic, TRUE);
5529 /*-----------------------------------------------------------------*/
5530 /* genModbits :- modulus of bits */
5531 /*-----------------------------------------------------------------*/
5533 genModbits (operand * left,
5541 /* the result must be bit */
5542 LOAD_AB_FOR_DIV (left, right, l);
5543 emitcode ("div", "ab");
5544 emitcode ("mov", "a,b");
5545 emitcode ("rrc", "a");
5546 aopOp(result, ic, TRUE, FALSE);
5547 aopPut (AOP (result), "c", 0);
5550 /*-----------------------------------------------------------------*/
5551 /* genModOneByte : 8 bit modulus */
5552 /*-----------------------------------------------------------------*/
5554 genModOneByte (operand * left,
5559 bool lUnsigned, rUnsigned;
5560 bool runtimeSign, compiletimeSign;
5566 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5567 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5569 /* signed or unsigned */
5570 if (lUnsigned && rUnsigned)
5572 /* unsigned is easy */
5573 LOAD_AB_FOR_DIV (left, right, l);
5574 emitcode ("div", "ab");
5575 aopOp (result, ic, TRUE, FALSE);
5576 aopPut (AOP (result), "b", 0);
5578 for (size = AOP_SIZE (result) - 1; size--;)
5579 aopPut (AOP (result), zero, offset++);
5583 /* signed is a little bit more difficult */
5585 /* now sign adjust for both left & right */
5587 /* modulus: sign of the right operand has no influence on the result! */
5588 if (AOP_TYPE(right) == AOP_LIT)
5590 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5592 if (!rUnsigned && val < 0)
5593 emitcode ("mov", "b,#0x%02x", -val);
5595 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5597 else /* ! literal */
5600 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5603 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5604 lbl = newiTempLabel (NULL);
5605 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5606 emitcode ("cpl", "a"); /* 2's complement */
5607 emitcode ("inc", "a");
5608 emitcode ("", "!tlabeldef", lbl->key + 100);
5609 emitcode ("mov", "b,a");
5613 /* let's see what's needed: */
5614 /* apply negative sign during runtime */
5615 runtimeSign = FALSE;
5616 /* negative sign from literals */
5617 compiletimeSign = FALSE;
5619 /* sign adjust left side */
5620 if (AOP_TYPE(left) == AOP_LIT)
5622 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5624 if (!lUnsigned && val < 0)
5626 compiletimeSign = TRUE; /* set sign flag */
5627 emitcode ("mov", "a,#0x%02x", -val);
5630 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5632 else /* ! literal */
5634 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5639 emitcode ("clr", "F0"); /* clear sign flag */
5641 lbl = newiTempLabel (NULL);
5642 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5643 emitcode ("setb", "F0"); /* set sign flag */
5644 emitcode ("cpl", "a"); /* 2's complement */
5645 emitcode ("inc", "a");
5646 emitcode ("", "!tlabeldef", lbl->key + 100);
5650 /* now the modulus */
5651 emitcode ("nop", "; workaround for DS80C390 div bug.");
5652 emitcode ("div", "ab");
5654 if (runtimeSign || compiletimeSign)
5656 emitcode ("mov", "a,b");
5657 lbl = newiTempLabel (NULL);
5659 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5660 emitcode ("cpl", "a"); /* lsb 2's complement */
5661 emitcode ("inc", "a");
5662 emitcode ("", "!tlabeldef", lbl->key + 100);
5664 _G.accInUse++; _G.bInUse++;
5665 aopOp (result, ic, TRUE, FALSE);
5666 size = AOP_SIZE (result) - 1;
5670 /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
5671 then the result will be in b, a */
5672 emitcode ("mov", "b,a"); /* 1 */
5673 /* msb is 0x00 or 0xff depending on the sign */
5676 emitcode ("mov", "c,F0");
5677 emitcode ("subb", "a,acc");
5678 emitcode ("xch", "a,b"); /* 2 */
5680 aopPut (AOP (result), "b", offset++); /* write msb's */
5682 else /* compiletimeSign */
5684 aopPut (AOP (result), "#0xff", offset++); /* write msb's */
5686 aopPut (AOP (result), "a", 0); /* 3: write lsb */
5690 _G.accInUse++; _G.bInUse++;
5691 aopOp(result, ic, TRUE, FALSE);
5692 size = AOP_SIZE (result) - 1;
5694 aopPut (AOP (result), "b", 0);
5696 aopPut (AOP (result), zero, offset++);
5698 _G.accInUse--; _G.bInUse--;
5702 /*-----------------------------------------------------------------*/
5703 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
5704 /*-----------------------------------------------------------------*/
5705 static void genModTwoByte (operand *left, operand *right,
5706 operand *result, iCode *ic)
5708 sym_link *retype = getSpec(operandType(right));
5709 sym_link *letype = getSpec(operandType(left));
5710 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5713 /* load up MA with left */
5714 /* save EA bit in F1 */
5715 lbl = newiTempLabel(NULL);
5716 emitcode ("setb","F1");
5717 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5718 emitcode ("clr","F1");
5719 emitcode("","!tlabeldef",lbl->key+100);
5722 lbl = newiTempLabel(NULL);
5723 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5724 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5725 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5726 emitcode ("xch", "a,b");
5727 emitcode ("cpl","a");
5728 emitcode ("add", "a,#1");
5729 emitcode ("xch", "a,b");
5730 emitcode ("cpl", "a"); // msb
5731 emitcode ("addc","a,#0");
5732 emitcode ("","!tlabeldef",lbl->key+100);
5733 emitcode ("mov","ma,b");
5734 emitcode ("mov","ma,a");
5736 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5737 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5740 /* load up MB with right */
5742 if (AOP_TYPE(right) == AOP_LIT) {
5743 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5747 emitcode ("mov","mb,#!constbyte",val & 0xff);
5748 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5750 lbl = newiTempLabel(NULL);
5751 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5752 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5753 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5754 emitcode ("xch", "a,b");
5755 emitcode ("cpl","a");
5756 emitcode ("add", "a,#1");
5757 emitcode ("xch", "a,b");
5758 emitcode ("cpl", "a"); // msb
5759 emitcode ("addc", "a,#0");
5760 emitcode ("","!tlabeldef",lbl->key+100);
5761 emitcode ("mov","mb,b");
5762 emitcode ("mov","mb,a");
5765 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5766 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5769 /* wait for multiplication to finish */
5770 lbl = newiTempLabel(NULL);
5771 emitcode("","!tlabeldef", lbl->key+100);
5772 emitcode("mov","a,mcnt1");
5773 emitcode("anl","a,#!constbyte",0x80);
5774 emitcode("jnz","!tlabel",lbl->key+100);
5776 freeAsmop (left, NULL, ic, TRUE);
5777 freeAsmop (right, NULL, ic,TRUE);
5778 aopOp(result, ic, TRUE, FALSE);
5780 aopPut(AOP(result),"mb",1);
5781 aopPut(AOP(result),"mb",0);
5782 freeAsmop (result, NULL, ic, TRUE);
5784 /* restore EA bit in F1 */
5785 lbl = newiTempLabel(NULL);
5786 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5787 emitcode ("setb","EA");
5788 emitcode("","!tlabeldef",lbl->key+100);
5792 /*-----------------------------------------------------------------*/
5793 /* genMod - generates code for division */
5794 /*-----------------------------------------------------------------*/
5798 operand *left = IC_LEFT (ic);
5799 operand *right = IC_RIGHT (ic);
5800 operand *result = IC_RESULT (ic);
5802 D (emitcode (";", "genMod "); );
5804 /* assign the amsops */
5807 /* special cases first */
5809 if (AOP_TYPE (left) == AOP_CRY &&
5810 AOP_TYPE (right) == AOP_CRY)
5812 genModbits (left, right, result, ic);
5816 /* if both are of size == 1 */
5817 if (AOP_SIZE (left) == 1 &&
5818 AOP_SIZE (right) == 1)
5820 genModOneByte (left, right, result, ic);
5824 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5825 /* use the ds390 ARITHMETIC accel UNIT */
5826 genModTwoByte (left, right, result, ic);
5830 /* should have been converted to function call */
5834 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5835 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5836 freeAsmop (result, NULL, ic, TRUE);
5839 /*-----------------------------------------------------------------*/
5840 /* genIfxJump :- will create a jump depending on the ifx */
5841 /*-----------------------------------------------------------------*/
5843 genIfxJump (iCode * ic, char *jval)
5846 symbol *tlbl = newiTempLabel (NULL);
5849 D (emitcode (";", "genIfxJump"););
5851 /* if true label then we jump if condition
5855 jlbl = IC_TRUE (ic);
5856 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5857 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5861 /* false label is present */
5862 jlbl = IC_FALSE (ic);
5863 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5864 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5866 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5867 emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5869 emitcode (inst, "!tlabel", tlbl->key + 100);
5870 emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5871 emitcode ("", "!tlabeldef", tlbl->key + 100);
5873 /* mark the icode as generated */
5877 /*-----------------------------------------------------------------*/
5878 /* genCmp :- greater or less than comparison */
5879 /*-----------------------------------------------------------------*/
5881 genCmp (operand * left, operand * right,
5882 iCode * ic, iCode * ifx, int sign)
5884 int size, offset = 0;
5885 unsigned long lit = 0L;
5888 D (emitcode (";", "genCmp"););
5890 result = IC_RESULT (ic);
5892 /* if left & right are bit variables */
5893 if (AOP_TYPE (left) == AOP_CRY &&
5894 AOP_TYPE (right) == AOP_CRY)
5896 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5897 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5901 /* subtract right from left if at the
5902 end the carry flag is set then we know that
5903 left is greater than right */
5904 size = max (AOP_SIZE (left), AOP_SIZE (right));
5906 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5907 if ((size == 1) && !sign
5908 && (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5910 symbol *lbl = newiTempLabel (NULL);
5911 emitcode ("cjne", "%s,%s,!tlabel",
5912 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
5913 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5915 emitcode ("", "!tlabeldef", lbl->key + 100);
5919 if (AOP_TYPE (right) == AOP_LIT)
5921 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5922 /* optimize if(x < 0) or if(x >= 0) */
5931 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
5933 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5934 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5936 aopOp (result, ic, FALSE, FALSE);
5938 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5940 freeAsmop (result, NULL, ic, TRUE);
5941 genIfxJump (ifx, "acc.7");
5946 emitcode ("rlc", "a");
5948 goto release_freedLR;
5956 // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5957 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5958 // emitcode (";", "genCmp #2");
5959 if (sign && (size == 0))
5961 // emitcode (";", "genCmp #3");
5962 emitcode ("xrl", "a,#!constbyte",0x80);
5963 if (AOP_TYPE (right) == AOP_LIT)
5965 unsigned long lit = (unsigned long)
5966 floatFromVal (AOP (right)->aopu.aop_lit);
5967 // emitcode (";", "genCmp #3.1");
5968 emitcode ("subb", "a,#!constbyte",
5969 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5973 // emitcode (";", "genCmp #3.2");
5975 MOVB(aopGet (AOP (right), offset++, FALSE, FALSE, "b"));
5976 saveAccWarn = DEFAULT_ACC_WARNING;
5977 emitcode ("xrl", "b,#!constbyte",0x80);
5978 emitcode ("subb", "a,b");
5985 // emitcode (";", "genCmp #4");
5987 s = aopGet (AOP (right), offset++, FALSE, FALSE, "b");
5988 saveAccWarn = DEFAULT_ACC_WARNING;
5990 emitcode ("subb", "a,%s", s);
5997 /* Don't need the left & right operands any more; do need the result. */
5998 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5999 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6001 aopOp (result, ic, FALSE, FALSE);
6005 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6011 /* if the result is used in the next
6012 ifx conditional branch then generate
6013 code a little differently */
6016 genIfxJump (ifx, "c");
6022 /* leave the result in acc */
6024 freeAsmop (result, NULL, ic, TRUE);
6027 /*-----------------------------------------------------------------*/
6028 /* genCmpGt :- greater than comparison */
6029 /*-----------------------------------------------------------------*/
6031 genCmpGt (iCode * ic, iCode * ifx)
6033 operand *left, *right;
6034 sym_link *letype, *retype;
6037 D (emitcode (";", "genCmpGt ");
6040 left = IC_LEFT (ic);
6041 right = IC_RIGHT (ic);
6043 letype = getSpec (operandType (left));
6044 retype = getSpec (operandType (right));
6045 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6047 /* assign the left & right amsops */
6050 genCmp (right, left, ic, ifx, sign);
6053 /*-----------------------------------------------------------------*/
6054 /* genCmpLt - less than comparisons */
6055 /*-----------------------------------------------------------------*/
6057 genCmpLt (iCode * ic, iCode * ifx)
6059 operand *left, *right;
6060 sym_link *letype, *retype;
6063 D (emitcode (";", "genCmpLt "););
6065 left = IC_LEFT (ic);
6066 right = IC_RIGHT (ic);
6068 letype = getSpec (operandType (left));
6069 retype = getSpec (operandType (right));
6070 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6072 /* assign the left & right amsops */
6075 genCmp (left, right, ic, ifx, sign);
6078 /*-----------------------------------------------------------------*/
6079 /* gencjneshort - compare and jump if not equal */
6080 /*-----------------------------------------------------------------*/
6082 gencjneshort (operand * left, operand * right, symbol * lbl)
6084 int size = max (AOP_SIZE (left), AOP_SIZE (right));
6086 unsigned long lit = 0L;
6088 D (emitcode (";", "gencjneshort");
6091 /* if the left side is a literal or
6092 if the right is in a pointer register and left
6094 if ((AOP_TYPE (left) == AOP_LIT) ||
6095 (AOP_TYPE (left) == AOP_IMMD) ||
6096 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6103 if (AOP_TYPE (right) == AOP_LIT)
6104 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6106 if (opIsGptr (left) || opIsGptr (right))
6108 /* We are comparing a generic pointer to something.
6109 * Exclude the generic type byte from the comparison.
6112 D (emitcode (";", "cjneshort: generic ptr special case."););
6116 /* if the right side is a literal then anything goes */
6117 if (AOP_TYPE (right) == AOP_LIT &&
6118 AOP_TYPE (left) != AOP_DIR)
6122 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6123 emitcode ("cjne", "a,%s,!tlabel",
6124 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
6130 /* if the right side is in a register or in direct space or
6131 if the left is a pointer register & right is not */
6132 else if (AOP_TYPE (right) == AOP_REG ||
6133 AOP_TYPE (right) == AOP_DIR ||
6134 AOP_TYPE (right) == AOP_LIT ||
6135 AOP_TYPE (right) == AOP_IMMD ||
6136 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6137 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6141 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6142 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6143 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6144 emitcode ("jnz", "!tlabel", lbl->key + 100);
6146 emitcode ("cjne", "a,%s,!tlabel",
6147 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
6154 /* right is a pointer reg need both a & b */
6157 MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6158 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6159 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
6165 /*-----------------------------------------------------------------*/
6166 /* gencjne - compare and jump if not equal */
6167 /*-----------------------------------------------------------------*/
6169 gencjne (operand * left, operand * right, symbol * lbl)
6171 symbol *tlbl = newiTempLabel (NULL);
6173 D (emitcode (";", "gencjne");
6176 gencjneshort (left, right, lbl);
6178 emitcode ("mov", "a,%s", one);
6179 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
6180 emitcode ("", "!tlabeldef", lbl->key + 100);
6181 emitcode ("clr", "a");
6182 emitcode ("", "!tlabeldef", tlbl->key + 100);
6185 /*-----------------------------------------------------------------*/
6186 /* genCmpEq - generates code for equal to */
6187 /*-----------------------------------------------------------------*/
6189 genCmpEq (iCode * ic, iCode * ifx)
6191 operand *left, *right, *result;
6193 D (emitcode (";", "genCmpEq ");
6197 AOP_SET_LOCALS (ic);
6199 /* if literal, literal on the right or
6200 if the right is in a pointer register and left
6202 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6203 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6205 operand *t = IC_RIGHT (ic);
6206 IC_RIGHT (ic) = IC_LEFT (ic);
6210 if (ifx && /* !AOP_SIZE(result) */
6211 OP_SYMBOL (result) &&
6212 OP_SYMBOL (result)->regType == REG_CND)
6215 /* if they are both bit variables */
6216 if (AOP_TYPE (left) == AOP_CRY &&
6217 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6219 if (AOP_TYPE (right) == AOP_LIT)
6221 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6224 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6225 emitcode ("cpl", "c");
6229 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6233 emitcode ("clr", "c");
6235 /* AOP_TYPE(right) == AOP_CRY */
6239 symbol *lbl = newiTempLabel (NULL);
6240 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6241 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6242 emitcode ("cpl", "c");
6243 emitcode ("", "!tlabeldef", (lbl->key + 100));
6245 /* if true label then we jump if condition
6247 tlbl = newiTempLabel (NULL);
6250 emitcode ("jnc", "!tlabel", tlbl->key + 100);
6251 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6255 emitcode ("jc", "!tlabel", tlbl->key + 100);
6256 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6258 emitcode ("", "!tlabeldef", tlbl->key + 100);
6262 tlbl = newiTempLabel (NULL);
6263 gencjneshort (left, right, tlbl);
6266 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6267 emitcode ("", "!tlabeldef", tlbl->key + 100);
6271 symbol *lbl = newiTempLabel (NULL);
6272 emitcode ("sjmp", "!tlabel", lbl->key + 100);
6273 emitcode ("", "!tlabeldef", tlbl->key + 100);
6274 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6275 emitcode ("", "!tlabeldef", lbl->key + 100);
6278 /* mark the icode as generated */
6281 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6282 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6286 /* if they are both bit variables */
6287 if (AOP_TYPE (left) == AOP_CRY &&
6288 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6290 if (AOP_TYPE (right) == AOP_LIT)
6292 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6295 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6296 emitcode ("cpl", "c");
6300 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6304 emitcode ("clr", "c");
6306 /* AOP_TYPE(right) == AOP_CRY */
6310 symbol *lbl = newiTempLabel (NULL);
6311 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6312 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6313 emitcode ("cpl", "c");
6314 emitcode ("", "!tlabeldef", (lbl->key + 100));
6317 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6318 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6320 aopOp (result, ic, TRUE, FALSE);
6323 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6330 genIfxJump (ifx, "c");
6333 /* if the result is used in an arithmetic operation
6334 then put the result in place */
6339 gencjne (left, right, newiTempLabel (NULL));
6341 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6342 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6344 aopOp (result, ic, TRUE, FALSE);
6346 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6348 aopPut (AOP (result), "a", 0);
6353 genIfxJump (ifx, "a");
6356 /* if the result is used in an arithmetic operation
6357 then put the result in place */
6358 if (AOP_TYPE (result) != AOP_CRY)
6360 /* leave the result in acc */
6364 freeAsmop (result, NULL, ic, TRUE);
6367 /*-----------------------------------------------------------------*/
6368 /* ifxForOp - returns the icode containing the ifx for operand */
6369 /*-----------------------------------------------------------------*/
6371 ifxForOp (operand * op, iCode * ic)
6373 /* if true symbol then needs to be assigned */
6374 if (IS_TRUE_SYMOP (op))
6377 /* if this has register type condition and
6378 the next instruction is ifx with the same operand
6379 and live to of the operand is upto the ifx only then */
6381 ic->next->op == IFX &&
6382 IC_COND (ic->next)->key == op->key &&
6383 OP_SYMBOL (op)->liveTo <= ic->next->seq)
6388 /*-----------------------------------------------------------------*/
6389 /* hasInc - operand is incremented before any other use */
6390 /*-----------------------------------------------------------------*/
6392 hasInc (operand *op, iCode *ic, int osize)
6394 sym_link *type = operandType(op);
6395 sym_link *retype = getSpec (type);
6396 iCode *lic = ic->next;
6399 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6400 if (!IS_SYMOP(op)) return NULL;
6402 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6403 if (IS_AGGREGATE(type->next)) return NULL;
6404 if (osize != (isize = getSize(type->next))) return NULL;
6407 /* if operand of the form op = op + <sizeof *op> */
6408 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6409 isOperandEqual(IC_RESULT(lic),op) &&
6410 isOperandLiteral(IC_RIGHT(lic)) &&
6411 operandLitValue(IC_RIGHT(lic)) == isize) {
6414 /* if the operand used or deffed */
6415 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
6418 /* if GOTO or IFX */
6419 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6425 /*-----------------------------------------------------------------*/
6426 /* genAndOp - for && operation */
6427 /*-----------------------------------------------------------------*/
6429 genAndOp (iCode * ic)
6431 operand *left, *right, *result;
6434 D (emitcode (";", "genAndOp "););
6436 /* note here that && operations that are in an
6437 if statement are taken away by backPatchLabels
6438 only those used in arthmetic operations remain */
6440 AOP_SET_LOCALS (ic);
6442 /* if both are bit variables */
6443 if (AOP_TYPE (left) == AOP_CRY &&
6444 AOP_TYPE (right) == AOP_CRY)
6446 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6447 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6448 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6449 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6451 aopOp (result,ic,FALSE, FALSE);
6456 tlbl = newiTempLabel (NULL);
6458 emitcode ("jz", "!tlabel", tlbl->key + 100);
6460 emitcode ("", "!tlabeldef", tlbl->key + 100);
6461 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6462 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6464 aopOp (result,ic,FALSE, FALSE);
6467 freeAsmop (result, NULL, ic, TRUE);
6471 /*-----------------------------------------------------------------*/
6472 /* genOrOp - for || operation */
6473 /*-----------------------------------------------------------------*/
6475 genOrOp (iCode * ic)
6477 operand *left, *right, *result;
6480 D (emitcode (";", "genOrOp "););
6482 /* note here that || operations that are in an
6483 if statement are taken away by backPatchLabels
6484 only those used in arthmetic operations remain */
6486 AOP_SET_LOCALS (ic);
6488 /* if both are bit variables */
6489 if (AOP_TYPE (left) == AOP_CRY &&
6490 AOP_TYPE (right) == AOP_CRY)
6492 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6493 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6494 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6495 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6497 aopOp (result,ic,FALSE, FALSE);
6503 tlbl = newiTempLabel (NULL);
6505 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6507 emitcode ("", "!tlabeldef", tlbl->key + 100);
6508 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6509 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6511 aopOp (result,ic,FALSE, FALSE);
6516 freeAsmop (result, NULL, ic, TRUE);
6519 /*-----------------------------------------------------------------*/
6520 /* isLiteralBit - test if lit == 2^n */
6521 /*-----------------------------------------------------------------*/
6523 isLiteralBit (unsigned long lit)
6525 unsigned long pw[32] =
6526 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6527 0x100L, 0x200L, 0x400L, 0x800L,
6528 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6529 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6530 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6531 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6532 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6535 for (idx = 0; idx < 32; idx++)
6541 /*-----------------------------------------------------------------*/
6542 /* continueIfTrue - */
6543 /*-----------------------------------------------------------------*/
6545 continueIfTrue (iCode * ic)
6548 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6552 /*-----------------------------------------------------------------*/
6554 /*-----------------------------------------------------------------*/
6556 jumpIfTrue (iCode * ic)
6559 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6563 /*-----------------------------------------------------------------*/
6564 /* jmpTrueOrFalse - */
6565 /*-----------------------------------------------------------------*/
6567 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6569 // ugly but optimized by peephole
6572 symbol *nlbl = newiTempLabel (NULL);
6573 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6574 emitcode ("", "!tlabeldef", tlbl->key + 100);
6575 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6576 emitcode ("", "!tlabeldef", nlbl->key + 100);
6580 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6581 emitcode ("", "!tlabeldef", tlbl->key + 100);
6586 // Generate code to perform a bit-wise logic operation
6587 // on two operands in far space (assumed to already have been
6588 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6589 // in far space. This requires pushing the result on the stack
6590 // then popping it into the result.
6592 genFarFarLogicOp(iCode *ic, char *logicOp)
6594 int size, resultSize, compSize;
6598 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6599 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
6600 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6602 _startLazyDPSEvaluation();
6603 for (size = compSize; (size--); offset++)
6605 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6606 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6607 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6609 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6610 emitcode ("push", "acc");
6612 _endLazyDPSEvaluation();
6614 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6615 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6616 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6618 resultSize = AOP_SIZE(IC_RESULT(ic));
6620 ADJUST_PUSHED_RESULT(compSize, resultSize);
6622 _startLazyDPSEvaluation();
6625 emitcode ("pop", "acc");
6626 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6628 _endLazyDPSEvaluation();
6629 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6633 /*-----------------------------------------------------------------*/
6634 /* genAnd - code for and */
6635 /*-----------------------------------------------------------------*/
6637 genAnd (iCode * ic, iCode * ifx)
6639 operand *left, *right, *result;
6640 int size, offset = 0;
6641 unsigned long lit = 0L;
6646 D (emitcode (";", "genAnd "););
6648 AOP_OP_3_NOFATAL (ic, pushResult);
6649 AOP_SET_LOCALS (ic);
6653 genFarFarLogicOp(ic, "anl");
6658 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6660 AOP_TYPE (left), AOP_TYPE (right));
6661 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6663 AOP_SIZE (left), AOP_SIZE (right));
6666 /* if left is a literal & right is not then exchange them */
6667 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6668 #ifdef LOGIC_OPS_BROKEN
6669 || AOP_NEEDSACC (left)
6673 operand *tmp = right;
6678 /* if result = right then exchange them */
6679 if (sameRegs (AOP (result), AOP (right)))
6681 operand *tmp = right;
6686 /* if right is bit then exchange them */
6687 if (AOP_TYPE (right) == AOP_CRY &&
6688 AOP_TYPE (left) != AOP_CRY)
6690 operand *tmp = right;
6694 if (AOP_TYPE (right) == AOP_LIT)
6695 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6697 size = AOP_SIZE (result);
6700 // result = bit & yy;
6701 if (AOP_TYPE (left) == AOP_CRY)
6703 // c = bit & literal;
6704 if (AOP_TYPE (right) == AOP_LIT)
6708 if (size && sameRegs (AOP (result), AOP (left)))
6711 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6716 if (size && (AOP_TYPE (result) == AOP_CRY))
6718 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6721 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6726 emitcode ("clr", "c");
6731 if (AOP_TYPE (right) == AOP_CRY)
6734 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6735 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6740 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6742 emitcode ("rrc", "a");
6743 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6751 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6752 genIfxJump (ifx, "c");
6756 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6757 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6758 if ((AOP_TYPE (right) == AOP_LIT) &&
6759 (AOP_TYPE (result) == AOP_CRY) &&
6760 (AOP_TYPE (left) != AOP_CRY))
6762 int posbit = isLiteralBit (lit);
6767 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6770 emitcode ("mov", "c,acc.%d", posbit & 0x07);
6776 SNPRINTF (buff, sizeof(buff),
6777 "acc.%d", posbit & 0x07);
6778 genIfxJump (ifx, buff);
6782 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6789 symbol *tlbl = newiTempLabel (NULL);
6790 int sizel = AOP_SIZE (left);
6792 emitcode ("setb", "c");
6795 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6797 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6799 if ((posbit = isLiteralBit (bytelit)) != 0)
6800 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6803 if (bytelit != 0x0FFL)
6804 emitcode ("anl", "a,%s",
6805 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6806 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6811 // bit = left & literal
6814 emitcode ("clr", "c");
6815 emitcode ("", "!tlabeldef", tlbl->key + 100);
6817 // if(left & literal)
6821 jmpTrueOrFalse (ifx, tlbl);
6823 emitcode ("", "!tlabeldef", tlbl->key + 100);
6831 /* if left is same as result */
6832 if (sameRegs (AOP (result), AOP (left)))
6834 for (; size--; offset++)
6836 if (AOP_TYPE (right) == AOP_LIT)
6838 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6840 else if (bytelit == 0)
6841 aopPut (AOP (result), zero, offset);
6842 else if (IS_AOP_PREG (result))
6844 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6845 emitcode ("anl", "a,%s",
6846 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6847 aopPut (AOP (result), "a", offset);
6850 emitcode ("anl", "%s,%s",
6851 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6852 aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6856 if (AOP_TYPE (left) == AOP_ACC)
6857 emitcode ("anl", "a,%s",
6858 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6861 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6862 if (IS_AOP_PREG (result))
6864 emitcode ("anl", "a,%s",
6865 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6866 aopPut (AOP (result), "a", offset);
6869 emitcode ("anl", "%s,a",
6870 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6877 // left & result in different registers
6878 if (AOP_TYPE (result) == AOP_CRY)
6881 // if(size), result in bit
6882 // if(!size && ifx), conditional oper: if(left & right)
6883 symbol *tlbl = newiTempLabel (NULL);
6884 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6886 emitcode ("setb", "c");
6889 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6890 emitcode ("anl", "a,%s",
6891 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6893 if (AOP_TYPE(left)==AOP_ACC) {
6894 emitcode("mov", "b,a");
6895 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6896 emitcode("anl", "a,b");
6898 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6899 emitcode ("anl", "a,%s",
6900 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6903 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6909 emitcode ("", "!tlabeldef", tlbl->key + 100);
6913 jmpTrueOrFalse (ifx, tlbl);
6915 emitcode ("", "!tlabeldef", tlbl->key + 100);
6919 for (; (size--); offset++)
6922 // result = left & right
6923 if (AOP_TYPE (right) == AOP_LIT)
6925 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6927 aopPut (AOP (result),
6928 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6932 else if (bytelit == 0)
6934 aopPut (AOP (result), zero, offset);
6937 D (emitcode (";", "better literal AND."););
6938 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6939 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6940 FALSE, FALSE, DP2_RESULT_REG));
6945 // faster than result <- left, anl result,right
6946 // and better if result is SFR
6947 if (AOP_TYPE (left) == AOP_ACC)
6949 emitcode ("anl", "a,%s",
6950 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6954 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6955 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6957 emitcode("mov", "b,a");
6961 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6962 emitcode ("anl", "a,%s", rOp);
6965 aopPut (AOP (result), "a", offset);
6971 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6972 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6973 freeAsmop (result, NULL, ic, TRUE);
6977 /*-----------------------------------------------------------------*/
6978 /* genOr - code for or */
6979 /*-----------------------------------------------------------------*/
6981 genOr (iCode * ic, iCode * ifx)
6983 operand *left, *right, *result;
6984 int size, offset = 0;
6985 unsigned long lit = 0L;
6988 D (emitcode (";", "genOr "););
6990 AOP_OP_3_NOFATAL (ic, pushResult);
6991 AOP_SET_LOCALS (ic);
6995 genFarFarLogicOp(ic, "orl");
7001 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7003 AOP_TYPE (left), AOP_TYPE (right));
7004 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7006 AOP_SIZE (left), AOP_SIZE (right));
7009 /* if left is a literal & right is not then exchange them */
7010 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7011 #ifdef LOGIC_OPS_BROKEN
7012 || AOP_NEEDSACC (left) // I think this is a net loss now.
7016 operand *tmp = right;
7021 /* if result = right then exchange them */
7022 if (sameRegs (AOP (result), AOP (right)))
7024 operand *tmp = right;
7029 /* if right is bit then exchange them */
7030 if (AOP_TYPE (right) == AOP_CRY &&
7031 AOP_TYPE (left) != AOP_CRY)
7033 operand *tmp = right;
7037 if (AOP_TYPE (right) == AOP_LIT)
7038 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7040 size = AOP_SIZE (result);
7044 if (AOP_TYPE (left) == AOP_CRY)
7046 if (AOP_TYPE (right) == AOP_LIT)
7048 // c = bit & literal;
7051 // lit != 0 => result = 1
7052 if (AOP_TYPE (result) == AOP_CRY)
7055 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7057 continueIfTrue (ifx);
7060 emitcode ("setb", "c");
7064 // lit == 0 => result = left
7065 if (size && sameRegs (AOP (result), AOP (left)))
7067 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7072 if (AOP_TYPE (right) == AOP_CRY)
7075 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7076 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7081 symbol *tlbl = newiTempLabel (NULL);
7082 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
7083 emitcode ("setb", "c");
7084 emitcode ("jb", "%s,!tlabel",
7085 AOP (left)->aopu.aop_dir, tlbl->key + 100);
7087 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7088 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7090 jmpTrueOrFalse (ifx, tlbl);
7096 emitcode ("", "!tlabeldef", tlbl->key + 100);
7105 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7106 genIfxJump (ifx, "c");
7110 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7111 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7112 if ((AOP_TYPE (right) == AOP_LIT) &&
7113 (AOP_TYPE (result) == AOP_CRY) &&
7114 (AOP_TYPE (left) != AOP_CRY))
7120 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7122 continueIfTrue (ifx);
7127 // lit = 0, result = boolean(left)
7129 emitcode ("setb", "c");
7133 symbol *tlbl = newiTempLabel (NULL);
7134 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7136 emitcode ("", "!tlabeldef", tlbl->key + 100);
7140 genIfxJump (ifx, "a");
7148 /* if left is same as result */
7149 if (sameRegs (AOP (result), AOP (left)))
7151 for (; size--; offset++)
7153 if (AOP_TYPE (right) == AOP_LIT)
7155 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7161 if (IS_AOP_PREG (left))
7163 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7164 emitcode ("orl", "a,%s",
7165 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7166 aopPut (AOP (result), "a", offset);
7170 emitcode ("orl", "%s,%s",
7171 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
7172 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7178 if (AOP_TYPE (left) == AOP_ACC)
7180 emitcode ("orl", "a,%s",
7181 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7185 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7186 if (IS_AOP_PREG (left))
7188 emitcode ("orl", "a,%s",
7189 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7190 aopPut (AOP (result), "a", offset);
7194 emitcode ("orl", "%s,a",
7195 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7203 // left & result in different registers
7204 if (AOP_TYPE (result) == AOP_CRY)
7207 // if(size), result in bit
7208 // if(!size && ifx), conditional oper: if(left | right)
7209 symbol *tlbl = newiTempLabel (NULL);
7210 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7212 emitcode ("setb", "c");
7215 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7216 emitcode ("orl", "a,%s",
7217 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7219 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7220 emitcode ("orl", "a,%s",
7221 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
7223 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7229 emitcode ("", "!tlabeldef", tlbl->key + 100);
7233 jmpTrueOrFalse (ifx, tlbl);
7235 emitcode ("", "!tlabeldef", tlbl->key + 100);
7239 _startLazyDPSEvaluation();
7240 for (; (size--); offset++)
7243 // result = left & right
7244 if (AOP_TYPE (right) == AOP_LIT)
7246 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7248 aopPut (AOP (result),
7249 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7253 D (emitcode (";", "better literal OR."););
7254 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7255 emitcode ("orl", "a, %s",
7256 aopGet (AOP (right), offset,
7257 FALSE, FALSE, DP2_RESULT_REG));
7262 // faster than result <- left, anl result,right
7263 // and better if result is SFR
7264 if (AOP_TYPE (left) == AOP_ACC)
7266 emitcode ("orl", "a,%s",
7267 aopGet (AOP (right), offset,
7268 FALSE, FALSE, DP2_RESULT_REG));
7272 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7274 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7276 emitcode("mov", "b,a");
7280 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7281 emitcode ("orl", "a,%s", rOp);
7284 aopPut (AOP (result), "a", offset);
7286 _endLazyDPSEvaluation();
7291 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7292 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7293 freeAsmop (result, NULL, ic, TRUE);
7296 /*-----------------------------------------------------------------*/
7297 /* genXor - code for xclusive or */
7298 /*-----------------------------------------------------------------*/
7300 genXor (iCode * ic, iCode * ifx)
7302 operand *left, *right, *result;
7303 int size, offset = 0;
7304 unsigned long lit = 0L;
7307 D (emitcode (";", "genXor "););
7309 AOP_OP_3_NOFATAL (ic, pushResult);
7310 AOP_SET_LOCALS (ic);
7314 genFarFarLogicOp(ic, "xrl");
7319 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7321 AOP_TYPE (left), AOP_TYPE (right));
7322 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7324 AOP_SIZE (left), AOP_SIZE (right));
7327 /* if left is a literal & right is not ||
7328 if left needs acc & right does not */
7329 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7330 #ifdef LOGIC_OPS_BROKEN
7331 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
7335 operand *tmp = right;
7340 /* if result = right then exchange them */
7341 if (sameRegs (AOP (result), AOP (right)))
7343 operand *tmp = right;
7348 /* if right is bit then exchange them */
7349 if (AOP_TYPE (right) == AOP_CRY &&
7350 AOP_TYPE (left) != AOP_CRY)
7352 operand *tmp = right;
7356 if (AOP_TYPE (right) == AOP_LIT)
7357 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7359 size = AOP_SIZE (result);
7363 if (AOP_TYPE (left) == AOP_CRY)
7365 if (AOP_TYPE (right) == AOP_LIT)
7367 // c = bit & literal;
7370 // lit>>1 != 0 => result = 1
7371 if (AOP_TYPE (result) == AOP_CRY)
7374 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7376 continueIfTrue (ifx);
7379 emitcode ("setb", "c");
7386 // lit == 0, result = left
7387 if (size && sameRegs (AOP (result), AOP (left)))
7389 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7393 // lit == 1, result = not(left)
7394 if (size && sameRegs (AOP (result), AOP (left)))
7396 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7401 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7402 emitcode ("cpl", "c");
7411 symbol *tlbl = newiTempLabel (NULL);
7412 if (AOP_TYPE (right) == AOP_CRY)
7415 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7419 int sizer = AOP_SIZE (right);
7421 // if val>>1 != 0, result = 1
7422 emitcode ("setb", "c");
7425 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
7427 // test the msb of the lsb
7428 emitcode ("anl", "a,#!constbyte",0xfe);
7429 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7433 emitcode ("rrc", "a");
7435 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7436 emitcode ("cpl", "c");
7437 emitcode ("", "!tlabeldef", (tlbl->key + 100));
7444 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7445 genIfxJump (ifx, "c");
7449 if (sameRegs (AOP (result), AOP (left)))
7451 /* if left is same as result */
7452 for (; size--; offset++)
7454 if (AOP_TYPE (right) == AOP_LIT)
7456 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7458 else if (IS_AOP_PREG (left))
7460 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7461 emitcode ("xrl", "a,%s",
7462 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7463 aopPut (AOP (result), "a", offset);
7466 emitcode ("xrl", "%s,%s",
7467 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
7468 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7472 if (AOP_TYPE (left) == AOP_ACC)
7473 emitcode ("xrl", "a,%s",
7474 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7477 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7478 if (IS_AOP_PREG (left))
7480 emitcode ("xrl", "a,%s",
7481 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7482 aopPut (AOP (result), "a", offset);
7485 emitcode ("xrl", "%s,a",
7486 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7493 // left & result in different registers
7494 if (AOP_TYPE (result) == AOP_CRY)
7497 // if(size), result in bit
7498 // if(!size && ifx), conditional oper: if(left ^ right)
7499 symbol *tlbl = newiTempLabel (NULL);
7500 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7503 emitcode ("setb", "c");
7506 if ((AOP_TYPE (right) == AOP_LIT) &&
7507 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7509 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7513 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7514 emitcode ("xrl", "a,%s",
7515 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7517 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7518 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7520 emitcode("mov", "b,a");
7524 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7525 emitcode ("xrl", "a,%s", rOp);
7528 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7534 emitcode ("", "!tlabeldef", tlbl->key + 100);
7538 jmpTrueOrFalse (ifx, tlbl);
7542 for (; (size--); offset++)
7545 // result = left & right
7546 if (AOP_TYPE (right) == AOP_LIT)
7548 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7550 aopPut (AOP (result),
7551 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7555 D (emitcode (";", "better literal XOR."););
7556 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7557 emitcode ("xrl", "a, %s",
7558 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7562 // faster than result <- left, anl result,right
7563 // and better if result is SFR
7564 if (AOP_TYPE (left) == AOP_ACC)
7566 emitcode ("xrl", "a,%s",
7567 aopGet (AOP (right), offset,
7568 FALSE, FALSE, DP2_RESULT_REG));
7572 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7573 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7575 emitcode("mov", "b,a");
7579 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7580 emitcode ("xrl", "a,%s", rOp);
7583 aopPut (AOP (result), "a", offset);
7590 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7591 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7592 freeAsmop (result, NULL, ic, TRUE);
7595 /*-----------------------------------------------------------------*/
7596 /* genInline - write the inline code out */
7597 /*-----------------------------------------------------------------*/
7599 genInline (iCode * ic)
7601 char *buffer, *bp, *bp1;
7603 D (emitcode (";", "genInline "); );
7605 _G.inLine += (!options.asmpeep);
7607 buffer = Safe_strdup(IC_INLINE(ic));
7611 /* emit each line as a code */
7636 /* emitcode("",buffer); */
7637 _G.inLine -= (!options.asmpeep);
7640 /*-----------------------------------------------------------------*/
7641 /* genRRC - rotate right with carry */
7642 /*-----------------------------------------------------------------*/
7646 operand *left, *result;
7649 D (emitcode (";", "genRRC "););
7651 /* rotate right with carry */
7652 left = IC_LEFT (ic);
7653 result = IC_RESULT (ic);
7654 aopOp (left, ic, FALSE, FALSE);
7655 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7657 /* move it to the result */
7658 size = AOP_SIZE (result);
7662 _startLazyDPSEvaluation ();
7665 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7666 emitcode ("rrc", "a");
7667 if (AOP_SIZE (result) > 1)
7668 aopPut (AOP (result), "a", offset--);
7670 _endLazyDPSEvaluation ();
7672 /* now we need to put the carry into the
7673 highest order byte of the result */
7674 if (AOP_SIZE (result) > 1)
7676 MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7678 emitcode ("mov", "acc.7,c");
7679 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7680 freeAsmop (left, NULL, ic, TRUE);
7681 freeAsmop (result, NULL, ic, TRUE);
7684 /*-----------------------------------------------------------------*/
7685 /* genRLC - generate code for rotate left with carry */
7686 /*-----------------------------------------------------------------*/
7690 operand *left, *result;
7694 D (emitcode (";", "genRLC "););
7696 /* rotate right with carry */
7697 left = IC_LEFT (ic);
7698 result = IC_RESULT (ic);
7699 aopOp (left, ic, FALSE, FALSE);
7700 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7702 /* move it to the result */
7703 size = AOP_SIZE (result);
7707 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7709 emitcode ("add", "a,acc");
7710 if (AOP_SIZE (result) > 1)
7712 aopPut (AOP (result), "a", offset++);
7715 _startLazyDPSEvaluation ();
7718 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7720 emitcode ("rlc", "a");
7721 if (AOP_SIZE (result) > 1)
7722 aopPut (AOP (result), "a", offset++);
7724 _endLazyDPSEvaluation ();
7726 /* now we need to put the carry into the
7727 highest order byte of the result */
7728 if (AOP_SIZE (result) > 1)
7730 l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7733 emitcode ("mov", "acc.0,c");
7734 aopPut (AOP (result), "a", 0);
7735 freeAsmop (left, NULL, ic, TRUE);
7736 freeAsmop (result, NULL, ic, TRUE);
7739 /*-----------------------------------------------------------------*/
7740 /* genGetHbit - generates code get highest order bit */
7741 /*-----------------------------------------------------------------*/
7743 genGetHbit (iCode * ic)
7745 operand *left, *result;
7746 left = IC_LEFT (ic);
7747 result = IC_RESULT (ic);
7748 aopOp (left, ic, FALSE, FALSE);
7749 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7751 D (emitcode (";", "genGetHbit "););
7753 /* get the highest order byte into a */
7754 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7755 if (AOP_TYPE (result) == AOP_CRY)
7757 emitcode ("rlc", "a");
7762 emitcode ("rl", "a");
7763 emitcode ("anl", "a,#1");
7768 freeAsmop (left, NULL, ic, TRUE);
7769 freeAsmop (result, NULL, ic, TRUE);
7772 /*-----------------------------------------------------------------*/
7773 /* genSwap - generates code to swap nibbles or bytes */
7774 /*-----------------------------------------------------------------*/
7776 genSwap (iCode * ic)
7778 operand *left, *result;
7780 D(emitcode ("; genSwap",""));
7782 left = IC_LEFT (ic);
7783 result = IC_RESULT (ic);
7784 aopOp (left, ic, FALSE, FALSE);
7785 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7787 _startLazyDPSEvaluation ();
7788 switch (AOP_SIZE (left))
7790 case 1: /* swap nibbles in byte */
7791 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7792 emitcode ("swap", "a");
7793 aopPut (AOP (result), "a", 0);
7795 case 2: /* swap bytes in word */
7796 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7798 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7799 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7800 aopPut (AOP (result), "a", 1);
7802 else if (operandsEqu (left, result))
7805 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7806 if (AOP_NEEDSACC (left) || AOP_NEEDSACC (result))
7808 emitcode ("mov", "b,a");
7812 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7813 aopPut (AOP (result), reg, 1);
7818 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7819 aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE, NULL), 1);
7823 wassertl(FALSE, "unsupported SWAP operand size");
7825 _endLazyDPSEvaluation ();
7827 freeAsmop (left, NULL, ic, TRUE);
7828 freeAsmop (result, NULL, ic, TRUE);
7831 /*-----------------------------------------------------------------*/
7832 /* AccRol - rotate left accumulator by known count */
7833 /*-----------------------------------------------------------------*/
7835 AccRol (int shCount)
7837 shCount &= 0x0007; // shCount : 0..7
7844 emitcode ("rl", "a");
7847 emitcode ("rl", "a");
7848 emitcode ("rl", "a");
7851 emitcode ("swap", "a");
7852 emitcode ("rr", "a");
7855 emitcode ("swap", "a");
7858 emitcode ("swap", "a");
7859 emitcode ("rl", "a");
7862 emitcode ("rr", "a");
7863 emitcode ("rr", "a");
7866 emitcode ("rr", "a");
7871 /*-----------------------------------------------------------------*/
7872 /* AccLsh - left shift accumulator by known count */
7873 /*-----------------------------------------------------------------*/
7875 AccLsh (int shCount)
7880 emitcode ("add", "a,acc");
7881 else if (shCount == 2)
7883 emitcode ("add", "a,acc");
7884 emitcode ("add", "a,acc");
7888 /* rotate left accumulator */
7890 /* and kill the lower order bits */
7891 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7896 /*-----------------------------------------------------------------*/
7897 /* AccRsh - right shift accumulator by known count */
7898 /*-----------------------------------------------------------------*/
7900 AccRsh (int shCount)
7907 emitcode ("rrc", "a");
7911 /* rotate right accumulator */
7912 AccRol (8 - shCount);
7913 /* and kill the higher order bits */
7914 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7919 #ifdef BETTER_LITERAL_SHIFT
7920 /*-----------------------------------------------------------------*/
7921 /* AccSRsh - signed right shift accumulator by known count */
7922 /*-----------------------------------------------------------------*/
7924 AccSRsh (int shCount)
7931 emitcode ("mov", "c,acc.7");
7932 emitcode ("rrc", "a");
7934 else if (shCount == 2)
7936 emitcode ("mov", "c,acc.7");
7937 emitcode ("rrc", "a");
7938 emitcode ("mov", "c,acc.7");
7939 emitcode ("rrc", "a");
7943 tlbl = newiTempLabel (NULL);
7944 /* rotate right accumulator */
7945 AccRol (8 - shCount);
7946 /* and kill the higher order bits */
7947 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7948 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7949 emitcode ("orl", "a,#!constbyte",
7950 (unsigned char) ~SRMask[shCount]);
7951 emitcode ("", "!tlabeldef", tlbl->key + 100);
7957 #ifdef BETTER_LITERAL_SHIFT
7958 /*-----------------------------------------------------------------*/
7959 /* shiftR1Left2Result - shift right one byte from left to result */
7960 /*-----------------------------------------------------------------*/
7962 shiftR1Left2Result (operand * left, int offl,
7963 operand * result, int offr,
7964 int shCount, int sign)
7966 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7967 /* shift right accumulator */
7972 aopPut (AOP (result), "a", offr);
7976 #ifdef BETTER_LITERAL_SHIFT
7977 /*-----------------------------------------------------------------*/
7978 /* shiftL1Left2Result - shift left one byte from left to result */
7979 /*-----------------------------------------------------------------*/
7981 shiftL1Left2Result (operand * left, int offl,
7982 operand * result, int offr, int shCount)
7984 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7985 /* shift left accumulator */
7987 aopPut (AOP (result), "a", offr);
7991 #ifdef BETTER_LITERAL_SHIFT
7992 /*-----------------------------------------------------------------*/
7993 /* movLeft2Result - move byte from left to result */
7994 /*-----------------------------------------------------------------*/
7996 movLeft2Result (operand * left, int offl,
7997 operand * result, int offr, int sign)
8000 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8002 l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
8004 if (*l == '@' && (IS_AOP_PREG (result)))
8006 emitcode ("mov", "a,%s", l);
8007 aopPut (AOP (result), "a", offr);
8013 aopPut (AOP (result), l, offr);
8017 /* MSB sign in acc.7 ! */
8018 if (getDataSize (left) == offl + 1)
8020 emitcode ("mov", "a,%s", l);
8021 aopPut (AOP (result), "a", offr);
8029 #ifdef BETTER_LITERAL_SHIFT
8030 /*-----------------------------------------------------------------*/
8031 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
8032 /*-----------------------------------------------------------------*/
8036 emitcode ("rrc", "a");
8037 emitcode ("xch", "a,%s", x);
8038 emitcode ("rrc", "a");
8039 emitcode ("xch", "a,%s", x);
8043 #ifdef BETTER_LITERAL_SHIFT
8045 /*-----------------------------------------------------------------*/
8046 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
8047 /*-----------------------------------------------------------------*/
8051 emitcode ("xch", "a,%s", x);
8052 emitcode ("rlc", "a");
8053 emitcode ("xch", "a,%s", x);
8054 emitcode ("rlc", "a");
8058 #ifdef BETTER_LITERAL_SHIFT
8059 /*-----------------------------------------------------------------*/
8060 /* AccAXLsh1 - left shift a:x<-0 by 1 */
8061 /*-----------------------------------------------------------------*/
8065 emitcode ("xch", "a,%s", x);
8066 emitcode ("add", "a,acc");
8067 emitcode ("xch", "a,%s", x);
8068 emitcode ("rlc", "a");
8072 #ifdef BETTER_LITERAL_SHIFT
8073 /*-----------------------------------------------------------------*/
8074 /* AccAXLsh - left shift a:x by known count (0..7) */
8075 /*-----------------------------------------------------------------*/
8077 AccAXLsh (char *x, int shCount)
8092 case 5: // AAAAABBB:CCCCCDDD
8094 AccRol (shCount); // BBBAAAAA:CCCCCDDD
8096 emitcode ("anl", "a,#!constbyte",
8097 SLMask[shCount]); // BBB00000:CCCCCDDD
8099 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
8101 AccRol (shCount); // DDDCCCCC:BBB00000
8103 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8105 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8107 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8109 emitcode ("anl", "a,#!constbyte",
8110 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8112 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8114 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8117 case 6: // AAAAAABB:CCCCCCDD
8118 emitcode ("anl", "a,#!constbyte",
8119 SRMask[shCount]); // 000000BB:CCCCCCDD
8120 emitcode ("mov", "c,acc.0"); // c = B
8121 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8123 AccAXRrl1 (x); // BCCCCCCD:D000000B
8124 AccAXRrl1 (x); // BBCCCCCC:DD000000
8126 emitcode("rrc","a");
8127 emitcode("xch","a,%s", x);
8128 emitcode("rrc","a");
8129 emitcode("mov","c,acc.0"); //<< get correct bit
8130 emitcode("xch","a,%s", x);
8132 emitcode("rrc","a");
8133 emitcode("xch","a,%s", x);
8134 emitcode("rrc","a");
8135 emitcode("xch","a,%s", x);
8138 case 7: // a:x <<= 7
8140 emitcode ("anl", "a,#!constbyte",
8141 SRMask[shCount]); // 0000000B:CCCCCCCD
8143 emitcode ("mov", "c,acc.0"); // c = B
8145 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
8147 AccAXRrl1 (x); // BCCCCCCC:D0000000
8156 #ifdef BETTER_LITERAL_SHIFT
8158 /*-----------------------------------------------------------------*/
8159 /* AccAXRsh - right shift a:x known count (0..7) */
8160 /*-----------------------------------------------------------------*/
8162 AccAXRsh (char *x, int shCount)
8170 AccAXRrl1 (x); // 0->a:x
8175 AccAXRrl1 (x); // 0->a:x
8178 AccAXRrl1 (x); // 0->a:x
8183 case 5: // AAAAABBB:CCCCCDDD = a:x
8185 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8187 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8189 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8191 emitcode ("anl", "a,#!constbyte",
8192 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8194 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8196 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8198 emitcode ("anl", "a,#!constbyte",
8199 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8201 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8203 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8205 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8208 case 6: // AABBBBBB:CCDDDDDD
8210 emitcode ("mov", "c,acc.7");
8211 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8213 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8215 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8217 emitcode ("anl", "a,#!constbyte",
8218 SRMask[shCount]); // 000000AA:BBBBBBCC
8221 case 7: // ABBBBBBB:CDDDDDDD
8223 emitcode ("mov", "c,acc.7"); // c = A
8225 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8227 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8229 emitcode ("anl", "a,#!constbyte",
8230 SRMask[shCount]); // 0000000A:BBBBBBBC
8239 #ifdef BETTER_LITERAL_SHIFT
8240 /*-----------------------------------------------------------------*/
8241 /* AccAXRshS - right shift signed a:x known count (0..7) */
8242 /*-----------------------------------------------------------------*/
8244 AccAXRshS (char *x, int shCount)
8252 emitcode ("mov", "c,acc.7");
8253 AccAXRrl1 (x); // s->a:x
8257 emitcode ("mov", "c,acc.7");
8258 AccAXRrl1 (x); // s->a:x
8260 emitcode ("mov", "c,acc.7");
8261 AccAXRrl1 (x); // s->a:x
8266 case 5: // AAAAABBB:CCCCCDDD = a:x
8268 tlbl = newiTempLabel (NULL);
8269 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8271 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8273 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8275 emitcode ("anl", "a,#!constbyte",
8276 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8278 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8280 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8282 emitcode ("anl", "a,#!constbyte",
8283 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8285 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8287 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8289 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
8291 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8292 emitcode ("orl", "a,#!constbyte",
8293 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
8295 emitcode ("", "!tlabeldef", tlbl->key + 100);
8296 break; // SSSSAAAA:BBBCCCCC
8298 case 6: // AABBBBBB:CCDDDDDD
8300 tlbl = newiTempLabel (NULL);
8301 emitcode ("mov", "c,acc.7");
8302 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8304 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8306 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8308 emitcode ("anl", "a,#!constbyte",
8309 SRMask[shCount]); // 000000AA:BBBBBBCC
8311 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8312 emitcode ("orl", "a,#!constbyte",
8313 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
8315 emitcode ("", "!tlabeldef", tlbl->key + 100);
8317 case 7: // ABBBBBBB:CDDDDDDD
8319 tlbl = newiTempLabel (NULL);
8320 emitcode ("mov", "c,acc.7"); // c = A
8322 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8324 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8326 emitcode ("anl", "a,#!constbyte",
8327 SRMask[shCount]); // 0000000A:BBBBBBBC
8329 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8330 emitcode ("orl", "a,#!constbyte",
8331 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
8333 emitcode ("", "!tlabeldef", tlbl->key + 100);
8341 #ifdef BETTER_LITERAL_SHIFT
8343 _loadLeftIntoAx(char **lsb,
8349 // Get the initial value from left into a pair of registers.
8350 // MSB must be in A, LSB can be any register.
8352 // If the result is held in registers, it is an optimization
8353 // if the LSB can be held in the register which will hold the,
8354 // result LSB since this saves us from having to copy it into
8355 // the result following AccAXLsh.
8357 // If the result is addressed indirectly, this is not a gain.
8358 if (AOP_NEEDSACC(result))
8362 _startLazyDPSEvaluation();
8363 if (AOP_TYPE(left) == AOP_DPTR2)
8366 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
8367 // get LSB in DP2_RESULT_REG.
8368 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
8369 assert(!strcmp(leftByte, DP2_RESULT_REG));
8373 // get LSB into DP2_RESULT_REG
8374 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
8375 if (strcmp(leftByte, DP2_RESULT_REG))
8378 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
8381 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
8382 assert(strcmp(leftByte, DP2_RESULT_REG));
8385 _endLazyDPSEvaluation();
8386 *lsb = DP2_RESULT_REG;
8390 if (sameRegs (AOP (result), AOP (left)) &&
8391 ((offl + MSB16) == offr))
8393 /* don't crash result[offr] */
8394 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
8395 emitcode ("xch", "a,%s",
8396 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
8400 movLeft2Result (left, offl, result, offr, 0);
8401 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
8403 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
8404 assert(strcmp(*lsb,"a"));
8409 _storeAxResults(char *lsb,
8413 _startLazyDPSEvaluation();
8414 if (AOP_NEEDSACC(result))
8416 /* We have to explicitly update the result LSB.
8418 emitcode("xch","a,%s", lsb);
8419 aopPut(AOP(result), "a", offr);
8420 emitcode("mov","a,%s", lsb);
8422 if (getDataSize (result) > 1)
8424 aopPut (AOP (result), "a", offr + MSB16);
8426 _endLazyDPSEvaluation();
8429 /*-----------------------------------------------------------------*/
8430 /* shiftL2Left2Result - shift left two bytes from left to result */
8431 /*-----------------------------------------------------------------*/
8433 shiftL2Left2Result (operand * left, int offl,
8434 operand * result, int offr, int shCount)
8438 _loadLeftIntoAx(&lsb, left, result, offl, offr);
8440 AccAXLsh (lsb, shCount);
8442 _storeAxResults(lsb, result, offr);
8446 #ifdef BETTER_LITERAL_SHIFT
8447 /*-----------------------------------------------------------------*/
8448 /* shiftR2Left2Result - shift right two bytes from left to result */
8449 /*-----------------------------------------------------------------*/
8451 shiftR2Left2Result (operand * left, int offl,
8452 operand * result, int offr,
8453 int shCount, int sign)
8457 _loadLeftIntoAx(&lsb, left, result, offl, offr);
8459 /* a:x >> shCount (x = lsb(result)) */
8462 AccAXRshS(lsb, shCount);
8466 AccAXRsh(lsb, shCount);
8469 _storeAxResults(lsb, result, offr);
8473 /*-----------------------------------------------------------------*/
8474 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8475 /*-----------------------------------------------------------------*/
8477 shiftLLeftOrResult (operand * left, int offl,
8478 operand * result, int offr, int shCount)
8480 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8481 /* shift left accumulator */
8483 /* or with result */
8484 emitcode ("orl", "a,%s",
8485 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8486 /* back to result */
8487 aopPut (AOP (result), "a", offr);
8492 /*-----------------------------------------------------------------*/
8493 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8494 /*-----------------------------------------------------------------*/
8496 shiftRLeftOrResult (operand * left, int offl,
8497 operand * result, int offr, int shCount)
8499 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8500 /* shift right accumulator */
8502 /* or with result */
8503 emitcode ("orl", "a,%s",
8504 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8505 /* back to result */
8506 aopPut (AOP (result), "a", offr);
8510 #ifdef BETTER_LITERAL_SHIFT
8511 /*-----------------------------------------------------------------*/
8512 /* genlshOne - left shift a one byte quantity by known count */
8513 /*-----------------------------------------------------------------*/
8515 genlshOne (operand * result, operand * left, int shCount)
8517 D (emitcode (";", "genlshOne "););
8518 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8522 #ifdef BETTER_LITERAL_SHIFT
8523 /*-----------------------------------------------------------------*/
8524 /* genlshTwo - left shift two bytes by known amount != 0 */
8525 /*-----------------------------------------------------------------*/
8527 genlshTwo (operand * result, operand * left, int shCount)
8531 D (emitcode (";", "genlshTwo "););
8533 size = getDataSize (result);
8535 /* if shCount >= 8 */
8540 _startLazyDPSEvaluation();
8546 _endLazyDPSEvaluation();
8547 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8548 aopPut (AOP (result), zero, LSB);
8552 movLeft2Result (left, LSB, result, MSB16, 0);
8553 aopPut (AOP (result), zero, LSB);
8554 _endLazyDPSEvaluation();
8559 aopPut (AOP (result), zero, LSB);
8560 _endLazyDPSEvaluation();
8564 /* 1 <= shCount <= 7 */
8569 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8573 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8581 /*-----------------------------------------------------------------*/
8582 /* shiftLLong - shift left one long from left to result */
8583 /* offl = LSB or MSB16 */
8584 /*-----------------------------------------------------------------*/
8586 shiftLLong (operand * left, operand * result, int offr)
8589 int size = AOP_SIZE (result);
8591 if (size >= LSB + offr)
8593 l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8595 emitcode ("add", "a,acc");
8596 if (sameRegs (AOP (left), AOP (result)) &&
8597 size >= MSB16 + offr && offr != LSB)
8598 emitcode ("xch", "a,%s",
8599 aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8601 aopPut (AOP (result), "a", LSB + offr);
8604 if (size >= MSB16 + offr)
8606 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8608 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8610 emitcode ("rlc", "a");
8611 if (sameRegs (AOP (left), AOP (result)) &&
8612 size >= MSB24 + offr && offr != LSB)
8613 emitcode ("xch", "a,%s",
8614 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8616 aopPut (AOP (result), "a", MSB16 + offr);
8619 if (size >= MSB24 + offr)
8621 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8623 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8625 emitcode ("rlc", "a");
8626 if (sameRegs (AOP (left), AOP (result)) &&
8627 size >= MSB32 + offr && offr != LSB)
8628 emitcode ("xch", "a,%s",
8629 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8631 aopPut (AOP (result), "a", MSB24 + offr);
8634 if (size > MSB32 + offr)
8636 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8638 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8640 emitcode ("rlc", "a");
8641 aopPut (AOP (result), "a", MSB32 + offr);
8644 aopPut (AOP (result), zero, LSB);
8650 /*-----------------------------------------------------------------*/
8651 /* genlshFour - shift four byte by a known amount != 0 */
8652 /*-----------------------------------------------------------------*/
8654 genlshFour (operand * result, operand * left, int shCount)
8658 D (emitcode (";", "genlshFour ");
8661 size = AOP_SIZE (result);
8663 /* if shifting more that 3 bytes */
8668 /* lowest order of left goes to the highest
8669 order of the destination */
8670 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8672 movLeft2Result (left, LSB, result, MSB32, 0);
8673 aopPut (AOP (result), zero, LSB);
8674 aopPut (AOP (result), zero, MSB16);
8675 aopPut (AOP (result), zero, MSB24);
8679 /* more than two bytes */
8680 else if (shCount >= 16)
8682 /* lower order two bytes goes to higher order two bytes */
8684 /* if some more remaining */
8686 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8689 movLeft2Result (left, MSB16, result, MSB32, 0);
8690 movLeft2Result (left, LSB, result, MSB24, 0);
8692 aopPut (AOP (result), zero, MSB16);
8693 aopPut (AOP (result), zero, LSB);
8697 /* if more than 1 byte */
8698 else if (shCount >= 8)
8700 /* lower order three bytes goes to higher order three bytes */
8705 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8707 movLeft2Result (left, LSB, result, MSB16, 0);
8713 movLeft2Result (left, MSB24, result, MSB32, 0);
8714 movLeft2Result (left, MSB16, result, MSB24, 0);
8715 movLeft2Result (left, LSB, result, MSB16, 0);
8716 aopPut (AOP (result), zero, LSB);
8718 else if (shCount == 1)
8719 shiftLLong (left, result, MSB16);
8722 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8723 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8724 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8725 aopPut (AOP (result), zero, LSB);
8730 /* 1 <= shCount <= 7 */
8731 else if (shCount <= 2)
8733 shiftLLong (left, result, LSB);
8735 shiftLLong (result, result, LSB);
8737 /* 3 <= shCount <= 7, optimize */
8740 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8741 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8742 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8747 #ifdef BETTER_LITERAL_SHIFT
8748 /*-----------------------------------------------------------------*/
8749 /* genLeftShiftLiteral - left shifting by known count */
8750 /*-----------------------------------------------------------------*/
8752 genLeftShiftLiteral (operand * left,
8757 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8760 size = getSize (operandType (result));
8762 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8764 /* We only handle certain easy cases so far. */
8766 && (shCount < (size * 8))
8770 D(emitcode (";", "genLeftShiftLiteral wimping out"););
8774 freeAsmop (right, NULL, ic, TRUE);
8776 aopOp(left, ic, FALSE, FALSE);
8777 aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8780 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8782 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8783 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8785 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8788 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8790 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8791 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8793 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8799 emitcode ("; shift left ", "result %d, left %d", size,
8803 /* I suppose that the left size >= result size */
8806 _startLazyDPSEvaluation();
8809 movLeft2Result (left, size, result, size, 0);
8811 _endLazyDPSEvaluation();
8813 else if (shCount >= (size * 8))
8815 _startLazyDPSEvaluation();
8818 aopPut (AOP (result), zero, size);
8820 _endLazyDPSEvaluation();
8827 genlshOne (result, left, shCount);
8831 genlshTwo (result, left, shCount);
8835 genlshFour (result, left, shCount);
8839 fprintf(stderr, "*** ack! mystery literal shift!\n");
8843 freeAsmop (left, NULL, ic, TRUE);
8844 freeAsmop (result, NULL, ic, TRUE);
8849 /*-----------------------------------------------------------------*/
8850 /* genLeftShift - generates code for left shifting */
8851 /*-----------------------------------------------------------------*/
8853 genLeftShift (iCode * ic)
8855 operand *left, *right, *result;
8858 symbol *tlbl, *tlbl1;
8860 D (emitcode (";", "genLeftShift "););
8862 right = IC_RIGHT (ic);
8863 left = IC_LEFT (ic);
8864 result = IC_RESULT (ic);
8866 aopOp (right, ic, FALSE, FALSE);
8869 #ifdef BETTER_LITERAL_SHIFT
8870 /* if the shift count is known then do it
8871 as efficiently as possible */
8872 if (AOP_TYPE (right) == AOP_LIT)
8874 if (genLeftShiftLiteral (left, right, result, ic))
8881 /* shift count is unknown then we have to form
8882 a loop get the loop count in B : Note: we take
8883 only the lower order byte since shifting
8884 more that 32 bits make no sense anyway, ( the
8885 largest size of an object can be only 32 bits ) */
8887 if (AOP_TYPE (right) == AOP_LIT)
8889 /* Really should be handled by genLeftShiftLiteral,
8890 * but since I'm too lazy to fix that today, at least we can make
8891 * some small improvement.
8893 emitcode("mov", "b,#!constbyte",
8894 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8898 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8899 emitcode ("inc", "b");
8901 freeAsmop (right, NULL, ic, TRUE);
8902 aopOp (left, ic, FALSE, FALSE);
8903 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8905 /* now move the left to the result if they are not the
8907 if (!sameRegs (AOP (left), AOP (result)) &&
8908 AOP_SIZE (result) > 1)
8911 size = AOP_SIZE (result);
8913 _startLazyDPSEvaluation ();
8916 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8917 if (*l == '@' && (IS_AOP_PREG (result)))
8920 emitcode ("mov", "a,%s", l);
8921 aopPut (AOP (result), "a", offset);
8924 aopPut (AOP (result), l, offset);
8927 _endLazyDPSEvaluation ();
8930 tlbl = newiTempLabel (NULL);
8931 size = AOP_SIZE (result);
8933 tlbl1 = newiTempLabel (NULL);
8935 /* if it is only one byte then */
8938 symbol *tlbl1 = newiTempLabel (NULL);
8940 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8941 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8942 emitcode ("", "!tlabeldef", tlbl->key + 100);
8943 emitcode ("add", "a,acc");
8944 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8945 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8946 aopPut (AOP (result), "a", 0);
8950 reAdjustPreg (AOP (result));
8952 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8953 emitcode ("", "!tlabeldef", tlbl->key + 100);
8954 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8955 emitcode ("add", "a,acc");
8956 aopPut (AOP (result), "a", offset++);
8957 _startLazyDPSEvaluation ();
8960 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8961 emitcode ("rlc", "a");
8962 aopPut (AOP (result), "a", offset++);
8964 _endLazyDPSEvaluation ();
8965 reAdjustPreg (AOP (result));
8967 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8968 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8970 freeAsmop (left, NULL, ic, TRUE);
8971 freeAsmop (result, NULL, ic, TRUE);
8974 #ifdef BETTER_LITERAL_SHIFT
8975 /*-----------------------------------------------------------------*/
8976 /* genrshOne - right shift a one byte quantity by known count */
8977 /*-----------------------------------------------------------------*/
8979 genrshOne (operand * result, operand * left,
8980 int shCount, int sign)
8982 D (emitcode (";", "genrshOne"););
8983 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8987 #ifdef BETTER_LITERAL_SHIFT
8988 /*-----------------------------------------------------------------*/
8989 /* genrshTwo - right shift two bytes by known amount != 0 */
8990 /*-----------------------------------------------------------------*/
8992 genrshTwo (operand * result, operand * left,
8993 int shCount, int sign)
8995 D (emitcode (";", "genrshTwo"););
8997 /* if shCount >= 8 */
9001 _startLazyDPSEvaluation();
9004 shiftR1Left2Result (left, MSB16, result, LSB,
9009 movLeft2Result (left, MSB16, result, LSB, sign);
9011 addSign (result, MSB16, sign);
9012 _endLazyDPSEvaluation();
9015 /* 1 <= shCount <= 7 */
9018 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9023 /*-----------------------------------------------------------------*/
9024 /* shiftRLong - shift right one long from left to result */
9025 /* offl = LSB or MSB16 */
9026 /*-----------------------------------------------------------------*/
9028 shiftRLong (operand * left, int offl,
9029 operand * result, int sign)
9031 int isSameRegs=sameRegs(AOP(left),AOP(result));
9033 if (isSameRegs && offl>1) {
9034 // we are in big trouble, but this shouldn't happen
9035 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9038 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
9043 emitcode ("rlc", "a");
9044 emitcode ("subb", "a,acc");
9045 emitcode ("xch", "a,%s",
9046 aopGet(AOP(left), MSB32, FALSE, FALSE, DP2_RESULT_REG));
9048 aopPut (AOP(result), zero, MSB32);
9053 emitcode ("clr", "c");
9055 emitcode ("mov", "c,acc.7");
9058 emitcode ("rrc", "a");
9060 if (isSameRegs && offl==MSB16) {
9062 "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE, DP2_RESULT_REG));
9064 aopPut (AOP (result), "a", MSB32);
9065 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
9068 emitcode ("rrc", "a");
9069 if (isSameRegs && offl==1) {
9070 emitcode ("xch", "a,%s",
9071 aopGet (AOP (left), MSB16, FALSE, FALSE, DP2_RESULT_REG));
9073 aopPut (AOP (result), "a", MSB24);
9074 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, NULL));
9076 emitcode ("rrc", "a");
9077 aopPut (AOP (result), "a", MSB16 - offl);
9081 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, NULL));
9082 emitcode ("rrc", "a");
9083 aopPut (AOP (result), "a", LSB);
9087 /*-----------------------------------------------------------------*/
9088 /* genrshFour - shift four byte by a known amount != 0 */
9089 /*-----------------------------------------------------------------*/
9091 genrshFour (operand * result, operand * left,
9092 int shCount, int sign)
9094 D (emitcode (";", "genrshFour"););
9096 /* if shifting more that 3 bytes */
9100 _startLazyDPSEvaluation();
9102 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9104 movLeft2Result (left, MSB32, result, LSB, sign);
9105 addSign (result, MSB16, sign);
9106 _endLazyDPSEvaluation();
9108 else if (shCount >= 16)
9111 _startLazyDPSEvaluation();
9113 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9116 movLeft2Result (left, MSB24, result, LSB, 0);
9117 movLeft2Result (left, MSB32, result, MSB16, sign);
9119 addSign (result, MSB24, sign);
9120 _endLazyDPSEvaluation();
9122 else if (shCount >= 8)
9125 _startLazyDPSEvaluation();
9128 shiftRLong (left, MSB16, result, sign);
9130 else if (shCount == 0)
9132 movLeft2Result (left, MSB16, result, LSB, 0);
9133 movLeft2Result (left, MSB24, result, MSB16, 0);
9134 movLeft2Result (left, MSB32, result, MSB24, sign);
9135 addSign (result, MSB32, sign);
9139 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9140 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9141 /* the last shift is signed */
9142 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9143 addSign (result, MSB32, sign);
9145 _endLazyDPSEvaluation();
9149 /* 1 <= shCount <= 7 */
9152 shiftRLong (left, LSB, result, sign);
9154 shiftRLong (result, LSB, result, sign);
9158 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9159 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9160 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9165 #ifdef BETTER_LITERAL_SHIFT
9166 /*-----------------------------------------------------------------*/
9167 /* genRightShiftLiteral - right shifting by known count */
9168 /*-----------------------------------------------------------------*/
9170 genRightShiftLiteral (operand * left,
9176 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9179 size = getSize (operandType (result));
9181 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
9183 /* We only handle certain easy cases so far. */
9185 && (shCount < (size * 8))
9190 D(emitcode (";", "genRightShiftLiteral wimping out"););
9194 freeAsmop (right, NULL, ic, TRUE);
9196 aopOp (left, ic, FALSE, FALSE);
9197 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9200 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9204 /* test the LEFT size !!! */
9206 /* I suppose that the left size >= result size */
9209 size = getDataSize (result);
9210 _startLazyDPSEvaluation();
9213 movLeft2Result (left, size, result, size, 0);
9215 _endLazyDPSEvaluation();
9217 else if (shCount >= (size * 8))
9221 /* get sign in acc.7 */
9222 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
9224 addSign (result, LSB, sign);
9231 genrshOne (result, left, shCount, sign);
9235 genrshTwo (result, left, shCount, sign);
9239 genrshFour (result, left, shCount, sign);
9246 freeAsmop (left, NULL, ic, TRUE);
9247 freeAsmop (result, NULL, ic, TRUE);
9253 /*-----------------------------------------------------------------*/
9254 /* genSignedRightShift - right shift of signed number */
9255 /*-----------------------------------------------------------------*/
9257 genSignedRightShift (iCode * ic)
9259 operand *right, *left, *result;
9262 symbol *tlbl, *tlbl1;
9264 D (emitcode (";", "genSignedRightShift "););
9266 /* we do it the hard way put the shift count in b
9267 and loop thru preserving the sign */
9269 right = IC_RIGHT (ic);
9270 left = IC_LEFT (ic);
9271 result = IC_RESULT (ic);
9273 aopOp (right, ic, FALSE, FALSE);
9275 #ifdef BETTER_LITERAL_SHIFT
9276 if (AOP_TYPE (right) == AOP_LIT)
9278 if (genRightShiftLiteral (left, right, result, ic, 1))
9284 /* shift count is unknown then we have to form
9285 a loop get the loop count in B : Note: we take
9286 only the lower order byte since shifting
9287 more that 32 bits make no sense anyway, ( the
9288 largest size of an object can be only 32 bits ) */
9290 if (AOP_TYPE (right) == AOP_LIT)
9292 /* Really should be handled by genRightShiftLiteral,
9293 * but since I'm too lazy to fix that today, at least we can make
9294 * some small improvement.
9296 emitcode("mov", "b,#!constbyte",
9297 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9301 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
9302 emitcode ("inc", "b");
9304 freeAsmop (right, NULL, ic, TRUE);
9305 aopOp (left, ic, FALSE, FALSE);
9306 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9308 /* now move the left to the result if they are not the
9310 if (!sameRegs (AOP (left), AOP (result)) &&
9311 AOP_SIZE (result) > 1)
9314 size = AOP_SIZE (result);
9316 _startLazyDPSEvaluation ();
9319 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
9320 if (*l == '@' && IS_AOP_PREG (result))
9323 emitcode ("mov", "a,%s", l);
9324 aopPut (AOP (result), "a", offset);
9327 aopPut (AOP (result), l, offset);
9330 _endLazyDPSEvaluation ();
9333 /* mov the highest order bit to OVR */
9334 tlbl = newiTempLabel (NULL);
9335 tlbl1 = newiTempLabel (NULL);
9337 size = AOP_SIZE (result);
9339 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
9340 emitcode ("rlc", "a");
9341 emitcode ("mov", "ov,c");
9342 /* if it is only one byte then */
9345 MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9346 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9347 emitcode ("", "!tlabeldef", tlbl->key + 100);
9348 emitcode ("mov", "c,ov");
9349 emitcode ("rrc", "a");
9350 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9351 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9352 aopPut (AOP (result), "a", 0);
9356 reAdjustPreg (AOP (result));
9357 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9358 emitcode ("", "!tlabeldef", tlbl->key + 100);
9359 emitcode ("mov", "c,ov");
9360 _startLazyDPSEvaluation ();
9363 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
9364 emitcode ("rrc", "a");
9365 aopPut (AOP (result), "a", offset--);
9367 _endLazyDPSEvaluation ();
9368 reAdjustPreg (AOP (result));
9369 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9370 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9373 freeAsmop (left, NULL, ic, TRUE);
9374 freeAsmop (result, NULL, ic, TRUE);
9377 /*-----------------------------------------------------------------*/
9378 /* genRightShift - generate code for right shifting */
9379 /*-----------------------------------------------------------------*/
9381 genRightShift (iCode * ic)
9383 operand *right, *left, *result;
9387 symbol *tlbl, *tlbl1;
9389 D (emitcode (";", "genRightShift "););
9391 /* if signed then we do it the hard way preserve the
9392 sign bit moving it inwards */
9393 letype = getSpec (operandType (IC_LEFT (ic)));
9395 if (!SPEC_USIGN (letype))
9397 genSignedRightShift (ic);
9401 /* signed & unsigned types are treated the same : i.e. the
9402 signed is NOT propagated inwards : quoting from the
9403 ANSI - standard : "for E1 >> E2, is equivalent to division
9404 by 2**E2 if unsigned or if it has a non-negative value,
9405 otherwise the result is implementation defined ", MY definition
9406 is that the sign does not get propagated */
9408 right = IC_RIGHT (ic);
9409 left = IC_LEFT (ic);
9410 result = IC_RESULT (ic);
9412 aopOp (right, ic, FALSE, FALSE);
9414 #ifdef BETTER_LITERAL_SHIFT
9415 /* if the shift count is known then do it
9416 as efficiently as possible */
9417 if (AOP_TYPE (right) == AOP_LIT)
9419 if (genRightShiftLiteral (left, right, result, ic, 0))
9426 /* shift count is unknown then we have to form
9427 a loop get the loop count in B : Note: we take
9428 only the lower order byte since shifting
9429 more that 32 bits make no sense anyway, ( the
9430 largest size of an object can be only 32 bits ) */
9432 if (AOP_TYPE (right) == AOP_LIT)
9434 /* Really should be handled by genRightShiftLiteral,
9435 * but since I'm too lazy to fix that today, at least we can make
9436 * some small improvement.
9438 emitcode("mov", "b,#!constbyte",
9439 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9443 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
9444 emitcode ("inc", "b");
9446 freeAsmop (right, NULL, ic, TRUE);
9447 aopOp (left, ic, FALSE, FALSE);
9448 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9450 /* now move the left to the result if they are not the
9452 if (!sameRegs (AOP (left), AOP (result)) &&
9453 AOP_SIZE (result) > 1)
9456 size = AOP_SIZE (result);
9458 _startLazyDPSEvaluation ();
9461 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
9462 if (*l == '@' && IS_AOP_PREG (result))
9465 emitcode ("mov", "a,%s", l);
9466 aopPut (AOP (result), "a", offset);
9469 aopPut (AOP (result), l, offset);
9472 _endLazyDPSEvaluation ();
9475 tlbl = newiTempLabel (NULL);
9476 tlbl1 = newiTempLabel (NULL);
9477 size = AOP_SIZE (result);
9480 /* if it is only one byte then */
9483 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9484 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9485 emitcode ("", "!tlabeldef", tlbl->key + 100);
9487 emitcode ("rrc", "a");
9488 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9489 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9490 aopPut (AOP (result), "a", 0);
9494 reAdjustPreg (AOP (result));
9495 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9496 emitcode ("", "!tlabeldef", tlbl->key + 100);
9498 _startLazyDPSEvaluation ();
9501 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
9502 emitcode ("rrc", "a");
9503 aopPut (AOP (result), "a", offset--);
9505 _endLazyDPSEvaluation ();
9506 reAdjustPreg (AOP (result));
9508 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9509 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9512 freeAsmop (left, NULL, ic, TRUE);
9513 freeAsmop (result, NULL, ic, TRUE);
9517 /*-----------------------------------------------------------------*/
9518 /* emitPtrByteGet - emits code to get a byte into A through a */
9519 /* pointer register (R0, R1, or DPTR). The */
9520 /* original value of A can be preserved in B. */
9521 /*-----------------------------------------------------------------*/
9523 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9530 emitcode ("mov", "b,a");
9531 emitcode ("mov", "a,@%s", rname);
9536 emitcode ("mov", "b,a");
9537 emitcode ("movx", "a,@%s", rname);
9542 emitcode ("mov", "b,a");
9543 emitcode ("movx", "a,@dptr");
9548 emitcode ("mov", "b,a");
9549 emitcode ("clr", "a");
9550 emitcode ("movc", "a,@a+dptr");
9556 emitcode ("push", "b");
9557 emitcode ("push", "acc");
9559 emitcode ("lcall", "__gptrget");
9561 emitcode ("pop", "b");
9566 /*-----------------------------------------------------------------*/
9567 /* emitPtrByteSet - emits code to set a byte from src through a */
9568 /* pointer register (R0, R1, or DPTR). */
9569 /*-----------------------------------------------------------------*/
9571 emitPtrByteSet (char *rname, int p_type, char *src)
9580 emitcode ("mov", "@%s,a", rname);
9583 emitcode ("mov", "@%s,%s", rname, src);
9588 emitcode ("movx", "@%s,a", rname);
9593 emitcode ("movx", "@dptr,a");
9598 emitcode ("lcall", "__gptrput");
9603 /*-----------------------------------------------------------------*/
9604 /* genUnpackBits - generates code for unpacking bits */
9605 /*-----------------------------------------------------------------*/
9607 genUnpackBits (operand * result, char *rname, int ptype)
9609 int offset = 0; /* result byte offset */
9610 int rsize; /* result size */
9611 int rlen = 0; /* remaining bitfield length */
9612 sym_link *etype; /* bitfield type information */
9613 int blen; /* bitfield length */
9614 int bstr; /* bitfield starting bit within byte */
9616 D(emitcode ("; genUnpackBits",""));
9618 etype = getSpec (operandType (result));
9619 rsize = getSize (operandType (result));
9620 blen = SPEC_BLEN (etype);
9621 bstr = SPEC_BSTR (etype);
9623 /* If the bitfield length is less than a byte */
9626 emitPtrByteGet (rname, ptype, FALSE);
9628 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
9629 aopPut (AOP (result), "a", offset++);
9633 /* Bit field did not fit in a byte. Copy all
9634 but the partial byte at the end. */
9635 for (rlen=blen;rlen>=8;rlen-=8)
9637 emitPtrByteGet (rname, ptype, FALSE);
9638 aopPut (AOP (result), "a", offset++);
9640 emitcode ("inc", "%s", rname);
9643 /* Handle the partial byte at the end */
9646 emitPtrByteGet (rname, ptype, FALSE);
9647 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
9648 aopPut (AOP (result), "a", offset++);
9656 aopPut (AOP (result), zero, offset++);
9661 /*-----------------------------------------------------------------*/
9662 /* genDataPointerGet - generates code when ptr offset is known */
9663 /*-----------------------------------------------------------------*/
9665 genDataPointerGet (operand * left,
9671 int size, offset = 0;
9672 aopOp (result, ic, TRUE, FALSE);
9674 /* get the string representation of the name */
9675 l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9676 size = AOP_SIZE (result);
9677 _startLazyDPSEvaluation ();
9682 SNPRINTF (buff, sizeof(buff),
9683 "(%s + %d)", l + 1, offset);
9687 SNPRINTF (buff, sizeof(buff),
9690 aopPut (AOP (result), buff, offset++);
9692 _endLazyDPSEvaluation ();
9694 freeAsmop (left, NULL, ic, TRUE);
9695 freeAsmop (result, NULL, ic, TRUE);
9698 /*-----------------------------------------------------------------*/
9699 /* genNearPointerGet - emitcode for near pointer fetch */
9700 /*-----------------------------------------------------------------*/
9702 genNearPointerGet (operand * left,
9710 sym_link *rtype, *retype, *letype;
9711 sym_link *ltype = operandType (left);
9714 rtype = operandType (result);
9715 retype = getSpec (rtype);
9716 letype = getSpec (ltype);
9718 aopOp (left, ic, FALSE, FALSE);
9720 /* if left is rematerialisable and
9721 result is not bitfield variable type and
9722 the left is pointer to data space i.e
9723 lower 128 bytes of space */
9724 if (AOP_TYPE (left) == AOP_IMMD &&
9725 !IS_BITFIELD (retype) &&
9726 !IS_BITFIELD (letype) &&
9727 DCL_TYPE (ltype) == POINTER)
9729 genDataPointerGet (left, result, ic);
9733 /* if the value is already in a pointer register
9734 then don't need anything more */
9735 if (!AOP_INPREG (AOP (left)))
9737 /* otherwise get a free pointer register */
9739 preg = getFreePtr (ic, &aop, FALSE);
9740 emitcode ("mov", "%s,%s",
9742 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9746 rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9748 freeAsmop (left, NULL, ic, TRUE);
9749 aopOp (result, ic, FALSE, FALSE);
9751 /* if bitfield then unpack the bits */
9752 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9753 genUnpackBits (result, rname, POINTER);
9756 /* we have can just get the values */
9757 int size = AOP_SIZE (result);
9762 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9765 emitcode ("mov", "a,@%s", rname);
9766 aopPut (AOP (result), "a", offset);
9770 SNPRINTF (buff, sizeof(buff), "@%s", rname);
9771 aopPut (AOP (result), buff, offset);
9776 emitcode ("inc", "%s", rname);
9781 /* now some housekeeping stuff */
9784 /* we had to allocate for this iCode */
9785 if (pi) { /* post increment present */
9786 aopPut(AOP ( left ),rname,0);
9788 freeAsmop (NULL, aop, ic, TRUE);
9792 /* we did not allocate which means left
9793 already in a pointer register, then
9794 if size > 0 && this could be used again
9795 we have to point it back to where it
9797 if (AOP_SIZE (result) > 1 &&
9798 !OP_SYMBOL (left)->remat &&
9799 (OP_SYMBOL (left)->liveTo > ic->seq ||
9803 int size = AOP_SIZE (result) - 1;
9805 emitcode ("dec", "%s", rname);
9810 freeAsmop (result, NULL, ic, TRUE);
9811 if (pi) pi->generated = 1;
9814 /*-----------------------------------------------------------------*/
9815 /* genPagedPointerGet - emitcode for paged pointer fetch */
9816 /*-----------------------------------------------------------------*/
9818 genPagedPointerGet (operand * left,
9826 sym_link *rtype, *retype, *letype;
9828 rtype = operandType (result);
9829 retype = getSpec (rtype);
9830 letype = getSpec (operandType (left));
9831 aopOp (left, ic, FALSE, FALSE);
9833 /* if the value is already in a pointer register
9834 then don't need anything more */
9835 if (!AOP_INPREG (AOP (left)))
9837 /* otherwise get a free pointer register */
9839 preg = getFreePtr (ic, &aop, FALSE);
9840 emitcode ("mov", "%s,%s",
9842 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9846 rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9848 freeAsmop (left, NULL, ic, TRUE);
9849 aopOp (result, ic, FALSE, FALSE);
9851 /* if bitfield then unpack the bits */
9852 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9853 genUnpackBits (result, rname, PPOINTER);
9856 /* we have can just get the values */
9857 int size = AOP_SIZE (result);
9863 emitcode ("movx", "a,@%s", rname);
9864 aopPut (AOP (result), "a", offset);
9869 emitcode ("inc", "%s", rname);
9873 /* now some housekeeping stuff */
9876 /* we had to allocate for this iCode */
9877 if (pi) aopPut ( AOP (left), rname, 0);
9878 freeAsmop (NULL, aop, ic, TRUE);
9882 /* we did not allocate which means left
9883 already in a pointer register, then
9884 if size > 0 && this could be used again
9885 we have to point it back to where it
9887 if (AOP_SIZE (result) > 1 &&
9888 !OP_SYMBOL (left)->remat &&
9889 (OP_SYMBOL (left)->liveTo > ic->seq ||
9893 int size = AOP_SIZE (result) - 1;
9895 emitcode ("dec", "%s", rname);
9900 freeAsmop (result, NULL, ic, TRUE);
9901 if (pi) pi->generated = 1;
9904 /*-----------------------------------------------------------------*/
9905 /* genFarPointerGet - gget value from far space */
9906 /*-----------------------------------------------------------------*/
9908 genFarPointerGet (operand * left,
9909 operand * result, iCode * ic, iCode *pi)
9911 int size, offset, dopi=1;
9912 sym_link *retype = getSpec (operandType (result));
9913 sym_link *letype = getSpec (operandType (left));
9914 D (emitcode (";", "genFarPointerGet"););
9916 aopOp (left, ic, FALSE, FALSE);
9918 /* if the operand is already in dptr
9919 then we do nothing else we move the value to dptr */
9920 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9922 /* if this is remateriazable */
9923 if (AOP_TYPE (left) == AOP_IMMD)
9925 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9929 /* we need to get it byte by byte */
9930 _startLazyDPSEvaluation ();
9931 if (AOP_TYPE (left) != AOP_DPTR)
9933 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9934 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9935 if (options.model == MODEL_FLAT24)
9936 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9940 /* We need to generate a load to DPTR indirect through DPTR. */
9941 D (emitcode (";", "genFarPointerGet -- indirection special case."););
9942 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9943 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9944 if (options.model == MODEL_FLAT24)
9945 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9946 emitcode ("pop", "dph");
9947 emitcode ("pop", "dpl");
9950 _endLazyDPSEvaluation ();
9953 /* so dptr know contains the address */
9954 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9956 /* if bit then unpack */
9957 if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
9958 if (AOP_INDPTRn(left)) {
9959 genSetDPTR(AOP(left)->aopu.dptr);
9961 genUnpackBits (result, "dptr", FPOINTER);
9962 if (AOP_INDPTRn(left)) {
9967 size = AOP_SIZE (result);
9970 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9972 genSetDPTR(AOP(left)->aopu.dptr);
9973 emitcode ("movx", "a,@dptr");
9974 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9975 emitcode ("inc", "dptr");
9977 aopPut (AOP (result), "a", offset++);
9980 _startLazyDPSEvaluation ();
9982 if (AOP_INDPTRn(left)) {
9983 genSetDPTR(AOP(left)->aopu.dptr);
9989 emitcode ("movx", "a,@dptr");
9990 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9991 emitcode ("inc", "dptr");
9993 aopPut (AOP (result), "a", offset++);
9995 _endLazyDPSEvaluation ();
9998 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9999 if (!AOP_INDPTRn(left)) {
10000 _startLazyDPSEvaluation ();
10001 aopPut ( AOP (left), "dpl", 0);
10002 aopPut ( AOP (left), "dph", 1);
10003 if (options.model == MODEL_FLAT24)
10004 aopPut ( AOP (left), "dpx", 2);
10005 _endLazyDPSEvaluation ();
10008 } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) &&
10009 AOP_SIZE(result) > 1 &&
10011 (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
10013 size = AOP_SIZE (result) - 1;
10014 if (AOP_INDPTRn(left)) {
10015 genSetDPTR(AOP(left)->aopu.dptr);
10017 while (size--) emitcode ("lcall","__decdptr");
10018 if (AOP_INDPTRn(left)) {
10023 freeAsmop (left, NULL, ic, TRUE);
10024 freeAsmop (result, NULL, ic, TRUE);
10027 /*-----------------------------------------------------------------*/
10028 /* genCodePointerGet - get value from code space */
10029 /*-----------------------------------------------------------------*/
10031 genCodePointerGet (operand * left,
10032 operand * result, iCode * ic, iCode *pi)
10034 int size, offset, dopi=1;
10035 sym_link *retype = getSpec (operandType (result));
10037 aopOp (left, ic, FALSE, FALSE);
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 && !AOP_INDPTRn(left))
10043 /* if this is remateriazable */
10044 if (AOP_TYPE (left) == AOP_IMMD)
10046 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
10049 { /* we need to get it byte by byte */
10050 _startLazyDPSEvaluation ();
10051 if (AOP_TYPE (left) != AOP_DPTR)
10053 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10054 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10055 if (options.model == MODEL_FLAT24)
10056 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10060 /* We need to generate a load to DPTR indirect through DPTR. */
10061 D (emitcode (";", "gencodePointerGet -- indirection special case."););
10062 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
10063 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
10064 if (options.model == MODEL_FLAT24)
10065 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10066 emitcode ("pop", "dph");
10067 emitcode ("pop", "dpl");
10070 _endLazyDPSEvaluation ();
10073 /* so dptr know contains the address */
10074 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
10076 /* if bit then unpack */
10077 if (IS_BITFIELD (retype)) {
10078 if (AOP_INDPTRn(left)) {
10079 genSetDPTR(AOP(left)->aopu.dptr);
10081 genUnpackBits (result, "dptr", CPOINTER);
10082 if (AOP_INDPTRn(left)) {
10087 size = AOP_SIZE (result);
10089 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10091 genSetDPTR(AOP(left)->aopu.dptr);
10092 emitcode ("clr", "a");
10093 emitcode ("movc", "a,@a+dptr");
10094 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10095 emitcode ("inc", "dptr");
10097 aopPut (AOP (result), "a", offset++);
10100 _startLazyDPSEvaluation ();
10103 if (AOP_INDPTRn(left)) {
10104 genSetDPTR(AOP(left)->aopu.dptr);
10110 emitcode ("clr", "a");
10111 emitcode ("movc", "a,@a+dptr");
10112 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10113 emitcode ("inc", "dptr");
10114 aopPut (AOP (result), "a", offset++);
10116 _endLazyDPSEvaluation ();
10119 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10120 if (!AOP_INDPTRn(left)) {
10121 _startLazyDPSEvaluation ();
10123 aopPut ( AOP (left), "dpl", 0);
10124 aopPut ( AOP (left), "dph", 1);
10125 if (options.model == MODEL_FLAT24)
10126 aopPut ( AOP (left), "dpx", 2);
10128 _endLazyDPSEvaluation ();
10131 } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
10132 AOP_SIZE(result) > 1 &&
10133 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10135 size = AOP_SIZE (result) - 1;
10136 if (AOP_INDPTRn(left)) {
10137 genSetDPTR(AOP(left)->aopu.dptr);
10139 while (size--) emitcode ("lcall","__decdptr");
10140 if (AOP_INDPTRn(left)) {
10145 freeAsmop (left, NULL, ic, TRUE);
10146 freeAsmop (result, NULL, ic, TRUE);
10149 /*-----------------------------------------------------------------*/
10150 /* genGenPointerGet - gget value from generic pointer space */
10151 /*-----------------------------------------------------------------*/
10153 genGenPointerGet (operand * left,
10154 operand * result, iCode * ic, iCode * pi)
10157 sym_link *retype = getSpec (operandType (result));
10158 sym_link *letype = getSpec (operandType (left));
10160 D (emitcode (";", "genGenPointerGet "); );
10162 aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
10164 /* if the operand is already in dptr
10165 then we do nothing else we move the value to dptr */
10166 if (AOP_TYPE (left) != AOP_STR)
10168 /* if this is remateriazable */
10169 if (AOP_TYPE (left) == AOP_IMMD)
10171 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
10172 if (AOP(left)->aopu.aop_immd.from_cast_remat)
10174 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
10178 emitcode ("mov", "b,#%d", pointerCode (retype));
10182 { /* we need to get it byte by byte */
10183 _startLazyDPSEvaluation ();
10184 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
10185 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
10186 if (options.model == MODEL_FLAT24) {
10187 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
10188 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
10190 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
10192 _endLazyDPSEvaluation ();
10196 /* so dptr-b now contains the address */
10198 aopOp (result, ic, FALSE, TRUE);
10201 /* if bit then unpack */
10202 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10204 genUnpackBits (result, "dptr", GPOINTER);
10208 size = AOP_SIZE (result);
10215 // Get two bytes at a time, results in _AP & A.
10216 // dptr will be incremented ONCE by __gptrgetWord.
10218 // Note: any change here must be coordinated
10219 // with the implementation of __gptrgetWord
10220 // in device/lib/_gptrget.c
10221 emitcode ("lcall", "__gptrgetWord");
10222 aopPut (AOP (result), DP2_RESULT_REG, offset++);
10223 aopPut (AOP (result), "a", offset++);
10228 // Only one byte to get.
10229 emitcode ("lcall", "__gptrget");
10230 aopPut (AOP (result), "a", offset++);
10233 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
10235 emitcode ("inc", "dptr");
10240 if (pi && AOP_TYPE (left) != AOP_IMMD) {
10241 _startLazyDPSEvaluation ();
10243 aopPut ( AOP (left), "dpl", 0);
10244 aopPut ( AOP (left), "dph", 1);
10245 if (options.model == MODEL_FLAT24) {
10246 aopPut ( AOP (left), "dpx", 2);
10247 aopPut ( AOP (left), "b", 3);
10248 } else aopPut ( AOP (left), "b", 2);
10250 _endLazyDPSEvaluation ();
10253 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
10254 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10256 size = AOP_SIZE (result) - 1;
10257 while (size--) emitcode ("lcall","__decdptr");
10260 freeAsmop (left, NULL, ic, TRUE);
10261 freeAsmop (result, NULL, ic, TRUE);
10264 /*-----------------------------------------------------------------*/
10265 /* genPointerGet - generate code for pointer get */
10266 /*-----------------------------------------------------------------*/
10268 genPointerGet (iCode * ic, iCode *pi)
10270 operand *left, *result;
10271 sym_link *type, *etype;
10274 D (emitcode (";", "genPointerGet ");
10277 left = IC_LEFT (ic);
10278 result = IC_RESULT (ic);
10280 /* depending on the type of pointer we need to
10281 move it to the correct pointer register */
10282 type = operandType (left);
10283 etype = getSpec (type);
10284 /* if left is of type of pointer then it is simple */
10285 if (IS_PTR (type) && !IS_FUNC (type->next))
10286 p_type = DCL_TYPE (type);
10289 /* we have to go by the storage class */
10290 p_type = PTR_TYPE (SPEC_OCLS (etype));
10292 /* special case when cast remat */
10293 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10294 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
10295 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10296 type = operandType (left);
10297 p_type = DCL_TYPE (type);
10299 /* now that we have the pointer type we assign
10300 the pointer values */
10306 genNearPointerGet (left, result, ic, pi);
10310 genPagedPointerGet (left, result, ic, pi);
10314 genFarPointerGet (left, result, ic, pi);
10318 genCodePointerGet (left, result, ic, pi);
10322 genGenPointerGet (left, result, ic, pi);
10328 /*-----------------------------------------------------------------*/
10329 /* genPackBits - generates code for packed bit storage */
10330 /*-----------------------------------------------------------------*/
10332 genPackBits (sym_link * etype,
10334 char *rname, int p_type)
10336 int offset = 0; /* source byte offset */
10337 int rlen = 0; /* remaining bitfield length */
10338 int blen; /* bitfield length */
10339 int bstr; /* bitfield starting bit within byte */
10340 int litval; /* source literal value (if AOP_LIT) */
10341 unsigned char mask; /* bitmask within current byte */
10343 D(emitcode ("; genPackBits",""));
10345 blen = SPEC_BLEN (etype);
10346 bstr = SPEC_BSTR (etype);
10348 /* If the bitfield length is less than a byte */
10351 mask = ((unsigned char) (0xFF << (blen + bstr)) |
10352 (unsigned char) (0xFF >> (8 - bstr)));
10354 if (AOP_TYPE (right) == AOP_LIT)
10356 /* Case with a bitfield length <8 and literal source
10358 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10360 litval &= (~mask) & 0xff;
10361 emitPtrByteGet (rname, p_type, FALSE);
10362 if ((mask|litval)!=0xff)
10363 emitcode ("anl","a,#!constbyte", mask);
10365 emitcode ("orl","a,#!constbyte", litval);
10369 if ((blen==1) && (p_type!=GPOINTER))
10371 /* Case with a bitfield length == 1 and no generic pointer
10373 if (AOP_TYPE (right) == AOP_CRY)
10374 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10377 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
10378 emitcode ("rrc","a");
10380 emitPtrByteGet (rname, p_type, FALSE);
10381 emitcode ("mov","acc.%d,c",bstr);
10385 /* Case with a bitfield length < 8 and arbitrary source
10387 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
10388 /* shift and mask source value */
10390 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10392 /* transfer A to B and get next byte */
10393 emitPtrByteGet (rname, p_type, TRUE);
10395 emitcode ("anl", "a,#!constbyte", mask);
10396 emitcode ("orl", "a,b");
10397 if (p_type == GPOINTER)
10398 emitcode ("pop", "b");
10402 emitPtrByteSet (rname, p_type, "a");
10406 /* Bit length is greater than 7 bits. In this case, copy */
10407 /* all except the partial byte at the end */
10408 for (rlen=blen;rlen>=8;rlen-=8)
10410 emitPtrByteSet (rname, p_type,
10411 aopGet (AOP (right), offset++, FALSE, TRUE, NULL) );
10413 emitcode ("inc", "%s", rname);
10416 /* If there was a partial byte at the end */
10419 mask = (((unsigned char) -1 << rlen) & 0xff);
10421 if (AOP_TYPE (right) == AOP_LIT)
10423 /* Case with partial byte and literal source
10425 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10426 litval >>= (blen-rlen);
10427 litval &= (~mask) & 0xff;
10428 emitPtrByteGet (rname, p_type, FALSE);
10429 if ((mask|litval)!=0xff)
10430 emitcode ("anl","a,#!constbyte", mask);
10432 emitcode ("orl","a,#!constbyte", litval);
10436 /* Case with partial byte and arbitrary source
10438 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10439 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10441 /* transfer A to B and get next byte */
10442 emitPtrByteGet (rname, p_type, TRUE);
10444 emitcode ("anl", "a,#!constbyte", mask);
10445 emitcode ("orl", "a,b");
10446 if (p_type == GPOINTER)
10447 emitcode ("pop", "b");
10449 emitPtrByteSet (rname, p_type, "a");
10455 /*-----------------------------------------------------------------*/
10456 /* genDataPointerSet - remat pointer to data space */
10457 /*-----------------------------------------------------------------*/
10459 genDataPointerSet (operand * right,
10463 int size, offset = 0;
10464 char *l, buff[256];
10466 aopOp (right, ic, FALSE, FALSE);
10468 l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
10469 size = AOP_SIZE (right);
10474 SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
10478 SNPRINTF (buff, sizeof(buff), "%s", l + 1);
10481 emitcode ("mov", "%s,%s", buff,
10482 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10485 freeAsmop (right, NULL, ic, TRUE);
10486 freeAsmop (result, NULL, ic, TRUE);
10489 /*-----------------------------------------------------------------*/
10490 /* genNearPointerSet - emitcode for near pointer put */
10491 /*-----------------------------------------------------------------*/
10493 genNearPointerSet (operand * right,
10500 sym_link *retype, *letype;
10501 sym_link *ptype = operandType (result);
10503 retype = getSpec (operandType (right));
10504 letype = getSpec (ptype);
10506 aopOp (result, ic, FALSE, FALSE);
10508 /* if the result is rematerializable &
10509 in data space & not a bit variable */
10510 if (AOP_TYPE (result) == AOP_IMMD &&
10511 DCL_TYPE (ptype) == POINTER &&
10512 !IS_BITVAR (retype) &&
10513 !IS_BITVAR (letype))
10515 genDataPointerSet (right, result, ic);
10519 /* if the value is already in a pointer register
10520 then don't need anything more */
10521 if (!AOP_INPREG (AOP (result)))
10523 /* otherwise get a free pointer register */
10526 aop = newAsmop (0);
10527 preg = getFreePtr (ic, &aop, FALSE);
10528 emitcode ("mov", "%s,%s",
10530 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10531 rname = preg->name;
10534 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10536 aopOp (right, ic, FALSE, FALSE);
10538 /* if bitfield then unpack the bits */
10539 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10540 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10543 /* we have can just get the values */
10544 int size = AOP_SIZE (right);
10549 l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
10553 emitcode ("mov", "@%s,a", rname);
10556 emitcode ("mov", "@%s,%s", rname, l);
10558 emitcode ("inc", "%s", rname);
10563 /* now some housekeeping stuff */
10566 /* we had to allocate for this iCode */
10567 if (pi) aopPut (AOP (result),rname,0);
10568 freeAsmop (NULL, aop, ic, TRUE);
10572 /* we did not allocate which means left
10573 already in a pointer register, then
10574 if size > 0 && this could be used again
10575 we have to point it back to where it
10577 if (AOP_SIZE (right) > 1 &&
10578 !OP_SYMBOL (result)->remat &&
10579 (OP_SYMBOL (result)->liveTo > ic->seq ||
10583 int size = AOP_SIZE (right) - 1;
10585 emitcode ("dec", "%s", rname);
10590 if (pi) pi->generated = 1;
10591 freeAsmop (result, NULL, ic, TRUE);
10592 freeAsmop (right, NULL, ic, TRUE);
10597 /*-----------------------------------------------------------------*/
10598 /* genPagedPointerSet - emitcode for Paged pointer put */
10599 /*-----------------------------------------------------------------*/
10601 genPagedPointerSet (operand * right,
10608 sym_link *retype, *letype;
10610 retype = getSpec (operandType (right));
10611 letype = getSpec (operandType (result));
10613 aopOp (result, ic, FALSE, FALSE);
10615 /* if the value is already in a pointer register
10616 then don't need anything more */
10617 if (!AOP_INPREG (AOP (result)))
10619 /* otherwise get a free pointer register */
10622 aop = newAsmop (0);
10623 preg = getFreePtr (ic, &aop, FALSE);
10624 emitcode ("mov", "%s,%s",
10626 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10627 rname = preg->name;
10630 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10632 aopOp (right, ic, FALSE, FALSE);
10634 /* if bitfield then unpack the bits */
10635 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10636 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10639 /* we have can just get the values */
10640 int size = AOP_SIZE (right);
10645 MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10647 emitcode ("movx", "@%s,a", rname);
10650 emitcode ("inc", "%s", rname);
10656 /* now some housekeeping stuff */
10659 if (pi) aopPut (AOP (result),rname,0);
10660 /* we had to allocate for this iCode */
10661 freeAsmop (NULL, aop, ic, TRUE);
10665 /* we did not allocate which means left
10666 already in a pointer register, then
10667 if size > 0 && this could be used again
10668 we have to point it back to where it
10670 if (AOP_SIZE (right) > 1 &&
10671 !OP_SYMBOL (result)->remat &&
10672 (OP_SYMBOL (result)->liveTo > ic->seq ||
10676 int size = AOP_SIZE (right) - 1;
10678 emitcode ("dec", "%s", rname);
10683 if (pi) pi->generated = 1;
10684 freeAsmop (result, NULL, ic, TRUE);
10685 freeAsmop (right, NULL, ic, TRUE);
10690 /*-----------------------------------------------------------------*/
10691 /* genFarPointerSet - set value from far space */
10692 /*-----------------------------------------------------------------*/
10694 genFarPointerSet (operand * right,
10695 operand * result, iCode * ic, iCode *pi)
10697 int size, offset, dopi=1;
10698 sym_link *retype = getSpec (operandType (right));
10699 sym_link *letype = getSpec (operandType (result));
10701 aopOp (result, ic, FALSE, FALSE);
10703 /* if the operand is already in dptr
10704 then we do nothing else we move the value to dptr */
10705 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10707 /* if this is remateriazable */
10708 if (AOP_TYPE (result) == AOP_IMMD)
10709 emitcode ("mov", "dptr,%s",
10710 aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10713 /* we need to get it byte by byte */
10714 _startLazyDPSEvaluation ();
10715 if (AOP_TYPE (result) != AOP_DPTR)
10717 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10718 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10719 if (options.model == MODEL_FLAT24)
10720 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10724 /* We need to generate a load to DPTR indirect through DPTR. */
10725 D (emitcode (";", "genFarPointerSet -- indirection special case."););
10727 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10728 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10729 if (options.model == MODEL_FLAT24)
10730 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10731 emitcode ("pop", "dph");
10732 emitcode ("pop", "dpl");
10735 _endLazyDPSEvaluation ();
10738 /* so dptr know contains the address */
10739 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10741 /* if bit then unpack */
10742 if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
10743 if (AOP_INDPTRn(result)) {
10744 genSetDPTR(AOP(result)->aopu.dptr);
10746 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10747 if (AOP_INDPTRn(result)) {
10751 size = AOP_SIZE (right);
10753 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10755 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10757 genSetDPTR(AOP(result)->aopu.dptr);
10758 emitcode ("movx", "@dptr,a");
10759 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10760 emitcode ("inc", "dptr");
10764 _startLazyDPSEvaluation ();
10766 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10768 if (AOP_INDPTRn(result)) {
10769 genSetDPTR(AOP(result)->aopu.dptr);
10775 emitcode ("movx", "@dptr,a");
10776 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10777 emitcode ("inc", "dptr");
10779 _endLazyDPSEvaluation ();
10783 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10784 if (!AOP_INDPTRn(result)) {
10785 _startLazyDPSEvaluation ();
10787 aopPut (AOP(result),"dpl",0);
10788 aopPut (AOP(result),"dph",1);
10789 if (options.model == MODEL_FLAT24)
10790 aopPut (AOP(result),"dpx",2);
10792 _endLazyDPSEvaluation ();
10795 } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
10796 AOP_SIZE(right) > 1 &&
10797 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10799 size = AOP_SIZE (right) - 1;
10800 if (AOP_INDPTRn(result)) {
10801 genSetDPTR(AOP(result)->aopu.dptr);
10803 while (size--) emitcode ("lcall","__decdptr");
10804 if (AOP_INDPTRn(result)) {
10808 freeAsmop (result, NULL, ic, TRUE);
10809 freeAsmop (right, NULL, ic, TRUE);
10812 /*-----------------------------------------------------------------*/
10813 /* genGenPointerSet - set value from generic pointer space */
10814 /*-----------------------------------------------------------------*/
10816 genGenPointerSet (operand * right,
10817 operand * result, iCode * ic, iCode *pi)
10820 sym_link *retype = getSpec (operandType (right));
10821 sym_link *letype = getSpec (operandType (result));
10823 aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10825 /* if the operand is already in dptr
10826 then we do nothing else we move the value to dptr */
10827 if (AOP_TYPE (result) != AOP_STR)
10829 _startLazyDPSEvaluation ();
10830 /* if this is remateriazable */
10831 if (AOP_TYPE (result) == AOP_IMMD)
10833 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10834 if (AOP(result)->aopu.aop_immd.from_cast_remat)
10836 MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10841 "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10845 { /* we need to get it byte by byte */
10846 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10847 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10848 if (options.model == MODEL_FLAT24) {
10849 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10850 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10852 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10855 _endLazyDPSEvaluation ();
10857 /* so dptr + b now contains the address */
10859 aopOp (right, ic, FALSE, TRUE);
10863 /* if bit then unpack */
10864 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10866 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10870 size = AOP_SIZE (right);
10873 _startLazyDPSEvaluation ();
10878 // Set two bytes at a time, passed in _AP & A.
10879 // dptr will be incremented ONCE by __gptrputWord.
10881 // Note: any change here must be coordinated
10882 // with the implementation of __gptrputWord
10883 // in device/lib/_gptrput.c
10884 emitcode("mov", "_ap, %s",
10885 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10886 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10890 emitcode ("lcall", "__gptrputWord");
10895 // Only one byte to put.
10896 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10900 emitcode ("lcall", "__gptrput");
10903 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10905 emitcode ("inc", "dptr");
10908 _endLazyDPSEvaluation ();
10911 if (pi && AOP_TYPE (result) != AOP_IMMD) {
10912 _startLazyDPSEvaluation ();
10914 aopPut (AOP(result),"dpl",0);
10915 aopPut (AOP(result),"dph",1);
10916 if (options.model == MODEL_FLAT24) {
10917 aopPut (AOP(result),"dpx",2);
10918 aopPut (AOP(result),"b",3);
10920 aopPut (AOP(result),"b",2);
10922 _endLazyDPSEvaluation ();
10925 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10926 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10928 size = AOP_SIZE (right) - 1;
10929 while (size--) emitcode ("lcall","__decdptr");
10931 freeAsmop (result, NULL, ic, TRUE);
10932 freeAsmop (right, NULL, ic, TRUE);
10935 /*-----------------------------------------------------------------*/
10936 /* genPointerSet - stores the value into a pointer location */
10937 /*-----------------------------------------------------------------*/
10939 genPointerSet (iCode * ic, iCode *pi)
10941 operand *right, *result;
10942 sym_link *type, *etype;
10945 D (emitcode (";", "genPointerSet "););
10947 right = IC_RIGHT (ic);
10948 result = IC_RESULT (ic);
10950 /* depending on the type of pointer we need to
10951 move it to the correct pointer register */
10952 type = operandType (result);
10953 etype = getSpec (type);
10954 /* if left is of type of pointer then it is simple */
10955 if (IS_PTR (type) && !IS_FUNC (type->next))
10957 p_type = DCL_TYPE (type);
10961 /* we have to go by the storage class */
10962 p_type = PTR_TYPE (SPEC_OCLS (etype));
10964 /* special case when cast remat */
10965 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10966 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10967 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10968 type = operandType (result);
10969 p_type = DCL_TYPE (type);
10972 /* now that we have the pointer type we assign
10973 the pointer values */
10979 genNearPointerSet (right, result, ic, pi);
10983 genPagedPointerSet (right, result, ic, pi);
10987 genFarPointerSet (right, result, ic, pi);
10991 genGenPointerSet (right, result, ic, pi);
10995 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10996 "genPointerSet: illegal pointer type");
11001 /*-----------------------------------------------------------------*/
11002 /* genIfx - generate code for Ifx statement */
11003 /*-----------------------------------------------------------------*/
11005 genIfx (iCode * ic, iCode * popIc)
11007 operand *cond = IC_COND (ic);
11010 D (emitcode (";", "genIfx "););
11012 aopOp (cond, ic, FALSE, FALSE);
11014 /* get the value into acc */
11015 if (AOP_TYPE (cond) != AOP_CRY)
11024 /* the result is now in the accumulator */
11025 freeAsmop (cond, NULL, ic, TRUE);
11027 /* if there was something to be popped then do it */
11031 /* if the condition is a bit variable */
11032 if (isbit && IS_ITEMP (cond) &&
11035 genIfxJump (ic, SPIL_LOC (cond)->rname);
11037 else if (isbit && !IS_ITEMP (cond))
11039 genIfxJump (ic, OP_SYMBOL (cond)->rname);
11043 genIfxJump (ic, "a");
11049 /*-----------------------------------------------------------------*/
11050 /* genAddrOf - generates code for address of */
11051 /*-----------------------------------------------------------------*/
11053 genAddrOf (iCode * ic)
11055 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
11058 D (emitcode (";", "genAddrOf ");
11061 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11063 /* if the operand is on the stack then we
11064 need to get the stack offset of this
11066 if (sym->onStack) {
11068 /* if 10 bit stack */
11069 if (options.stack10bit) {
11073 tsprintf(buff, sizeof(buff),
11074 "#!constbyte",(options.stack_loc >> 16) & 0xff);
11075 /* if it has an offset then we need to compute it */
11076 /* emitcode ("subb", "a,#!constbyte", */
11077 /* -((sym->stack < 0) ? */
11078 /* ((short) (sym->stack - _G.nRegsSaved)) : */
11079 /* ((short) sym->stack)) & 0xff); */
11080 /* emitcode ("mov","b,a"); */
11081 /* emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
11082 /* ((short) (sym->stack - _G.nRegsSaved)) : */
11083 /* ((short) sym->stack)) >> 8) & 0xff); */
11085 emitcode ("mov", "a,_bpx");
11086 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
11087 ((char) (sym->stack - _G.nRegsSaved)) :
11088 ((char) sym->stack )) & 0xff);
11089 emitcode ("mov", "b,a");
11090 emitcode ("mov", "a,_bpx+1");
11092 offset = (((sym->stack < 0) ?
11093 ((short) (sym->stack - _G.nRegsSaved)) :
11094 ((short) sym->stack )) >> 8) & 0xff;
11096 emitcode ("addc","a,#!constbyte", offset);
11098 aopPut (AOP (IC_RESULT (ic)), "b", 0);
11099 aopPut (AOP (IC_RESULT (ic)), "a", 1);
11100 aopPut (AOP (IC_RESULT (ic)), buff, 2);
11102 /* we can just move _bp */
11103 aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
11104 aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
11105 aopPut (AOP (IC_RESULT (ic)), buff, 2);
11108 /* if it has an offset then we need to compute it */
11110 emitcode ("mov", "a,_bp");
11111 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
11112 aopPut (AOP (IC_RESULT (ic)), "a", 0);
11114 /* we can just move _bp */
11115 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
11117 /* fill the result with zero */
11118 size = AOP_SIZE (IC_RESULT (ic)) - 1;
11121 if (options.stack10bit && size < (FPTRSIZE - 1)) {
11123 "*** warning: pointer to stack var truncated.\n");
11128 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
11134 /* object not on stack then we need the name */
11135 size = AOP_SIZE (IC_RESULT (ic));
11140 char s[SDCC_NAME_MAX];
11144 tsprintf(s, sizeof(s), "#!his",sym->rname);
11147 tsprintf(s, sizeof(s), "#!hihis",sym->rname);
11150 tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
11152 default: /* should not need this (just in case) */
11153 SNPRINTF (s, sizeof(s), "#(%s >> %d)",
11160 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11163 aopPut (AOP (IC_RESULT (ic)), s, offset++);
11167 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11171 #if 0 // obsolete, and buggy for != xdata
11172 /*-----------------------------------------------------------------*/
11173 /* genArrayInit - generates code for address of */
11174 /*-----------------------------------------------------------------*/
11176 genArrayInit (iCode * ic)
11178 literalList *iLoop;
11180 int elementSize = 0, eIndex;
11181 unsigned val, lastVal;
11183 operand *left=IC_LEFT(ic);
11185 D (emitcode (";", "genArrayInit "););
11187 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
11189 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
11191 // Load immediate value into DPTR.
11192 emitcode("mov", "dptr, %s",
11193 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
11195 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
11198 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11199 "Unexpected operand to genArrayInit.\n");
11202 // a regression because of SDCCcse.c:1.52
11203 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
11204 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
11205 if (options.model == MODEL_FLAT24)
11206 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
11210 type = operandType(IC_LEFT(ic));
11212 if (type && type->next)
11214 elementSize = getSize(type->next);
11218 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11219 "can't determine element size in genArrayInit.\n");
11223 iLoop = IC_ARRAYILIST(ic);
11228 bool firstpass = TRUE;
11230 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
11231 iLoop->count, (int)iLoop->literalValue, elementSize);
11237 symbol *tlbl = NULL;
11239 count = ix > 256 ? 256 : ix;
11243 tlbl = newiTempLabel (NULL);
11244 if (firstpass || (count & 0xff))
11246 emitcode("mov", "b, #!constbyte", count & 0xff);
11249 emitcode ("", "!tlabeldef", tlbl->key + 100);
11254 for (eIndex = 0; eIndex < elementSize; eIndex++)
11256 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
11257 if (val != lastVal)
11259 emitcode("mov", "a, #!constbyte", val);
11263 emitcode("movx", "@dptr, a");
11264 emitcode("inc", "dptr");
11269 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
11275 iLoop = iLoop->next;
11278 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
11282 /*-----------------------------------------------------------------*/
11283 /* genFarFarAssign - assignment when both are in far space */
11284 /*-----------------------------------------------------------------*/
11286 genFarFarAssign (operand * result, operand * right, iCode * ic)
11288 int size = AOP_SIZE (right);
11290 symbol *rSym = NULL;
11294 /* quick & easy case. */
11295 D(emitcode(";","genFarFarAssign (1 byte case)"););
11296 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
11297 freeAsmop (right, NULL, ic, FALSE);
11298 /* now assign DPTR to result */
11300 aopOp(result, ic, FALSE, FALSE);
11302 aopPut(AOP(result), "a", 0);
11303 freeAsmop(result, NULL, ic, FALSE);
11307 /* See if we've got an underlying symbol to abuse. */
11308 if (IS_SYMOP(result) && OP_SYMBOL(result))
11310 if (IS_TRUE_SYMOP(result))
11312 rSym = OP_SYMBOL(result);
11314 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
11316 rSym = OP_SYMBOL(result)->usl.spillLoc;
11320 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
11322 /* We can use the '390 auto-toggle feature to good effect here. */
11324 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
11325 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11326 emitcode ("mov", "dptr,#%s", rSym->rname);
11327 /* DP2 = result, DP1 = right, DP1 is current. */
11330 emitcode("movx", "a,@dptr");
11331 emitcode("movx", "@dptr,a");
11334 emitcode("inc", "dptr");
11335 emitcode("inc", "dptr");
11338 emitcode("mov", "dps,#0");
11339 freeAsmop (right, NULL, ic, FALSE);
11341 some alternative code for processors without auto-toggle
11342 no time to test now, so later well put in...kpb
11343 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
11344 emitcode("mov", "dps,#1"); /* Select DPTR2. */
11345 emitcode ("mov", "dptr,#%s", rSym->rname);
11346 /* DP2 = result, DP1 = right, DP1 is current. */
11350 emitcode("movx", "a,@dptr");
11352 emitcode("inc", "dptr");
11353 emitcode("inc", "dps");
11354 emitcode("movx", "@dptr,a");
11356 emitcode("inc", "dptr");
11357 emitcode("inc", "dps");
11359 emitcode("mov", "dps,#0");
11360 freeAsmop (right, NULL, ic, FALSE);
11365 D (emitcode (";", "genFarFarAssign"););
11366 aopOp (result, ic, TRUE, TRUE);
11368 _startLazyDPSEvaluation ();
11372 aopPut (AOP (result),
11373 aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
11376 _endLazyDPSEvaluation ();
11377 freeAsmop (result, NULL, ic, FALSE);
11378 freeAsmop (right, NULL, ic, FALSE);
11382 /*-----------------------------------------------------------------*/
11383 /* genAssign - generate code for assignment */
11384 /*-----------------------------------------------------------------*/
11386 genAssign (iCode * ic)
11388 operand *result, *right;
11390 unsigned long lit = 0L;
11392 D (emitcode (";", "genAssign ");
11395 result = IC_RESULT (ic);
11396 right = IC_RIGHT (ic);
11398 /* if they are the same */
11399 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11402 aopOp (right, ic, FALSE, FALSE);
11404 emitcode (";", "genAssign: resultIsFar = %s",
11405 isOperandInFarSpace (result) ?
11408 /* special case both in far space */
11409 if ((AOP_TYPE (right) == AOP_DPTR ||
11410 AOP_TYPE (right) == AOP_DPTR2) &&
11411 /* IS_TRUE_SYMOP(result) && */
11412 isOperandInFarSpace (result))
11414 genFarFarAssign (result, right, ic);
11418 aopOp (result, ic, TRUE, FALSE);
11420 /* if they are the same registers */
11421 if (sameRegs (AOP (right), AOP (result)))
11424 /* if the result is a bit */
11425 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
11427 /* if the right size is a literal then
11428 we know what the value is */
11429 if (AOP_TYPE (right) == AOP_LIT)
11431 if (((int) operandLitValue (right)))
11432 aopPut (AOP (result), one, 0);
11434 aopPut (AOP (result), zero, 0);
11438 /* the right is also a bit variable */
11439 if (AOP_TYPE (right) == AOP_CRY)
11441 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11442 aopPut (AOP (result), "c", 0);
11446 /* we need to or */
11448 aopPut (AOP (result), "a", 0);
11452 /* bit variables done */
11454 size = AOP_SIZE (result);
11456 if (AOP_TYPE (right) == AOP_LIT)
11457 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11460 (AOP_TYPE (result) != AOP_REG) &&
11461 (AOP_TYPE (right) == AOP_LIT) &&
11462 !IS_FLOAT (operandType (right)))
11464 _startLazyDPSEvaluation ();
11465 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
11467 aopPut (AOP (result),
11468 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11473 /* And now fill the rest with zeros. */
11476 emitcode ("clr", "a");
11480 aopPut (AOP (result), "a", offset++);
11482 _endLazyDPSEvaluation ();
11486 _startLazyDPSEvaluation ();
11489 aopPut (AOP (result),
11490 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11494 _endLazyDPSEvaluation ();
11498 freeAsmop (right, NULL, ic, FALSE);
11499 freeAsmop (result, NULL, ic, TRUE);
11502 /*-----------------------------------------------------------------*/
11503 /* genJumpTab - generates code for jump table */
11504 /*-----------------------------------------------------------------*/
11506 genJumpTab (iCode * ic)
11511 D (emitcode (";", "genJumpTab ");
11514 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
11515 /* get the condition into accumulator */
11516 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
11518 /* multiply by four! */
11519 emitcode ("add", "a,acc");
11520 emitcode ("add", "a,acc");
11521 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11523 jtab = newiTempLabel (NULL);
11524 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
11525 emitcode ("jmp", "@a+dptr");
11526 emitcode ("", "!tlabeldef", jtab->key + 100);
11527 /* now generate the jump labels */
11528 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11529 jtab = setNextItem (IC_JTLABELS (ic)))
11530 emitcode ("ljmp", "!tlabel", jtab->key + 100);
11534 /*-----------------------------------------------------------------*/
11535 /* genCast - gen code for casting */
11536 /*-----------------------------------------------------------------*/
11538 genCast (iCode * ic)
11540 operand *result = IC_RESULT (ic);
11541 sym_link *ctype = operandType (IC_LEFT (ic));
11542 sym_link *rtype = operandType (IC_RIGHT (ic));
11543 operand *right = IC_RIGHT (ic);
11546 D (emitcode (";", "genCast "););
11548 /* if they are equivalent then do nothing */
11549 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11552 aopOp (right, ic, FALSE, AOP_IS_STR (result));
11553 aopOp (result, ic, FALSE, (AOP_TYPE(right) == AOP_DPTR));
11555 /* if the result is a bit */
11556 if (IS_BITVAR (OP_SYMBOL (result)->type)
11557 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
11559 /* if the right size is a literal then
11560 we know what the value is */
11561 if (AOP_TYPE (right) == AOP_LIT)
11563 if (((int) operandLitValue (right)))
11564 aopPut (AOP (result), one, 0);
11566 aopPut (AOP (result), zero, 0);
11571 /* the right is also a bit variable */
11572 if (AOP_TYPE (right) == AOP_CRY)
11574 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11575 aopPut (AOP (result), "c", 0);
11579 /* we need to or */
11581 aopPut (AOP (result), "a", 0);
11585 /* if they are the same size : or less */
11586 if (AOP_SIZE (result) <= AOP_SIZE (right))
11589 /* if they are in the same place */
11590 if (sameRegs (AOP (right), AOP (result)))
11593 /* if they in different places then copy */
11594 size = AOP_SIZE (result);
11596 _startLazyDPSEvaluation ();
11599 aopPut (AOP (result),
11600 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11604 _endLazyDPSEvaluation ();
11609 /* if the result is of type pointer */
11610 if (IS_PTR (ctype))
11614 sym_link *type = operandType (right);
11616 /* pointer to generic pointer */
11617 if (IS_GENPTR (ctype))
11621 p_type = DCL_TYPE (type);
11625 #if OLD_CAST_BEHAVIOR
11626 /* KV: we are converting a non-pointer type to
11627 * a generic pointer. This (ifdef'd out) code
11628 * says that the resulting generic pointer
11629 * should have the same class as the storage
11630 * location of the non-pointer variable.
11632 * For example, converting an int (which happens
11633 * to be stored in DATA space) to a pointer results
11634 * in a DATA generic pointer; if the original int
11635 * in XDATA space, so will be the resulting pointer.
11637 * I don't like that behavior, and thus this change:
11638 * all such conversions will be forced to XDATA and
11639 * throw a warning. If you want some non-XDATA
11640 * type, or you want to suppress the warning, you
11641 * must go through an intermediate cast, like so:
11643 * char _generic *gp = (char _xdata *)(intVar);
11645 sym_link *etype = getSpec (type);
11647 /* we have to go by the storage class */
11648 if (SPEC_OCLS (etype) != generic)
11650 p_type = PTR_TYPE (SPEC_OCLS (etype));
11655 /* Converting unknown class (i.e. register variable)
11656 * to generic pointer. This is not good, but
11657 * we'll make a guess (and throw a warning).
11660 werror (W_INT_TO_GEN_PTR_CAST);
11664 /* the first two bytes are known */
11665 size = GPTRSIZE - 1;
11667 _startLazyDPSEvaluation ();
11670 aopPut (AOP (result),
11671 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11675 _endLazyDPSEvaluation ();
11677 /* the last byte depending on type */
11679 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11684 // pointerTypeToGPByte will have bitched.
11688 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11689 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11694 /* just copy the pointers */
11695 size = AOP_SIZE (result);
11697 _startLazyDPSEvaluation ();
11700 aopPut (AOP (result),
11701 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11705 _endLazyDPSEvaluation ();
11709 /* so we now know that the size of destination is greater
11710 than the size of the source */
11711 /* we move to result for the size of source */
11712 size = AOP_SIZE (right);
11714 _startLazyDPSEvaluation ();
11717 aopPut (AOP (result),
11718 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11722 _endLazyDPSEvaluation ();
11724 /* now depending on the sign of the source && destination */
11725 size = AOP_SIZE (result) - AOP_SIZE (right);
11726 /* if unsigned or not an integral type */
11727 /* also, if the source is a bit, we don't need to sign extend, because
11728 * it can't possibly have set the sign bit.
11730 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
11734 aopPut (AOP (result), zero, offset++);
11739 /* we need to extend the sign :{ */
11740 MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11741 FALSE, FALSE, NULL));
11742 emitcode ("rlc", "a");
11743 emitcode ("subb", "a,acc");
11745 aopPut (AOP (result), "a", offset++);
11748 /* we are done hurray !!!! */
11751 freeAsmop (right, NULL, ic, TRUE);
11752 freeAsmop (result, NULL, ic, TRUE);
11756 /*-----------------------------------------------------------------*/
11757 /* genDjnz - generate decrement & jump if not zero instrucion */
11758 /*-----------------------------------------------------------------*/
11760 genDjnz (iCode * ic, iCode * ifx)
11762 symbol *lbl, *lbl1;
11766 /* if the if condition has a false label
11767 then we cannot save */
11768 if (IC_FALSE (ifx))
11771 /* if the minus is not of the form
11773 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11774 !IS_OP_LITERAL (IC_RIGHT (ic)))
11777 if (operandLitValue (IC_RIGHT (ic)) != 1)
11780 /* if the size of this greater than one then no
11782 if (getSize (operandType (IC_RESULT (ic))) > 1)
11785 /* otherwise we can save BIG */
11786 D(emitcode(";", "genDjnz"););
11788 lbl = newiTempLabel (NULL);
11789 lbl1 = newiTempLabel (NULL);
11791 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11793 if (AOP_NEEDSACC(IC_RESULT(ic)))
11795 /* If the result is accessed indirectly via
11796 * the accumulator, we must explicitly write
11797 * it back after the decrement.
11799 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11801 if (strcmp(rByte, "a"))
11803 /* Something is hopelessly wrong */
11804 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11805 __FILE__, __LINE__);
11806 /* We can just give up; the generated code will be inefficient,
11807 * but what the hey.
11809 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11812 emitcode ("dec", "%s", rByte);
11813 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11814 emitcode ("jnz", "!tlabel", lbl->key + 100);
11816 else if (IS_AOP_PREG (IC_RESULT (ic)))
11818 emitcode ("dec", "%s",
11819 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11820 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11821 emitcode ("jnz", "!tlabel", lbl->key + 100);
11825 emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11828 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11829 emitcode ("", "!tlabeldef", lbl->key + 100);
11830 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11831 emitcode ("", "!tlabeldef", lbl1->key + 100);
11833 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11834 ifx->generated = 1;
11838 /*-----------------------------------------------------------------*/
11839 /* genReceive - generate code for a receive iCode */
11840 /*-----------------------------------------------------------------*/
11842 genReceive (iCode * ic)
11844 int size = getSize (operandType (IC_RESULT (ic)));
11848 D (emitcode (";", "genReceive "););
11850 if (ic->argreg == 1)
11852 /* first parameter */
11853 if (AOP_IS_STR(IC_RESULT(ic)))
11855 /* Nothing to do: it's already in the proper place. */
11862 useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11863 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11864 IS_TRUE_SYMOP (IC_RESULT (ic)));
11867 aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11870 /* Sanity checking... */
11871 if (AOP_USESDPTR(IC_RESULT(ic)))
11873 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11874 "genReceive got unexpected DPTR.");
11876 assignResultValue (IC_RESULT (ic));
11881 /* second receive onwards */
11882 /* this gets a little tricky since unused recevies will be
11883 eliminated, we have saved the reg in the type field . and
11884 we use that to figure out which register to use */
11885 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11886 rb1off = ic->argreg;
11889 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11892 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11895 /*-----------------------------------------------------------------*/
11896 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
11897 /*-----------------------------------------------------------------*/
11898 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11900 operand *from , *to , *count;
11905 /* we know it has to be 3 parameters */
11906 assert (nparms == 3);
11908 rsave = newBitVect(16);
11909 /* save DPTR if it needs to be saved */
11910 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11911 if (bitVectBitValue(ic->rMask,i))
11912 rsave = bitVectSetBit(rsave,i);
11914 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11915 ds390_rUmaskForOp (IC_RESULT(ic))));
11922 aopOp (from, ic->next, FALSE, FALSE);
11924 /* get from into DPTR1 */
11925 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11926 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11927 if (options.model == MODEL_FLAT24) {
11928 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11931 freeAsmop (from, NULL, ic, FALSE);
11932 aopOp (to, ic, FALSE, FALSE);
11933 /* get "to" into DPTR */
11934 /* if the operand is already in dptr
11935 then we do nothing else we move the value to dptr */
11936 if (AOP_TYPE (to) != AOP_STR) {
11937 /* if already in DPTR then we need to push */
11938 if (AOP_TYPE(to) == AOP_DPTR) {
11939 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11940 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11941 if (options.model == MODEL_FLAT24)
11942 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11943 emitcode ("pop", "dph");
11944 emitcode ("pop", "dpl");
11946 _startLazyDPSEvaluation ();
11947 /* if this is remateriazable */
11948 if (AOP_TYPE (to) == AOP_IMMD) {
11949 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11950 } else { /* we need to get it byte by byte */
11951 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11952 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11953 if (options.model == MODEL_FLAT24) {
11954 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11957 _endLazyDPSEvaluation ();
11960 freeAsmop (to, NULL, ic, FALSE);
11961 _G.dptrInUse = _G.dptr1InUse = 1;
11962 aopOp (count, ic->next->next, FALSE,FALSE);
11963 lbl =newiTempLabel(NULL);
11965 /* now for the actual copy */
11966 if (AOP_TYPE(count) == AOP_LIT &&
11967 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11968 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11970 emitcode ("lcall","__bi_memcpyc2x_s");
11972 emitcode ("lcall","__bi_memcpyx2x_s");
11974 freeAsmop (count, NULL, ic, FALSE);
11976 symbol *lbl1 = newiTempLabel(NULL);
11978 emitcode (";"," Auto increment but no djnz");
11979 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11980 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11981 freeAsmop (count, NULL, ic, FALSE);
11982 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11983 emitcode ("","!tlabeldef",lbl->key+100);
11985 emitcode ("clr","a");
11986 emitcode ("movc", "a,@a+dptr");
11988 emitcode ("movx", "a,@dptr");
11989 emitcode ("movx", "@dptr,a");
11990 emitcode ("inc", "dptr");
11991 emitcode ("inc", "dptr");
11992 emitcode ("mov","a,b");
11993 emitcode ("orl","a,_ap");
11994 emitcode ("jz","!tlabel",lbl1->key+100);
11995 emitcode ("mov","a,_ap");
11996 emitcode ("add","a,#!constbyte",0xFF);
11997 emitcode ("mov","_ap,a");
11998 emitcode ("mov","a,b");
11999 emitcode ("addc","a,#!constbyte",0xFF);
12000 emitcode ("mov","b,a");
12001 emitcode ("sjmp","!tlabel",lbl->key+100);
12002 emitcode ("","!tlabeldef",lbl1->key+100);
12004 emitcode ("mov", "dps,#0");
12005 _G.dptrInUse = _G.dptr1InUse = 0;
12006 unsavermask(rsave);
12010 /*-----------------------------------------------------------------*/
12011 /* genMemcmpX2X - gen code for memcmp xdata to xdata */
12012 /*-----------------------------------------------------------------*/
12013 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
12015 operand *from , *to , *count;
12020 /* we know it has to be 3 parameters */
12021 assert (nparms == 3);
12023 rsave = newBitVect(16);
12024 /* save DPTR if it needs to be saved */
12025 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12026 if (bitVectBitValue(ic->rMask,i))
12027 rsave = bitVectSetBit(rsave,i);
12029 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12030 ds390_rUmaskForOp (IC_RESULT(ic))));
12037 aopOp (from, ic->next, FALSE, FALSE);
12039 /* get from into DPTR1 */
12040 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12041 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12042 if (options.model == MODEL_FLAT24) {
12043 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12046 freeAsmop (from, NULL, ic, FALSE);
12047 aopOp (to, ic, FALSE, FALSE);
12048 /* get "to" into DPTR */
12049 /* if the operand is already in dptr
12050 then we do nothing else we move the value to dptr */
12051 if (AOP_TYPE (to) != AOP_STR) {
12052 /* if already in DPTR then we need to push */
12053 if (AOP_TYPE(to) == AOP_DPTR) {
12054 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12055 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12056 if (options.model == MODEL_FLAT24)
12057 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12058 emitcode ("pop", "dph");
12059 emitcode ("pop", "dpl");
12061 _startLazyDPSEvaluation ();
12062 /* if this is remateriazable */
12063 if (AOP_TYPE (to) == AOP_IMMD) {
12064 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12065 } else { /* we need to get it byte by byte */
12066 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12067 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12068 if (options.model == MODEL_FLAT24) {
12069 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12072 _endLazyDPSEvaluation ();
12075 freeAsmop (to, NULL, ic, FALSE);
12076 _G.dptrInUse = _G.dptr1InUse = 1;
12077 aopOp (count, ic->next->next, FALSE,FALSE);
12078 lbl =newiTempLabel(NULL);
12079 lbl2 =newiTempLabel(NULL);
12081 /* now for the actual compare */
12082 if (AOP_TYPE(count) == AOP_LIT &&
12083 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12084 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12086 emitcode("lcall","__bi_memcmpc2x_s");
12088 emitcode("lcall","__bi_memcmpx2x_s");
12089 freeAsmop (count, NULL, ic, FALSE);
12090 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12091 aopPut(AOP(IC_RESULT(ic)),"a",0);
12092 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12094 symbol *lbl1 = newiTempLabel(NULL);
12096 emitcode("push","ar0");
12097 emitcode (";"," Auto increment but no djnz");
12098 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12099 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12100 freeAsmop (count, NULL, ic, FALSE);
12101 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12102 emitcode ("","!tlabeldef",lbl->key+100);
12104 emitcode ("clr","a");
12105 emitcode ("movc", "a,@a+dptr");
12107 emitcode ("movx", "a,@dptr");
12108 emitcode ("mov","r0,a");
12109 emitcode ("movx", "a,@dptr");
12110 emitcode ("clr","c");
12111 emitcode ("subb","a,r0");
12112 emitcode ("jnz","!tlabel",lbl2->key+100);
12113 emitcode ("inc", "dptr");
12114 emitcode ("inc", "dptr");
12115 emitcode ("mov","a,b");
12116 emitcode ("orl","a,_ap");
12117 emitcode ("jz","!tlabel",lbl1->key+100);
12118 emitcode ("mov","a,_ap");
12119 emitcode ("add","a,#!constbyte",0xFF);
12120 emitcode ("mov","_ap,a");
12121 emitcode ("mov","a,b");
12122 emitcode ("addc","a,#!constbyte",0xFF);
12123 emitcode ("mov","b,a");
12124 emitcode ("sjmp","!tlabel",lbl->key+100);
12125 emitcode ("","!tlabeldef",lbl1->key+100);
12126 emitcode ("clr","a");
12127 emitcode ("","!tlabeldef",lbl2->key+100);
12128 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12129 aopPut(AOP(IC_RESULT(ic)),"a",0);
12130 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12131 emitcode("pop","ar0");
12132 emitcode ("mov", "dps,#0");
12134 _G.dptrInUse = _G.dptr1InUse = 0;
12135 unsavermask(rsave);
12139 /*-----------------------------------------------------------------*/
12140 /* genInp - gen code for __builtin_inp read data from a mem mapped */
12141 /* port, first parameter output area second parameter pointer to */
12142 /* port third parameter count */
12143 /*-----------------------------------------------------------------*/
12144 static void genInp( iCode *ic, int nparms, operand **parms)
12146 operand *from , *to , *count;
12151 /* we know it has to be 3 parameters */
12152 assert (nparms == 3);
12154 rsave = newBitVect(16);
12155 /* save DPTR if it needs to be saved */
12156 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12157 if (bitVectBitValue(ic->rMask,i))
12158 rsave = bitVectSetBit(rsave,i);
12160 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12161 ds390_rUmaskForOp (IC_RESULT(ic))));
12168 aopOp (from, ic->next, FALSE, FALSE);
12170 /* get from into DPTR1 */
12171 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12172 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12173 if (options.model == MODEL_FLAT24) {
12174 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12177 freeAsmop (from, NULL, ic, FALSE);
12178 aopOp (to, ic, FALSE, FALSE);
12179 /* get "to" into DPTR */
12180 /* if the operand is already in dptr
12181 then we do nothing else we move the value to dptr */
12182 if (AOP_TYPE (to) != AOP_STR) {
12183 /* if already in DPTR then we need to push */
12184 if (AOP_TYPE(to) == AOP_DPTR) {
12185 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12186 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12187 if (options.model == MODEL_FLAT24)
12188 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12189 emitcode ("pop", "dph");
12190 emitcode ("pop", "dpl");
12192 _startLazyDPSEvaluation ();
12193 /* if this is remateriazable */
12194 if (AOP_TYPE (to) == AOP_IMMD) {
12195 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12196 } else { /* we need to get it byte by byte */
12197 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12198 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12199 if (options.model == MODEL_FLAT24) {
12200 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12203 _endLazyDPSEvaluation ();
12206 freeAsmop (to, NULL, ic, FALSE);
12208 _G.dptrInUse = _G.dptr1InUse = 1;
12209 aopOp (count, ic->next->next, FALSE,FALSE);
12210 lbl =newiTempLabel(NULL);
12212 /* now for the actual copy */
12213 if (AOP_TYPE(count) == AOP_LIT &&
12214 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12215 emitcode (";","OH JOY auto increment with djnz (very fast)");
12216 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
12217 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12218 freeAsmop (count, NULL, ic, FALSE);
12219 emitcode ("","!tlabeldef",lbl->key+100);
12220 emitcode ("movx", "a,@dptr"); /* read data from port */
12221 emitcode ("dec","dps"); /* switch to DPTR */
12222 emitcode ("movx", "@dptr,a"); /* save into location */
12223 emitcode ("inc", "dptr"); /* point to next area */
12224 emitcode ("inc","dps"); /* switch to DPTR2 */
12225 emitcode ("djnz","b,!tlabel",lbl->key+100);
12227 symbol *lbl1 = newiTempLabel(NULL);
12229 emitcode (";"," Auto increment but no djnz");
12230 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12231 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12232 freeAsmop (count, NULL, ic, FALSE);
12233 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
12234 emitcode ("","!tlabeldef",lbl->key+100);
12235 emitcode ("movx", "a,@dptr");
12236 emitcode ("dec","dps"); /* switch to DPTR */
12237 emitcode ("movx", "@dptr,a");
12238 emitcode ("inc", "dptr");
12239 emitcode ("inc","dps"); /* switch to DPTR2 */
12240 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
12241 /* emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
12242 emitcode ("mov","a,b");
12243 emitcode ("orl","a,_ap");
12244 emitcode ("jz","!tlabel",lbl1->key+100);
12245 emitcode ("mov","a,_ap");
12246 emitcode ("add","a,#!constbyte",0xFF);
12247 emitcode ("mov","_ap,a");
12248 emitcode ("mov","a,b");
12249 emitcode ("addc","a,#!constbyte",0xFF);
12250 emitcode ("mov","b,a");
12251 emitcode ("sjmp","!tlabel",lbl->key+100);
12252 emitcode ("","!tlabeldef",lbl1->key+100);
12254 emitcode ("mov", "dps,#0");
12255 _G.dptrInUse = _G.dptr1InUse = 0;
12256 unsavermask(rsave);
12260 /*-----------------------------------------------------------------*/
12261 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
12262 /* port, first parameter output area second parameter pointer to */
12263 /* port third parameter count */
12264 /*-----------------------------------------------------------------*/
12265 static void genOutp( iCode *ic, int nparms, operand **parms)
12267 operand *from , *to , *count;
12272 /* we know it has to be 3 parameters */
12273 assert (nparms == 3);
12275 rsave = newBitVect(16);
12276 /* save DPTR if it needs to be saved */
12277 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12278 if (bitVectBitValue(ic->rMask,i))
12279 rsave = bitVectSetBit(rsave,i);
12281 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12282 ds390_rUmaskForOp (IC_RESULT(ic))));
12289 aopOp (from, ic->next, FALSE, FALSE);
12291 /* get from into DPTR1 */
12292 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12293 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12294 if (options.model == MODEL_FLAT24) {
12295 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12298 freeAsmop (from, NULL, ic, FALSE);
12299 aopOp (to, ic, FALSE, FALSE);
12300 /* get "to" into DPTR */
12301 /* if the operand is already in dptr
12302 then we do nothing else we move the value to dptr */
12303 if (AOP_TYPE (to) != AOP_STR) {
12304 /* if already in DPTR then we need to push */
12305 if (AOP_TYPE(to) == AOP_DPTR) {
12306 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12307 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12308 if (options.model == MODEL_FLAT24)
12309 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12310 emitcode ("pop", "dph");
12311 emitcode ("pop", "dpl");
12313 _startLazyDPSEvaluation ();
12314 /* if this is remateriazable */
12315 if (AOP_TYPE (to) == AOP_IMMD) {
12316 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12317 } else { /* we need to get it byte by byte */
12318 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12319 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12320 if (options.model == MODEL_FLAT24) {
12321 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12324 _endLazyDPSEvaluation ();
12327 freeAsmop (to, NULL, ic, FALSE);
12329 _G.dptrInUse = _G.dptr1InUse = 1;
12330 aopOp (count, ic->next->next, FALSE,FALSE);
12331 lbl =newiTempLabel(NULL);
12333 /* now for the actual copy */
12334 if (AOP_TYPE(count) == AOP_LIT &&
12335 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12336 emitcode (";","OH JOY auto increment with djnz (very fast)");
12337 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
12338 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12339 emitcode ("","!tlabeldef",lbl->key+100);
12340 emitcode ("movx", "a,@dptr"); /* read data from port */
12341 emitcode ("inc","dps"); /* switch to DPTR2 */
12342 emitcode ("movx", "@dptr,a"); /* save into location */
12343 emitcode ("inc", "dptr"); /* point to next area */
12344 emitcode ("dec","dps"); /* switch to DPTR */
12345 emitcode ("djnz","b,!tlabel",lbl->key+100);
12346 freeAsmop (count, NULL, ic, FALSE);
12348 symbol *lbl1 = newiTempLabel(NULL);
12350 emitcode (";"," Auto increment but no djnz");
12351 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12352 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12353 freeAsmop (count, NULL, ic, FALSE);
12354 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
12355 emitcode ("","!tlabeldef",lbl->key+100);
12356 emitcode ("movx", "a,@dptr");
12357 emitcode ("inc", "dptr");
12358 emitcode ("inc","dps"); /* switch to DPTR2 */
12359 emitcode ("movx", "@dptr,a");
12360 emitcode ("dec","dps"); /* switch to 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 emitcode ("mov", "dps,#0");
12374 _G.dptrInUse = _G.dptr1InUse = 0;
12375 unsavermask(rsave);
12379 /*-----------------------------------------------------------------*/
12380 /* genSwapW - swap lower & high order bytes */
12381 /*-----------------------------------------------------------------*/
12382 static void genSwapW(iCode *ic, int nparms, operand **parms)
12386 assert (nparms==1);
12389 dest=IC_RESULT(ic);
12391 assert(getSize(operandType(src))==2);
12393 aopOp (src, ic, FALSE, FALSE);
12394 emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
12396 MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
12398 freeAsmop (src, NULL, ic, FALSE);
12400 aopOp (dest,ic, FALSE, FALSE);
12401 aopPut(AOP(dest),"b",0);
12402 aopPut(AOP(dest),"a",1);
12403 freeAsmop (dest, NULL, ic, FALSE);
12406 /*-----------------------------------------------------------------*/
12407 /* genMemsetX - gencode for memSetX data */
12408 /*-----------------------------------------------------------------*/
12409 static void genMemsetX(iCode *ic, int nparms, operand **parms)
12411 operand *to , *val , *count;
12417 /* we know it has to be 3 parameters */
12418 assert (nparms == 3);
12424 /* save DPTR if it needs to be saved */
12425 rsave = newBitVect(16);
12426 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12427 if (bitVectBitValue(ic->rMask,i))
12428 rsave = bitVectSetBit(rsave,i);
12430 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12431 ds390_rUmaskForOp (IC_RESULT(ic))));
12434 aopOp (to, ic, FALSE, FALSE);
12435 /* get "to" into DPTR */
12436 /* if the operand is already in dptr
12437 then we do nothing else we move the value to dptr */
12438 if (AOP_TYPE (to) != AOP_STR) {
12439 /* if already in DPTR then we need to push */
12440 if (AOP_TYPE(to) == AOP_DPTR) {
12441 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12442 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12443 if (options.model == MODEL_FLAT24)
12444 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12445 emitcode ("pop", "dph");
12446 emitcode ("pop", "dpl");
12448 _startLazyDPSEvaluation ();
12449 /* if this is remateriazable */
12450 if (AOP_TYPE (to) == AOP_IMMD) {
12451 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12452 } else { /* we need to get it byte by byte */
12453 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12454 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12455 if (options.model == MODEL_FLAT24) {
12456 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12459 _endLazyDPSEvaluation ();
12462 freeAsmop (to, NULL, ic, FALSE);
12464 aopOp (val, ic->next->next, FALSE,FALSE);
12465 aopOp (count, ic->next->next, FALSE,FALSE);
12466 lbl =newiTempLabel(NULL);
12467 /* now for the actual copy */
12468 if (AOP_TYPE(count) == AOP_LIT &&
12469 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12470 l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
12471 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12473 emitcode ("","!tlabeldef",lbl->key+100);
12474 emitcode ("movx", "@dptr,a");
12475 emitcode ("inc", "dptr");
12476 emitcode ("djnz","b,!tlabel",lbl->key+100);
12478 symbol *lbl1 = newiTempLabel(NULL);
12480 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12481 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12482 emitcode ("","!tlabeldef",lbl->key+100);
12483 MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
12484 emitcode ("movx", "@dptr,a");
12485 emitcode ("inc", "dptr");
12486 emitcode ("mov","a,b");
12487 emitcode ("orl","a,_ap");
12488 emitcode ("jz","!tlabel",lbl1->key+100);
12489 emitcode ("mov","a,_ap");
12490 emitcode ("add","a,#!constbyte",0xFF);
12491 emitcode ("mov","_ap,a");
12492 emitcode ("mov","a,b");
12493 emitcode ("addc","a,#!constbyte",0xFF);
12494 emitcode ("mov","b,a");
12495 emitcode ("sjmp","!tlabel",lbl->key+100);
12496 emitcode ("","!tlabeldef",lbl1->key+100);
12498 freeAsmop (count, NULL, ic, FALSE);
12499 unsavermask(rsave);
12502 /*-----------------------------------------------------------------*/
12503 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
12504 /*-----------------------------------------------------------------*/
12505 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
12508 operand *pnum, *result;
12511 assert (nparms==1);
12512 /* save registers that need to be saved */
12513 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12514 ds390_rUmaskForOp (IC_RESULT(ic))));
12517 aopOp (pnum, ic, FALSE, FALSE);
12518 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12519 freeAsmop (pnum, NULL, ic, FALSE);
12520 emitcode ("lcall","NatLib_LoadPrimitive");
12521 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12522 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
12523 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
12524 for (i = (size-1) ; i >= 0 ; i-- ) {
12525 emitcode ("push","a%s",javaRet[i]);
12527 for (i=0; i < size ; i++ ) {
12528 emitcode ("pop","a%s",
12529 aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
12532 for (i = 0 ; i < size ; i++ ) {
12533 aopPut(AOP(result),javaRet[i],i);
12536 freeAsmop (result, NULL, ic, FALSE);
12537 unsavermask(rsave);
12540 /*-----------------------------------------------------------------*/
12541 /* genNatLibLoadPointer - calls TINI api function to load pointer */
12542 /*-----------------------------------------------------------------*/
12543 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
12546 operand *pnum, *result;
12550 assert (nparms==1);
12551 /* save registers that need to be saved */
12552 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12553 ds390_rUmaskForOp (IC_RESULT(ic))));
12556 aopOp (pnum, ic, FALSE, FALSE);
12557 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12558 freeAsmop (pnum, NULL, ic, FALSE);
12559 emitcode ("lcall","NatLib_LoadPointer");
12560 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12561 if (AOP_TYPE(result)!=AOP_STR) {
12562 for (i = 0 ; i < size ; i++ ) {
12563 aopPut(AOP(result),fReturn[i],i);
12566 freeAsmop (result, NULL, ic, FALSE);
12567 unsavermask(rsave);
12570 /*-----------------------------------------------------------------*/
12571 /* genNatLibInstallStateBlock - */
12572 /*-----------------------------------------------------------------*/
12573 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
12574 operand **parms, const char *name)
12577 operand *psb, *handle;
12578 assert (nparms==2);
12580 /* save registers that need to be saved */
12581 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12582 ds390_rUmaskForOp (IC_RESULT(ic))));
12586 /* put pointer to state block into DPTR1 */
12587 aopOp (psb, ic, FALSE, FALSE);
12588 if (AOP_TYPE (psb) == AOP_IMMD) {
12589 emitcode ("mov","dps,#1");
12590 emitcode ("mov", "dptr,%s",
12591 aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12592 emitcode ("mov","dps,#0");
12594 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12595 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12596 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12598 freeAsmop (psb, NULL, ic, FALSE);
12600 /* put libraryID into DPTR */
12601 emitcode ("mov","dptr,#LibraryID");
12603 /* put handle into r3:r2 */
12604 aopOp (handle, ic, FALSE, FALSE);
12605 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12606 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12607 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12608 emitcode ("pop","ar3");
12609 emitcode ("pop","ar2");
12611 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12612 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12614 freeAsmop (psb, NULL, ic, FALSE);
12616 /* make the call */
12617 emitcode ("lcall","NatLib_Install%sStateBlock",name);
12619 /* put return value into place*/
12621 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12623 aopPut(AOP(IC_RESULT(ic)),"a",0);
12624 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12625 unsavermask(rsave);
12628 /*-----------------------------------------------------------------*/
12629 /* genNatLibRemoveStateBlock - */
12630 /*-----------------------------------------------------------------*/
12631 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12637 /* save registers that need to be saved */
12638 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12639 ds390_rUmaskForOp (IC_RESULT(ic))));
12641 /* put libraryID into DPTR */
12642 emitcode ("mov","dptr,#LibraryID");
12643 /* make the call */
12644 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12645 unsavermask(rsave);
12648 /*-----------------------------------------------------------------*/
12649 /* genNatLibGetStateBlock - */
12650 /*-----------------------------------------------------------------*/
12651 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12652 operand **parms,const char *name)
12655 symbol *lbl = newiTempLabel(NULL);
12658 /* save registers that need to be saved */
12659 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12660 ds390_rUmaskForOp (IC_RESULT(ic))));
12662 /* put libraryID into DPTR */
12663 emitcode ("mov","dptr,#LibraryID");
12664 /* make the call */
12665 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12666 emitcode ("jnz","!tlabel",lbl->key+100);
12668 /* put return value into place */
12669 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12670 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12671 emitcode ("push","ar3");
12672 emitcode ("push","ar2");
12673 emitcode ("pop","%s",
12674 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12675 emitcode ("pop","%s",
12676 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12678 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12679 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12681 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12682 emitcode ("","!tlabeldef",lbl->key+100);
12683 unsavermask(rsave);
12686 /*-----------------------------------------------------------------*/
12687 /* genMMMalloc - */
12688 /*-----------------------------------------------------------------*/
12689 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12690 int size, const char *name)
12695 symbol *lbl = newiTempLabel(NULL);
12697 assert (nparms == 1);
12698 /* save registers that need to be saved */
12699 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12700 ds390_rUmaskForOp (IC_RESULT(ic))));
12703 aopOp (bsize,ic,FALSE,FALSE);
12705 /* put the size in R4-R2 */
12706 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12707 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12708 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12710 emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12711 emitcode("pop","ar4");
12713 emitcode("pop","ar3");
12714 emitcode("pop","ar2");
12716 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12717 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12719 emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12722 freeAsmop (bsize, NULL, ic, FALSE);
12724 /* make the call */
12725 emitcode ("lcall","MM_%s",name);
12726 emitcode ("jz","!tlabel",lbl->key+100);
12727 emitcode ("mov","r2,#!constbyte",0xff);
12728 emitcode ("mov","r3,#!constbyte",0xff);
12729 emitcode ("","!tlabeldef",lbl->key+100);
12730 /* we don't care about the pointer : we just save the handle */
12731 rsym = OP_SYMBOL(IC_RESULT(ic));
12732 if (rsym->liveFrom != rsym->liveTo) {
12733 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12734 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12735 emitcode ("push","ar3");
12736 emitcode ("push","ar2");
12737 emitcode ("pop","%s",
12738 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12739 emitcode ("pop","%s",
12740 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12742 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12743 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12745 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12747 unsavermask(rsave);
12750 /*-----------------------------------------------------------------*/
12752 /*-----------------------------------------------------------------*/
12753 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12758 assert (nparms == 1);
12759 /* save registers that need to be saved */
12760 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12761 ds390_rUmaskForOp (IC_RESULT(ic))));
12764 aopOp (handle,ic,FALSE,FALSE);
12766 /* put the size in R4-R2 */
12767 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12768 emitcode("push","%s",
12769 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12770 emitcode("push","%s",
12771 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12772 emitcode("pop","ar3");
12773 emitcode("pop","ar2");
12775 emitcode ("mov","r2,%s",
12776 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12777 emitcode ("mov","r3,%s",
12778 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12780 freeAsmop (handle, NULL, ic, FALSE);
12782 /* make the call */
12783 emitcode ("lcall","MM_Deref");
12786 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12787 if (rsym->liveFrom != rsym->liveTo) {
12788 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12789 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12790 _startLazyDPSEvaluation ();
12792 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12793 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12794 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12796 _endLazyDPSEvaluation ();
12801 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12802 unsavermask(rsave);
12805 /*-----------------------------------------------------------------*/
12806 /* genMMUnrestrictedPersist - */
12807 /*-----------------------------------------------------------------*/
12808 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12813 assert (nparms == 1);
12814 /* save registers that need to be saved */
12815 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12816 ds390_rUmaskForOp (IC_RESULT(ic))));
12819 aopOp (handle,ic,FALSE,FALSE);
12821 /* put the size in R3-R2 */
12822 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12823 emitcode("push","%s",
12824 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12825 emitcode("push","%s",
12826 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12827 emitcode("pop","ar3");
12828 emitcode("pop","ar2");
12830 emitcode ("mov","r2,%s",
12831 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12832 emitcode ("mov","r3,%s",
12833 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12835 freeAsmop (handle, NULL, ic, FALSE);
12837 /* make the call */
12838 emitcode ("lcall","MM_UnrestrictedPersist");
12841 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12842 if (rsym->liveFrom != rsym->liveTo) {
12843 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12844 aopPut(AOP(IC_RESULT(ic)),"a",0);
12845 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12848 unsavermask(rsave);
12851 /*-----------------------------------------------------------------*/
12852 /* genSystemExecJavaProcess - */
12853 /*-----------------------------------------------------------------*/
12854 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12857 operand *handle, *pp;
12859 assert (nparms==2);
12860 /* save registers that need to be saved */
12861 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12862 ds390_rUmaskForOp (IC_RESULT(ic))));
12867 /* put the handle in R3-R2 */
12868 aopOp (handle,ic,FALSE,FALSE);
12869 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12870 emitcode("push","%s",
12871 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12872 emitcode("push","%s",
12873 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12874 emitcode("pop","ar3");
12875 emitcode("pop","ar2");
12877 emitcode ("mov","r2,%s",
12878 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12879 emitcode ("mov","r3,%s",
12880 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12882 freeAsmop (handle, NULL, ic, FALSE);
12884 /* put pointer in DPTR */
12885 aopOp (pp,ic,FALSE,FALSE);
12886 if (AOP_TYPE(pp) == AOP_IMMD) {
12887 emitcode ("mov", "dptr,%s",
12888 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12889 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12890 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12891 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12892 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12894 freeAsmop (handle, NULL, ic, FALSE);
12896 /* make the call */
12897 emitcode ("lcall","System_ExecJavaProcess");
12899 /* put result in place */
12901 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12902 if (rsym->liveFrom != rsym->liveTo) {
12903 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12904 aopPut(AOP(IC_RESULT(ic)),"a",0);
12905 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12909 unsavermask(rsave);
12912 /*-----------------------------------------------------------------*/
12913 /* genSystemRTCRegisters - */
12914 /*-----------------------------------------------------------------*/
12915 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12921 assert (nparms==1);
12922 /* save registers that need to be saved */
12923 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12924 ds390_rUmaskForOp (IC_RESULT(ic))));
12927 /* put pointer in DPTR */
12928 aopOp (pp,ic,FALSE,FALSE);
12929 if (AOP_TYPE (pp) == AOP_IMMD) {
12930 emitcode ("mov","dps,#1");
12931 emitcode ("mov", "dptr,%s",
12932 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12933 emitcode ("mov","dps,#0");
12935 emitcode ("mov","dpl1,%s",
12936 aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12937 emitcode ("mov","dph1,%s",
12938 aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12939 emitcode ("mov","dpx1,%s",
12940 aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12942 freeAsmop (pp, NULL, ic, FALSE);
12944 /* make the call */
12945 emitcode ("lcall","System_%sRTCRegisters",name);
12947 unsavermask(rsave);
12950 /*-----------------------------------------------------------------*/
12951 /* genSystemThreadSleep - */
12952 /*-----------------------------------------------------------------*/
12953 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12958 assert (nparms==1);
12959 /* save registers that need to be saved */
12960 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12961 ds390_rUmaskForOp (IC_RESULT(ic))));
12964 aopOp(to,ic,FALSE,FALSE);
12965 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12966 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12967 emitcode ("push","%s",
12968 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12969 emitcode ("push","%s",
12970 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12971 emitcode ("push","%s",
12972 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12973 emitcode ("push","%s",
12974 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12975 emitcode ("pop","ar3");
12976 emitcode ("pop","ar2");
12977 emitcode ("pop","ar1");
12978 emitcode ("pop","ar0");
12980 emitcode ("mov","r0,%s",
12981 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12982 emitcode ("mov","r1,%s",
12983 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12984 emitcode ("mov","r2,%s",
12985 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12986 emitcode ("mov","r3,%s",
12987 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12989 freeAsmop (to, NULL, ic, FALSE);
12991 /* suspend in acc */
12993 aopOp(s,ic,FALSE,FALSE);
12994 emitcode ("mov","a,%s",
12995 aopGet(AOP(s),0,FALSE,TRUE,NULL));
12996 freeAsmop (s, NULL, ic, FALSE);
12998 /* make the call */
12999 emitcode ("lcall","System_%s",name);
13001 unsavermask(rsave);
13004 /*-----------------------------------------------------------------*/
13005 /* genSystemThreadResume - */
13006 /*-----------------------------------------------------------------*/
13007 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
13012 assert (nparms==2);
13013 /* save registers that need to be saved */
13014 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13015 ds390_rUmaskForOp (IC_RESULT(ic))));
13021 aopOp(pid,ic,FALSE,FALSE);
13022 emitcode ("mov","r0,%s",
13023 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
13024 freeAsmop (pid, NULL, ic, FALSE);
13027 aopOp(tid,ic,FALSE,FALSE);
13028 emitcode ("mov","a,%s",
13029 aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
13030 freeAsmop (tid, NULL, ic, FALSE);
13032 emitcode ("lcall","System_ThreadResume");
13034 /* put result into place */
13036 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13037 if (rsym->liveFrom != rsym->liveTo) {
13038 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13039 aopPut(AOP(IC_RESULT(ic)),"a",0);
13040 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13043 unsavermask(rsave);
13046 /*-----------------------------------------------------------------*/
13047 /* genSystemProcessResume - */
13048 /*-----------------------------------------------------------------*/
13049 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
13054 assert (nparms==1);
13055 /* save registers that need to be saved */
13056 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13057 ds390_rUmaskForOp (IC_RESULT(ic))));
13062 aopOp(pid,ic,FALSE,FALSE);
13063 emitcode ("mov","a,%s",
13064 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
13065 freeAsmop (pid, NULL, ic, FALSE);
13067 emitcode ("lcall","System_ProcessResume");
13069 unsavermask(rsave);
13072 /*-----------------------------------------------------------------*/
13074 /*-----------------------------------------------------------------*/
13075 static void genSystem (iCode *ic,int nparms,char *name)
13077 assert(nparms == 0);
13079 emitcode ("lcall","System_%s",name);
13082 /*-----------------------------------------------------------------*/
13083 /* genSystemPoll - */
13084 /*-----------------------------------------------------------------*/
13085 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
13090 assert (nparms==1);
13091 /* save registers that need to be saved */
13092 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13093 ds390_rUmaskForOp (IC_RESULT(ic))));
13096 aopOp (fp,ic,FALSE,FALSE);
13097 if (AOP_TYPE (fp) == AOP_IMMD) {
13098 emitcode ("mov", "dptr,%s",
13099 aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
13100 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
13101 emitcode ("mov","dpl,%s",
13102 aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
13103 emitcode ("mov","dph,%s",
13104 aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
13105 emitcode ("mov","dpx,%s",
13106 aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
13108 freeAsmop (fp, NULL, ic, FALSE);
13110 emitcode ("lcall","System_%sPoll",name);
13112 /* put result into place */
13114 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13115 if (rsym->liveFrom != rsym->liveTo) {
13116 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13117 aopPut(AOP(IC_RESULT(ic)),"a",0);
13118 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13121 unsavermask(rsave);
13124 /*-----------------------------------------------------------------*/
13125 /* genSystemGetCurrentID - */
13126 /*-----------------------------------------------------------------*/
13127 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
13129 assert (nparms==0);
13131 emitcode ("lcall","System_GetCurrent%sId",name);
13132 /* put result into place */
13134 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13135 if (rsym->liveFrom != rsym->liveTo) {
13136 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13137 aopPut(AOP(IC_RESULT(ic)),"a",0);
13138 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13143 /*-----------------------------------------------------------------*/
13144 /* genDummyRead - generate code for dummy read of volatiles */
13145 /*-----------------------------------------------------------------*/
13147 genDummyRead (iCode * ic)
13152 D(emitcode("; genDummyRead",""));
13154 op = IC_RIGHT (ic);
13155 if (op && IS_SYMOP (op))
13157 aopOp (op, ic, FALSE, FALSE);
13159 /* if the result is a bit */
13160 if (AOP_TYPE (op) == AOP_CRY)
13161 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13164 /* bit variables done */
13166 size = AOP_SIZE (op);
13170 MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
13175 freeAsmop (op, NULL, ic, TRUE);
13179 if (op && IS_SYMOP (op))
13181 aopOp (op, ic, FALSE, FALSE);
13183 /* if the result is a bit */
13184 if (AOP_TYPE (op) == AOP_CRY)
13185 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13188 /* bit variables done */
13190 size = AOP_SIZE (op);
13194 MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
13199 freeAsmop (op, NULL, ic, TRUE);
13204 /*-----------------------------------------------------------------*/
13205 /* genCritical - generate code for start of a critical sequence */
13206 /*-----------------------------------------------------------------*/
13208 genCritical (iCode *ic)
13210 symbol *tlbl = newiTempLabel (NULL);
13212 D(emitcode("; genCritical",""));
13214 if (IC_RESULT (ic))
13215 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
13217 emitcode ("setb", "c");
13218 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
13219 emitcode ("clr", "c");
13220 emitcode ("", "%05d$:", (tlbl->key + 100));
13222 if (IC_RESULT (ic))
13223 outBitC (IC_RESULT (ic)); /* save old ea in an operand */
13225 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
13227 if (IC_RESULT (ic))
13228 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13231 /*-----------------------------------------------------------------*/
13232 /* genEndCritical - generate code for end of a critical sequence */
13233 /*-----------------------------------------------------------------*/
13235 genEndCritical (iCode *ic)
13237 D(emitcode("; genEndCritical",""));
13241 aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
13242 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
13244 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
13245 emitcode ("mov", "ea,c");
13249 MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE, FALSE));
13250 emitcode ("rrc", "a");
13251 emitcode ("mov", "ea,c");
13253 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
13257 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
13258 emitcode ("mov", "ea,c");
13264 /*-----------------------------------------------------------------*/
13265 /* genBuiltIn - calls the appropriate function to generating code */
13266 /* for a built in function */
13267 /*-----------------------------------------------------------------*/
13268 static void genBuiltIn (iCode *ic)
13270 operand *bi_parms[MAX_BUILTIN_ARGS];
13275 /* get all the arguments for a built in function */
13276 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
13278 /* which function is it */
13279 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
13280 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
13281 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
13282 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
13283 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
13284 } else if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
13285 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
13286 } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
13287 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
13288 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
13289 genMemsetX(bi_iCode,nbi_parms,bi_parms);
13290 } else if (strcmp(bif->name,"__builtin_inp")==0) {
13291 genInp(bi_iCode,nbi_parms,bi_parms);
13292 } else if (strcmp(bif->name,"__builtin_outp")==0) {
13293 genOutp(bi_iCode,nbi_parms,bi_parms);
13294 } else if (strcmp(bif->name,"__builtin_swapw")==0) {
13295 genSwapW(bi_iCode,nbi_parms,bi_parms);
13296 /* JavaNative builtIns */
13297 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
13298 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
13299 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
13300 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
13301 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
13302 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
13303 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
13304 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
13305 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
13306 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
13307 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
13308 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
13309 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
13310 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
13311 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
13312 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
13313 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
13314 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
13315 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
13316 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
13317 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
13318 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
13319 } else if (strcmp(bif->name,"MM_Malloc")==0) {
13320 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
13321 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
13322 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
13323 } else if (strcmp(bif->name,"MM_Free")==0) {
13324 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
13325 } else if (strcmp(bif->name,"MM_Deref")==0) {
13326 genMMDeref(bi_iCode,nbi_parms,bi_parms);
13327 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
13328 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
13329 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
13330 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
13331 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
13332 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
13333 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
13334 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
13335 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
13336 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
13337 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
13338 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
13339 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
13340 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
13341 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
13342 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
13343 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
13344 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13345 } else if (strcmp(bif->name,"System_SaveThread")==0) {
13346 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13347 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
13348 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13349 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
13350 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
13351 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
13352 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
13353 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
13354 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
13355 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
13356 genSystem(bi_iCode,nbi_parms,"ProcessYield");
13357 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
13358 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
13359 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
13360 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
13361 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
13362 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
13363 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
13364 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
13365 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
13366 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
13368 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
13374 /*-----------------------------------------------------------------*/
13375 /* gen390Code - generate code for Dallas 390 based controllers */
13376 /*-----------------------------------------------------------------*/
13378 gen390Code (iCode * lic)
13383 lineHead = lineCurr = NULL;
13384 dptrn[1][0] = "dpl1";
13385 dptrn[1][1] = "dph1";
13386 dptrn[1][2] = "dpx1";
13388 if (options.model == MODEL_FLAT24) {
13389 fReturnSizeDS390 = 5;
13390 fReturn = fReturn24;
13392 fReturnSizeDS390 = 4;
13393 fReturn = fReturn16;
13394 options.stack10bit=0;
13397 /* print the allocation information */
13398 if (allocInfo && currFunc)
13399 printAllocInfo (currFunc, codeOutFile);
13401 /* if debug information required */
13402 if (options.debug && currFunc)
13404 debugFile->writeFunction(currFunc);
13406 if (IS_STATIC (currFunc->etype))
13407 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
13409 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
13412 /* stack pointer name */
13413 if (options.useXstack)
13419 for (ic = lic; ic; ic = ic->next)
13422 _G.current_iCode = ic;
13424 if (ic->lineno && cln != ic->lineno)
13429 emitcode ("", "C$%s$%d$%d$%d ==.",
13430 FileBaseName (ic->filename), ic->lineno,
13431 ic->level, ic->block);
13434 if (!options.noCcodeInAsm) {
13435 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
13436 printCLine(ic->filename, ic->lineno));
13440 if (options.iCodeInAsm) {
13441 emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
13443 /* if the result is marked as
13444 spilt and rematerializable or code for
13445 this has already been generated then
13447 if (resultRemat (ic) || ic->generated)
13450 /* depending on the operation */
13470 /* IPOP happens only when trying to restore a
13471 spilt live range, if there is an ifx statement
13472 following this pop then the if statement might
13473 be using some of the registers being popped which
13474 would destory the contents of the register so
13475 we need to check for this condition and handle it */
13477 ic->next->op == IFX &&
13478 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
13479 genIfx (ic->next, ic);
13497 genEndFunction (ic);
13517 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
13534 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
13538 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
13545 /* note these two are xlated by algebraic equivalence
13546 during parsing SDCC.y */
13547 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
13548 "got '>=' or '<=' shouldn't have come here");
13552 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
13564 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
13568 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
13572 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
13596 genRightShift (ic);
13599 case GET_VALUE_AT_ADDRESS:
13600 genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
13604 if (POINTER_SET (ic))
13605 genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
13631 if (ic->builtinSEND) genBuiltIn(ic);
13632 else addSet (&_G.sendSet, ic);
13635 case DUMMY_READ_VOLATILE:
13644 genEndCritical (ic);
13651 #if 0 // obsolete, and buggy for != xdata
13663 /* now we are ready to call the
13664 peep hole optimizer */
13665 if (!options.nopeep)
13666 peepHole (&lineHead);
13668 /* now do the actual printing */
13669 printLine (lineHead, codeOutFile);