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 -------------------------------------------------------------------------*/
37 #include "SDCCglobl.h"
40 #define BETTER_LITERAL_SHIFT
42 char *aopLiteral (value * val, int offset);
45 /* this is the down and dirty file with all kinds of
46 kludgy & hacky stuff. This is what it is all about
47 CODE GENERATION for a specific MCU . some of the
48 routines may be reusable, will have to see */
50 static char *zero = "#0";
51 static char *one = "#1";
56 #define TR_DPTR(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_DPTR1 %s ", s); }
57 #define TR_AP(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_AP %s ", s); }
59 short fReturnSizeDS390 = 5;
60 static char *fReturn24[] =
61 {"dpl", "dph", "dpx", "b", "a"};
62 static char *fReturn16[] =
63 {"dpl", "dph", "b", "a"};
64 static char **fReturn = fReturn24;
65 static char *accUse[] =
67 static char *dptrn[2][3];
68 static char *javaRet[] = { "r0","r1","r2","r3"};
69 static short rbank = -1;
87 static char *rb1regs[] = {
88 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
91 static void saveRBank (int, iCode *, bool);
93 #define RESULTONSTACK(x) \
94 (IC_RESULT(x) && IC_RESULT(x)->aop && \
95 IC_RESULT(x)->aop->type == AOP_STK )
97 #define MOVA(x) _movA(x)
98 #define MOVB(x) _movB(x)
100 #define CLRC emitcode("clr","c")
101 #define SETC emitcode("setb","c")
103 // A scratch register which will be used to hold
104 // result bytes from operands in far space via DPTR2.
105 #define DP2_RESULT_REG "_ap"
107 static lineNode *lineHead = NULL;
108 static lineNode *lineCurr = NULL;
110 static unsigned char SLMask[] =
111 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
112 0xE0, 0xC0, 0x80, 0x00};
113 static unsigned char SRMask[] =
114 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
115 0x07, 0x03, 0x01, 0x00};
121 #define PROTECT_SP {if (options.protect_sp_update) { \
122 symbol *lbl = newiTempLabel(NULL); \
123 emitcode ("setb","F1"); \
124 emitcode ("jbc","EA,!tlabel",lbl->key+100); \
125 emitcode ("clr","F1"); \
126 emitcode ("","!tlabeldef",lbl->key+100); \
128 #define UNPROTECT_SP { if (options.protect_sp_update) { \
129 symbol *lbl = newiTempLabel(NULL); \
130 emitcode ("jnb","F1,!tlabel",lbl->key+100); \
131 emitcode ("setb","EA"); \
132 emitcode ("","!tlabeldef",lbl->key+100); \
135 static int _currentDPS; /* Current processor DPS. */
136 static int _desiredDPS; /* DPS value compiler thinks we should be using. */
137 static int _lazyDPS = 0; /* if non-zero, we are doing lazy evaluation of DPS changes. */
139 /*-----------------------------------------------------------------*/
140 /* emitcode - writes the code into a file : for now it is simple */
141 /*-----------------------------------------------------------------*/
143 emitcode (char *inst, char *fmt,...)
146 char lb[INITIAL_INLINEASM];
155 SNPRINTF (lb, sizeof(lb), "%s\t", inst);
159 SNPRINTF (lb, sizeof(lb), "%s", inst);
162 tvsprintf (lb + strlen(lb), sizeof(lb) - strlen(lb),
167 tvsprintf (lb, sizeof(lb), fmt, ap);
171 while (isspace (*lbp))
178 lineCurr = (lineCurr ?
179 connectLine (lineCurr, newLineNode (lb)) :
180 (lineHead = newLineNode (lb)));
183 lineCurr->isInline = _G.inLine;
184 lineCurr->isDebug = _G.debugLine;
185 lineCurr->ic = _G.current_iCode;
186 lineCurr->aln = ds390newAsmLineNode(_currentDPS);
190 /*-----------------------------------------------------------------*/
191 /* ds390_emitDebuggerSymbol - associate the current code location */
192 /* with a debugger symbol */
193 /*-----------------------------------------------------------------*/
195 ds390_emitDebuggerSymbol (char * debugSym)
198 emitcode ("", "%s ==.", debugSym);
203 // Move the passed value into A unless it is already there.
208 if (strcmp(s,"a") && strcmp(s,"acc"))
210 emitcode("mov","a,%s",s);
215 // Move the passed value into B unless it is already there.
222 emitcode("mov","b,%s",s);
226 /*-----------------------------------------------------------------*/
227 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
228 /*-----------------------------------------------------------------*/
230 getFreePtr (iCode * ic, asmop ** aopp, bool result)
235 /* the logic: if r0 & r1 used in the instruction
236 then we are in trouble otherwise */
238 /* first check if r0 & r1 are used by this
239 instruction, in which case we are in trouble */
240 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
241 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
246 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
247 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
249 /* if no usage of r0 then return it */
252 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
253 (*aopp)->type = AOP_R0;
255 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
258 /* if no usage of r1 then return it */
261 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
262 (*aopp)->type = AOP_R1;
264 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
267 /* now we know they both have usage */
268 /* if r0 not used in this instruction */
271 /* push it if not already pushed */
274 emitcode ("push", "%s",
275 ds390_regWithIdx (R0_IDX)->dname);
279 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
280 (*aopp)->type = AOP_R0;
282 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
285 /* if r1 not used then */
289 /* push it if not already pushed */
292 emitcode ("push", "%s",
293 ds390_regWithIdx (R1_IDX)->dname);
297 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
298 (*aopp)->type = AOP_R1;
299 return ds390_regWithIdx (R1_IDX);
303 /* I said end of world but not quite end of world yet */
304 /* if this is a result then we can push it on the stack */
307 (*aopp)->type = AOP_STK;
311 /* other wise this is true end of the world */
312 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
313 "getFreePtr should never reach here");
316 return NULL; // notreached, but makes compiler happy.
319 /*-----------------------------------------------------------------*/
320 /* newAsmop - creates a new asmOp */
321 /*-----------------------------------------------------------------*/
323 newAsmop (short type)
327 aop = Safe_calloc (1, sizeof (asmop));
333 /*-----------------------------------------------------------------*/
334 /* genSetDPTR: generate code to select which DPTR is in use (zero */
335 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390 */
336 /* alternate DPTR (DPL1/DPH1/DPX1). */
337 /*-----------------------------------------------------------------*/
342 /* If we are doing lazy evaluation, simply note the desired
343 * change, but don't emit any code yet.
353 emitcode ("mov", "dps,#0");
358 emitcode ("mov", "dps,#1");
362 /*-----------------------------------------------------------------*/
363 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
365 /* Any code that operates on DPTR (NB: not on the individual */
366 /* components, like DPH) *must* call _flushLazyDPS() before using */
367 /* DPTR within a lazy DPS evaluation block. */
369 /* Note that aopPut and aopGet already contain the proper calls to */
370 /* _flushLazyDPS, so it is safe to use these calls within a lazy */
371 /* DPS evaluation block. */
373 /* Also, _flushLazyDPS must be called before any flow control */
374 /* operations that could potentially branch out of the block. */
376 /* Lazy DPS evaluation is simply an optimization (though an */
377 /* important one), so if in doubt, leave it out. */
378 /*-----------------------------------------------------------------*/
380 _startLazyDPSEvaluation (void)
384 #ifdef BETTER_LITERAL_SHIFT
391 /*-----------------------------------------------------------------*/
392 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
393 /* desired one. Call before using DPTR within a lazy DPS evaluation */
395 /*-----------------------------------------------------------------*/
405 if (_desiredDPS != _currentDPS)
409 emitcode ("inc", "dps");
413 emitcode ("dec", "dps");
415 _currentDPS = _desiredDPS;
419 /*-----------------------------------------------------------------*/
420 /* _endLazyDPSEvaluation: end lazy DPS evaluation block. */
422 /* Forces us back to the safe state (standard DPTR selected). */
423 /*-----------------------------------------------------------------*/
425 _endLazyDPSEvaluation (void)
427 #ifdef BETTER_LITERAL_SHIFT
446 /*-----------------------------------------------------------------*/
447 /* pointerCode - returns the code for a pointer type */
448 /*-----------------------------------------------------------------*/
450 pointerCode (sym_link * etype)
453 return PTR_TYPE (SPEC_OCLS (etype));
457 /*-----------------------------------------------------------------*/
458 /* leftRightUseAcc - returns size of accumulator use by operands */
459 /*-----------------------------------------------------------------*/
461 leftRightUseAcc(iCode *ic)
470 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
471 "null iCode pointer");
478 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
481 size = getSize (OP_SYMBOL (op)->type);
486 else if (ic->op == JUMPTABLE)
489 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
492 size = getSize (OP_SYMBOL (op)->type);
500 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
503 size = getSize (OP_SYMBOL (op)->type);
508 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
511 size = getSize (OP_SYMBOL (op)->type);
523 /*-----------------------------------------------------------------*/
524 /* aopForSym - for a true symbol */
525 /*-----------------------------------------------------------------*/
527 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
530 memmap *space = SPEC_OCLS (sym->etype);
531 int accuse = leftRightUseAcc (ic);
533 /* if already has one */
536 if ((sym->aop->type == AOP_DPTR && useDP2)
537 || (sym->aop->type == AOP_DPTR2 && !useDP2))
543 /* assign depending on the storage class */
544 /* if it is on the stack or indirectly addressable */
545 /* space we need to assign either r0 or r1 to it */
546 if ((sym->onStack && !options.stack10bit) || sym->iaccess)
548 sym->aop = aop = newAsmop (0);
549 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
550 aop->size = getSize (sym->type);
552 /* now assign the address of the variable to
553 the pointer register */
554 if (aop->type != AOP_STK)
559 if (_G.accInUse || accuse)
560 emitcode ("push", "acc");
562 if (_G.bInUse || (accuse>1))
563 emitcode ("push", "b");
565 emitcode ("mov", "a,_bp");
566 emitcode ("add", "a,#!constbyte",
568 ((char) (sym->stack - _G.nRegsSaved)) :
569 ((char) sym->stack)) & 0xff);
570 emitcode ("mov", "%s,a",
571 aop->aopu.aop_ptr->name);
573 if (_G.bInUse || (accuse>1))
574 emitcode ("pop", "b");
576 if (_G.accInUse || accuse)
577 emitcode ("pop", "acc");
580 emitcode ("mov", "%s,#%s",
581 aop->aopu.aop_ptr->name,
583 aop->paged = space->paged;
586 aop->aopu.aop_stk = sym->stack;
590 if (sym->onStack && options.stack10bit)
592 short stack_val = -((sym->stack < 0) ?
593 ((short) (sym->stack - _G.nRegsSaved)) :
594 ((short) sym->stack)) ;
595 if (useDP2 && _G.dptr1InUse) {
596 emitcode ("push","dpl1");
597 emitcode ("push","dph1");
598 emitcode ("push","dpx1");
599 } else if (_G.dptrInUse ) {
600 emitcode ("push","dpl");
601 emitcode ("push","dph");
602 emitcode ("push","dpx");
604 /* It's on the 10 bit stack, which is located in
607 if (stack_val < 0 && stack_val > -5) { /* between -5 & -1 */
609 if (options.model == MODEL_FLAT24)
611 emitcode ("mov", "dpx1,#!constbyte",
612 (options.stack_loc >> 16) & 0xff);
614 emitcode ("mov", "dph1,_bpx+1");
616 emitcode ("mov", "dpl1,_bpx");
617 emitcode ("mov","dps,#1");
619 if (options.model == MODEL_FLAT24)
621 emitcode ("mov", "dpx,#!constbyte",
622 (options.stack_loc >> 16) & 0xff);
624 emitcode ("mov", "dph,_bpx+1");
625 emitcode ("mov", "dpl,_bpx");
627 stack_val = -stack_val;
628 while (stack_val--) {
629 emitcode ("inc","dptr");
632 emitcode("mov","dps,#0");
635 if (_G.accInUse || accuse)
636 emitcode ("push", "acc");
638 if (_G.bInUse || (accuse>1))
639 emitcode ("push", "b");
641 emitcode ("mov", "a,_bpx");
642 emitcode ("clr","c");
643 emitcode ("subb", "a,#!constbyte", stack_val & 0xff);
644 emitcode ("mov","b,a");
645 emitcode ("mov","a,_bpx+1");
646 emitcode ("subb","a,#!constbyte",(stack_val >> 8) & 0xff);
648 if (options.model == MODEL_FLAT24)
650 emitcode ("mov", "dpx1,#!constbyte",
651 (options.stack_loc >> 16) & 0xff);
653 emitcode ("mov", "dph1,a");
654 emitcode ("mov", "dpl1,b");
656 if (options.model == MODEL_FLAT24)
658 emitcode ("mov", "dpx,#!constbyte",
659 (options.stack_loc >> 16) & 0xff);
661 emitcode ("mov", "dph,a");
662 emitcode ("mov", "dpl,b");
665 if (_G.bInUse || (accuse>1))
666 emitcode ("pop", "b");
668 if (_G.accInUse || accuse)
669 emitcode ("pop", "acc");
671 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
672 aop->size = getSize (sym->type);
676 /* if in bit space */
677 if (IN_BITSPACE (space))
679 sym->aop = aop = newAsmop (AOP_CRY);
680 aop->aopu.aop_dir = sym->rname;
681 aop->size = getSize (sym->type);
684 /* if it is in direct space */
685 if (IN_DIRSPACE (space))
687 sym->aop = aop = newAsmop (AOP_DIR);
688 aop->aopu.aop_dir = sym->rname;
689 aop->size = getSize (sym->type);
693 /* special case for a function */
694 if (IS_FUNC (sym->type) && !(sym->isitmp))
696 sym->aop = aop = newAsmop (AOP_IMMD);
697 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
698 aop->size = FPTRSIZE;
702 /* only remaining is far space */
703 /* in which case DPTR gets the address */
704 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
709 emitcode ("mov", "dptr,#%s", sym->rname);
714 emitcode ("mov", "dptr,#%s", sym->rname);
716 aop->size = getSize (sym->type);
718 /* if it is in code space */
719 if (IN_CODESPACE (space))
725 /*-----------------------------------------------------------------*/
726 /* aopForRemat - rematerialzes an object */
727 /*-----------------------------------------------------------------*/
729 aopForRemat (symbol * sym)
731 iCode *ic = sym->rematiCode;
732 asmop *aop = newAsmop (AOP_IMMD);
739 val += (int) operandLitValue (IC_RIGHT (ic));
740 else if (ic->op == '-')
741 val -= (int) operandLitValue (IC_RIGHT (ic));
742 else if (IS_CAST_ICODE(ic)) {
743 sym_link *from_type = operandType(IC_RIGHT(ic));
744 aop->aopu.aop_immd.from_cast_remat = 1;
745 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
746 ptr_type = DCL_TYPE(from_type);
747 if (ptr_type == IPOINTER) {
754 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
759 SNPRINTF (buffer, sizeof(buffer),
761 OP_SYMBOL (IC_LEFT (ic))->rname,
762 val >= 0 ? '+' : '-',
763 abs (val) & 0xffffff);
767 if (IS_ASSIGN_ICODE(ic) && isOperandLiteral(IC_RIGHT(ic)))
769 SNPRINTF(buffer, sizeof(buffer),
770 "0x%x",(int) operandLitValue (IC_RIGHT (ic)));
774 strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
778 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);
779 /* set immd2 field if required */
780 if (aop->aopu.aop_immd.from_cast_remat)
782 tsprintf(buffer, sizeof(buffer), "#!constbyte",ptr_type);
783 aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
789 /*-----------------------------------------------------------------*/
790 /* aopHasRegs - returns true if aop has regs between from-to */
791 /*-----------------------------------------------------------------*/
792 static int aopHasRegs(asmop *aop, int from, int to)
796 if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
798 for (; size < aop->size ; size++) {
800 for (reg = from ; reg <= to ; reg++)
801 if (aop->aopu.aop_reg[size] == ds390_regWithIdx(reg)) return 1;
806 /*-----------------------------------------------------------------*/
807 /* regsInCommon - two operands have some registers in common */
808 /*-----------------------------------------------------------------*/
810 regsInCommon (operand * op1, operand * op2)
815 /* if they have registers in common */
816 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
819 sym1 = OP_SYMBOL (op1);
820 sym2 = OP_SYMBOL (op2);
822 if (sym1->nRegs == 0 || sym2->nRegs == 0)
825 for (i = 0; i < sym1->nRegs; i++)
831 for (j = 0; j < sym2->nRegs; j++)
836 if (sym2->regs[j] == sym1->regs[i])
844 /*-----------------------------------------------------------------*/
845 /* operandsEqu - equivalent */
846 /*-----------------------------------------------------------------*/
848 operandsEqu (operand * op1, operand * op2)
852 /* if they not symbols */
853 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
856 sym1 = OP_SYMBOL (op1);
857 sym2 = OP_SYMBOL (op2);
859 /* if both are itemps & one is spilt
860 and the other is not then false */
861 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
862 sym1->isspilt != sym2->isspilt)
865 /* if they are the same */
869 if (sym1->rname[0] && sym2->rname[0]
870 && strcmp (sym1->rname, sym2->rname) == 0)
874 /* if left is a tmp & right is not */
875 if (IS_ITEMP (op1) &&
878 (sym1->usl.spillLoc == sym2))
881 if (IS_ITEMP (op2) &&
885 (sym2->usl.spillLoc == sym1))
888 /* are they spilt to the same location */
889 if (IS_ITEMP (op2) &&
893 (sym1->usl.spillLoc == sym2->usl.spillLoc))
899 /*-----------------------------------------------------------------*/
900 /* sameRegs - two asmops have the same registers */
901 /*-----------------------------------------------------------------*/
903 sameRegs (asmop * aop1, asmop * aop2)
909 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
916 if (aop1->type != AOP_REG ||
917 aop2->type != AOP_REG)
920 if (aop1->size != aop2->size)
923 for (i = 0; i < aop1->size; i++)
924 if (aop1->aopu.aop_reg[i] !=
925 aop2->aopu.aop_reg[i])
931 /*-----------------------------------------------------------------*/
932 /* aopOp - allocates an asmop for an operand : */
933 /*-----------------------------------------------------------------*/
935 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
944 /* if this a literal */
945 if (IS_OP_LITERAL (op))
947 op->aop = aop = newAsmop (AOP_LIT);
948 aop->aopu.aop_lit = op->operand.valOperand;
949 aop->size = getSize (operandType (op));
953 /* if already has a asmop then continue */
956 if ((op->aop->type == AOP_DPTR && useDP2)
957 || (op->aop->type == AOP_DPTR2 && !useDP2))
963 /* if the underlying symbol has a aop */
964 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
966 op->aop = OP_SYMBOL (op)->aop;
967 if ((op->aop->type == AOP_DPTR && useDP2)
968 || (op->aop->type == AOP_DPTR2 && !useDP2))
974 /* if this is a true symbol */
975 if (IS_TRUE_SYMOP (op))
977 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
981 /* this is a temporary : this has
987 e) can be a return use only */
989 sym = OP_SYMBOL (op);
992 /* if the type is a conditional */
993 if (sym->regType == REG_CND)
995 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
1000 /* if it is spilt then two situations
1002 b) has a spill location */
1003 if (sym->isspilt || sym->nRegs == 0)
1006 /* rematerialize it NOW */
1009 sym->aop = op->aop = aop =
1011 aop->size = getSize (sym->type);
1018 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
1019 aop->size = getSize (sym->type);
1020 for (i = 0; i < 2; i++)
1021 aop->aopu.aop_str[i] = accUse[i];
1031 /* a AOP_STR uses DPTR, but DPTR is already in use;
1034 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"AOP_STR with DPTR in use!");
1037 aop = op->aop = sym->aop = newAsmop (AOP_STR);
1038 aop->size = getSize (sym->type);
1039 for (i = 0; i < fReturnSizeDS390; i++)
1040 aop->aopu.aop_str[i] = fReturn[i];
1044 if (sym->dptr) { /* has been allocated to a DPTRn */
1045 aop = op->aop = sym->aop = newAsmop (AOP_DPTRn);
1046 aop->size = getSize (sym->type);
1047 aop->aopu.dptr = sym->dptr;
1051 if (sym->usl.spillLoc)
1053 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1055 /* force a new aop if sizes differ */
1056 sym->usl.spillLoc->aop = NULL;
1058 sym->aop = op->aop = aop =
1059 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
1060 aop->size = getSize (sym->type);
1064 /* else must be a dummy iTemp */
1065 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1066 aop->size = getSize (sym->type);
1070 /* must be in a register */
1071 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1072 aop->size = sym->nRegs;
1073 for (i = 0; i < sym->nRegs; i++)
1074 aop->aopu.aop_reg[i] = sym->regs[i];
1077 /*-----------------------------------------------------------------*/
1078 /* freeAsmop - free up the asmop given to an operand */
1079 /*----------------------------------------------------------------*/
1081 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1098 /* depending on the asmop type only three cases need work AOP_RO
1099 , AOP_R1 && AOP_STK */
1107 emitcode ("pop", "ar0");
1111 bitVectUnSetBit (ic->rUsed, R0_IDX);
1119 emitcode ("pop", "ar1");
1123 bitVectUnSetBit (ic->rUsed, R1_IDX);
1129 int stk = aop->aopu.aop_stk + aop->size;
1130 bitVectUnSetBit (ic->rUsed, R0_IDX);
1131 bitVectUnSetBit (ic->rUsed, R1_IDX);
1133 getFreePtr (ic, &aop, FALSE);
1135 if (options.stack10bit)
1137 /* I'm not sure what to do here yet... */
1140 "*** Warning: probably generating bad code for "
1141 "10 bit stack mode.\n");
1146 emitcode ("mov", "a,_bp");
1147 emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
1148 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1152 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1157 emitcode ("pop", "acc");
1158 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1161 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1164 freeAsmop (op, NULL, ic, TRUE);
1167 emitcode ("pop", "ar0");
1173 emitcode ("pop", "ar1");
1178 if (_G.dptr1InUse) {
1179 emitcode ("pop","dpx1");
1180 emitcode ("pop","dph1");
1181 emitcode ("pop","dpl1");
1186 emitcode ("pop","dpx");
1187 emitcode ("pop","dph");
1188 emitcode ("pop","dpl");
1193 /* all other cases just dealloc */
1199 OP_SYMBOL (op)->aop = NULL;
1200 /* if the symbol has a spill */
1202 SPIL_LOC (op)->aop = NULL;
1207 #define DEFAULT_ACC_WARNING 0
1208 static int saveAccWarn = DEFAULT_ACC_WARNING;
1210 /*-------------------------------------------------------------------*/
1211 /* aopGet - for fetching value of the aop */
1213 /* Set saveAcc to NULL if you are sure it is OK to clobber the value */
1214 /* in the accumulator. Set it to the name of a free register */
1215 /* if acc must be preserved; the register will be used to preserve */
1216 /* acc temporarily and to return the result byte. */
1217 /*-------------------------------------------------------------------*/
1226 /* offset is greater than
1228 if (offset > (aop->size - 1) &&
1229 aop->type != AOP_LIT)
1232 /* depending on type */
1240 /* if we need to increment it */
1241 while (offset > aop->coff)
1243 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1247 while (offset < aop->coff)
1249 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1256 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1257 return (dname ? "acc" : "a");
1259 SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1260 return Safe_strdup(buffer);
1263 assert(offset <= 3);
1264 return dptrn[aop->aopu.dptr][offset];
1269 if (aop->type == AOP_DPTR2)
1277 // if (aop->type != AOP_DPTR2)
1279 // if (saveAccWarn) { fprintf(stderr, "saveAcc for DPTR...\n"); }
1280 // emitcode(";", "spanky: saveAcc for DPTR");
1283 emitcode ("xch", "a, %s", saveAcc);
1288 while (offset > aop->coff)
1290 emitcode ("inc", "dptr");
1294 while (offset < aop->coff)
1296 emitcode ("lcall", "__decdptr");
1303 emitcode ("clr", "a");
1304 emitcode ("movc", "a,@a+dptr");
1308 emitcode ("movx", "a,@dptr");
1311 if (aop->type == AOP_DPTR2)
1319 emitcode ("xch", "a, %s", saveAcc);
1320 // if (strcmp(saveAcc, "_ap"))
1322 // emitcode(";", "spiffy: non _ap return from aopGet.");
1327 return (dname ? "acc" : "a");
1330 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1332 SNPRINTF(buffer, sizeof(buffer),
1333 "%s",aop->aopu.aop_immd.aop_immd2);
1337 SNPRINTF(buffer, sizeof(buffer),
1338 "#%s", aop->aopu.aop_immd.aop_immd1);
1344 tsprintf(buffer, sizeof(buffer),
1345 "#!his",aop->aopu.aop_immd.aop_immd1);
1348 tsprintf(buffer, sizeof(buffer),
1349 "#!hihis",aop->aopu.aop_immd.aop_immd1);
1352 tsprintf(buffer, sizeof(buffer),
1353 "#!hihihis",aop->aopu.aop_immd.aop_immd1);
1355 default: /* should not need this (just in case) */
1356 SNPRINTF (buffer, sizeof(buffer),
1358 aop->aopu.aop_immd.aop_immd1,
1364 SNPRINTF (buffer, sizeof(buffer),
1365 "#%s", aop->aopu.aop_immd.aop_immd1);
1367 return Safe_strdup(buffer);
1372 SNPRINTF (buffer, sizeof(buffer),
1379 SNPRINTF(buffer, sizeof(buffer),
1380 "%s", aop->aopu.aop_dir);
1383 return Safe_strdup(buffer);
1387 return aop->aopu.aop_reg[offset]->dname;
1389 return aop->aopu.aop_reg[offset]->name;
1392 emitcode ("clr", "a");
1393 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1394 emitcode ("rlc", "a");
1395 return (dname ? "acc" : "a");
1398 if (!offset && dname)
1400 return aop->aopu.aop_str[offset];
1403 return aopLiteral (aop->aopu.aop_lit, offset);
1407 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1411 return aop->aopu.aop_str[offset];
1415 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1416 "aopget got unsupported aop->type");
1419 return NULL; // not reached, but makes compiler happy.
1421 /*-----------------------------------------------------------------*/
1422 /* aopPut - puts a string for a aop */
1423 /*-----------------------------------------------------------------*/
1425 aopPut (asmop * aop, char *s, int offset)
1427 if (aop->size && offset > (aop->size - 1))
1429 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1430 "aopPut got offset > aop->size");
1434 /* will assign value to value */
1435 /* depending on where it is ofcourse */
1439 MOVA (s); /* read s in case it was volatile */
1445 SNPRINTF (buffer, sizeof(buffer),
1447 aop->aopu.aop_dir, offset);
1451 SNPRINTF (buffer, sizeof(buffer),
1452 "%s", aop->aopu.aop_dir);
1456 if (strcmp (buffer, s))
1458 emitcode ("mov", "%s,%s", buffer, s);
1463 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1464 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1467 strcmp (s, "r0") == 0 ||
1468 strcmp (s, "r1") == 0 ||
1469 strcmp (s, "r2") == 0 ||
1470 strcmp (s, "r3") == 0 ||
1471 strcmp (s, "r4") == 0 ||
1472 strcmp (s, "r5") == 0 ||
1473 strcmp (s, "r6") == 0 ||
1474 strcmp (s, "r7") == 0)
1476 emitcode ("mov", "%s,%s",
1477 aop->aopu.aop_reg[offset]->dname, s);
1481 emitcode ("mov", "%s,%s",
1482 aop->aopu.aop_reg[offset]->name, s);
1488 emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1494 if (aop->type == AOP_DPTR2)
1502 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1503 "aopPut writting to code space");
1507 while (offset > aop->coff)
1510 emitcode ("inc", "dptr");
1513 while (offset < aop->coff)
1516 emitcode ("lcall", "__decdptr");
1521 /* if not in accumulater */
1524 emitcode ("movx", "@dptr,a");
1526 if (aop->type == AOP_DPTR2)
1534 while (offset > aop->coff)
1537 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1539 while (offset < aop->coff)
1542 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1549 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1555 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1557 else if (strcmp (s, "r0") == 0 ||
1558 strcmp (s, "r1") == 0 ||
1559 strcmp (s, "r2") == 0 ||
1560 strcmp (s, "r3") == 0 ||
1561 strcmp (s, "r4") == 0 ||
1562 strcmp (s, "r5") == 0 ||
1563 strcmp (s, "r6") == 0 ||
1564 strcmp (s, "r7") == 0)
1567 SNPRINTF(buff, sizeof(buff),
1569 emitcode ("mov", "@%s,%s",
1570 aop->aopu.aop_ptr->name, buff);
1574 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1579 if (strcmp (s, "a") == 0)
1580 emitcode ("push", "acc");
1584 emitcode ("push", "acc");
1586 emitcode ("push", s);
1592 /* if bit variable */
1593 if (!aop->aopu.aop_dir)
1595 emitcode ("clr", "a");
1596 emitcode ("rlc", "a");
1601 emitcode ("clr", "%s", aop->aopu.aop_dir);
1603 emitcode ("setb", "%s", aop->aopu.aop_dir);
1604 else if (!strcmp (s, "c"))
1605 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1608 if (strcmp (s, "a"))
1613 /* set C, if a >= 1 */
1614 emitcode ("add", "a,#!constbyte",0xff);
1615 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1623 if (strcmp (aop->aopu.aop_str[offset], s))
1624 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1629 if (!offset && (strcmp (s, "acc") == 0))
1632 if (strcmp (aop->aopu.aop_str[offset], s))
1633 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1637 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1638 "aopPut got unsupported aop->type");
1645 /*--------------------------------------------------------------------*/
1646 /* reAdjustPreg - points a register back to where it should (coff==0) */
1647 /*--------------------------------------------------------------------*/
1649 reAdjustPreg (asmop * aop)
1651 if ((aop->coff==0) || (aop->size <= 1)) {
1660 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1664 if (aop->type == AOP_DPTR2)
1671 emitcode ("lcall", "__decdptr");
1674 if (aop->type == AOP_DPTR2)
1684 #define AOP(op) op->aop
1685 #define AOP_TYPE(op) AOP(op)->type
1686 #define AOP_SIZE(op) AOP(op)->size
1687 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1688 AOP_TYPE(x) == AOP_R0))
1690 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1691 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1694 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1695 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1696 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1697 #define AOP_INDPTRn(x) (AOP_TYPE(x) == AOP_DPTRn)
1698 #define AOP_USESDPTR(x) ((AOP_TYPE(x) == AOP_DPTR) || (AOP_TYPE(x) == AOP_STR))
1699 #define AOP_USESDPTR2(x) ((AOP_TYPE(x) == AOP_DPTR2) || (AOP_TYPE(x) == AOP_DPTRn))
1701 // The following two macros can be used even if the aop has not yet been aopOp'd.
1702 #define AOP_IS_STR(x) (IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
1703 #define AOP_IS_DPTRn(x) (IS_SYMOP(x) && OP_SYMBOL(x)->dptr)
1705 /* Workaround for DS80C390 bug: div ab may return bogus results
1706 * if A is accessed in instruction immediately before the div.
1708 * Will be fixed in B4 rev of processor, Dallas claims.
1711 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1712 if (!AOP_NEEDSACC(RIGHT)) \
1714 /* We can load A first, then B, since \
1715 * B (the RIGHT operand) won't clobber A, \
1716 * thus avoiding touching A right before the div. \
1718 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1719 L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL); \
1721 L = aopGet(AOP(RIGHT),0,FALSE,FALSE,"b"); \
1726 /* Just stuff in a nop after loading A. */ \
1727 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,NULL));\
1728 L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL); \
1730 emitcode("nop", "; workaround for DS80C390 div bug."); \
1734 /*-----------------------------------------------------------------*/
1735 /* opIsGptr: returns non-zero if the passed operand is */
1736 /* a generic pointer type. */
1737 /*-----------------------------------------------------------------*/
1739 opIsGptr (operand * op)
1741 sym_link *type = operandType (op);
1743 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1750 /*-----------------------------------------------------------------*/
1751 /* getDataSize - get the operand data size */
1752 /*-----------------------------------------------------------------*/
1754 getDataSize (operand * op)
1757 size = AOP_SIZE (op);
1758 if (size == GPTRSIZE)
1760 sym_link *type = operandType (op);
1761 if (IS_GENPTR (type))
1763 /* generic pointer; arithmetic operations
1764 * should ignore the high byte (pointer type).
1772 /*-----------------------------------------------------------------*/
1773 /* outAcc - output Acc */
1774 /*-----------------------------------------------------------------*/
1776 outAcc (operand * result)
1779 size = getDataSize (result);
1782 aopPut (AOP (result), "a", 0);
1785 /* unsigned or positive */
1788 aopPut (AOP (result), zero, offset++);
1793 /*-----------------------------------------------------------------*/
1794 /* outBitC - output a bit C */
1795 /*-----------------------------------------------------------------*/
1797 outBitC (operand * result)
1799 /* if the result is bit */
1800 if (AOP_TYPE (result) == AOP_CRY)
1802 aopPut (AOP (result), "c", 0);
1806 emitcode ("clr", "a");
1807 emitcode ("rlc", "a");
1812 /*-----------------------------------------------------------------*/
1813 /* toBoolean - emit code for orl a,operator(sizeop) */
1814 /*-----------------------------------------------------------------*/
1816 toBoolean (operand * oper)
1818 int size = AOP_SIZE (oper) - 1;
1822 /* The generic part of a generic pointer should
1823 * not participate in it's truth value.
1825 * i.e. 0x10000000 is zero.
1827 if (opIsGptr (oper))
1829 D (emitcode (";", "toBoolean: generic ptr special case."););
1833 _startLazyDPSEvaluation ();
1834 if (AOP_NEEDSACC (oper) && size)
1839 emitcode ("push", "b");
1841 MOVB (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1845 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1852 emitcode ("orl", "b,%s",
1853 aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1857 emitcode ("orl", "a,%s",
1858 aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1861 _endLazyDPSEvaluation ();
1865 emitcode ("mov", "a,b");
1868 emitcode ("pop", "b");
1875 /*-----------------------------------------------------------------*/
1876 /* genNot - generate code for ! operation */
1877 /*-----------------------------------------------------------------*/
1883 D (emitcode (";", "genNot "););
1885 /* assign asmOps to operand & result */
1886 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1887 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1889 /* if in bit space then a special case */
1890 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1892 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1893 emitcode ("cpl", "c");
1894 outBitC (IC_RESULT (ic));
1898 toBoolean (IC_LEFT (ic));
1900 tlbl = newiTempLabel (NULL);
1901 emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1902 emitcode ("", "!tlabeldef", tlbl->key + 100);
1903 outBitC (IC_RESULT (ic));
1906 /* release the aops */
1907 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1908 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1912 /*-----------------------------------------------------------------*/
1913 /* genCpl - generate code for complement */
1914 /*-----------------------------------------------------------------*/
1922 D (emitcode (";", "genCpl "););
1925 /* assign asmOps to operand & result */
1926 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1927 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1929 /* special case if in bit space */
1930 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1931 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1932 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1933 emitcode ("cpl", "c");
1934 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1937 tlbl=newiTempLabel(NULL);
1938 emitcode ("cjne", "%s,#0x01,%05d$",
1939 aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE,NULL), tlbl->key+100);
1940 emitcode ("", "%05d$:", tlbl->key+100);
1941 outBitC (IC_RESULT(ic));
1945 size = AOP_SIZE (IC_RESULT (ic));
1946 _startLazyDPSEvaluation ();
1949 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
1950 emitcode ("cpl", "a");
1951 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1953 _endLazyDPSEvaluation ();
1957 /* release the aops */
1958 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1959 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1962 /*-----------------------------------------------------------------*/
1963 /* genUminusFloat - unary minus for floating points */
1964 /*-----------------------------------------------------------------*/
1966 genUminusFloat (operand * op, operand * result)
1968 int size, offset = 0;
1970 D(emitcode (";", "genUminusFloat"););
1972 /* for this we just copy and then flip the bit */
1974 _startLazyDPSEvaluation ();
1975 size = AOP_SIZE (op) - 1;
1979 aopPut (AOP (result),
1980 aopGet (AOP (op), offset, FALSE, FALSE, NULL),
1985 MOVA(aopGet (AOP (op), offset, FALSE, FALSE, NULL));
1987 emitcode ("cpl", "acc.7");
1988 aopPut (AOP (result), "a", offset);
1989 _endLazyDPSEvaluation ();
1992 /*-----------------------------------------------------------------*/
1993 /* genUminus - unary minus code generation */
1994 /*-----------------------------------------------------------------*/
1996 genUminus (iCode * ic)
2001 D (emitcode (";", "genUminus "););
2004 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2005 aopOp (IC_RESULT (ic), ic, TRUE, (AOP_TYPE(IC_LEFT (ic)) == AOP_DPTR));
2007 /* if both in bit space then special
2009 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2010 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2013 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2014 emitcode ("cpl", "c");
2015 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2019 optype = operandType (IC_LEFT (ic));
2021 /* if float then do float stuff */
2022 if (IS_FLOAT (optype))
2024 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2028 /* otherwise subtract from zero */
2029 size = AOP_SIZE (IC_LEFT (ic));
2031 _startLazyDPSEvaluation ();
2034 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL);
2035 if (!strcmp (l, "a"))
2039 emitcode ("cpl", "a");
2040 emitcode ("addc", "a,#0");
2046 emitcode ("clr", "a");
2047 emitcode ("subb", "a,%s", l);
2049 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2051 _endLazyDPSEvaluation ();
2053 /* if any remaining bytes in the result */
2054 /* we just need to propagate the sign */
2055 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic)))) != 0)
2057 emitcode ("rlc", "a");
2058 emitcode ("subb", "a,acc");
2060 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2064 /* release the aops */
2065 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2066 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2069 /*-----------------------------------------------------------------*/
2070 /* savermask - saves registers in the mask */
2071 /*-----------------------------------------------------------------*/
2072 static void savermask(bitVect *rs_mask)
2075 if (options.useXstack) {
2076 if (bitVectBitValue (rs_mask, R0_IDX))
2077 emitcode ("mov", "b,r0");
2078 emitcode ("mov", "r0,%s", spname);
2079 for (i = 0; i < ds390_nRegs; i++) {
2080 if (bitVectBitValue (rs_mask, i)) {
2082 emitcode ("mov", "a,b");
2084 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
2085 emitcode ("movx", "@r0,a");
2086 emitcode ("inc", "r0");
2089 emitcode ("mov", "%s,r0", spname);
2090 if (bitVectBitValue (rs_mask, R0_IDX))
2091 emitcode ("mov", "r0,b");
2093 for (i = 0; i < ds390_nRegs; i++) {
2094 if (bitVectBitValue (rs_mask, i))
2095 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2100 /*-----------------------------------------------------------------*/
2101 /* saveRegisters - will look for a call and save the registers */
2102 /*-----------------------------------------------------------------*/
2104 saveRegisters (iCode * lic)
2110 for (ic = lic; ic; ic = ic->next)
2111 if (ic->op == CALL || ic->op == PCALL)
2116 fprintf (stderr, "found parameter push with no function call\n");
2120 /* if the registers have been saved already then
2123 || (IS_SYMOP(IC_LEFT(ic)) && IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))) && !TARGET_IS_DS400) )
2126 /* special case if DPTR alive across a function call then must save it
2127 even though callee saves */
2128 if (IS_SYMOP(IC_LEFT(ic)) &&
2129 IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2131 rsave = newBitVect(ic->rMask->size);
2132 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2133 if (bitVectBitValue(ic->rMask,i))
2134 rsave = bitVectSetBit(rsave,i);
2136 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2138 /* safe the registers in use at this time but skip the
2139 ones for the result */
2140 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2141 ds390_rUmaskForOp (IC_RESULT(ic)));
2147 /*-----------------------------------------------------------------*/
2148 /* usavermask - restore registers with mask */
2149 /*-----------------------------------------------------------------*/
2150 static void unsavermask(bitVect *rs_mask)
2153 if (options.useXstack) {
2154 emitcode ("mov", "r0,%s", spname);
2155 for (i = ds390_nRegs; i >= 0; i--) {
2156 if (bitVectBitValue (rs_mask, i)) {
2157 emitcode ("dec", "r0");
2158 emitcode ("movx", "a,@r0");
2160 emitcode ("mov", "b,a");
2162 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
2165 emitcode ("mov", "%s,r0", spname);
2166 if (bitVectBitValue (rs_mask, R0_IDX))
2167 emitcode ("mov", "r0,b");
2169 for (i = ds390_nRegs; i >= 0; i--) {
2170 if (bitVectBitValue (rs_mask, i))
2171 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2176 /*-----------------------------------------------------------------*/
2177 /* unsaveRegisters - pop the pushed registers */
2178 /*-----------------------------------------------------------------*/
2180 unsaveRegisters (iCode * ic)
2184 if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2186 rsave = newBitVect(ic->rMask->size);
2187 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2188 if (bitVectBitValue(ic->rMask,i))
2189 rsave = bitVectSetBit(rsave,i);
2191 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2193 /* restore the registers in use at this time but skip the
2194 ones for the result */
2195 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2196 ds390_rUmaskForOp (IC_RESULT(ic)));
2202 /*-----------------------------------------------------------------*/
2204 /*-----------------------------------------------------------------*/
2206 pushSide (operand * oper, int size)
2209 _startLazyDPSEvaluation ();
2212 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, NULL);
2213 if (AOP_TYPE (oper) != AOP_REG &&
2214 AOP_TYPE (oper) != AOP_DIR &&
2217 emitcode ("mov", "a,%s", l);
2218 emitcode ("push", "acc");
2221 emitcode ("push", "%s", l);
2223 _endLazyDPSEvaluation ();
2226 /*-----------------------------------------------------------------*/
2227 /* assignResultValue - */
2228 /*-----------------------------------------------------------------*/
2230 assignResultValue (operand * oper)
2233 int size = AOP_SIZE (oper);
2234 bool pushedAcc = FALSE;
2236 if (size == fReturnSizeDS390)
2238 /* I don't think this case can ever happen... */
2239 /* ACC is the last part of this. If writing the result
2240 * uses AC, we must preserve it.
2242 if (AOP_NEEDSACC(oper))
2244 emitcode(";", "assignResultValue special case for ACC.");
2245 emitcode("push", "acc");
2252 _startLazyDPSEvaluation ();
2255 aopPut (AOP (oper), fReturn[offset], offset);
2258 _endLazyDPSEvaluation ();
2262 emitcode("pop", "acc");
2263 aopPut(AOP(oper), "a", offset);
2268 /*-----------------------------------------------------------------*/
2269 /* genXpush - pushes onto the external stack */
2270 /*-----------------------------------------------------------------*/
2272 genXpush (iCode * ic)
2274 asmop *aop = newAsmop (0);
2276 int size, offset = 0;
2278 D (emitcode (";", "genXpush ");
2281 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2282 r = getFreePtr (ic, &aop, FALSE);
2285 emitcode ("mov", "%s,_spx", r->name);
2287 size = AOP_SIZE (IC_LEFT (ic));
2288 _startLazyDPSEvaluation ();
2292 MOVA (aopGet (AOP (IC_LEFT (ic)),
2293 offset++, FALSE, FALSE, NULL));
2294 emitcode ("movx", "@%s,a", r->name);
2295 emitcode ("inc", "%s", r->name);
2298 _endLazyDPSEvaluation ();
2301 emitcode ("mov", "_spx,%s", r->name);
2303 freeAsmop (NULL, aop, ic, TRUE);
2304 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2307 /*-----------------------------------------------------------------*/
2308 /* genIpush - generate code for pushing this gets a little complex */
2309 /*-----------------------------------------------------------------*/
2311 genIpush (iCode * ic)
2313 int size, offset = 0;
2316 D (emitcode (";", "genIpush ");
2319 /* if this is not a parm push : ie. it is spill push
2320 and spill push is always done on the local stack */
2324 /* and the item is spilt then do nothing */
2325 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2328 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2329 size = AOP_SIZE (IC_LEFT (ic));
2330 /* push it on the stack */
2331 _startLazyDPSEvaluation ();
2334 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2340 emitcode ("push", "%s", l);
2342 _endLazyDPSEvaluation ();
2346 /* this is a paramter push: in this case we call
2347 the routine to find the call and save those
2348 registers that need to be saved */
2351 /* if use external stack then call the external
2352 stack pushing routine */
2353 if (options.useXstack)
2359 /* then do the push */
2360 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2362 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2363 size = AOP_SIZE (IC_LEFT (ic));
2365 _startLazyDPSEvaluation ();
2368 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2369 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2370 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2373 emitcode ("mov", "a,%s", l);
2374 emitcode ("push", "acc");
2378 emitcode ("push", "%s", l);
2381 _endLazyDPSEvaluation ();
2383 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2386 /*-----------------------------------------------------------------*/
2387 /* genIpop - recover the registers: can happen only for spilling */
2388 /*-----------------------------------------------------------------*/
2390 genIpop (iCode * ic)
2394 D (emitcode (";", "genIpop ");
2398 /* if the temp was not pushed then */
2399 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2402 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2403 size = AOP_SIZE (IC_LEFT (ic));
2404 offset = (size - 1);
2405 _startLazyDPSEvaluation ();
2408 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2409 FALSE, TRUE, NULL));
2411 _endLazyDPSEvaluation ();
2413 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2416 /*-----------------------------------------------------------------*/
2417 /* unsaveRBank - restores the resgister bank from stack */
2418 /*-----------------------------------------------------------------*/
2420 unsaveRBank (int bank, iCode * ic, bool popPsw)
2426 if (options.useXstack)
2430 /* Assume r0 is available for use. */
2431 r = ds390_regWithIdx (R0_IDX);;
2436 r = getFreePtr (ic, &aop, FALSE);
2438 emitcode ("mov", "%s,_spx", r->name);
2443 if (options.useXstack)
2445 emitcode ("movx", "a,@%s", r->name);
2446 emitcode ("mov", "psw,a");
2447 emitcode ("dec", "%s", r->name);
2451 emitcode ("pop", "psw");
2455 for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2457 if (options.useXstack)
2459 emitcode ("movx", "a,@%s", r->name);
2460 emitcode ("mov", "(%s+%d),a",
2461 regs390[i].base, 8 * bank + regs390[i].offset);
2462 emitcode ("dec", "%s", r->name);
2466 emitcode ("pop", "(%s+%d)",
2467 regs390[i].base, 8 * bank + regs390[i].offset);
2470 if (options.useXstack)
2472 emitcode ("mov", "_spx,%s", r->name);
2477 freeAsmop (NULL, aop, ic, TRUE);
2481 /*-----------------------------------------------------------------*/
2482 /* saveRBank - saves an entire register bank on the stack */
2483 /*-----------------------------------------------------------------*/
2485 saveRBank (int bank, iCode * ic, bool pushPsw)
2491 if (options.useXstack)
2495 /* Assume r0 is available for use. */
2496 r = ds390_regWithIdx (R0_IDX);;
2501 r = getFreePtr (ic, &aop, FALSE);
2503 emitcode ("mov", "%s,_spx", r->name);
2506 for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2508 if (options.useXstack)
2510 emitcode ("inc", "%s", r->name);
2511 emitcode ("mov", "a,(%s+%d)",
2512 regs390[i].base, 8 * bank + regs390[i].offset);
2513 emitcode ("movx", "@%s,a", r->name);
2516 emitcode ("push", "(%s+%d)",
2517 regs390[i].base, 8 * bank + regs390[i].offset);
2522 if (options.useXstack)
2524 emitcode ("mov", "a,psw");
2525 emitcode ("movx", "@%s,a", r->name);
2526 emitcode ("inc", "%s", r->name);
2527 emitcode ("mov", "_spx,%s", r->name);
2531 emitcode ("push", "psw");
2534 emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2539 freeAsmop (NULL, aop, ic, TRUE);
2548 /*-----------------------------------------------------------------*/
2549 /* genSend - gen code for SEND */
2550 /*-----------------------------------------------------------------*/
2551 static void genSend(set *sendSet)
2555 static int rb1_count = 0;
2557 for (sic = setFirstItem (sendSet); sic;
2558 sic = setNextItem (sendSet)) {
2559 int size, offset = 0;
2561 size=getSize(operandType(IC_LEFT(sic)));
2562 D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2563 if (sendCount == 0) { /* first parameter */
2564 // we know that dpl(hxb) is the result, so
2566 _startLazyDPSEvaluation ();
2568 aopOp (IC_LEFT (sic), sic, FALSE,
2569 (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2571 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2574 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2575 FALSE, FALSE, NULL);
2576 if (strcmp (l, fReturn[offset])) {
2577 emitcode ("mov", "%s,%s",
2583 _endLazyDPSEvaluation ();
2584 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2586 } else { /* if more parameter in registers */
2587 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2589 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
2590 FALSE, FALSE, NULL));
2592 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2599 adjustEsp(const char *reg)
2601 emitcode ("anl","%s,#3", reg);
2602 if (TARGET_IS_DS400)
2604 emitcode ("orl","%s,#!constbyte",
2606 (options.stack_loc >> 8) & 0xff);
2610 /*-----------------------------------------------------------------*/
2611 /* genCall - generates a call statement */
2612 /*-----------------------------------------------------------------*/
2614 genCall (iCode * ic)
2617 bool restoreBank = FALSE;
2618 bool swapBanks = FALSE;
2620 D (emitcode (";", "genCall "););
2622 /* if we are calling a not _naked function that is not using
2623 the same register bank then we need to save the
2624 destination registers on the stack */
2625 dtype = operandType (IC_LEFT (ic));
2626 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2627 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2628 IFFUNC_ISISR (currFunc->type))
2632 /* This is unexpected; the bank should have been saved in
2635 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2641 /* if caller saves & we have not saved then */
2645 /* if send set is not empty the assign */
2646 /* We've saved all the registers we care about;
2647 * therefore, we may clobber any register not used
2648 * in the calling convention (i.e. anything not in
2653 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2654 genSend(reverseSet(_G.sendSet));
2656 genSend(_G.sendSet);
2663 emitcode ("mov", "psw,#!constbyte",
2664 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2668 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2669 OP_SYMBOL (IC_LEFT (ic))->rname :
2670 OP_SYMBOL (IC_LEFT (ic))->name));
2674 emitcode ("mov", "psw,#!constbyte",
2675 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2678 /* if we need assign a result value */
2679 if ((IS_ITEMP (IC_RESULT (ic)) &&
2680 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2681 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2682 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2683 IS_TRUE_SYMOP (IC_RESULT (ic)))
2685 if (isOperandInFarSpace (IC_RESULT (ic))
2686 && getSize (operandType (IC_RESULT (ic))) <= 2)
2688 int size = getSize (operandType (IC_RESULT (ic)));
2690 /* Special case for 1 or 2 byte return in far space. */
2694 emitcode ("mov", "b,%s", fReturn[1]);
2699 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2705 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2709 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2711 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2716 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2719 assignResultValue (IC_RESULT (ic));
2721 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2725 /* adjust the stack for parameters if
2727 if (ic->parmBytes) {
2729 if (options.stack10bit) {
2730 if (ic->parmBytes <= 10) {
2731 emitcode(";","stack adjustment for parms");
2732 for (i=0; i < ic->parmBytes ; i++) {
2733 emitcode("pop","acc");
2737 emitcode ("clr","c");
2738 emitcode ("mov","a,sp");
2739 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2740 emitcode ("mov","sp,a");
2741 emitcode ("mov","a,esp");
2743 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2744 emitcode ("mov","esp,a");
2748 if (ic->parmBytes > 3) {
2749 emitcode ("mov", "a,%s", spname);
2750 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2751 emitcode ("mov", "%s,a", spname);
2753 for (i = 0; i < ic->parmBytes; i++)
2754 emitcode ("dec", "%s", spname);
2758 /* if we hade saved some registers then unsave them */
2760 unsaveRegisters (ic);
2762 /* if register bank was saved then pop them */
2764 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2767 /*-----------------------------------------------------------------*/
2768 /* genPcall - generates a call by pointer statement */
2769 /*-----------------------------------------------------------------*/
2771 genPcall (iCode * ic)
2774 symbol *rlbl = newiTempLabel (NULL);
2775 bool restoreBank=FALSE;
2777 D (emitcode (";", "genPcall ");
2781 /* if caller saves & we have not saved then */
2785 /* if we are calling a function that is not using
2786 the same register bank then we need to save the
2787 destination registers on the stack */
2788 dtype = operandType (IC_LEFT (ic));
2789 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2790 IFFUNC_ISISR (currFunc->type) &&
2791 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2792 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2796 /* push the return address on to the stack */
2797 emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2798 emitcode ("push", "acc");
2799 emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2800 emitcode ("push", "acc");
2802 if (options.model == MODEL_FLAT24)
2804 emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2805 emitcode ("push", "acc");
2808 /* now push the calling address */
2809 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2811 pushSide (IC_LEFT (ic), FPTRSIZE);
2813 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2815 /* if send set is not empty the assign */
2818 genSend(reverseSet(_G.sendSet));
2822 emitcode ("ret", "");
2823 emitcode ("", "!tlabeldef", (rlbl->key + 100));
2826 /* if we need assign a result value */
2827 if ((IS_ITEMP (IC_RESULT (ic)) &&
2828 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2829 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2830 IS_TRUE_SYMOP (IC_RESULT (ic)))
2834 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2837 assignResultValue (IC_RESULT (ic));
2839 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2842 /* adjust the stack for parameters if
2847 if (options.stack10bit) {
2848 if (ic->parmBytes <= 10) {
2849 emitcode(";","stack adjustment for parms");
2850 for (i=0; i < ic->parmBytes ; i++) {
2851 emitcode("pop","acc");
2855 emitcode ("clr","c");
2856 emitcode ("mov","a,sp");
2857 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2858 emitcode ("mov","sp,a");
2859 emitcode ("mov","a,esp");
2861 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2862 emitcode ("mov","esp,a");
2866 if (ic->parmBytes > 3) {
2867 emitcode ("mov", "a,%s", spname);
2868 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2869 emitcode ("mov", "%s,a", spname);
2872 for (i = 0; i < ic->parmBytes; i++)
2873 emitcode ("dec", "%s", spname);
2877 /* if register bank was saved then unsave them */
2879 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2881 /* if we hade saved some registers then
2884 unsaveRegisters (ic);
2888 /*-----------------------------------------------------------------*/
2889 /* resultRemat - result is rematerializable */
2890 /*-----------------------------------------------------------------*/
2892 resultRemat (iCode * ic)
2894 if (SKIP_IC (ic) || ic->op == IFX)
2897 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2899 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2900 if (sym->remat && !POINTER_SET (ic))
2907 #if defined(__BORLANDC__) || defined(_MSC_VER)
2908 #define STRCASECMP stricmp
2910 #define STRCASECMP strcasecmp
2913 /*-----------------------------------------------------------------*/
2914 /* inExcludeList - return 1 if the string is in exclude Reg list */
2915 /*-----------------------------------------------------------------*/
2917 regsCmp(void *p1, void *p2)
2919 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2923 inExcludeList (char *s)
2925 const char *p = setFirstItem(options.excludeRegsSet);
2927 if (p == NULL || STRCASECMP(p, "none") == 0)
2931 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2934 /*-----------------------------------------------------------------*/
2935 /* genFunction - generated code for function entry */
2936 /*-----------------------------------------------------------------*/
2938 genFunction (iCode * ic)
2942 bool switchedPSW = FALSE;
2944 D (emitcode (";", "genFunction "););
2947 /* create the function header */
2948 emitcode (";", "-----------------------------------------");
2949 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2950 emitcode (";", "-----------------------------------------");
2952 emitcode ("", "%s:", sym->rname);
2953 ftype = operandType (IC_LEFT (ic));
2955 if (IFFUNC_ISNAKED(ftype))
2957 emitcode(";", "naked function: no prologue.");
2961 if (options.stack_probe)
2962 emitcode ("lcall","__stack_probe");
2964 /* here we need to generate the equates for the
2965 register bank if required */
2966 if (FUNC_REGBANK (ftype) != rbank)
2970 rbank = FUNC_REGBANK (ftype);
2971 for (i = 0; i < ds390_nRegs; i++)
2973 if (regs390[i].print) {
2974 if (strcmp (regs390[i].base, "0") == 0)
2975 emitcode ("", "%s !equ !constbyte",
2977 8 * rbank + regs390[i].offset);
2979 emitcode ("", "%s !equ %s + !constbyte",
2982 8 * rbank + regs390[i].offset);
2987 /* if this is an interrupt service routine then
2988 save acc, b, dpl, dph */
2989 if (IFFUNC_ISISR (sym->type))
2991 if (!inExcludeList ("acc"))
2992 emitcode ("push", "acc");
2993 if (!inExcludeList ("b"))
2994 emitcode ("push", "b");
2995 if (!inExcludeList ("dpl"))
2996 emitcode ("push", "dpl");
2997 if (!inExcludeList ("dph"))
2998 emitcode ("push", "dph");
2999 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3001 emitcode ("push", "dpx");
3002 /* Make sure we're using standard DPTR */
3003 emitcode ("push", "dps");
3004 emitcode ("mov", "dps,#0");
3005 if (options.stack10bit)
3007 /* This ISR could conceivably use DPTR2. Better save it. */
3008 emitcode ("push", "dpl1");
3009 emitcode ("push", "dph1");
3010 emitcode ("push", "dpx1");
3011 emitcode ("push", DP2_RESULT_REG);
3014 /* if this isr has no bank i.e. is going to
3015 run with bank 0 , then we need to save more
3017 if (!FUNC_REGBANK (sym->type))
3021 /* if this function does not call any other
3022 function then we can be economical and
3023 save only those registers that are used */
3024 if (!IFFUNC_HASFCALL(sym->type))
3027 /* if any registers used */
3030 /* save the registers used */
3031 for (i = 0; i < sym->regsUsed->size; i++)
3033 if (bitVectBitValue (sym->regsUsed, i))
3034 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3040 /* this function has a function call cannot
3041 determines register usage so we will have to push the
3043 saveRBank (0, ic, FALSE);
3044 if (options.parms_in_bank1) {
3045 for (i=0; i < 8 ; i++ ) {
3046 emitcode ("push","%s",rb1regs[i]);
3053 /* This ISR uses a non-zero bank.
3055 * We assume that the bank is available for our
3058 * However, if this ISR calls a function which uses some
3059 * other bank, we must save that bank entirely.
3061 unsigned long banksToSave = 0;
3063 if (IFFUNC_HASFCALL(sym->type))
3066 #define MAX_REGISTER_BANKS 4
3071 for (i = ic; i; i = i->next)
3073 if (i->op == ENDFUNCTION)
3075 /* we got to the end OK. */
3083 dtype = operandType (IC_LEFT(i));
3085 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3087 /* Mark this bank for saving. */
3088 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3090 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3094 banksToSave |= (1 << FUNC_REGBANK(dtype));
3097 /* And note that we don't need to do it in
3105 /* This is a mess; we have no idea what
3106 * register bank the called function might
3109 * The only thing I can think of to do is
3110 * throw a warning and hope.
3112 werror(W_FUNCPTR_IN_USING_ISR);
3116 if (banksToSave && options.useXstack)
3118 /* Since we aren't passing it an ic,
3119 * saveRBank will assume r0 is available to abuse.
3121 * So switch to our (trashable) bank now, so
3122 * the caller's R0 isn't trashed.
3124 emitcode ("push", "psw");
3125 emitcode ("mov", "psw,#!constbyte",
3126 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3130 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3132 if (banksToSave & (1 << ix))
3134 saveRBank(ix, NULL, FALSE);
3138 // TODO: this needs a closer look
3139 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3144 /* if callee-save to be used for this function
3145 then save the registers being used in this function */
3146 if (IFFUNC_CALLEESAVES(sym->type))
3150 /* if any registers used */
3153 /* save the registers used */
3154 for (i = 0; i < sym->regsUsed->size; i++)
3156 if (bitVectBitValue (sym->regsUsed, i))
3158 emitcode ("push", "%s", ds390_regWithIdx (i)->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.");
3270 if (options.debug && currFunc)
3271 debugFile->writeEndFunction (currFunc, ic, 0);
3275 if (IFFUNC_ISCRITICAL (sym->type))
3277 emitcode ("pop", "psw"); /* restore ea via c in psw */
3278 emitcode ("mov", "ea,c");
3281 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3282 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3284 if (options.stack10bit) {
3286 emitcode ("mov", "sp,_bpx", spname);
3287 emitcode ("mov", "esp,_bpx+1", spname);
3290 emitcode ("mov", "%s,_bp", spname);
3294 /* if use external stack but some variables were
3295 added to the local stack then decrement the
3297 if (options.useXstack && sym->stack) {
3298 emitcode ("mov", "a,sp");
3299 emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3300 emitcode ("mov", "sp,a");
3304 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3305 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3307 if (options.useXstack) {
3308 emitcode ("mov", "r0,%s", spname);
3309 emitcode ("movx", "a,@r0");
3310 emitcode ("mov", "_bp,a");
3311 emitcode ("dec", "%s", spname);
3313 if (options.stack10bit) {
3314 emitcode ("pop", "_bpx+1");
3315 emitcode ("pop", "_bpx");
3317 emitcode ("pop", "_bp");
3322 /* restore the register bank */
3323 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3325 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3326 || !options.useXstack)
3328 /* Special case of ISR using non-zero bank with useXstack
3331 emitcode ("pop", "psw");
3335 if (IFFUNC_ISISR (sym->type))
3338 /* now we need to restore the registers */
3339 /* if this isr has no bank i.e. is going to
3340 run with bank 0 , then we need to save more
3342 if (!FUNC_REGBANK (sym->type))
3345 /* if this function does not call any other
3346 function then we can be economical and
3347 save only those registers that are used */
3348 if (!IFFUNC_HASFCALL(sym->type))
3351 /* if any registers used */
3354 /* save the registers used */
3355 for (i = sym->regsUsed->size; i >= 0; i--)
3357 if (bitVectBitValue (sym->regsUsed, i))
3358 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3364 /* this function has a function call cannot
3365 determines register usage so we will have to pop the
3367 if (options.parms_in_bank1) {
3368 for (i = 7 ; i >= 0 ; i-- ) {
3369 emitcode ("pop","%s",rb1regs[i]);
3372 unsaveRBank (0, ic, FALSE);
3377 /* This ISR uses a non-zero bank.
3379 * Restore any register banks saved by genFunction
3382 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3385 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3387 if (savedBanks & (1 << ix))
3389 unsaveRBank(ix, NULL, FALSE);
3393 if (options.useXstack)
3395 /* Restore bank AFTER calling unsaveRBank,
3396 * since it can trash r0.
3398 emitcode ("pop", "psw");
3402 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3404 if (options.stack10bit)
3406 emitcode ("pop", DP2_RESULT_REG);
3407 emitcode ("pop", "dpx1");
3408 emitcode ("pop", "dph1");
3409 emitcode ("pop", "dpl1");
3411 emitcode ("pop", "dps");
3412 emitcode ("pop", "dpx");
3414 if (!inExcludeList ("dph"))
3415 emitcode ("pop", "dph");
3416 if (!inExcludeList ("dpl"))
3417 emitcode ("pop", "dpl");
3418 if (!inExcludeList ("b"))
3419 emitcode ("pop", "b");
3420 if (!inExcludeList ("acc"))
3421 emitcode ("pop", "acc");
3423 /* if debug then send end of function */
3424 if (options.debug && currFunc) {
3425 debugFile->writeEndFunction (currFunc, ic, 1);
3428 emitcode ("reti", "");
3432 if (IFFUNC_CALLEESAVES(sym->type))
3436 /* if any registers used */
3439 /* save the registers used */
3440 for (i = sym->regsUsed->size; i >= 0; i--)
3442 if (bitVectBitValue (sym->regsUsed, i))
3443 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3448 /* if debug then send end of function */
3449 if (options.debug && currFunc)
3451 debugFile->writeEndFunction (currFunc, ic, 1);
3454 emitcode ("ret", "");
3457 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3460 /* If this was an interrupt handler using bank 0 that called another */
3461 /* function, then all registers must be saved; nothing to optimized. */
3462 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3463 && !FUNC_REGBANK(sym->type))
3466 /* There are no push/pops to optimize if not callee-saves or ISR */
3467 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3470 /* If there were stack parameters, we cannot optimize without also */
3471 /* fixing all of the stack offsets; this is too dificult to consider. */
3472 if (FUNC_HASSTACKPARM(sym->type))
3475 /* Compute the registers actually used */
3476 regsUsed = newBitVect (ds390_nRegs);
3477 regsUsedPrologue = newBitVect (ds390_nRegs);
3480 if (lnp->ic && lnp->ic->op == FUNCTION)
3481 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3483 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3485 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3486 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3493 if (bitVectBitValue (regsUsedPrologue, DPS_IDX)
3494 && !bitVectBitValue (regsUsed, DPS_IDX))
3496 bitVectUnSetBit (regsUsedPrologue, DPS_IDX);
3499 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3500 && !bitVectBitValue (regsUsed, CND_IDX))
3502 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3503 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3504 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3505 bitVectUnSetBit (regsUsed, CND_IDX);
3508 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3510 /* If this was an interrupt handler that called another function */
3511 /* function, then assume working registers may be modified by it. */
3512 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3514 regsUsed = bitVectSetBit (regsUsed, AP_IDX);
3515 regsUsed = bitVectSetBit (regsUsed, DPX1_IDX);
3516 regsUsed = bitVectSetBit (regsUsed, DPL1_IDX);
3517 regsUsed = bitVectSetBit (regsUsed, DPH1_IDX);
3518 regsUsed = bitVectSetBit (regsUsed, DPX_IDX);
3519 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3520 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3521 regsUsed = bitVectSetBit (regsUsed, DPS_IDX);
3522 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3523 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3524 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3527 /* Remove the unneeded push/pops */
3528 regsUnneeded = newBitVect (ds390_nRegs);
3531 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3533 if (!strncmp(lnp->line, "push", 4))
3535 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3536 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3538 connectLine (lnp->prev, lnp->next);
3539 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3542 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3544 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3545 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3547 connectLine (lnp->prev, lnp->next);
3548 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3555 for (idx = 0; idx < regsUnneeded->size; idx++)
3556 if (bitVectBitValue (regsUnneeded, idx))
3557 emitcode ("", ";\teliminated unneeded push/pop %s", ds390_regWithIdx (idx)->dname);
3559 freeBitVect (regsUnneeded);
3560 freeBitVect (regsUsed);
3561 freeBitVect (regsUsedPrologue);
3564 /*-----------------------------------------------------------------*/
3565 /* genJavaNativeRet - generate code for return JavaNative */
3566 /*-----------------------------------------------------------------*/
3567 static void genJavaNativeRet(iCode *ic)
3571 aopOp (IC_LEFT (ic), ic, FALSE,
3572 AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
3573 size = AOP_SIZE (IC_LEFT (ic));
3577 /* it is assigned to GPR0-R3 then push them */
3578 if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3579 aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3580 for (i = 0 ; i < size ; i++ ) {
3581 emitcode ("push","%s",
3582 aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3584 for (i = (size-1) ; i >= 0 ; i--) {
3585 emitcode ("pop","a%s",javaRet[i]);
3588 for (i = 0 ; i < size ; i++)
3589 emitcode ("mov","%s,%s",javaRet[i],
3590 aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3592 for (i = size ; i < 4 ; i++ )
3593 emitcode ("mov","%s,#0",javaRet[i]);
3597 /*-----------------------------------------------------------------*/
3598 /* genRet - generate code for return statement */
3599 /*-----------------------------------------------------------------*/
3603 int size, offset = 0, pushed = 0;
3605 D (emitcode (";", "genRet "););
3607 /* if we have no return value then
3608 just generate the "ret" */
3612 /* if this is a JavaNative function then return
3613 value in different register */
3614 if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3615 genJavaNativeRet(ic);
3618 /* we have something to return then
3619 move the return value into place */
3620 aopOp (IC_LEFT (ic), ic, FALSE,
3621 (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
3622 size = AOP_SIZE (IC_LEFT (ic));
3624 _startLazyDPSEvaluation ();
3628 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3630 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3632 emitcode ("push", "%s", l);
3637 /* Since A is the last element of fReturn,
3638 * is is OK to clobber it in the aopGet.
3640 l = aopGet (AOP (IC_LEFT (ic)), offset,
3641 FALSE, FALSE, NULL);
3642 if (strcmp (fReturn[offset], l))
3643 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3646 _endLazyDPSEvaluation ();
3653 if (strcmp (fReturn[pushed], "a"))
3654 emitcode ("pop", fReturn[pushed]);
3656 emitcode ("pop", "acc");
3659 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3662 /* generate a jump to the return label
3663 if the next is not the return statement */
3664 if (!(ic->next && ic->next->op == LABEL &&
3665 IC_LABEL (ic->next) == returnLabel))
3667 emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3671 /*-----------------------------------------------------------------*/
3672 /* genLabel - generates a label */
3673 /*-----------------------------------------------------------------*/
3675 genLabel (iCode * ic)
3677 /* special case never generate */
3678 if (IC_LABEL (ic) == entryLabel)
3681 D (emitcode (";", "genLabel ");
3684 emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3687 /*-----------------------------------------------------------------*/
3688 /* genGoto - generates a ljmp */
3689 /*-----------------------------------------------------------------*/
3691 genGoto (iCode * ic)
3693 D (emitcode (";", "genGoto ");
3695 emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3698 /*-----------------------------------------------------------------*/
3699 /* findLabelBackwards: walks back through the iCode chain looking */
3700 /* for the given label. Returns number of iCode instructions */
3701 /* between that label and given ic. */
3702 /* Returns zero if label not found. */
3703 /*-----------------------------------------------------------------*/
3705 findLabelBackwards (iCode * ic, int key)
3714 /* If we have any pushes or pops, we cannot predict the distance.
3715 I don't like this at all, this should be dealt with in the
3717 if (ic->op == IPUSH || ic->op == IPOP) {
3721 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3723 /* printf("findLabelBackwards = %d\n", count); */
3731 /*-----------------------------------------------------------------*/
3732 /* genPlusIncr :- does addition with increment if possible */
3733 /*-----------------------------------------------------------------*/
3735 genPlusIncr (iCode * ic)
3737 unsigned int icount;
3738 unsigned int size = getDataSize (IC_RESULT (ic));
3740 /* will try to generate an increment */
3741 /* if the right side is not a literal
3743 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3746 /* if the literal value of the right hand side
3747 is greater than 4 then it is not worth it */
3748 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3751 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3752 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3754 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
3758 /* if increment 16 bits in register */
3760 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3761 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3762 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3771 /* If the next instruction is a goto and the goto target
3772 * is <= 5 instructions previous to this, we can generate
3773 * jumps straight to that target.
3775 if (ic->next && ic->next->op == GOTO
3776 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3779 D(emitcode (";", "tail increment optimized (range %d)", labelRange););
3780 tlbl = IC_LABEL (ic->next);
3785 tlbl = newiTempLabel (NULL);
3789 l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
3790 emitcode ("inc", "%s", l);
3792 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3793 IS_AOP_PREG (IC_RESULT (ic)))
3795 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3799 emitcode ("clr", "a");
3800 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3803 l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
3804 emitcode ("inc", "%s", l);
3807 if (!strcmp(l, "acc"))
3809 emitcode("jnz", "!tlabel", tlbl->key + 100);
3811 else 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 ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3821 l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
3822 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)), MSB32, FALSE, FALSE, NULL);
3841 emitcode ("inc", "%s", l); }
3845 emitcode ("", "!tlabeldef", tlbl->key + 100);
3850 if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3851 !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 &&
3852 options.model == MODEL_FLAT24 ) {
3856 emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, NULL));
3858 emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, NULL));
3860 emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3863 while (icount--) emitcode ("inc","dptr");
3867 if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3868 AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3870 emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3871 while (icount--) emitcode ("inc","dptr");
3872 emitcode ("mov","dps,#0");
3876 /* if the sizes are greater than 1 then we cannot */
3877 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3878 AOP_SIZE (IC_LEFT (ic)) > 1)
3881 /* we can if the aops of the left & result match or
3882 if they are in registers and the registers are the
3885 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3886 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3887 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3892 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3893 emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3894 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3899 _startLazyDPSEvaluation ();
3902 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3904 _endLazyDPSEvaluation ();
3913 /*-----------------------------------------------------------------*/
3914 /* outBitAcc - output a bit in acc */
3915 /*-----------------------------------------------------------------*/
3917 outBitAcc (operand * result)
3919 symbol *tlbl = newiTempLabel (NULL);
3920 /* if the result is a bit */
3921 if (AOP_TYPE (result) == AOP_CRY)
3923 aopPut (AOP (result), "a", 0);
3927 emitcode ("jz", "!tlabel", tlbl->key + 100);
3928 emitcode ("mov", "a,%s", one);
3929 emitcode ("", "!tlabeldef", tlbl->key + 100);
3934 /*-----------------------------------------------------------------*/
3935 /* genPlusBits - generates code for addition of two bits */
3936 /*-----------------------------------------------------------------*/
3938 genPlusBits (iCode * ic)
3940 D (emitcode (";", "genPlusBits "););
3942 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3944 symbol *lbl = newiTempLabel (NULL);
3945 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3946 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3947 emitcode ("cpl", "c");
3948 emitcode ("", "!tlabeldef", (lbl->key + 100));
3949 outBitC (IC_RESULT (ic));
3953 emitcode ("clr", "a");
3954 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3955 emitcode ("rlc", "a");
3956 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3957 emitcode ("addc", "a,#0");
3958 outAcc (IC_RESULT (ic));
3963 adjustArithmeticResult (iCode * ic)
3965 if (opIsGptr (IC_RESULT (ic)) &&
3966 opIsGptr (IC_LEFT (ic)) &&
3967 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3969 aopPut (AOP (IC_RESULT (ic)),
3970 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3974 if (opIsGptr (IC_RESULT (ic)) &&
3975 opIsGptr (IC_RIGHT (ic)) &&
3976 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3978 aopPut (AOP (IC_RESULT (ic)),
3979 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3983 if (opIsGptr (IC_RESULT (ic)) &&
3984 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3985 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3986 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3987 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3990 SNPRINTF (buff, sizeof(buff),
3991 "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3992 aopPut (AOP (IC_RESULT (ic)), buff, GPTRSIZE - 1);
3996 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
3997 // generates the result if possible. If result is generated, returns TRUE; otherwise
3998 // returns false and caller must deal with fact that result isn't aopOp'd.
3999 bool aopOp3(iCode * ic)
4001 bool dp1InUse, dp2InUse;
4004 // First, generate the right opcode. DPTR may be used if neither left nor result are
4007 // D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
4008 // AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
4009 // AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
4010 // AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
4012 // D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
4013 // AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
4014 // AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
4015 // AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
4018 // Right uses DPTR unless left or result is an AOP_STR; however,
4019 // if right is an AOP_STR, it must use DPTR regardless.
4020 if ((AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)))
4021 && !AOP_IS_STR(IC_RIGHT(ic)))
4030 aopOp (IC_RIGHT(ic),ic,FALSE, useDp2);
4032 // if the right used DPTR, left MUST use DPTR2.
4033 // if the right used DPTR2, left MUST use DPTR.
4034 // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
4035 // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
4036 // enabling us to assign DPTR to result.
4038 if (AOP_USESDPTR(IC_RIGHT(ic)))
4042 else if (AOP_USESDPTR2(IC_RIGHT(ic)))
4048 if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
4058 aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
4061 // We've op'd the left & right. So, if left or right are the same operand as result,
4062 // we know aopOp will succeed, and we can just do it & bail.
4063 if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)))
4065 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4068 if (isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
4070 // D(emitcode(";", "aopOp3: (left | right) & result equal"););
4071 aopOp(IC_RESULT(ic),ic,TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4075 // Operands may be equivalent (but not equal) if they share a spill location. If
4076 // so, use the same DPTR or DPTR2.
4077 if (operandsEqu (IC_LEFT(ic), IC_RESULT(ic)))
4079 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4082 if (operandsEqu (IC_RIGHT(ic), IC_RESULT(ic)))
4084 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4088 // Note which dptrs are currently in use.
4089 dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
4090 dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
4092 // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot
4094 if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
4099 // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
4100 if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
4105 // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck
4106 if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
4111 aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
4113 // Some sanity checking...
4114 if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
4117 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
4118 __FILE__, __LINE__, ic->filename, ic->lineno);
4119 emitcode(";", ">>> unexpected DPTR here.");
4122 if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
4125 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
4126 __FILE__, __LINE__, ic->filename, ic->lineno);
4127 emitcode(";", ">>> unexpected DPTR2 here.");
4133 // Macro to aopOp all three operands of an ic. If this cannot be done,
4134 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
4135 // will be set TRUE. The caller must then handle the case specially, noting
4136 // that the IC_RESULT operand is not aopOp'd.
4138 #define AOP_OP_3_NOFATAL(ic, rc) \
4139 do { rc = !aopOp3(ic); } while (0)
4141 // aopOp the left & right operands of an ic.
4142 #define AOP_OP_2(ic) \
4143 aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
4144 aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
4146 // convienience macro.
4147 #define AOP_SET_LOCALS(ic) \
4148 left = IC_LEFT(ic); \
4149 right = IC_RIGHT(ic); \
4150 result = IC_RESULT(ic);
4153 // Given an integer value of pushedSize bytes on the stack,
4154 // adjust it to be resultSize bytes, either by discarding
4155 // the most significant bytes or by zero-padding.
4157 // On exit from this macro, pushedSize will have been adjusted to
4158 // equal resultSize, and ACC may be trashed.
4159 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
4160 /* If the pushed data is bigger than the result, \
4161 * simply discard unused bytes. Icky, but works. \
4163 while (pushedSize > resultSize) \
4165 D (emitcode (";", "discarding unused result byte."););\
4166 emitcode ("pop", "acc"); \
4169 if (pushedSize < resultSize) \
4171 emitcode ("clr", "a"); \
4172 /* Conversly, we haven't pushed enough here. \
4173 * just zero-pad, and all is well. \
4175 while (pushedSize < resultSize) \
4177 emitcode("push", "acc"); \
4181 assert(pushedSize == resultSize);
4183 /*-----------------------------------------------------------------*/
4184 /* genPlus - generates code for addition */
4185 /*-----------------------------------------------------------------*/
4187 genPlus (iCode * ic)
4189 int size, offset = 0;
4193 D (emitcode (";", "genPlus "););
4195 /* special cases :- */
4196 if ( AOP_IS_STR(IC_LEFT(ic)) &&
4197 isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
4198 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
4199 size = (int)floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
4201 while (size--) emitcode ("inc","dptr");
4203 emitcode ("mov","a,dpl");
4204 emitcode ("add","a,#!constbyte",size & 0xff);
4205 emitcode ("mov","dpl,a");
4206 emitcode ("mov","a,dph");
4207 emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
4208 emitcode ("mov","dph,a");
4209 emitcode ("mov","a,dpx");
4210 emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
4211 emitcode ("mov","dpx,a");
4213 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
4216 if ( IS_SYMOP(IC_LEFT(ic)) &&
4217 OP_SYMBOL(IC_LEFT(ic))->remat &&
4218 isOperandInFarSpace(IC_RIGHT(ic))) {
4219 operand *op = IC_RIGHT(ic);
4220 IC_RIGHT(ic) = IC_LEFT(ic);
4224 AOP_OP_3_NOFATAL (ic, pushResult);
4228 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
4233 /* if literal, literal on the right or
4234 if left requires ACC or right is already
4236 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4237 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
4238 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4240 operand *t = IC_RIGHT (ic);
4241 IC_RIGHT (ic) = IC_LEFT (ic);
4243 emitcode (";", "Swapped plus args.");
4246 /* if both left & right are in bit
4248 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4249 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4255 /* if left in bit space & right literal */
4256 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4257 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4259 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4260 /* if result in bit space */
4261 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4263 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4264 emitcode ("cpl", "c");
4265 outBitC (IC_RESULT (ic));
4269 size = getDataSize (IC_RESULT (ic));
4270 _startLazyDPSEvaluation ();
4273 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4274 emitcode ("addc", "a,#0");
4275 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4277 _endLazyDPSEvaluation ();
4282 /* if I can do an increment instead
4283 of add then GOOD for ME */
4284 if (genPlusIncr (ic) == TRUE)
4286 emitcode (";", "did genPlusIncr");
4291 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4293 _startLazyDPSEvaluation ();
4296 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4298 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4300 emitcode ("add", "a,%s",
4301 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4303 emitcode ("addc", "a,%s",
4304 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4308 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4310 /* right is going to use ACC or we would have taken the
4313 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4315 D(emitcode(";", "+ AOP_ACC special case."););
4316 emitcode("xch", "a, %s", DP2_RESULT_REG);
4318 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4321 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4324 emitcode("add", "a, %s", DP2_RESULT_REG);
4328 emitcode ("add", "a,%s",
4329 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE,
4335 emitcode ("addc", "a,%s",
4336 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE,
4342 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4346 emitcode ("push", "acc");
4350 _endLazyDPSEvaluation ();
4354 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4356 size = getDataSize (IC_LEFT (ic));
4357 rSize = getDataSize (IC_RESULT (ic));
4359 ADJUST_PUSHED_RESULT(size, rSize);
4361 _startLazyDPSEvaluation ();
4364 emitcode ("pop", "acc");
4365 aopPut (AOP (IC_RESULT (ic)), "a", size);
4367 _endLazyDPSEvaluation ();
4370 adjustArithmeticResult (ic);
4373 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4374 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4375 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4378 /*-----------------------------------------------------------------*/
4379 /* genMinusDec :- does subtraction with deccrement if possible */
4380 /*-----------------------------------------------------------------*/
4382 genMinusDec (iCode * ic)
4384 unsigned int icount;
4385 unsigned int size = getDataSize (IC_RESULT (ic));
4387 /* will try to generate an increment */
4388 /* if the right side is not a literal
4390 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4393 /* if the literal value of the right hand side
4394 is greater than 4 then it is not worth it */
4395 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4398 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4399 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4401 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
4405 /* if decrement 16 bits in register */
4406 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4407 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4408 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4417 /* If the next instruction is a goto and the goto target
4418 * is <= 5 instructions previous to this, we can generate
4419 * jumps straight to that target.
4421 if (ic->next && ic->next->op == GOTO
4422 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4425 emitcode (";", "tail decrement optimized (range %d)", labelRange);
4426 tlbl = IC_LABEL (ic->next);
4431 tlbl = newiTempLabel (NULL);
4435 l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
4436 emitcode ("dec", "%s", l);
4438 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4439 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4440 IS_AOP_PREG (IC_RESULT (ic)))
4442 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4446 emitcode ("mov", "a,#!constbyte",0xff);
4447 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4449 l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
4450 emitcode ("dec", "%s", l);
4453 if (!strcmp(l, "acc"))
4455 emitcode("jnz", "!tlabel", tlbl->key + 100);
4457 else 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)), MSB24, FALSE, FALSE, NULL);
4469 emitcode ("dec", "%s", l);
4473 if (!strcmp(l, "acc"))
4475 emitcode("jnz", "!tlabel", tlbl->key + 100);
4477 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4478 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4479 IS_AOP_PREG (IC_RESULT (ic)))
4481 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4485 emitcode ("mov", "a,#!constbyte",0xff);
4486 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4488 l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
4489 emitcode ("dec", "%s", l);
4493 emitcode ("", "!tlabeldef", tlbl->key + 100);
4498 /* if the sizes are greater than 1 then we cannot */
4499 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4500 AOP_SIZE (IC_LEFT (ic)) > 1)
4503 /* we can if the aops of the left & result match or
4504 if they are in registers and the registers are the
4507 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4508 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4509 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4512 _startLazyDPSEvaluation ();
4515 emitcode ("dec", "%s",
4516 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
4518 _endLazyDPSEvaluation ();
4526 /*-----------------------------------------------------------------*/
4527 /* addSign - complete with sign */
4528 /*-----------------------------------------------------------------*/
4530 addSign (operand * result, int offset, int sign)
4532 int size = (getDataSize (result) - offset);
4535 _startLazyDPSEvaluation();
4538 emitcode ("rlc", "a");
4539 emitcode ("subb", "a,acc");
4542 aopPut (AOP (result), "a", offset++);
4549 aopPut (AOP (result), zero, offset++);
4552 _endLazyDPSEvaluation();
4556 /*-----------------------------------------------------------------*/
4557 /* genMinusBits - generates code for subtraction of two bits */
4558 /*-----------------------------------------------------------------*/
4560 genMinusBits (iCode * ic)
4562 symbol *lbl = newiTempLabel (NULL);
4564 D (emitcode (";", "genMinusBits "););
4566 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4568 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4569 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4570 emitcode ("cpl", "c");
4571 emitcode ("", "!tlabeldef", (lbl->key + 100));
4572 outBitC (IC_RESULT (ic));
4576 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4577 emitcode ("subb", "a,acc");
4578 emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4579 emitcode ("inc", "a");
4580 emitcode ("", "!tlabeldef", (lbl->key + 100));
4581 aopPut (AOP (IC_RESULT (ic)), "a", 0);
4582 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4586 /*-----------------------------------------------------------------*/
4587 /* genMinus - generates code for subtraction */
4588 /*-----------------------------------------------------------------*/
4590 genMinus (iCode * ic)
4592 int size, offset = 0;
4597 D (emitcode (";", "genMinus "););
4599 AOP_OP_3_NOFATAL(ic, pushResult);
4603 /* special cases :- */
4604 /* if both left & right are in bit space */
4605 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4606 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4612 /* if I can do an decrement instead
4613 of subtract then GOOD for ME */
4614 if (genMinusDec (ic) == TRUE)
4619 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4621 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4627 lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4632 /* if literal, add a,#-lit, else normal subb */
4633 _startLazyDPSEvaluation ();
4635 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4636 if (AOP_USESDPTR(IC_RIGHT(ic))) {
4637 emitcode ("mov","b,%s",
4638 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4639 MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4640 emitcode ("subb","a,b");
4642 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4643 emitcode ("subb", "a,%s",
4644 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE,
4648 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4649 /* first add without previous c */
4651 if (!size && lit==-1) {
4652 emitcode ("dec", "a");
4654 emitcode ("add", "a,#!constbyte",
4655 (unsigned int) (lit & 0x0FFL));
4658 emitcode ("addc", "a,#!constbyte",
4659 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4664 emitcode ("push", "acc");
4666 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4670 _endLazyDPSEvaluation ();
4674 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4676 size = getDataSize (IC_LEFT (ic));
4677 rSize = getDataSize (IC_RESULT (ic));
4679 ADJUST_PUSHED_RESULT(size, rSize);
4681 _startLazyDPSEvaluation ();
4684 emitcode ("pop", "acc");
4685 aopPut (AOP (IC_RESULT (ic)), "a", size);
4687 _endLazyDPSEvaluation ();
4690 adjustArithmeticResult (ic);
4693 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4694 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4695 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4699 /*-----------------------------------------------------------------*/
4700 /* genMultbits :- multiplication of bits */
4701 /*-----------------------------------------------------------------*/
4703 genMultbits (operand * left,
4708 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4709 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4710 aopOp(result, ic, TRUE, FALSE);
4715 /*-----------------------------------------------------------------*/
4716 /* genMultOneByte : 8*8=8/16 bit multiplication */
4717 /*-----------------------------------------------------------------*/
4719 genMultOneByte (operand * left,
4726 bool runtimeSign, compiletimeSign;
4727 bool lUnsigned, rUnsigned;
4730 /* (if two literals: the value is computed before) */
4731 /* if one literal, literal on the right */
4732 if (AOP_TYPE (left) == AOP_LIT)
4737 emitcode (";", "swapped left and right");
4740 /* (if two literals: the value is computed before) */
4741 /* if one literal, literal on the right */
4742 if (AOP_TYPE (left) == AOP_LIT)
4747 /* emitcode (";", "swapped left and right"); */
4749 /* if no literal, unsigned on the right: shorter code */
4750 if ( AOP_TYPE (right) != AOP_LIT
4751 && SPEC_USIGN (getSpec (operandType (left))))
4758 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4759 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4761 if ((lUnsigned && rUnsigned)
4762 /* sorry, I don't know how to get size
4763 without calling aopOp (result,...);
4764 see Feature Request */
4765 /* || size == 1 */ ) /* no, this is not a bug; with a 1 byte result there's
4766 no need to take care about the signedness! */
4768 /* just an unsigned 8 * 8 = 8 multiply
4770 /* emitcode (";","unsigned"); */
4771 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4772 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4773 emitcode ("mul", "ab");
4775 _G.accInUse++; _G.bInUse++;
4776 aopOp (result, ic, TRUE, FALSE);
4777 size = AOP_SIZE (result);
4779 if (size < 1 || size > 2)
4781 /* this should never happen */
4782 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4783 size, __FILE__, lineno);
4787 aopPut (AOP (result), "a", 0);
4788 _G.accInUse--; _G.bInUse--;
4790 aopPut (AOP (result), "b", 1);
4794 /* we have to do a signed multiply */
4795 /* emitcode (";", "signed"); */
4797 /* now sign adjust for both left & right */
4799 /* let's see what's needed: */
4800 /* apply negative sign during runtime */
4801 runtimeSign = FALSE;
4802 /* negative sign from literals */
4803 compiletimeSign = FALSE;
4807 if (AOP_TYPE(left) == AOP_LIT)
4809 /* signed literal */
4810 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4812 compiletimeSign = TRUE;
4815 /* signed but not literal */
4821 if (AOP_TYPE(right) == AOP_LIT)
4823 /* signed literal */
4824 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4826 compiletimeSign ^= TRUE;
4829 /* signed but not literal */
4833 /* initialize F0, which stores the runtime sign */
4836 if (compiletimeSign)
4837 emitcode ("setb", "F0"); /* set sign flag */
4839 emitcode ("clr", "F0"); /* reset sign flag */
4842 /* save the signs of the operands */
4843 if (AOP_TYPE(right) == AOP_LIT)
4845 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4847 if (!rUnsigned && val < 0)
4848 emitcode ("mov", "b,#!constbyte", -val);
4850 emitcode ("mov", "b,#!constbyte", (unsigned char) val);
4852 else /* ! literal */
4854 if (rUnsigned) /* emitcode (";", "signed"); */
4855 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4858 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4859 lbl = newiTempLabel (NULL);
4860 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
4861 emitcode ("cpl", "F0"); /* complement sign flag */
4862 emitcode ("cpl", "a"); /* 2's complement */
4863 emitcode ("inc", "a");
4864 emitcode ("", "!tlabeldef", lbl->key + 100);
4865 emitcode ("mov", "b,a");
4869 if (AOP_TYPE(left) == AOP_LIT)
4871 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4873 if (!lUnsigned && val < 0)
4874 emitcode ("mov", "a,#!constbyte", -val);
4876 emitcode ("mov", "a,#!constbyte", (unsigned char) val);
4878 else /* ! literal */
4880 if (lUnsigned) /* emitcode (";", "signed"); */
4882 emitcode ("mov", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4885 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4886 lbl = newiTempLabel (NULL);
4887 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
4888 emitcode ("cpl", "F0"); /* complement sign flag */
4889 emitcode ("cpl", "a"); /* 2's complement */
4890 emitcode ("inc", "a");
4891 emitcode ("", "!tlabeldef", lbl->key + 100);
4895 /* now the multiplication */
4896 emitcode ("mul", "ab");
4897 _G.accInUse++;_G.bInUse++;
4898 aopOp(result, ic, TRUE, FALSE);
4899 size = AOP_SIZE (result);
4901 if (size < 1 || size > 2)
4903 /* this should never happen */
4904 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4905 size, __FILE__, lineno);
4909 if (runtimeSign || compiletimeSign)
4911 lbl = newiTempLabel (NULL);
4913 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
4914 emitcode ("cpl", "a"); /* lsb 2's complement */
4916 emitcode ("inc", "a"); /* inc doesn't set carry flag */
4919 emitcode ("add", "a,#1"); /* this sets carry flag */
4920 emitcode ("xch", "a,b");
4921 emitcode ("cpl", "a"); /* msb 2's complement */
4922 emitcode ("addc", "a,#0");
4923 emitcode ("xch", "a,b");
4925 emitcode ("", "!tlabeldef", lbl->key + 100);
4927 aopPut (AOP (result), "a", 0);
4928 _G.accInUse--;_G.bInUse--;
4930 aopPut (AOP (result), "b", 1);
4933 /*-----------------------------------------------------------------*/
4934 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
4935 /*-----------------------------------------------------------------*/
4936 static void genMultTwoByte (operand *left, operand *right,
4937 operand *result, iCode *ic)
4939 sym_link *retype = getSpec(operandType(right));
4940 sym_link *letype = getSpec(operandType(left));
4941 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4944 if (AOP_TYPE (left) == AOP_LIT) {
4949 /* save EA bit in F1 */
4950 lbl = newiTempLabel(NULL);
4951 emitcode ("setb","F1");
4952 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4953 emitcode ("clr","F1");
4954 emitcode("","!tlabeldef",lbl->key+100);
4956 /* load up MB with right */
4958 emitcode("clr","F0");
4959 if (AOP_TYPE(right) == AOP_LIT) {
4960 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
4962 emitcode("setb","F0");
4965 emitcode ("mov","mb,#!constbyte",val & 0xff);
4966 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4968 lbl = newiTempLabel(NULL);
4969 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4970 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4971 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4972 emitcode ("xch", "a,b");
4973 emitcode ("cpl","a");
4974 emitcode ("add", "a,#1");
4975 emitcode ("xch", "a,b");
4976 emitcode ("cpl", "a"); // msb
4977 emitcode ("addc", "a,#0");
4978 emitcode ("setb","F0");
4979 emitcode ("","!tlabeldef",lbl->key+100);
4980 emitcode ("mov","mb,b");
4981 emitcode ("mov","mb,a");
4984 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4985 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4987 /* load up MA with left */
4989 lbl = newiTempLabel(NULL);
4990 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4991 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4992 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4993 emitcode ("xch", "a,b");
4994 emitcode ("cpl","a");
4995 emitcode ("add", "a,#1");
4996 emitcode ("xch", "a,b");
4997 emitcode ("cpl", "a"); // msb
4998 emitcode ("addc","a,#0");
4999 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5000 emitcode ("setb","F0");
5001 emitcode ("","!tlabeldef",lbl->key+100);
5002 emitcode ("mov","ma,b");
5003 emitcode ("mov","ma,a");
5005 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5006 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5008 /* wait for multiplication to finish */
5009 lbl = newiTempLabel(NULL);
5010 emitcode("","!tlabeldef", lbl->key+100);
5011 emitcode("mov","a,mcnt1");
5012 emitcode("anl","a,#!constbyte",0x80);
5013 emitcode("jnz","!tlabel",lbl->key+100);
5015 freeAsmop (left, NULL, ic, TRUE);
5016 freeAsmop (right, NULL, ic,TRUE);
5017 aopOp(result, ic, TRUE, FALSE);
5019 /* if unsigned then simple */
5021 emitcode ("mov","a,ma");
5022 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
5023 emitcode ("mov","a,ma");
5024 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
5025 aopPut(AOP(result),"ma",1);
5026 aopPut(AOP(result),"ma",0);
5028 emitcode("push","ma");
5029 emitcode("push","ma");
5030 emitcode("push","ma");
5032 /* negate result if needed */
5033 lbl = newiTempLabel(NULL);
5034 emitcode("jnb","F0,!tlabel",lbl->key+100);
5035 emitcode("cpl","a");
5036 emitcode("add","a,#1");
5037 emitcode("","!tlabeldef", lbl->key+100);
5038 if (AOP_TYPE(result) == AOP_ACC)
5040 D(emitcode(";", "ACC special case."););
5041 /* We know result is the only live aop, and
5042 * it's obviously not a DPTR2, so AP is available.
5044 emitcode("mov", "%s,acc", DP2_RESULT_REG);
5048 aopPut(AOP(result),"a",0);
5051 emitcode("pop","acc");
5052 lbl = newiTempLabel(NULL);
5053 emitcode("jnb","F0,!tlabel",lbl->key+100);
5054 emitcode("cpl","a");
5055 emitcode("addc","a,#0");
5056 emitcode("","!tlabeldef", lbl->key+100);
5057 aopPut(AOP(result),"a",1);
5058 emitcode("pop","acc");
5059 if (AOP_SIZE(result) >= 3) {
5060 lbl = newiTempLabel(NULL);
5061 emitcode("jnb","F0,!tlabel",lbl->key+100);
5062 emitcode("cpl","a");
5063 emitcode("addc","a,#0");
5064 emitcode("","!tlabeldef", lbl->key+100);
5065 aopPut(AOP(result),"a",2);
5067 emitcode("pop","acc");
5068 if (AOP_SIZE(result) >= 4) {
5069 lbl = newiTempLabel(NULL);
5070 emitcode("jnb","F0,!tlabel",lbl->key+100);
5071 emitcode("cpl","a");
5072 emitcode("addc","a,#0");
5073 emitcode("","!tlabeldef", lbl->key+100);
5074 aopPut(AOP(result),"a",3);
5076 if (AOP_TYPE(result) == AOP_ACC)
5078 /* We stashed the result away above. */
5079 emitcode("mov", "acc,%s", DP2_RESULT_REG);
5083 freeAsmop (result, NULL, ic, TRUE);
5085 /* restore EA bit in F1 */
5086 lbl = newiTempLabel(NULL);
5087 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5088 emitcode ("setb","EA");
5089 emitcode("","!tlabeldef",lbl->key+100);
5093 /*-----------------------------------------------------------------*/
5094 /* genMult - generates code for multiplication */
5095 /*-----------------------------------------------------------------*/
5097 genMult (iCode * ic)
5099 operand *left = IC_LEFT (ic);
5100 operand *right = IC_RIGHT (ic);
5101 operand *result = IC_RESULT (ic);
5103 D (emitcode (";", "genMult "););
5105 /* assign the amsops */
5108 /* special cases first */
5110 if (AOP_TYPE (left) == AOP_CRY &&
5111 AOP_TYPE (right) == AOP_CRY)
5113 genMultbits (left, right, result, ic);
5117 /* if both are of size == 1 */
5118 if (AOP_SIZE (left) == 1 &&
5119 AOP_SIZE (right) == 1)
5121 genMultOneByte (left, right, result, ic);
5125 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5126 /* use the ds390 ARITHMETIC accel UNIT */
5127 genMultTwoByte (left, right, result, ic);
5130 /* should have been converted to function call */
5134 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5135 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5136 freeAsmop (result, NULL, ic, TRUE);
5139 /*-----------------------------------------------------------------*/
5140 /* genDivbits :- division of bits */
5141 /*-----------------------------------------------------------------*/
5143 genDivbits (operand * left,
5151 /* the result must be bit */
5152 LOAD_AB_FOR_DIV (left, right, l);
5153 emitcode ("div", "ab");
5154 emitcode ("rrc", "a");
5155 aopOp(result, ic, TRUE, FALSE);
5157 aopPut (AOP (result), "c", 0);
5160 /*-----------------------------------------------------------------*/
5161 /* genDivOneByte : 8 bit division */
5162 /*-----------------------------------------------------------------*/
5164 genDivOneByte (operand * left,
5169 bool lUnsigned, rUnsigned;
5170 bool runtimeSign, compiletimeSign;
5176 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5177 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5179 /* signed or unsigned */
5180 if (lUnsigned && rUnsigned)
5182 /* unsigned is easy */
5183 LOAD_AB_FOR_DIV (left, right, l);
5184 emitcode ("div", "ab");
5187 aopOp (result, ic, TRUE, FALSE);
5188 aopPut (AOP (result), "a", 0);
5191 size = AOP_SIZE (result) - 1;
5194 aopPut (AOP (result), zero, offset++);
5198 /* signed is a little bit more difficult */
5200 /* now sign adjust for both left & right */
5202 /* let's see what's needed: */
5203 /* apply negative sign during runtime */
5204 runtimeSign = FALSE;
5205 /* negative sign from literals */
5206 compiletimeSign = FALSE;
5210 if (AOP_TYPE(left) == AOP_LIT)
5212 /* signed literal */
5213 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5215 compiletimeSign = TRUE;
5218 /* signed but not literal */
5224 if (AOP_TYPE(right) == AOP_LIT)
5226 /* signed literal */
5227 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5229 compiletimeSign ^= TRUE;
5232 /* signed but not literal */
5236 /* initialize F0, which stores the runtime sign */
5239 if (compiletimeSign)
5240 emitcode ("setb", "F0"); /* set sign flag */
5242 emitcode ("clr", "F0"); /* reset sign flag */
5245 /* save the signs of the operands */
5246 if (AOP_TYPE(right) == AOP_LIT)
5248 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5250 if (!rUnsigned && val < 0)
5251 emitcode ("mov", "b,#0x%02x", -val);
5253 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5255 else /* ! literal */
5258 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5261 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5262 lbl = newiTempLabel (NULL);
5263 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5264 emitcode ("cpl", "F0"); /* complement sign flag */
5265 emitcode ("cpl", "a"); /* 2's complement */
5266 emitcode ("inc", "a");
5267 emitcode ("", "!tlabeldef", lbl->key + 100);
5268 emitcode ("mov", "b,a");
5272 if (AOP_TYPE(left) == AOP_LIT)
5274 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5276 if (!lUnsigned && val < 0)
5277 emitcode ("mov", "a,#0x%02x", -val);
5279 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5281 else /* ! literal */
5284 emitcode ("mov", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5287 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5288 lbl = newiTempLabel (NULL);
5289 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5290 emitcode ("cpl", "F0"); /* complement sign flag */
5291 emitcode ("cpl", "a"); /* 2's complement */
5292 emitcode ("inc", "a");
5293 emitcode ("", "!tlabeldef", lbl->key + 100);
5297 /* now the division */
5298 emitcode ("nop", "; workaround for DS80C390 div bug.");
5299 emitcode ("div", "ab");
5301 if (runtimeSign || compiletimeSign)
5303 lbl = newiTempLabel (NULL);
5305 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5306 emitcode ("cpl", "a"); /* lsb 2's complement */
5307 emitcode ("inc", "a");
5308 emitcode ("", "!tlabeldef", lbl->key + 100);
5310 _G.accInUse++; _G.bInUse++;
5311 aopOp (result, ic, TRUE, FALSE);
5312 size = AOP_SIZE (result) - 1;
5316 /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
5317 then the result will be in b, a */
5318 emitcode ("mov", "b,a"); /* 1 */
5319 /* msb is 0x00 or 0xff depending on the sign */
5322 emitcode ("mov", "c,F0");
5323 emitcode ("subb", "a,acc");
5324 emitcode ("xch", "a,b"); /* 2 */
5326 aopPut (AOP (result), "b", offset++); /* write msb's */
5328 else /* compiletimeSign */
5330 aopPut (AOP (result), "#0xff", offset++); /* write msb's */
5332 aopPut (AOP (result), "a", 0); /* 3: write lsb */
5336 _G.accInUse++; _G.bInUse++;
5337 aopOp(result, ic, TRUE, FALSE);
5338 size = AOP_SIZE (result) - 1;
5340 aopPut (AOP (result), "a", 0);
5342 aopPut (AOP (result), zero, offset++);
5344 _G.accInUse--; _G.bInUse--;
5348 /*-----------------------------------------------------------------*/
5349 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
5350 /*-----------------------------------------------------------------*/
5351 static void genDivTwoByte (operand *left, operand *right,
5352 operand *result, iCode *ic)
5354 sym_link *retype = getSpec(operandType(right));
5355 sym_link *letype = getSpec(operandType(left));
5356 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5359 /* save EA bit in F1 */
5360 lbl = newiTempLabel(NULL);
5361 emitcode ("setb","F1");
5362 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5363 emitcode ("clr","F1");
5364 emitcode("","!tlabeldef",lbl->key+100);
5366 /* load up MA with left */
5368 emitcode("clr","F0");
5369 lbl = newiTempLabel(NULL);
5370 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5371 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5372 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5373 emitcode ("xch", "a,b");
5374 emitcode ("cpl","a");
5375 emitcode ("add", "a,#1");
5376 emitcode ("xch", "a,b");
5377 emitcode ("cpl", "a"); // msb
5378 emitcode ("addc","a,#0");
5379 emitcode ("setb","F0");
5380 emitcode ("","!tlabeldef",lbl->key+100);
5381 emitcode ("mov","ma,b");
5382 emitcode ("mov","ma,a");
5384 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5385 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5388 /* load up MB with right */
5390 if (AOP_TYPE(right) == AOP_LIT) {
5391 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5393 lbl = newiTempLabel(NULL);
5394 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5395 emitcode("setb","F0");
5396 emitcode ("","!tlabeldef",lbl->key+100);
5399 emitcode ("mov","mb,#!constbyte",val & 0xff);
5400 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5402 lbl = newiTempLabel(NULL);
5403 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5404 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5405 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5406 emitcode ("xch", "a,b");
5407 emitcode ("cpl","a");
5408 emitcode ("add", "a,#1");
5409 emitcode ("xch", "a,b");
5410 emitcode ("cpl", "a"); // msb
5411 emitcode ("addc", "a,#0");
5412 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5413 emitcode ("setb","F0");
5414 emitcode ("","!tlabeldef",lbl->key+100);
5415 emitcode ("mov","mb,b");
5416 emitcode ("mov","mb,a");
5419 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5420 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5423 /* wait for multiplication to finish */
5424 lbl = newiTempLabel(NULL);
5425 emitcode("","!tlabeldef", lbl->key+100);
5426 emitcode("mov","a,mcnt1");
5427 emitcode("anl","a,#!constbyte",0x80);
5428 emitcode("jnz","!tlabel",lbl->key+100);
5430 freeAsmop (left, NULL, ic, TRUE);
5431 freeAsmop (right, NULL, ic,TRUE);
5432 aopOp(result, ic, TRUE, FALSE);
5434 /* if unsigned then simple */
5436 aopPut(AOP(result),"ma",1);
5437 aopPut(AOP(result),"ma",0);
5439 emitcode("push","ma");
5441 /* negate result if needed */
5442 lbl = newiTempLabel(NULL);
5443 emitcode("jnb","F0,!tlabel",lbl->key+100);
5444 emitcode("cpl","a");
5445 emitcode("add","a,#1");
5446 emitcode("","!tlabeldef", lbl->key+100);
5447 aopPut(AOP(result),"a",0);
5448 emitcode("pop","acc");
5449 lbl = newiTempLabel(NULL);
5450 emitcode("jnb","F0,!tlabel",lbl->key+100);
5451 emitcode("cpl","a");
5452 emitcode("addc","a,#0");
5453 emitcode("","!tlabeldef", lbl->key+100);
5454 aopPut(AOP(result),"a",1);
5456 freeAsmop (result, NULL, ic, TRUE);
5457 /* restore EA bit in F1 */
5458 lbl = newiTempLabel(NULL);
5459 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5460 emitcode ("setb","EA");
5461 emitcode("","!tlabeldef",lbl->key+100);
5465 /*-----------------------------------------------------------------*/
5466 /* genDiv - generates code for division */
5467 /*-----------------------------------------------------------------*/
5471 operand *left = IC_LEFT (ic);
5472 operand *right = IC_RIGHT (ic);
5473 operand *result = IC_RESULT (ic);
5475 D (emitcode (";", "genDiv "););
5477 /* assign the amsops */
5480 /* special cases first */
5482 if (AOP_TYPE (left) == AOP_CRY &&
5483 AOP_TYPE (right) == AOP_CRY)
5485 genDivbits (left, right, result, ic);
5489 /* if both are of size == 1 */
5490 if (AOP_SIZE (left) == 1 &&
5491 AOP_SIZE (right) == 1)
5493 genDivOneByte (left, right, result, ic);
5497 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5498 /* use the ds390 ARITHMETIC accel UNIT */
5499 genDivTwoByte (left, right, result, ic);
5502 /* should have been converted to function call */
5505 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5506 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5507 freeAsmop (result, NULL, ic, TRUE);
5510 /*-----------------------------------------------------------------*/
5511 /* genModbits :- modulus of bits */
5512 /*-----------------------------------------------------------------*/
5514 genModbits (operand * left,
5522 /* the result must be bit */
5523 LOAD_AB_FOR_DIV (left, right, l);
5524 emitcode ("div", "ab");
5525 emitcode ("mov", "a,b");
5526 emitcode ("rrc", "a");
5527 aopOp(result, ic, TRUE, FALSE);
5528 aopPut (AOP (result), "c", 0);
5531 /*-----------------------------------------------------------------*/
5532 /* genModOneByte : 8 bit modulus */
5533 /*-----------------------------------------------------------------*/
5535 genModOneByte (operand * left,
5540 bool lUnsigned, rUnsigned;
5541 bool runtimeSign, compiletimeSign;
5547 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5548 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5550 /* signed or unsigned */
5551 if (lUnsigned && rUnsigned)
5553 /* unsigned is easy */
5554 LOAD_AB_FOR_DIV (left, right, l);
5555 emitcode ("div", "ab");
5556 aopOp (result, ic, TRUE, FALSE);
5557 aopPut (AOP (result), "b", 0);
5559 for (size = AOP_SIZE (result) - 1; size--;)
5560 aopPut (AOP (result), zero, offset++);
5564 /* signed is a little bit more difficult */
5566 /* now sign adjust for both left & right */
5568 /* modulus: sign of the right operand has no influence on the result! */
5569 if (AOP_TYPE(right) == AOP_LIT)
5571 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5573 if (!rUnsigned && val < 0)
5574 emitcode ("mov", "b,#0x%02x", -val);
5576 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5578 else /* ! literal */
5581 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5584 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5585 lbl = newiTempLabel (NULL);
5586 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5587 emitcode ("cpl", "a"); /* 2's complement */
5588 emitcode ("inc", "a");
5589 emitcode ("", "!tlabeldef", lbl->key + 100);
5590 emitcode ("mov", "b,a");
5594 /* let's see what's needed: */
5595 /* apply negative sign during runtime */
5596 runtimeSign = FALSE;
5597 /* negative sign from literals */
5598 compiletimeSign = FALSE;
5600 /* sign adjust left side */
5601 if (AOP_TYPE(left) == AOP_LIT)
5603 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5605 if (!lUnsigned && val < 0)
5607 compiletimeSign = TRUE; /* set sign flag */
5608 emitcode ("mov", "a,#0x%02x", -val);
5611 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5613 else /* ! literal */
5615 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5620 emitcode ("clr", "F0"); /* clear sign flag */
5622 lbl = newiTempLabel (NULL);
5623 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5624 emitcode ("setb", "F0"); /* set sign flag */
5625 emitcode ("cpl", "a"); /* 2's complement */
5626 emitcode ("inc", "a");
5627 emitcode ("", "!tlabeldef", lbl->key + 100);
5631 /* now the modulus */
5632 emitcode ("nop", "; workaround for DS80C390 div bug.");
5633 emitcode ("div", "ab");
5635 if (runtimeSign || compiletimeSign)
5637 emitcode ("mov", "a,b");
5638 lbl = newiTempLabel (NULL);
5640 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5641 emitcode ("cpl", "a"); /* lsb 2's complement */
5642 emitcode ("inc", "a");
5643 emitcode ("", "!tlabeldef", lbl->key + 100);
5645 _G.accInUse++; _G.bInUse++;
5646 aopOp (result, ic, TRUE, FALSE);
5647 size = AOP_SIZE (result) - 1;
5651 /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
5652 then the result will be in b, a */
5653 emitcode ("mov", "b,a"); /* 1 */
5654 /* msb is 0x00 or 0xff depending on the sign */
5657 emitcode ("mov", "c,F0");
5658 emitcode ("subb", "a,acc");
5659 emitcode ("xch", "a,b"); /* 2 */
5661 aopPut (AOP (result), "b", offset++); /* write msb's */
5663 else /* compiletimeSign */
5665 aopPut (AOP (result), "#0xff", offset++); /* write msb's */
5667 aopPut (AOP (result), "a", 0); /* 3: write lsb */
5671 _G.accInUse++; _G.bInUse++;
5672 aopOp(result, ic, TRUE, FALSE);
5673 size = AOP_SIZE (result) - 1;
5675 aopPut (AOP (result), "b", 0);
5677 aopPut (AOP (result), zero, offset++);
5679 _G.accInUse--; _G.bInUse--;
5683 /*-----------------------------------------------------------------*/
5684 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
5685 /*-----------------------------------------------------------------*/
5686 static void genModTwoByte (operand *left, operand *right,
5687 operand *result, iCode *ic)
5689 sym_link *retype = getSpec(operandType(right));
5690 sym_link *letype = getSpec(operandType(left));
5691 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5694 /* load up MA with left */
5695 /* save EA bit in F1 */
5696 lbl = newiTempLabel(NULL);
5697 emitcode ("setb","F1");
5698 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5699 emitcode ("clr","F1");
5700 emitcode("","!tlabeldef",lbl->key+100);
5703 lbl = newiTempLabel(NULL);
5704 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5705 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5706 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5707 emitcode ("xch", "a,b");
5708 emitcode ("cpl","a");
5709 emitcode ("add", "a,#1");
5710 emitcode ("xch", "a,b");
5711 emitcode ("cpl", "a"); // msb
5712 emitcode ("addc","a,#0");
5713 emitcode ("","!tlabeldef",lbl->key+100);
5714 emitcode ("mov","ma,b");
5715 emitcode ("mov","ma,a");
5717 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5718 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5721 /* load up MB with right */
5723 if (AOP_TYPE(right) == AOP_LIT) {
5724 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5728 emitcode ("mov","mb,#!constbyte",val & 0xff);
5729 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5731 lbl = newiTempLabel(NULL);
5732 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5733 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5734 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5735 emitcode ("xch", "a,b");
5736 emitcode ("cpl","a");
5737 emitcode ("add", "a,#1");
5738 emitcode ("xch", "a,b");
5739 emitcode ("cpl", "a"); // msb
5740 emitcode ("addc", "a,#0");
5741 emitcode ("","!tlabeldef",lbl->key+100);
5742 emitcode ("mov","mb,b");
5743 emitcode ("mov","mb,a");
5746 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5747 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5750 /* wait for multiplication to finish */
5751 lbl = newiTempLabel(NULL);
5752 emitcode("","!tlabeldef", lbl->key+100);
5753 emitcode("mov","a,mcnt1");
5754 emitcode("anl","a,#!constbyte",0x80);
5755 emitcode("jnz","!tlabel",lbl->key+100);
5757 freeAsmop (left, NULL, ic, TRUE);
5758 freeAsmop (right, NULL, ic,TRUE);
5759 aopOp(result, ic, TRUE, FALSE);
5761 aopPut(AOP(result),"mb",1);
5762 aopPut(AOP(result),"mb",0);
5763 freeAsmop (result, NULL, ic, TRUE);
5765 /* restore EA bit in F1 */
5766 lbl = newiTempLabel(NULL);
5767 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5768 emitcode ("setb","EA");
5769 emitcode("","!tlabeldef",lbl->key+100);
5773 /*-----------------------------------------------------------------*/
5774 /* genMod - generates code for division */
5775 /*-----------------------------------------------------------------*/
5779 operand *left = IC_LEFT (ic);
5780 operand *right = IC_RIGHT (ic);
5781 operand *result = IC_RESULT (ic);
5783 D (emitcode (";", "genMod "); );
5785 /* assign the amsops */
5788 /* special cases first */
5790 if (AOP_TYPE (left) == AOP_CRY &&
5791 AOP_TYPE (right) == AOP_CRY)
5793 genModbits (left, right, result, ic);
5797 /* if both are of size == 1 */
5798 if (AOP_SIZE (left) == 1 &&
5799 AOP_SIZE (right) == 1)
5801 genModOneByte (left, right, result, ic);
5805 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5806 /* use the ds390 ARITHMETIC accel UNIT */
5807 genModTwoByte (left, right, result, ic);
5811 /* should have been converted to function call */
5815 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5816 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5817 freeAsmop (result, NULL, ic, TRUE);
5820 /*-----------------------------------------------------------------*/
5821 /* genIfxJump :- will create a jump depending on the ifx */
5822 /*-----------------------------------------------------------------*/
5824 genIfxJump (iCode * ic, char *jval)
5827 symbol *tlbl = newiTempLabel (NULL);
5830 D (emitcode (";", "genIfxJump"););
5832 /* if true label then we jump if condition
5836 jlbl = IC_TRUE (ic);
5837 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5838 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5842 /* false label is present */
5843 jlbl = IC_FALSE (ic);
5844 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5845 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5847 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5848 emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5850 emitcode (inst, "!tlabel", tlbl->key + 100);
5851 emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5852 emitcode ("", "!tlabeldef", tlbl->key + 100);
5854 /* mark the icode as generated */
5858 /*-----------------------------------------------------------------*/
5859 /* genCmp :- greater or less than comparison */
5860 /*-----------------------------------------------------------------*/
5862 genCmp (operand * left, operand * right,
5863 iCode * ic, iCode * ifx, int sign)
5865 int size, offset = 0;
5866 unsigned long lit = 0L;
5869 D (emitcode (";", "genCmp"););
5871 result = IC_RESULT (ic);
5873 /* if left & right are bit variables */
5874 if (AOP_TYPE (left) == AOP_CRY &&
5875 AOP_TYPE (right) == AOP_CRY)
5877 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5878 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5882 /* subtract right from left if at the
5883 end the carry flag is set then we know that
5884 left is greater than right */
5885 size = max (AOP_SIZE (left), AOP_SIZE (right));
5887 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5888 if ((size == 1) && !sign
5889 && (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5891 symbol *lbl = newiTempLabel (NULL);
5892 emitcode ("cjne", "%s,%s,!tlabel",
5893 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
5894 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5896 emitcode ("", "!tlabeldef", lbl->key + 100);
5900 if (AOP_TYPE (right) == AOP_LIT)
5902 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5903 /* optimize if(x < 0) or if(x >= 0) */
5912 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
5914 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5915 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5917 aopOp (result, ic, FALSE, FALSE);
5919 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5921 freeAsmop (result, NULL, ic, TRUE);
5922 genIfxJump (ifx, "acc.7");
5927 emitcode ("rlc", "a");
5929 goto release_freedLR;
5937 // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5938 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5939 // emitcode (";", "genCmp #2");
5940 if (sign && (size == 0))
5942 // emitcode (";", "genCmp #3");
5943 emitcode ("xrl", "a,#!constbyte",0x80);
5944 if (AOP_TYPE (right) == AOP_LIT)
5946 unsigned long lit = (unsigned long)
5947 floatFromVal (AOP (right)->aopu.aop_lit);
5948 // emitcode (";", "genCmp #3.1");
5949 emitcode ("subb", "a,#!constbyte",
5950 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5954 // emitcode (";", "genCmp #3.2");
5956 MOVB(aopGet (AOP (right), offset++, FALSE, FALSE, "b"));
5957 saveAccWarn = DEFAULT_ACC_WARNING;
5958 emitcode ("xrl", "b,#!constbyte",0x80);
5959 emitcode ("subb", "a,b");
5966 // emitcode (";", "genCmp #4");
5968 s = aopGet (AOP (right), offset++, FALSE, FALSE, "b");
5969 saveAccWarn = DEFAULT_ACC_WARNING;
5971 emitcode ("subb", "a,%s", s);
5978 /* Don't need the left & right operands any more; do need the result. */
5979 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5980 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5982 aopOp (result, ic, FALSE, FALSE);
5986 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5992 /* if the result is used in the next
5993 ifx conditional branch then generate
5994 code a little differently */
5997 genIfxJump (ifx, "c");
6003 /* leave the result in acc */
6005 freeAsmop (result, NULL, ic, TRUE);
6008 /*-----------------------------------------------------------------*/
6009 /* genCmpGt :- greater than comparison */
6010 /*-----------------------------------------------------------------*/
6012 genCmpGt (iCode * ic, iCode * ifx)
6014 operand *left, *right;
6015 sym_link *letype, *retype;
6018 D (emitcode (";", "genCmpGt ");
6021 left = IC_LEFT (ic);
6022 right = IC_RIGHT (ic);
6024 letype = getSpec (operandType (left));
6025 retype = getSpec (operandType (right));
6026 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6028 /* assign the left & right amsops */
6031 genCmp (right, left, ic, ifx, sign);
6034 /*-----------------------------------------------------------------*/
6035 /* genCmpLt - less than comparisons */
6036 /*-----------------------------------------------------------------*/
6038 genCmpLt (iCode * ic, iCode * ifx)
6040 operand *left, *right;
6041 sym_link *letype, *retype;
6044 D (emitcode (";", "genCmpLt "););
6046 left = IC_LEFT (ic);
6047 right = IC_RIGHT (ic);
6049 letype = getSpec (operandType (left));
6050 retype = getSpec (operandType (right));
6051 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6053 /* assign the left & right amsops */
6056 genCmp (left, right, ic, ifx, sign);
6059 /*-----------------------------------------------------------------*/
6060 /* gencjneshort - compare and jump if not equal */
6061 /*-----------------------------------------------------------------*/
6063 gencjneshort (operand * left, operand * right, symbol * lbl)
6065 int size = max (AOP_SIZE (left), AOP_SIZE (right));
6067 unsigned long lit = 0L;
6069 D (emitcode (";", "gencjneshort");
6072 /* if the left side is a literal or
6073 if the right is in a pointer register and left
6075 if ((AOP_TYPE (left) == AOP_LIT) ||
6076 (AOP_TYPE (left) == AOP_IMMD) ||
6077 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6084 if (AOP_TYPE (right) == AOP_LIT)
6085 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6087 if (opIsGptr (left) || opIsGptr (right))
6089 /* We are comparing a generic pointer to something.
6090 * Exclude the generic type byte from the comparison.
6093 D (emitcode (";", "cjneshort: generic ptr special case."););
6097 /* if the right side is a literal then anything goes */
6098 if (AOP_TYPE (right) == AOP_LIT &&
6099 AOP_TYPE (left) != AOP_DIR)
6103 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6104 emitcode ("cjne", "a,%s,!tlabel",
6105 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
6111 /* if the right side is in a register or in direct space or
6112 if the left is a pointer register & right is not */
6113 else if (AOP_TYPE (right) == AOP_REG ||
6114 AOP_TYPE (right) == AOP_DIR ||
6115 AOP_TYPE (right) == AOP_LIT ||
6116 AOP_TYPE (right) == AOP_IMMD ||
6117 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6118 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6122 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6123 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6124 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6125 emitcode ("jnz", "!tlabel", lbl->key + 100);
6127 emitcode ("cjne", "a,%s,!tlabel",
6128 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
6135 /* right is a pointer reg need both a & b */
6138 MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6139 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6140 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
6146 /*-----------------------------------------------------------------*/
6147 /* gencjne - compare and jump if not equal */
6148 /*-----------------------------------------------------------------*/
6150 gencjne (operand * left, operand * right, symbol * lbl)
6152 symbol *tlbl = newiTempLabel (NULL);
6154 D (emitcode (";", "gencjne");
6157 gencjneshort (left, right, lbl);
6159 emitcode ("mov", "a,%s", one);
6160 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
6161 emitcode ("", "!tlabeldef", lbl->key + 100);
6162 emitcode ("clr", "a");
6163 emitcode ("", "!tlabeldef", tlbl->key + 100);
6166 /*-----------------------------------------------------------------*/
6167 /* genCmpEq - generates code for equal to */
6168 /*-----------------------------------------------------------------*/
6170 genCmpEq (iCode * ic, iCode * ifx)
6172 operand *left, *right, *result;
6174 D (emitcode (";", "genCmpEq ");
6178 AOP_SET_LOCALS (ic);
6180 /* if literal, literal on the right or
6181 if the right is in a pointer register and left
6183 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6184 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6186 operand *t = IC_RIGHT (ic);
6187 IC_RIGHT (ic) = IC_LEFT (ic);
6191 if (ifx && /* !AOP_SIZE(result) */
6192 OP_SYMBOL (result) &&
6193 OP_SYMBOL (result)->regType == REG_CND)
6196 /* if they are both bit variables */
6197 if (AOP_TYPE (left) == AOP_CRY &&
6198 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6200 if (AOP_TYPE (right) == AOP_LIT)
6202 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6205 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6206 emitcode ("cpl", "c");
6210 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6214 emitcode ("clr", "c");
6216 /* AOP_TYPE(right) == AOP_CRY */
6220 symbol *lbl = newiTempLabel (NULL);
6221 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6222 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6223 emitcode ("cpl", "c");
6224 emitcode ("", "!tlabeldef", (lbl->key + 100));
6226 /* if true label then we jump if condition
6228 tlbl = newiTempLabel (NULL);
6231 emitcode ("jnc", "!tlabel", tlbl->key + 100);
6232 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6236 emitcode ("jc", "!tlabel", tlbl->key + 100);
6237 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6239 emitcode ("", "!tlabeldef", tlbl->key + 100);
6243 tlbl = newiTempLabel (NULL);
6244 gencjneshort (left, right, tlbl);
6247 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6248 emitcode ("", "!tlabeldef", tlbl->key + 100);
6252 symbol *lbl = newiTempLabel (NULL);
6253 emitcode ("sjmp", "!tlabel", lbl->key + 100);
6254 emitcode ("", "!tlabeldef", tlbl->key + 100);
6255 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6256 emitcode ("", "!tlabeldef", lbl->key + 100);
6259 /* mark the icode as generated */
6262 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6263 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6267 /* if they are both bit variables */
6268 if (AOP_TYPE (left) == AOP_CRY &&
6269 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6271 if (AOP_TYPE (right) == AOP_LIT)
6273 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6276 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6277 emitcode ("cpl", "c");
6281 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6285 emitcode ("clr", "c");
6287 /* AOP_TYPE(right) == AOP_CRY */
6291 symbol *lbl = newiTempLabel (NULL);
6292 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6293 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6294 emitcode ("cpl", "c");
6295 emitcode ("", "!tlabeldef", (lbl->key + 100));
6298 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6299 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6301 aopOp (result, ic, TRUE, FALSE);
6304 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6311 genIfxJump (ifx, "c");
6314 /* if the result is used in an arithmetic operation
6315 then put the result in place */
6320 gencjne (left, right, newiTempLabel (NULL));
6322 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6323 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6325 aopOp (result, ic, TRUE, FALSE);
6327 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6329 aopPut (AOP (result), "a", 0);
6334 genIfxJump (ifx, "a");
6337 /* if the result is used in an arithmetic operation
6338 then put the result in place */
6339 if (AOP_TYPE (result) != AOP_CRY)
6341 /* leave the result in acc */
6345 freeAsmop (result, NULL, ic, TRUE);
6348 /*-----------------------------------------------------------------*/
6349 /* ifxForOp - returns the icode containing the ifx for operand */
6350 /*-----------------------------------------------------------------*/
6352 ifxForOp (operand * op, iCode * ic)
6354 /* if true symbol then needs to be assigned */
6355 if (IS_TRUE_SYMOP (op))
6358 /* if this has register type condition and
6359 the next instruction is ifx with the same operand
6360 and live to of the operand is upto the ifx only then */
6362 ic->next->op == IFX &&
6363 IC_COND (ic->next)->key == op->key &&
6364 OP_SYMBOL (op)->liveTo <= ic->next->seq)
6369 /*-----------------------------------------------------------------*/
6370 /* hasInc - operand is incremented before any other use */
6371 /*-----------------------------------------------------------------*/
6373 hasInc (operand *op, iCode *ic, int osize)
6375 sym_link *type = operandType(op);
6376 sym_link *retype = getSpec (type);
6377 iCode *lic = ic->next;
6380 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6381 if (!IS_SYMOP(op)) return NULL;
6383 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6384 if (IS_AGGREGATE(type->next)) return NULL;
6385 if (osize != (isize = getSize(type->next))) return NULL;
6388 /* if operand of the form op = op + <sizeof *op> */
6389 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6390 isOperandEqual(IC_RESULT(lic),op) &&
6391 isOperandLiteral(IC_RIGHT(lic)) &&
6392 operandLitValue(IC_RIGHT(lic)) == isize) {
6395 /* if the operand used or deffed */
6396 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
6399 /* if GOTO or IFX */
6400 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6406 /*-----------------------------------------------------------------*/
6407 /* genAndOp - for && operation */
6408 /*-----------------------------------------------------------------*/
6410 genAndOp (iCode * ic)
6412 operand *left, *right, *result;
6415 D (emitcode (";", "genAndOp "););
6417 /* note here that && operations that are in an
6418 if statement are taken away by backPatchLabels
6419 only those used in arthmetic operations remain */
6421 AOP_SET_LOCALS (ic);
6423 /* if both are bit variables */
6424 if (AOP_TYPE (left) == AOP_CRY &&
6425 AOP_TYPE (right) == AOP_CRY)
6427 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6428 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6429 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6430 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6432 aopOp (result,ic,FALSE, FALSE);
6437 tlbl = newiTempLabel (NULL);
6439 emitcode ("jz", "!tlabel", tlbl->key + 100);
6441 emitcode ("", "!tlabeldef", tlbl->key + 100);
6442 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6443 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6445 aopOp (result,ic,FALSE, FALSE);
6448 freeAsmop (result, NULL, ic, TRUE);
6452 /*-----------------------------------------------------------------*/
6453 /* genOrOp - for || operation */
6454 /*-----------------------------------------------------------------*/
6456 genOrOp (iCode * ic)
6458 operand *left, *right, *result;
6461 D (emitcode (";", "genOrOp "););
6463 /* note here that || operations that are in an
6464 if statement are taken away by backPatchLabels
6465 only those used in arthmetic operations remain */
6467 AOP_SET_LOCALS (ic);
6469 /* if both are bit variables */
6470 if (AOP_TYPE (left) == AOP_CRY &&
6471 AOP_TYPE (right) == AOP_CRY)
6473 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6474 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6475 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6476 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6478 aopOp (result,ic,FALSE, FALSE);
6484 tlbl = newiTempLabel (NULL);
6486 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6488 emitcode ("", "!tlabeldef", tlbl->key + 100);
6489 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6490 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6492 aopOp (result,ic,FALSE, FALSE);
6497 freeAsmop (result, NULL, ic, TRUE);
6500 /*-----------------------------------------------------------------*/
6501 /* isLiteralBit - test if lit == 2^n */
6502 /*-----------------------------------------------------------------*/
6504 isLiteralBit (unsigned long lit)
6506 unsigned long pw[32] =
6507 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6508 0x100L, 0x200L, 0x400L, 0x800L,
6509 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6510 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6511 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6512 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6513 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6516 for (idx = 0; idx < 32; idx++)
6522 /*-----------------------------------------------------------------*/
6523 /* continueIfTrue - */
6524 /*-----------------------------------------------------------------*/
6526 continueIfTrue (iCode * ic)
6529 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6533 /*-----------------------------------------------------------------*/
6535 /*-----------------------------------------------------------------*/
6537 jumpIfTrue (iCode * ic)
6540 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6544 /*-----------------------------------------------------------------*/
6545 /* jmpTrueOrFalse - */
6546 /*-----------------------------------------------------------------*/
6548 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6550 // ugly but optimized by peephole
6553 symbol *nlbl = newiTempLabel (NULL);
6554 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6555 emitcode ("", "!tlabeldef", tlbl->key + 100);
6556 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6557 emitcode ("", "!tlabeldef", nlbl->key + 100);
6561 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6562 emitcode ("", "!tlabeldef", tlbl->key + 100);
6567 // Generate code to perform a bit-wise logic operation
6568 // on two operands in far space (assumed to already have been
6569 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6570 // in far space. This requires pushing the result on the stack
6571 // then popping it into the result.
6573 genFarFarLogicOp(iCode *ic, char *logicOp)
6575 int size, resultSize, compSize;
6579 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6580 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
6581 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6583 _startLazyDPSEvaluation();
6584 for (size = compSize; (size--); offset++)
6586 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6587 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6588 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6590 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6591 emitcode ("push", "acc");
6593 _endLazyDPSEvaluation();
6595 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6596 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6597 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6599 resultSize = AOP_SIZE(IC_RESULT(ic));
6601 ADJUST_PUSHED_RESULT(compSize, resultSize);
6603 _startLazyDPSEvaluation();
6606 emitcode ("pop", "acc");
6607 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6609 _endLazyDPSEvaluation();
6610 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6614 /*-----------------------------------------------------------------*/
6615 /* genAnd - code for and */
6616 /*-----------------------------------------------------------------*/
6618 genAnd (iCode * ic, iCode * ifx)
6620 operand *left, *right, *result;
6621 int size, offset = 0;
6622 unsigned long lit = 0L;
6627 D (emitcode (";", "genAnd "););
6629 AOP_OP_3_NOFATAL (ic, pushResult);
6630 AOP_SET_LOCALS (ic);
6634 genFarFarLogicOp(ic, "anl");
6639 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6641 AOP_TYPE (left), AOP_TYPE (right));
6642 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6644 AOP_SIZE (left), AOP_SIZE (right));
6647 /* if left is a literal & right is not then exchange them */
6648 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6649 #ifdef LOGIC_OPS_BROKEN
6650 || AOP_NEEDSACC (left)
6654 operand *tmp = right;
6659 /* if result = right then exchange left and right */
6660 if (sameRegs (AOP (result), AOP (right)))
6662 operand *tmp = right;
6667 /* if right is bit then exchange them */
6668 if (AOP_TYPE (right) == AOP_CRY &&
6669 AOP_TYPE (left) != AOP_CRY)
6671 operand *tmp = right;
6675 if (AOP_TYPE (right) == AOP_LIT)
6676 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6678 size = AOP_SIZE (result);
6681 // result = bit & yy;
6682 if (AOP_TYPE (left) == AOP_CRY)
6684 // c = bit & literal;
6685 if (AOP_TYPE (right) == AOP_LIT)
6689 if (size && sameRegs (AOP (result), AOP (left)))
6692 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6697 if (size && (AOP_TYPE (result) == AOP_CRY))
6699 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6702 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6707 emitcode ("clr", "c");
6712 if (AOP_TYPE (right) == AOP_CRY)
6715 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6716 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6721 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6723 emitcode ("rrc", "a");
6724 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6732 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6733 genIfxJump (ifx, "c");
6737 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6738 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6739 if ((AOP_TYPE (right) == AOP_LIT) &&
6740 (AOP_TYPE (result) == AOP_CRY) &&
6741 (AOP_TYPE (left) != AOP_CRY))
6743 int posbit = isLiteralBit (lit);
6748 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6751 emitcode ("mov", "c,acc.%d", posbit & 0x07);
6757 SNPRINTF (buff, sizeof(buff),
6758 "acc.%d", posbit & 0x07);
6759 genIfxJump (ifx, buff);
6763 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6770 symbol *tlbl = newiTempLabel (NULL);
6771 int sizel = AOP_SIZE (left);
6773 emitcode ("setb", "c");
6776 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6778 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6780 if ((posbit = isLiteralBit (bytelit)) != 0)
6781 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6784 if (bytelit != 0x0FFL)
6785 emitcode ("anl", "a,%s",
6786 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6787 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6792 // bit = left & literal
6795 emitcode ("clr", "c");
6796 emitcode ("", "!tlabeldef", tlbl->key + 100);
6798 // if(left & literal)
6802 jmpTrueOrFalse (ifx, tlbl);
6804 emitcode ("", "!tlabeldef", tlbl->key + 100);
6812 /* if left is same as result */
6813 if (sameRegs (AOP (result), AOP (left)))
6815 for (; size--; offset++)
6817 if (AOP_TYPE (right) == AOP_LIT)
6819 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6820 if (bytelit == 0x0FF)
6822 /* dummy read of volatile operand */
6823 if (isOperandVolatile (left, FALSE))
6824 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6828 else if (bytelit == 0)
6830 aopPut (AOP (result), zero, offset);
6832 else if (IS_AOP_PREG (result))
6834 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6835 emitcode ("anl", "a,%s",
6836 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6837 aopPut (AOP (result), "a", offset);
6840 emitcode ("anl", "%s,%s",
6841 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6842 aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6846 if (AOP_TYPE (left) == AOP_ACC)
6847 emitcode ("anl", "a,%s",
6848 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6851 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6852 if (IS_AOP_PREG (result))
6854 emitcode ("anl", "a,%s",
6855 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6856 aopPut (AOP (result), "a", offset);
6859 emitcode ("anl", "%s,a",
6860 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6867 // left & result in different registers
6868 if (AOP_TYPE (result) == AOP_CRY)
6871 // if(size), result in bit
6872 // if(!size && ifx), conditional oper: if(left & right)
6873 symbol *tlbl = newiTempLabel (NULL);
6874 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6876 emitcode ("setb", "c");
6879 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6880 emitcode ("anl", "a,%s",
6881 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6883 if (AOP_TYPE(left)==AOP_ACC) {
6884 emitcode("mov", "b,a");
6885 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6886 emitcode("anl", "a,b");
6888 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6889 emitcode ("anl", "a,%s",
6890 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6893 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6899 emitcode ("", "!tlabeldef", tlbl->key + 100);
6903 jmpTrueOrFalse (ifx, tlbl);
6905 emitcode ("", "!tlabeldef", tlbl->key + 100);
6909 for (; (size--); offset++)
6912 // result = left & right
6913 if (AOP_TYPE (right) == AOP_LIT)
6915 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6916 if (bytelit == 0x0FF)
6918 aopPut (AOP (result),
6919 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6923 else if (bytelit == 0)
6925 /* dummy read of volatile operand */
6926 if (isOperandVolatile (left, FALSE))
6927 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6928 aopPut (AOP (result), zero, offset);
6931 D (emitcode (";", "better literal AND."););
6932 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6933 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6934 FALSE, FALSE, DP2_RESULT_REG));
6939 // faster than result <- left, anl result,right
6940 // and better if result is SFR
6941 if (AOP_TYPE (left) == AOP_ACC)
6943 emitcode ("anl", "a,%s",
6944 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6948 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6949 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6951 emitcode("mov", "b,a");
6955 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6956 emitcode ("anl", "a,%s", rOp);
6959 aopPut (AOP (result), "a", offset);
6965 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6966 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6967 freeAsmop (result, NULL, ic, TRUE);
6971 /*-----------------------------------------------------------------*/
6972 /* genOr - code for or */
6973 /*-----------------------------------------------------------------*/
6975 genOr (iCode * ic, iCode * ifx)
6977 operand *left, *right, *result;
6978 int size, offset = 0;
6979 unsigned long lit = 0L;
6983 D (emitcode (";", "genOr "););
6985 AOP_OP_3_NOFATAL (ic, pushResult);
6986 AOP_SET_LOCALS (ic);
6990 genFarFarLogicOp(ic, "orl");
6996 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6998 AOP_TYPE (left), AOP_TYPE (right));
6999 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7001 AOP_SIZE (left), AOP_SIZE (right));
7004 /* if left is a literal & right is not then exchange them */
7005 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7006 #ifdef LOGIC_OPS_BROKEN
7007 || AOP_NEEDSACC (left) // I think this is a net loss now.
7011 operand *tmp = right;
7016 /* if result = right then exchange them */
7017 if (sameRegs (AOP (result), AOP (right)))
7019 operand *tmp = right;
7024 /* if right is bit then exchange them */
7025 if (AOP_TYPE (right) == AOP_CRY &&
7026 AOP_TYPE (left) != AOP_CRY)
7028 operand *tmp = right;
7032 if (AOP_TYPE (right) == AOP_LIT)
7033 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7035 size = AOP_SIZE (result);
7039 if (AOP_TYPE (left) == AOP_CRY)
7041 if (AOP_TYPE (right) == AOP_LIT)
7043 // c = bit & literal;
7046 // lit != 0 => result = 1
7047 if (AOP_TYPE (result) == AOP_CRY)
7050 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7052 continueIfTrue (ifx);
7055 emitcode ("setb", "c");
7059 // lit == 0 => result = left
7060 if (size && sameRegs (AOP (result), AOP (left)))
7062 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7067 if (AOP_TYPE (right) == AOP_CRY)
7070 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7071 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7076 symbol *tlbl = newiTempLabel (NULL);
7077 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
7078 emitcode ("setb", "c");
7079 emitcode ("jb", "%s,!tlabel",
7080 AOP (left)->aopu.aop_dir, tlbl->key + 100);
7082 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7083 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7085 jmpTrueOrFalse (ifx, tlbl);
7091 emitcode ("", "!tlabeldef", tlbl->key + 100);
7100 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7101 genIfxJump (ifx, "c");
7105 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7106 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7107 if ((AOP_TYPE (right) == AOP_LIT) &&
7108 (AOP_TYPE (result) == AOP_CRY) &&
7109 (AOP_TYPE (left) != AOP_CRY))
7115 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7117 continueIfTrue (ifx);
7122 // lit = 0, result = boolean(left)
7124 emitcode ("setb", "c");
7128 symbol *tlbl = newiTempLabel (NULL);
7129 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7131 emitcode ("", "!tlabeldef", tlbl->key + 100);
7135 genIfxJump (ifx, "a");
7143 /* if left is same as result */
7144 if (sameRegs (AOP (result), AOP (left)))
7146 for (; size--; offset++)
7148 if (AOP_TYPE (right) == AOP_LIT)
7150 bytelit = (int)((lit >> (offset * 8)) & 0x0FFL);
7151 if (bytelit == 0x00L)
7153 /* dummy read of volatile operand */
7154 if (isOperandVolatile (left, FALSE))
7155 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7159 else if (bytelit == 0x0FF)
7161 aopPut (AOP (result), "#0xFF", offset);
7163 else if (IS_AOP_PREG (left))
7165 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7166 emitcode ("orl", "a,%s",
7167 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7168 aopPut (AOP (result), "a", offset);
7172 emitcode ("orl", "%s,%s",
7173 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
7174 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7179 if (AOP_TYPE (left) == AOP_ACC)
7181 emitcode ("orl", "a,%s",
7182 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7186 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7187 if (IS_AOP_PREG (left))
7189 emitcode ("orl", "a,%s",
7190 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7191 aopPut (AOP (result), "a", offset);
7195 emitcode ("orl", "%s,a",
7196 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7204 // left & result in different registers
7205 if (AOP_TYPE (result) == AOP_CRY)
7208 // if(size), result in bit
7209 // if(!size && ifx), conditional oper: if(left | right)
7210 symbol *tlbl = newiTempLabel (NULL);
7211 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7213 emitcode ("setb", "c");
7216 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7217 emitcode ("orl", "a,%s",
7218 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7220 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7221 emitcode ("orl", "a,%s",
7222 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
7224 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7230 emitcode ("", "!tlabeldef", tlbl->key + 100);
7234 jmpTrueOrFalse (ifx, tlbl);
7236 emitcode ("", "!tlabeldef", tlbl->key + 100);
7240 _startLazyDPSEvaluation();
7241 for (; (size--); offset++)
7244 // result = left & right
7245 if (AOP_TYPE (right) == AOP_LIT)
7247 bytelit = (int)((lit >> (offset * 8)) & 0x0FFL);
7248 if (bytelit == 0x00L)
7250 aopPut (AOP (result),
7251 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7255 else if (bytelit == 0x0FF)
7257 /* dummy read of volatile operand */
7258 if (isOperandVolatile (left, FALSE))
7259 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7260 aopPut (AOP (result), "#0xFF", offset);
7263 D (emitcode (";", "better literal OR."););
7264 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7265 emitcode ("orl", "a, %s",
7266 aopGet (AOP (right), offset,
7267 FALSE, FALSE, DP2_RESULT_REG));
7272 // faster than result <- left, anl result,right
7273 // and better if result is SFR
7274 if (AOP_TYPE (left) == AOP_ACC)
7276 emitcode ("orl", "a,%s",
7277 aopGet (AOP (right), offset,
7278 FALSE, FALSE, DP2_RESULT_REG));
7282 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7284 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7286 emitcode("mov", "b,a");
7290 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7291 emitcode ("orl", "a,%s", rOp);
7294 aopPut (AOP (result), "a", offset);
7296 _endLazyDPSEvaluation();
7301 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7302 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7303 freeAsmop (result, NULL, ic, TRUE);
7306 /*-----------------------------------------------------------------*/
7307 /* genXor - code for xclusive or */
7308 /*-----------------------------------------------------------------*/
7310 genXor (iCode * ic, iCode * ifx)
7312 operand *left, *right, *result;
7313 int size, offset = 0;
7314 unsigned long lit = 0L;
7318 D (emitcode (";", "genXor "););
7320 AOP_OP_3_NOFATAL (ic, pushResult);
7321 AOP_SET_LOCALS (ic);
7325 genFarFarLogicOp(ic, "xrl");
7330 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7332 AOP_TYPE (left), AOP_TYPE (right));
7333 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7335 AOP_SIZE (left), AOP_SIZE (right));
7338 /* if left is a literal & right is not ||
7339 if left needs acc & right does not */
7340 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7341 #ifdef LOGIC_OPS_BROKEN
7342 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
7346 operand *tmp = right;
7351 /* if result = right then exchange them */
7352 if (sameRegs (AOP (result), AOP (right)))
7354 operand *tmp = right;
7359 /* if right is bit then exchange them */
7360 if (AOP_TYPE (right) == AOP_CRY &&
7361 AOP_TYPE (left) != AOP_CRY)
7363 operand *tmp = right;
7367 if (AOP_TYPE (right) == AOP_LIT)
7368 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7370 size = AOP_SIZE (result);
7374 if (AOP_TYPE (left) == AOP_CRY)
7376 if (AOP_TYPE (right) == AOP_LIT)
7378 // c = bit & literal;
7381 // lit>>1 != 0 => result = 1
7382 if (AOP_TYPE (result) == AOP_CRY)
7385 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7387 continueIfTrue (ifx);
7390 emitcode ("setb", "c");
7397 // lit == 0, result = left
7398 if (size && sameRegs (AOP (result), AOP (left)))
7400 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7404 // lit == 1, result = not(left)
7405 if (size && sameRegs (AOP (result), AOP (left)))
7407 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7412 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7413 emitcode ("cpl", "c");
7422 symbol *tlbl = newiTempLabel (NULL);
7423 if (AOP_TYPE (right) == AOP_CRY)
7426 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7430 int sizer = AOP_SIZE (right);
7432 // if val>>1 != 0, result = 1
7433 emitcode ("setb", "c");
7436 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
7438 // test the msb of the lsb
7439 emitcode ("anl", "a,#!constbyte",0xfe);
7440 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7444 emitcode ("rrc", "a");
7446 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7447 emitcode ("cpl", "c");
7448 emitcode ("", "!tlabeldef", (tlbl->key + 100));
7455 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7456 genIfxJump (ifx, "c");
7460 /* if left is same as result */
7461 if (sameRegs (AOP (result), AOP (left)))
7463 for (; size--; offset++)
7465 if (AOP_TYPE (right) == AOP_LIT)
7467 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7468 if (bytelit == 0x00L)
7470 /* dummy read of volatile operand */
7471 if (isOperandVolatile (left, FALSE))
7472 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7476 else if (IS_AOP_PREG (left))
7478 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7479 emitcode ("xrl", "a,%s",
7480 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7481 aopPut (AOP (result), "a", offset);
7485 emitcode ("xrl", "%s,%s",
7486 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
7487 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7492 if (AOP_TYPE (left) == AOP_ACC)
7493 emitcode ("xrl", "a,%s",
7494 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7497 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7498 if (IS_AOP_PREG (left))
7500 emitcode ("xrl", "a,%s",
7501 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7502 aopPut (AOP (result), "a", offset);
7505 emitcode ("xrl", "%s,a",
7506 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7513 // left & result in different registers
7514 if (AOP_TYPE (result) == AOP_CRY)
7517 // if(size), result in bit
7518 // if(!size && ifx), conditional oper: if(left ^ right)
7519 symbol *tlbl = newiTempLabel (NULL);
7520 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7523 emitcode ("setb", "c");
7526 if ((AOP_TYPE (right) == AOP_LIT) &&
7527 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7529 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7533 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7534 emitcode ("xrl", "a,%s",
7535 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7537 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7538 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7540 emitcode("mov", "b,a");
7544 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7545 emitcode ("xrl", "a,%s", rOp);
7548 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7554 emitcode ("", "!tlabeldef", tlbl->key + 100);
7558 jmpTrueOrFalse (ifx, tlbl);
7562 for (; (size--); offset++)
7565 // result = left & right
7566 if (AOP_TYPE (right) == AOP_LIT)
7568 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7570 aopPut (AOP (result),
7571 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7575 D (emitcode (";", "better literal XOR."););
7576 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7577 emitcode ("xrl", "a, %s",
7578 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7582 // faster than result <- left, anl result,right
7583 // and better if result is SFR
7584 if (AOP_TYPE (left) == AOP_ACC)
7586 emitcode ("xrl", "a,%s",
7587 aopGet (AOP (right), offset,
7588 FALSE, FALSE, DP2_RESULT_REG));
7592 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7593 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7595 emitcode("mov", "b,a");
7599 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7600 emitcode ("xrl", "a,%s", rOp);
7603 aopPut (AOP (result), "a", offset);
7610 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7611 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7612 freeAsmop (result, NULL, ic, TRUE);
7615 /*-----------------------------------------------------------------*/
7616 /* genInline - write the inline code out */
7617 /*-----------------------------------------------------------------*/
7619 genInline (iCode * ic)
7621 char *buffer, *bp, *bp1;
7623 D (emitcode (";", "genInline "); );
7625 _G.inLine += (!options.asmpeep);
7627 buffer = Safe_strdup(IC_INLINE(ic));
7631 /* emit each line as a code */
7656 /* emitcode("",buffer); */
7657 _G.inLine -= (!options.asmpeep);
7660 /*-----------------------------------------------------------------*/
7661 /* genRRC - rotate right with carry */
7662 /*-----------------------------------------------------------------*/
7666 operand *left, *result;
7669 D (emitcode (";", "genRRC "););
7671 /* rotate right with carry */
7672 left = IC_LEFT (ic);
7673 result = IC_RESULT (ic);
7674 aopOp (left, ic, FALSE, FALSE);
7675 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7677 /* move it to the result */
7678 size = AOP_SIZE (result);
7682 _startLazyDPSEvaluation ();
7685 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7686 emitcode ("rrc", "a");
7687 if (AOP_SIZE (result) > 1)
7688 aopPut (AOP (result), "a", offset--);
7690 _endLazyDPSEvaluation ();
7692 /* now we need to put the carry into the
7693 highest order byte of the result */
7694 if (AOP_SIZE (result) > 1)
7696 MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7698 emitcode ("mov", "acc.7,c");
7699 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7700 freeAsmop (left, NULL, ic, TRUE);
7701 freeAsmop (result, NULL, ic, TRUE);
7704 /*-----------------------------------------------------------------*/
7705 /* genRLC - generate code for rotate left with carry */
7706 /*-----------------------------------------------------------------*/
7710 operand *left, *result;
7714 D (emitcode (";", "genRLC "););
7716 /* rotate right with carry */
7717 left = IC_LEFT (ic);
7718 result = IC_RESULT (ic);
7719 aopOp (left, ic, FALSE, FALSE);
7720 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7722 /* move it to the result */
7723 size = AOP_SIZE (result);
7727 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7729 emitcode ("add", "a,acc");
7730 if (AOP_SIZE (result) > 1)
7732 aopPut (AOP (result), "a", offset++);
7735 _startLazyDPSEvaluation ();
7738 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7740 emitcode ("rlc", "a");
7741 if (AOP_SIZE (result) > 1)
7742 aopPut (AOP (result), "a", offset++);
7744 _endLazyDPSEvaluation ();
7746 /* now we need to put the carry into the
7747 highest order byte of the result */
7748 if (AOP_SIZE (result) > 1)
7750 l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7753 emitcode ("mov", "acc.0,c");
7754 aopPut (AOP (result), "a", 0);
7755 freeAsmop (left, NULL, ic, TRUE);
7756 freeAsmop (result, NULL, ic, TRUE);
7759 /*-----------------------------------------------------------------*/
7760 /* genGetHbit - generates code get highest order bit */
7761 /*-----------------------------------------------------------------*/
7763 genGetHbit (iCode * ic)
7765 operand *left, *result;
7766 left = IC_LEFT (ic);
7767 result = IC_RESULT (ic);
7768 aopOp (left, ic, FALSE, FALSE);
7769 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7771 D (emitcode (";", "genGetHbit "););
7773 /* get the highest order byte into a */
7774 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7775 if (AOP_TYPE (result) == AOP_CRY)
7777 emitcode ("rlc", "a");
7782 emitcode ("rl", "a");
7783 emitcode ("anl", "a,#1");
7788 freeAsmop (left, NULL, ic, TRUE);
7789 freeAsmop (result, NULL, ic, TRUE);
7792 /*-----------------------------------------------------------------*/
7793 /* genSwap - generates code to swap nibbles or bytes */
7794 /*-----------------------------------------------------------------*/
7796 genSwap (iCode * ic)
7798 operand *left, *result;
7800 D(emitcode ("; genSwap",""));
7802 left = IC_LEFT (ic);
7803 result = IC_RESULT (ic);
7804 aopOp (left, ic, FALSE, FALSE);
7805 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7807 _startLazyDPSEvaluation ();
7808 switch (AOP_SIZE (left))
7810 case 1: /* swap nibbles in byte */
7811 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7812 emitcode ("swap", "a");
7813 aopPut (AOP (result), "a", 0);
7815 case 2: /* swap bytes in word */
7816 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7818 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7819 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7820 aopPut (AOP (result), "a", 1);
7822 else if (operandsEqu (left, result))
7825 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7826 if (AOP_NEEDSACC (left) || AOP_NEEDSACC (result))
7828 emitcode ("mov", "b,a");
7832 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7833 aopPut (AOP (result), reg, 1);
7838 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7839 aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE, NULL), 1);
7843 wassertl(FALSE, "unsupported SWAP operand size");
7845 _endLazyDPSEvaluation ();
7847 freeAsmop (left, NULL, ic, TRUE);
7848 freeAsmop (result, NULL, ic, TRUE);
7851 /*-----------------------------------------------------------------*/
7852 /* AccRol - rotate left accumulator by known count */
7853 /*-----------------------------------------------------------------*/
7855 AccRol (int shCount)
7857 shCount &= 0x0007; // shCount : 0..7
7864 emitcode ("rl", "a");
7867 emitcode ("rl", "a");
7868 emitcode ("rl", "a");
7871 emitcode ("swap", "a");
7872 emitcode ("rr", "a");
7875 emitcode ("swap", "a");
7878 emitcode ("swap", "a");
7879 emitcode ("rl", "a");
7882 emitcode ("rr", "a");
7883 emitcode ("rr", "a");
7886 emitcode ("rr", "a");
7891 /*-----------------------------------------------------------------*/
7892 /* AccLsh - left shift accumulator by known count */
7893 /*-----------------------------------------------------------------*/
7895 AccLsh (int shCount)
7900 emitcode ("add", "a,acc");
7901 else if (shCount == 2)
7903 emitcode ("add", "a,acc");
7904 emitcode ("add", "a,acc");
7908 /* rotate left accumulator */
7910 /* and kill the lower order bits */
7911 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7916 /*-----------------------------------------------------------------*/
7917 /* AccRsh - right shift accumulator by known count */
7918 /*-----------------------------------------------------------------*/
7920 AccRsh (int shCount)
7927 emitcode ("rrc", "a");
7931 /* rotate right accumulator */
7932 AccRol (8 - shCount);
7933 /* and kill the higher order bits */
7934 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7939 #ifdef BETTER_LITERAL_SHIFT
7940 /*-----------------------------------------------------------------*/
7941 /* AccSRsh - signed right shift accumulator by known count */
7942 /*-----------------------------------------------------------------*/
7944 AccSRsh (int shCount)
7951 emitcode ("mov", "c,acc.7");
7952 emitcode ("rrc", "a");
7954 else if (shCount == 2)
7956 emitcode ("mov", "c,acc.7");
7957 emitcode ("rrc", "a");
7958 emitcode ("mov", "c,acc.7");
7959 emitcode ("rrc", "a");
7963 tlbl = newiTempLabel (NULL);
7964 /* rotate right accumulator */
7965 AccRol (8 - shCount);
7966 /* and kill the higher order bits */
7967 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7968 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7969 emitcode ("orl", "a,#!constbyte",
7970 (unsigned char) ~SRMask[shCount]);
7971 emitcode ("", "!tlabeldef", tlbl->key + 100);
7977 #ifdef BETTER_LITERAL_SHIFT
7978 /*-----------------------------------------------------------------*/
7979 /* shiftR1Left2Result - shift right one byte from left to result */
7980 /*-----------------------------------------------------------------*/
7982 shiftR1Left2Result (operand * left, int offl,
7983 operand * result, int offr,
7984 int shCount, int sign)
7986 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7987 /* shift right accumulator */
7992 aopPut (AOP (result), "a", offr);
7996 #ifdef BETTER_LITERAL_SHIFT
7997 /*-----------------------------------------------------------------*/
7998 /* shiftL1Left2Result - shift left one byte from left to result */
7999 /*-----------------------------------------------------------------*/
8001 shiftL1Left2Result (operand * left, int offl,
8002 operand * result, int offr, int shCount)
8004 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8005 /* shift left accumulator */
8007 aopPut (AOP (result), "a", offr);
8011 #ifdef BETTER_LITERAL_SHIFT
8012 /*-----------------------------------------------------------------*/
8013 /* movLeft2Result - move byte from left to result */
8014 /*-----------------------------------------------------------------*/
8016 movLeft2Result (operand * left, int offl,
8017 operand * result, int offr, int sign)
8020 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8022 l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
8024 if (*l == '@' && (IS_AOP_PREG (result)))
8026 emitcode ("mov", "a,%s", l);
8027 aopPut (AOP (result), "a", offr);
8033 aopPut (AOP (result), l, offr);
8037 /* MSB sign in acc.7 ! */
8038 if (getDataSize (left) == offl + 1)
8040 emitcode ("mov", "a,%s", l);
8041 aopPut (AOP (result), "a", offr);
8049 #ifdef BETTER_LITERAL_SHIFT
8050 /*-----------------------------------------------------------------*/
8051 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
8052 /*-----------------------------------------------------------------*/
8056 emitcode ("rrc", "a");
8057 emitcode ("xch", "a,%s", x);
8058 emitcode ("rrc", "a");
8059 emitcode ("xch", "a,%s", x);
8063 #ifdef BETTER_LITERAL_SHIFT
8065 /*-----------------------------------------------------------------*/
8066 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
8067 /*-----------------------------------------------------------------*/
8071 emitcode ("xch", "a,%s", x);
8072 emitcode ("rlc", "a");
8073 emitcode ("xch", "a,%s", x);
8074 emitcode ("rlc", "a");
8078 #ifdef BETTER_LITERAL_SHIFT
8079 /*-----------------------------------------------------------------*/
8080 /* AccAXLsh1 - left shift a:x<-0 by 1 */
8081 /*-----------------------------------------------------------------*/
8085 emitcode ("xch", "a,%s", x);
8086 emitcode ("add", "a,acc");
8087 emitcode ("xch", "a,%s", x);
8088 emitcode ("rlc", "a");
8092 #ifdef BETTER_LITERAL_SHIFT
8093 /*-----------------------------------------------------------------*/
8094 /* AccAXLsh - left shift a:x by known count (0..7) */
8095 /*-----------------------------------------------------------------*/
8097 AccAXLsh (char *x, int shCount)
8112 case 5: // AAAAABBB:CCCCCDDD
8114 AccRol (shCount); // BBBAAAAA:CCCCCDDD
8116 emitcode ("anl", "a,#!constbyte",
8117 SLMask[shCount]); // BBB00000:CCCCCDDD
8119 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
8121 AccRol (shCount); // DDDCCCCC:BBB00000
8123 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8125 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8127 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8129 emitcode ("anl", "a,#!constbyte",
8130 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8132 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8134 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8137 case 6: // AAAAAABB:CCCCCCDD
8138 emitcode ("anl", "a,#!constbyte",
8139 SRMask[shCount]); // 000000BB:CCCCCCDD
8140 emitcode ("mov", "c,acc.0"); // c = B
8141 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8143 AccAXRrl1 (x); // BCCCCCCD:D000000B
8144 AccAXRrl1 (x); // BBCCCCCC:DD000000
8146 emitcode("rrc","a");
8147 emitcode("xch","a,%s", x);
8148 emitcode("rrc","a");
8149 emitcode("mov","c,acc.0"); //<< get correct bit
8150 emitcode("xch","a,%s", x);
8152 emitcode("rrc","a");
8153 emitcode("xch","a,%s", x);
8154 emitcode("rrc","a");
8155 emitcode("xch","a,%s", x);
8158 case 7: // a:x <<= 7
8160 emitcode ("anl", "a,#!constbyte",
8161 SRMask[shCount]); // 0000000B:CCCCCCCD
8163 emitcode ("mov", "c,acc.0"); // c = B
8165 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
8167 AccAXRrl1 (x); // BCCCCCCC:D0000000
8176 #ifdef BETTER_LITERAL_SHIFT
8178 /*-----------------------------------------------------------------*/
8179 /* AccAXRsh - right shift a:x known count (0..7) */
8180 /*-----------------------------------------------------------------*/
8182 AccAXRsh (char *x, int shCount)
8190 AccAXRrl1 (x); // 0->a:x
8195 AccAXRrl1 (x); // 0->a:x
8198 AccAXRrl1 (x); // 0->a:x
8203 case 5: // AAAAABBB:CCCCCDDD = a:x
8205 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8207 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8209 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8211 emitcode ("anl", "a,#!constbyte",
8212 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8214 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8216 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8218 emitcode ("anl", "a,#!constbyte",
8219 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8221 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8223 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8225 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8228 case 6: // AABBBBBB:CCDDDDDD
8230 emitcode ("mov", "c,acc.7");
8231 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8233 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8235 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8237 emitcode ("anl", "a,#!constbyte",
8238 SRMask[shCount]); // 000000AA:BBBBBBCC
8241 case 7: // ABBBBBBB:CDDDDDDD
8243 emitcode ("mov", "c,acc.7"); // c = A
8245 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8247 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8249 emitcode ("anl", "a,#!constbyte",
8250 SRMask[shCount]); // 0000000A:BBBBBBBC
8259 #ifdef BETTER_LITERAL_SHIFT
8260 /*-----------------------------------------------------------------*/
8261 /* AccAXRshS - right shift signed a:x known count (0..7) */
8262 /*-----------------------------------------------------------------*/
8264 AccAXRshS (char *x, int shCount)
8272 emitcode ("mov", "c,acc.7");
8273 AccAXRrl1 (x); // s->a:x
8277 emitcode ("mov", "c,acc.7");
8278 AccAXRrl1 (x); // s->a:x
8280 emitcode ("mov", "c,acc.7");
8281 AccAXRrl1 (x); // s->a:x
8286 case 5: // AAAAABBB:CCCCCDDD = a:x
8288 tlbl = newiTempLabel (NULL);
8289 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8291 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8293 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8295 emitcode ("anl", "a,#!constbyte",
8296 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8298 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8300 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8302 emitcode ("anl", "a,#!constbyte",
8303 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8305 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8307 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8309 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
8311 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8312 emitcode ("orl", "a,#!constbyte",
8313 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
8315 emitcode ("", "!tlabeldef", tlbl->key + 100);
8316 break; // SSSSAAAA:BBBCCCCC
8318 case 6: // AABBBBBB:CCDDDDDD
8320 tlbl = newiTempLabel (NULL);
8321 emitcode ("mov", "c,acc.7");
8322 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8324 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8326 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8328 emitcode ("anl", "a,#!constbyte",
8329 SRMask[shCount]); // 000000AA:BBBBBBCC
8331 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8332 emitcode ("orl", "a,#!constbyte",
8333 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
8335 emitcode ("", "!tlabeldef", tlbl->key + 100);
8337 case 7: // ABBBBBBB:CDDDDDDD
8339 tlbl = newiTempLabel (NULL);
8340 emitcode ("mov", "c,acc.7"); // c = A
8342 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8344 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8346 emitcode ("anl", "a,#!constbyte",
8347 SRMask[shCount]); // 0000000A:BBBBBBBC
8349 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8350 emitcode ("orl", "a,#!constbyte",
8351 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
8353 emitcode ("", "!tlabeldef", tlbl->key + 100);
8361 #ifdef BETTER_LITERAL_SHIFT
8363 _loadLeftIntoAx(char **lsb,
8369 // Get the initial value from left into a pair of registers.
8370 // MSB must be in A, LSB can be any register.
8372 // If the result is held in registers, it is an optimization
8373 // if the LSB can be held in the register which will hold the,
8374 // result LSB since this saves us from having to copy it into
8375 // the result following AccAXLsh.
8377 // If the result is addressed indirectly, this is not a gain.
8378 if (AOP_NEEDSACC(result))
8382 _startLazyDPSEvaluation();
8383 if (AOP_TYPE(left) == AOP_DPTR2)
8386 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
8387 // get LSB in DP2_RESULT_REG.
8388 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
8389 assert(!strcmp(leftByte, DP2_RESULT_REG));
8393 // get LSB into DP2_RESULT_REG
8394 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
8395 if (strcmp(leftByte, DP2_RESULT_REG))
8398 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
8401 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
8402 assert(strcmp(leftByte, DP2_RESULT_REG));
8405 _endLazyDPSEvaluation();
8406 *lsb = DP2_RESULT_REG;
8410 if (sameRegs (AOP (result), AOP (left)) &&
8411 ((offl + MSB16) == offr))
8413 /* don't crash result[offr] */
8414 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
8415 emitcode ("xch", "a,%s",
8416 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
8420 movLeft2Result (left, offl, result, offr, 0);
8421 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
8423 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
8424 assert(strcmp(*lsb,"a"));
8429 _storeAxResults(char *lsb,
8433 _startLazyDPSEvaluation();
8434 if (AOP_NEEDSACC(result))
8436 /* We have to explicitly update the result LSB.
8438 emitcode("xch","a,%s", lsb);
8439 aopPut(AOP(result), "a", offr);
8440 emitcode("mov","a,%s", lsb);
8442 if (getDataSize (result) > 1)
8444 aopPut (AOP (result), "a", offr + MSB16);
8446 _endLazyDPSEvaluation();
8449 /*-----------------------------------------------------------------*/
8450 /* shiftL2Left2Result - shift left two bytes from left to result */
8451 /*-----------------------------------------------------------------*/
8453 shiftL2Left2Result (operand * left, int offl,
8454 operand * result, int offr, int shCount)
8458 _loadLeftIntoAx(&lsb, left, result, offl, offr);
8460 AccAXLsh (lsb, shCount);
8462 _storeAxResults(lsb, result, offr);
8466 #ifdef BETTER_LITERAL_SHIFT
8467 /*-----------------------------------------------------------------*/
8468 /* shiftR2Left2Result - shift right two bytes from left to result */
8469 /*-----------------------------------------------------------------*/
8471 shiftR2Left2Result (operand * left, int offl,
8472 operand * result, int offr,
8473 int shCount, int sign)
8477 _loadLeftIntoAx(&lsb, left, result, offl, offr);
8479 /* a:x >> shCount (x = lsb(result)) */
8482 AccAXRshS(lsb, shCount);
8486 AccAXRsh(lsb, shCount);
8489 _storeAxResults(lsb, result, offr);
8493 /*-----------------------------------------------------------------*/
8494 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8495 /*-----------------------------------------------------------------*/
8497 shiftLLeftOrResult (operand * left, int offl,
8498 operand * result, int offr, int shCount)
8500 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8501 /* shift left accumulator */
8503 /* or with result */
8504 emitcode ("orl", "a,%s",
8505 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8506 /* back to result */
8507 aopPut (AOP (result), "a", offr);
8512 /*-----------------------------------------------------------------*/
8513 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8514 /*-----------------------------------------------------------------*/
8516 shiftRLeftOrResult (operand * left, int offl,
8517 operand * result, int offr, int shCount)
8519 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8520 /* shift right accumulator */
8522 /* or with result */
8523 emitcode ("orl", "a,%s",
8524 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8525 /* back to result */
8526 aopPut (AOP (result), "a", offr);
8530 #ifdef BETTER_LITERAL_SHIFT
8531 /*-----------------------------------------------------------------*/
8532 /* genlshOne - left shift a one byte quantity by known count */
8533 /*-----------------------------------------------------------------*/
8535 genlshOne (operand * result, operand * left, int shCount)
8537 D (emitcode (";", "genlshOne "););
8538 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8542 #ifdef BETTER_LITERAL_SHIFT
8543 /*-----------------------------------------------------------------*/
8544 /* genlshTwo - left shift two bytes by known amount != 0 */
8545 /*-----------------------------------------------------------------*/
8547 genlshTwo (operand * result, operand * left, int shCount)
8551 D (emitcode (";", "genlshTwo "););
8553 size = getDataSize (result);
8555 /* if shCount >= 8 */
8560 _startLazyDPSEvaluation();
8566 _endLazyDPSEvaluation();
8567 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8568 aopPut (AOP (result), zero, LSB);
8572 movLeft2Result (left, LSB, result, MSB16, 0);
8573 aopPut (AOP (result), zero, LSB);
8574 _endLazyDPSEvaluation();
8579 aopPut (AOP (result), zero, LSB);
8580 _endLazyDPSEvaluation();
8584 /* 1 <= shCount <= 7 */
8589 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8593 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8601 /*-----------------------------------------------------------------*/
8602 /* shiftLLong - shift left one long from left to result */
8603 /* offl = LSB or MSB16 */
8604 /*-----------------------------------------------------------------*/
8606 shiftLLong (operand * left, operand * result, int offr)
8609 int size = AOP_SIZE (result);
8611 if (size >= LSB + offr)
8613 l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8615 emitcode ("add", "a,acc");
8616 if (sameRegs (AOP (left), AOP (result)) &&
8617 size >= MSB16 + offr && offr != LSB)
8618 emitcode ("xch", "a,%s",
8619 aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8621 aopPut (AOP (result), "a", LSB + offr);
8624 if (size >= MSB16 + offr)
8626 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8628 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8630 emitcode ("rlc", "a");
8631 if (sameRegs (AOP (left), AOP (result)) &&
8632 size >= MSB24 + offr && offr != LSB)
8633 emitcode ("xch", "a,%s",
8634 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8636 aopPut (AOP (result), "a", MSB16 + offr);
8639 if (size >= MSB24 + offr)
8641 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8643 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8645 emitcode ("rlc", "a");
8646 if (sameRegs (AOP (left), AOP (result)) &&
8647 size >= MSB32 + offr && offr != LSB)
8648 emitcode ("xch", "a,%s",
8649 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8651 aopPut (AOP (result), "a", MSB24 + offr);
8654 if (size > MSB32 + offr)
8656 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8658 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8660 emitcode ("rlc", "a");
8661 aopPut (AOP (result), "a", MSB32 + offr);
8664 aopPut (AOP (result), zero, LSB);
8670 /*-----------------------------------------------------------------*/
8671 /* genlshFour - shift four byte by a known amount != 0 */
8672 /*-----------------------------------------------------------------*/
8674 genlshFour (operand * result, operand * left, int shCount)
8678 D (emitcode (";", "genlshFour ");
8681 size = AOP_SIZE (result);
8683 /* if shifting more that 3 bytes */
8688 /* lowest order of left goes to the highest
8689 order of the destination */
8690 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8692 movLeft2Result (left, LSB, result, MSB32, 0);
8693 aopPut (AOP (result), zero, LSB);
8694 aopPut (AOP (result), zero, MSB16);
8695 aopPut (AOP (result), zero, MSB24);
8699 /* more than two bytes */
8700 else if (shCount >= 16)
8702 /* lower order two bytes goes to higher order two bytes */
8704 /* if some more remaining */
8706 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8709 movLeft2Result (left, MSB16, result, MSB32, 0);
8710 movLeft2Result (left, LSB, result, MSB24, 0);
8712 aopPut (AOP (result), zero, MSB16);
8713 aopPut (AOP (result), zero, LSB);
8717 /* if more than 1 byte */
8718 else if (shCount >= 8)
8720 /* lower order three bytes goes to higher order three bytes */
8725 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8727 movLeft2Result (left, LSB, result, MSB16, 0);
8733 movLeft2Result (left, MSB24, result, MSB32, 0);
8734 movLeft2Result (left, MSB16, result, MSB24, 0);
8735 movLeft2Result (left, LSB, result, MSB16, 0);
8736 aopPut (AOP (result), zero, LSB);
8738 else if (shCount == 1)
8739 shiftLLong (left, result, MSB16);
8742 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8743 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8744 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8745 aopPut (AOP (result), zero, LSB);
8750 /* 1 <= shCount <= 7 */
8751 else if (shCount <= 2)
8753 shiftLLong (left, result, LSB);
8755 shiftLLong (result, result, LSB);
8757 /* 3 <= shCount <= 7, optimize */
8760 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8761 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8762 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8767 #ifdef BETTER_LITERAL_SHIFT
8768 /*-----------------------------------------------------------------*/
8769 /* genLeftShiftLiteral - left shifting by known count */
8770 /*-----------------------------------------------------------------*/
8772 genLeftShiftLiteral (operand * left,
8777 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8780 size = getSize (operandType (result));
8782 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8784 /* We only handle certain easy cases so far. */
8786 && (shCount < (size * 8))
8790 D(emitcode (";", "genLeftShiftLiteral wimping out"););
8794 freeAsmop (right, NULL, ic, TRUE);
8796 aopOp(left, ic, FALSE, FALSE);
8797 aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8800 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8802 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8803 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8805 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8808 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8810 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8811 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8813 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8819 emitcode ("; shift left ", "result %d, left %d", size,
8823 /* I suppose that the left size >= result size */
8826 _startLazyDPSEvaluation();
8829 movLeft2Result (left, size, result, size, 0);
8831 _endLazyDPSEvaluation();
8833 else if (shCount >= (size * 8))
8835 _startLazyDPSEvaluation();
8838 aopPut (AOP (result), zero, size);
8840 _endLazyDPSEvaluation();
8847 genlshOne (result, left, shCount);
8851 genlshTwo (result, left, shCount);
8855 genlshFour (result, left, shCount);
8859 fprintf(stderr, "*** ack! mystery literal shift!\n");
8863 freeAsmop (left, NULL, ic, TRUE);
8864 freeAsmop (result, NULL, ic, TRUE);
8869 /*-----------------------------------------------------------------*/
8870 /* genLeftShift - generates code for left shifting */
8871 /*-----------------------------------------------------------------*/
8873 genLeftShift (iCode * ic)
8875 operand *left, *right, *result;
8878 symbol *tlbl, *tlbl1;
8880 D (emitcode (";", "genLeftShift "););
8882 right = IC_RIGHT (ic);
8883 left = IC_LEFT (ic);
8884 result = IC_RESULT (ic);
8886 aopOp (right, ic, FALSE, FALSE);
8889 #ifdef BETTER_LITERAL_SHIFT
8890 /* if the shift count is known then do it
8891 as efficiently as possible */
8892 if (AOP_TYPE (right) == AOP_LIT)
8894 if (genLeftShiftLiteral (left, right, result, ic))
8901 /* shift count is unknown then we have to form
8902 a loop get the loop count in B : Note: we take
8903 only the lower order byte since shifting
8904 more that 32 bits make no sense anyway, ( the
8905 largest size of an object can be only 32 bits ) */
8907 if (AOP_TYPE (right) == AOP_LIT)
8909 /* Really should be handled by genLeftShiftLiteral,
8910 * but since I'm too lazy to fix that today, at least we can make
8911 * some small improvement.
8913 emitcode("mov", "b,#!constbyte",
8914 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8918 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8919 emitcode ("inc", "b");
8921 freeAsmop (right, NULL, ic, TRUE);
8922 aopOp (left, ic, FALSE, FALSE);
8923 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8925 /* now move the left to the result if they are not the
8927 if (!sameRegs (AOP (left), AOP (result)) &&
8928 AOP_SIZE (result) > 1)
8931 size = AOP_SIZE (result);
8933 _startLazyDPSEvaluation ();
8936 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8937 if (*l == '@' && (IS_AOP_PREG (result)))
8940 emitcode ("mov", "a,%s", l);
8941 aopPut (AOP (result), "a", offset);
8944 aopPut (AOP (result), l, offset);
8947 _endLazyDPSEvaluation ();
8950 tlbl = newiTempLabel (NULL);
8951 size = AOP_SIZE (result);
8953 tlbl1 = newiTempLabel (NULL);
8955 /* if it is only one byte then */
8958 symbol *tlbl1 = newiTempLabel (NULL);
8960 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8961 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8962 emitcode ("", "!tlabeldef", tlbl->key + 100);
8963 emitcode ("add", "a,acc");
8964 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8965 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8966 aopPut (AOP (result), "a", 0);
8970 reAdjustPreg (AOP (result));
8972 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8973 emitcode ("", "!tlabeldef", tlbl->key + 100);
8974 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8975 emitcode ("add", "a,acc");
8976 aopPut (AOP (result), "a", offset++);
8977 _startLazyDPSEvaluation ();
8980 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8981 emitcode ("rlc", "a");
8982 aopPut (AOP (result), "a", offset++);
8984 _endLazyDPSEvaluation ();
8985 reAdjustPreg (AOP (result));
8987 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8988 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8990 freeAsmop (left, NULL, ic, TRUE);
8991 freeAsmop (result, NULL, ic, TRUE);
8994 #ifdef BETTER_LITERAL_SHIFT
8995 /*-----------------------------------------------------------------*/
8996 /* genrshOne - right shift a one byte quantity by known count */
8997 /*-----------------------------------------------------------------*/
8999 genrshOne (operand * result, operand * left,
9000 int shCount, int sign)
9002 D (emitcode (";", "genrshOne"););
9003 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9007 #ifdef BETTER_LITERAL_SHIFT
9008 /*-----------------------------------------------------------------*/
9009 /* genrshTwo - right shift two bytes by known amount != 0 */
9010 /*-----------------------------------------------------------------*/
9012 genrshTwo (operand * result, operand * left,
9013 int shCount, int sign)
9015 D (emitcode (";", "genrshTwo"););
9017 /* if shCount >= 8 */
9021 _startLazyDPSEvaluation();
9024 shiftR1Left2Result (left, MSB16, result, LSB,
9029 movLeft2Result (left, MSB16, result, LSB, sign);
9031 addSign (result, MSB16, sign);
9032 _endLazyDPSEvaluation();
9035 /* 1 <= shCount <= 7 */
9038 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9043 /*-----------------------------------------------------------------*/
9044 /* shiftRLong - shift right one long from left to result */
9045 /* offl = LSB or MSB16 */
9046 /*-----------------------------------------------------------------*/
9048 shiftRLong (operand * left, int offl,
9049 operand * result, int sign)
9051 int isSameRegs=sameRegs(AOP(left),AOP(result));
9053 if (isSameRegs && offl>1) {
9054 // we are in big trouble, but this shouldn't happen
9055 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9058 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
9063 emitcode ("rlc", "a");
9064 emitcode ("subb", "a,acc");
9065 emitcode ("xch", "a,%s",
9066 aopGet(AOP(left), MSB32, FALSE, FALSE, DP2_RESULT_REG));
9068 aopPut (AOP(result), zero, MSB32);
9073 emitcode ("clr", "c");
9075 emitcode ("mov", "c,acc.7");
9078 emitcode ("rrc", "a");
9080 if (isSameRegs && offl==MSB16) {
9082 "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE, DP2_RESULT_REG));
9084 aopPut (AOP (result), "a", MSB32);
9085 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
9088 emitcode ("rrc", "a");
9089 if (isSameRegs && offl==1) {
9090 emitcode ("xch", "a,%s",
9091 aopGet (AOP (left), MSB16, FALSE, FALSE, DP2_RESULT_REG));
9093 aopPut (AOP (result), "a", MSB24);
9094 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, NULL));
9096 emitcode ("rrc", "a");
9097 aopPut (AOP (result), "a", MSB16 - offl);
9101 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, NULL));
9102 emitcode ("rrc", "a");
9103 aopPut (AOP (result), "a", LSB);
9107 /*-----------------------------------------------------------------*/
9108 /* genrshFour - shift four byte by a known amount != 0 */
9109 /*-----------------------------------------------------------------*/
9111 genrshFour (operand * result, operand * left,
9112 int shCount, int sign)
9114 D (emitcode (";", "genrshFour"););
9116 /* if shifting more that 3 bytes */
9120 _startLazyDPSEvaluation();
9122 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9124 movLeft2Result (left, MSB32, result, LSB, sign);
9125 addSign (result, MSB16, sign);
9126 _endLazyDPSEvaluation();
9128 else if (shCount >= 16)
9131 _startLazyDPSEvaluation();
9133 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9136 movLeft2Result (left, MSB24, result, LSB, 0);
9137 movLeft2Result (left, MSB32, result, MSB16, sign);
9139 addSign (result, MSB24, sign);
9140 _endLazyDPSEvaluation();
9142 else if (shCount >= 8)
9145 _startLazyDPSEvaluation();
9148 shiftRLong (left, MSB16, result, sign);
9150 else if (shCount == 0)
9152 movLeft2Result (left, MSB16, result, LSB, 0);
9153 movLeft2Result (left, MSB24, result, MSB16, 0);
9154 movLeft2Result (left, MSB32, result, MSB24, sign);
9155 addSign (result, MSB32, sign);
9159 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9160 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9161 /* the last shift is signed */
9162 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9163 addSign (result, MSB32, sign);
9165 _endLazyDPSEvaluation();
9169 /* 1 <= shCount <= 7 */
9172 shiftRLong (left, LSB, result, sign);
9174 shiftRLong (result, LSB, result, sign);
9178 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9179 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9180 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9185 #ifdef BETTER_LITERAL_SHIFT
9186 /*-----------------------------------------------------------------*/
9187 /* genRightShiftLiteral - right shifting by known count */
9188 /*-----------------------------------------------------------------*/
9190 genRightShiftLiteral (operand * left,
9196 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9199 size = getSize (operandType (result));
9201 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
9203 /* We only handle certain easy cases so far. */
9205 && (shCount < (size * 8))
9210 D(emitcode (";", "genRightShiftLiteral wimping out"););
9214 freeAsmop (right, NULL, ic, TRUE);
9216 aopOp (left, ic, FALSE, FALSE);
9217 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9220 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9224 /* test the LEFT size !!! */
9226 /* I suppose that the left size >= result size */
9229 size = getDataSize (result);
9230 _startLazyDPSEvaluation();
9233 movLeft2Result (left, size, result, size, 0);
9235 _endLazyDPSEvaluation();
9237 else if (shCount >= (size * 8))
9241 /* get sign in acc.7 */
9242 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
9244 addSign (result, LSB, sign);
9251 genrshOne (result, left, shCount, sign);
9255 genrshTwo (result, left, shCount, sign);
9259 genrshFour (result, left, shCount, sign);
9266 freeAsmop (left, NULL, ic, TRUE);
9267 freeAsmop (result, NULL, ic, TRUE);
9273 /*-----------------------------------------------------------------*/
9274 /* genSignedRightShift - right shift of signed number */
9275 /*-----------------------------------------------------------------*/
9277 genSignedRightShift (iCode * ic)
9279 operand *right, *left, *result;
9282 symbol *tlbl, *tlbl1;
9284 D (emitcode (";", "genSignedRightShift "););
9286 /* we do it the hard way put the shift count in b
9287 and loop thru preserving the sign */
9289 right = IC_RIGHT (ic);
9290 left = IC_LEFT (ic);
9291 result = IC_RESULT (ic);
9293 aopOp (right, ic, FALSE, FALSE);
9295 #ifdef BETTER_LITERAL_SHIFT
9296 if (AOP_TYPE (right) == AOP_LIT)
9298 if (genRightShiftLiteral (left, right, result, ic, 1))
9304 /* shift count is unknown then we have to form
9305 a loop get the loop count in B : Note: we take
9306 only the lower order byte since shifting
9307 more that 32 bits make no sense anyway, ( the
9308 largest size of an object can be only 32 bits ) */
9310 if (AOP_TYPE (right) == AOP_LIT)
9312 /* Really should be handled by genRightShiftLiteral,
9313 * but since I'm too lazy to fix that today, at least we can make
9314 * some small improvement.
9316 emitcode("mov", "b,#!constbyte",
9317 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9321 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
9322 emitcode ("inc", "b");
9324 freeAsmop (right, NULL, ic, TRUE);
9325 aopOp (left, ic, FALSE, FALSE);
9326 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9328 /* now move the left to the result if they are not the
9330 if (!sameRegs (AOP (left), AOP (result)) &&
9331 AOP_SIZE (result) > 1)
9334 size = AOP_SIZE (result);
9336 _startLazyDPSEvaluation ();
9339 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
9340 if (*l == '@' && IS_AOP_PREG (result))
9343 emitcode ("mov", "a,%s", l);
9344 aopPut (AOP (result), "a", offset);
9347 aopPut (AOP (result), l, offset);
9350 _endLazyDPSEvaluation ();
9353 /* mov the highest order bit to OVR */
9354 tlbl = newiTempLabel (NULL);
9355 tlbl1 = newiTempLabel (NULL);
9357 size = AOP_SIZE (result);
9359 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
9360 emitcode ("rlc", "a");
9361 emitcode ("mov", "ov,c");
9362 /* if it is only one byte then */
9365 MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9366 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9367 emitcode ("", "!tlabeldef", tlbl->key + 100);
9368 emitcode ("mov", "c,ov");
9369 emitcode ("rrc", "a");
9370 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9371 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9372 aopPut (AOP (result), "a", 0);
9376 reAdjustPreg (AOP (result));
9377 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9378 emitcode ("", "!tlabeldef", tlbl->key + 100);
9379 emitcode ("mov", "c,ov");
9380 _startLazyDPSEvaluation ();
9383 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
9384 emitcode ("rrc", "a");
9385 aopPut (AOP (result), "a", offset--);
9387 _endLazyDPSEvaluation ();
9388 reAdjustPreg (AOP (result));
9389 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9390 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9393 freeAsmop (left, NULL, ic, TRUE);
9394 freeAsmop (result, NULL, ic, TRUE);
9397 /*-----------------------------------------------------------------*/
9398 /* genRightShift - generate code for right shifting */
9399 /*-----------------------------------------------------------------*/
9401 genRightShift (iCode * ic)
9403 operand *right, *left, *result;
9407 symbol *tlbl, *tlbl1;
9409 D (emitcode (";", "genRightShift "););
9411 /* if signed then we do it the hard way preserve the
9412 sign bit moving it inwards */
9413 letype = getSpec (operandType (IC_LEFT (ic)));
9415 if (!SPEC_USIGN (letype))
9417 genSignedRightShift (ic);
9421 /* signed & unsigned types are treated the same : i.e. the
9422 signed is NOT propagated inwards : quoting from the
9423 ANSI - standard : "for E1 >> E2, is equivalent to division
9424 by 2**E2 if unsigned or if it has a non-negative value,
9425 otherwise the result is implementation defined ", MY definition
9426 is that the sign does not get propagated */
9428 right = IC_RIGHT (ic);
9429 left = IC_LEFT (ic);
9430 result = IC_RESULT (ic);
9432 aopOp (right, ic, FALSE, FALSE);
9434 #ifdef BETTER_LITERAL_SHIFT
9435 /* if the shift count is known then do it
9436 as efficiently as possible */
9437 if (AOP_TYPE (right) == AOP_LIT)
9439 if (genRightShiftLiteral (left, right, result, ic, 0))
9446 /* shift count is unknown then we have to form
9447 a loop get the loop count in B : Note: we take
9448 only the lower order byte since shifting
9449 more that 32 bits make no sense anyway, ( the
9450 largest size of an object can be only 32 bits ) */
9452 if (AOP_TYPE (right) == AOP_LIT)
9454 /* Really should be handled by genRightShiftLiteral,
9455 * but since I'm too lazy to fix that today, at least we can make
9456 * some small improvement.
9458 emitcode("mov", "b,#!constbyte",
9459 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9463 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
9464 emitcode ("inc", "b");
9466 freeAsmop (right, NULL, ic, TRUE);
9467 aopOp (left, ic, FALSE, FALSE);
9468 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9470 /* now move the left to the result if they are not the
9472 if (!sameRegs (AOP (left), AOP (result)) &&
9473 AOP_SIZE (result) > 1)
9476 size = AOP_SIZE (result);
9478 _startLazyDPSEvaluation ();
9481 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
9482 if (*l == '@' && IS_AOP_PREG (result))
9485 emitcode ("mov", "a,%s", l);
9486 aopPut (AOP (result), "a", offset);
9489 aopPut (AOP (result), l, offset);
9492 _endLazyDPSEvaluation ();
9495 tlbl = newiTempLabel (NULL);
9496 tlbl1 = newiTempLabel (NULL);
9497 size = AOP_SIZE (result);
9500 /* if it is only one byte then */
9503 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9504 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9505 emitcode ("", "!tlabeldef", tlbl->key + 100);
9507 emitcode ("rrc", "a");
9508 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9509 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9510 aopPut (AOP (result), "a", 0);
9514 reAdjustPreg (AOP (result));
9515 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9516 emitcode ("", "!tlabeldef", tlbl->key + 100);
9518 _startLazyDPSEvaluation ();
9521 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
9522 emitcode ("rrc", "a");
9523 aopPut (AOP (result), "a", offset--);
9525 _endLazyDPSEvaluation ();
9526 reAdjustPreg (AOP (result));
9528 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9529 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9532 freeAsmop (left, NULL, ic, TRUE);
9533 freeAsmop (result, NULL, ic, TRUE);
9537 /*-----------------------------------------------------------------*/
9538 /* emitPtrByteGet - emits code to get a byte into A through a */
9539 /* pointer register (R0, R1, or DPTR). The */
9540 /* original value of A can be preserved in B. */
9541 /*-----------------------------------------------------------------*/
9543 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9550 emitcode ("mov", "b,a");
9551 emitcode ("mov", "a,@%s", rname);
9556 emitcode ("mov", "b,a");
9557 emitcode ("movx", "a,@%s", rname);
9562 emitcode ("mov", "b,a");
9563 emitcode ("movx", "a,@dptr");
9568 emitcode ("mov", "b,a");
9569 emitcode ("clr", "a");
9570 emitcode ("movc", "a,@a+dptr");
9576 emitcode ("push", "b");
9577 emitcode ("push", "acc");
9579 emitcode ("lcall", "__gptrget");
9581 emitcode ("pop", "b");
9586 /*-----------------------------------------------------------------*/
9587 /* emitPtrByteSet - emits code to set a byte from src through a */
9588 /* pointer register (R0, R1, or DPTR). */
9589 /*-----------------------------------------------------------------*/
9591 emitPtrByteSet (char *rname, int p_type, char *src)
9600 emitcode ("mov", "@%s,a", rname);
9603 emitcode ("mov", "@%s,%s", rname, src);
9608 emitcode ("movx", "@%s,a", rname);
9613 emitcode ("movx", "@dptr,a");
9618 emitcode ("lcall", "__gptrput");
9623 /*-----------------------------------------------------------------*/
9624 /* genUnpackBits - generates code for unpacking bits */
9625 /*-----------------------------------------------------------------*/
9627 genUnpackBits (operand * result, char *rname, int ptype)
9629 int offset = 0; /* result byte offset */
9630 int rsize; /* result size */
9631 int rlen = 0; /* remaining bitfield length */
9632 sym_link *etype; /* bitfield type information */
9633 int blen; /* bitfield length */
9634 int bstr; /* bitfield starting bit within byte */
9636 D(emitcode ("; genUnpackBits",""));
9638 etype = getSpec (operandType (result));
9639 rsize = getSize (operandType (result));
9640 blen = SPEC_BLEN (etype);
9641 bstr = SPEC_BSTR (etype);
9643 /* If the bitfield length is less than a byte */
9646 emitPtrByteGet (rname, ptype, FALSE);
9648 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
9649 aopPut (AOP (result), "a", offset++);
9653 /* Bit field did not fit in a byte. Copy all
9654 but the partial byte at the end. */
9655 for (rlen=blen;rlen>=8;rlen-=8)
9657 emitPtrByteGet (rname, ptype, FALSE);
9658 aopPut (AOP (result), "a", offset++);
9660 emitcode ("inc", "%s", rname);
9663 /* Handle the partial byte at the end */
9666 emitPtrByteGet (rname, ptype, FALSE);
9667 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
9668 aopPut (AOP (result), "a", offset++);
9676 aopPut (AOP (result), zero, offset++);
9681 /*-----------------------------------------------------------------*/
9682 /* genDataPointerGet - generates code when ptr offset is known */
9683 /*-----------------------------------------------------------------*/
9685 genDataPointerGet (operand * left,
9691 int size, offset = 0;
9692 aopOp (result, ic, TRUE, FALSE);
9694 /* get the string representation of the name */
9695 l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9696 size = AOP_SIZE (result);
9697 _startLazyDPSEvaluation ();
9702 SNPRINTF (buff, sizeof(buff),
9703 "(%s + %d)", l + 1, offset);
9707 SNPRINTF (buff, sizeof(buff),
9710 aopPut (AOP (result), buff, offset++);
9712 _endLazyDPSEvaluation ();
9714 freeAsmop (left, NULL, ic, TRUE);
9715 freeAsmop (result, NULL, ic, TRUE);
9718 /*-----------------------------------------------------------------*/
9719 /* genNearPointerGet - emitcode for near pointer fetch */
9720 /*-----------------------------------------------------------------*/
9722 genNearPointerGet (operand * left,
9730 sym_link *rtype, *retype, *letype;
9731 sym_link *ltype = operandType (left);
9734 rtype = operandType (result);
9735 retype = getSpec (rtype);
9736 letype = getSpec (ltype);
9738 aopOp (left, ic, FALSE, FALSE);
9740 /* if left is rematerialisable and
9741 result is not bitfield variable type and
9742 the left is pointer to data space i.e
9743 lower 128 bytes of space */
9744 if (AOP_TYPE (left) == AOP_IMMD &&
9745 !IS_BITFIELD (retype) &&
9746 !IS_BITFIELD (letype) &&
9747 DCL_TYPE (ltype) == POINTER)
9749 genDataPointerGet (left, result, ic);
9753 /* if the value is already in a pointer register
9754 then don't need anything more */
9755 if (!AOP_INPREG (AOP (left)))
9757 /* otherwise get a free pointer register */
9759 preg = getFreePtr (ic, &aop, FALSE);
9760 emitcode ("mov", "%s,%s",
9762 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9766 rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9768 freeAsmop (left, NULL, ic, TRUE);
9769 aopOp (result, ic, FALSE, FALSE);
9771 /* if bitfield then unpack the bits */
9772 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9773 genUnpackBits (result, rname, POINTER);
9776 /* we have can just get the values */
9777 int size = AOP_SIZE (result);
9782 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9785 emitcode ("mov", "a,@%s", rname);
9786 aopPut (AOP (result), "a", offset);
9790 SNPRINTF (buff, sizeof(buff), "@%s", rname);
9791 aopPut (AOP (result), buff, offset);
9796 emitcode ("inc", "%s", rname);
9801 /* now some housekeeping stuff */
9804 /* we had to allocate for this iCode */
9805 if (pi) { /* post increment present */
9806 aopPut(AOP ( left ),rname,0);
9808 freeAsmop (NULL, aop, ic, TRUE);
9812 /* we did not allocate which means left
9813 already in a pointer register, then
9814 if size > 0 && this could be used again
9815 we have to point it back to where it
9817 if (AOP_SIZE (result) > 1 &&
9818 !OP_SYMBOL (left)->remat &&
9819 (OP_SYMBOL (left)->liveTo > ic->seq ||
9823 int size = AOP_SIZE (result) - 1;
9825 emitcode ("dec", "%s", rname);
9830 freeAsmop (result, NULL, ic, TRUE);
9831 if (pi) pi->generated = 1;
9834 /*-----------------------------------------------------------------*/
9835 /* genPagedPointerGet - emitcode for paged pointer fetch */
9836 /*-----------------------------------------------------------------*/
9838 genPagedPointerGet (operand * left,
9846 sym_link *rtype, *retype, *letype;
9848 rtype = operandType (result);
9849 retype = getSpec (rtype);
9850 letype = getSpec (operandType (left));
9851 aopOp (left, ic, FALSE, FALSE);
9853 /* if the value is already in a pointer register
9854 then don't need anything more */
9855 if (!AOP_INPREG (AOP (left)))
9857 /* otherwise get a free pointer register */
9859 preg = getFreePtr (ic, &aop, FALSE);
9860 emitcode ("mov", "%s,%s",
9862 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9866 rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9868 freeAsmop (left, NULL, ic, TRUE);
9869 aopOp (result, ic, FALSE, FALSE);
9871 /* if bitfield then unpack the bits */
9872 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9873 genUnpackBits (result, rname, PPOINTER);
9876 /* we have can just get the values */
9877 int size = AOP_SIZE (result);
9883 emitcode ("movx", "a,@%s", rname);
9884 aopPut (AOP (result), "a", offset);
9889 emitcode ("inc", "%s", rname);
9893 /* now some housekeeping stuff */
9896 /* we had to allocate for this iCode */
9897 if (pi) aopPut ( AOP (left), rname, 0);
9898 freeAsmop (NULL, aop, ic, TRUE);
9902 /* we did not allocate which means left
9903 already in a pointer register, then
9904 if size > 0 && this could be used again
9905 we have to point it back to where it
9907 if (AOP_SIZE (result) > 1 &&
9908 !OP_SYMBOL (left)->remat &&
9909 (OP_SYMBOL (left)->liveTo > ic->seq ||
9913 int size = AOP_SIZE (result) - 1;
9915 emitcode ("dec", "%s", rname);
9920 freeAsmop (result, NULL, ic, TRUE);
9921 if (pi) pi->generated = 1;
9924 /*-----------------------------------------------------------------*/
9925 /* genFarPointerGet - gget value from far space */
9926 /*-----------------------------------------------------------------*/
9928 genFarPointerGet (operand * left,
9929 operand * result, iCode * ic, iCode *pi)
9931 int size, offset, dopi=1;
9932 sym_link *retype = getSpec (operandType (result));
9933 sym_link *letype = getSpec (operandType (left));
9934 D (emitcode (";", "genFarPointerGet"););
9936 aopOp (left, ic, FALSE, FALSE);
9938 /* if the operand is already in dptr
9939 then we do nothing else we move the value to dptr */
9940 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9942 /* if this is remateriazable */
9943 if (AOP_TYPE (left) == AOP_IMMD)
9945 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9949 /* we need to get it byte by byte */
9950 _startLazyDPSEvaluation ();
9951 if (AOP_TYPE (left) != AOP_DPTR)
9953 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9954 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9955 if (options.model == MODEL_FLAT24)
9956 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9960 /* We need to generate a load to DPTR indirect through DPTR. */
9961 D (emitcode (";", "genFarPointerGet -- indirection special case."););
9962 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9963 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9964 if (options.model == MODEL_FLAT24)
9965 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9966 emitcode ("pop", "dph");
9967 emitcode ("pop", "dpl");
9970 _endLazyDPSEvaluation ();
9973 /* so dptr know contains the address */
9974 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9976 /* if bit then unpack */
9977 if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
9978 if (AOP_INDPTRn(left)) {
9979 genSetDPTR(AOP(left)->aopu.dptr);
9981 genUnpackBits (result, "dptr", FPOINTER);
9982 if (AOP_INDPTRn(left)) {
9987 size = AOP_SIZE (result);
9990 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9992 genSetDPTR(AOP(left)->aopu.dptr);
9993 emitcode ("movx", "a,@dptr");
9994 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9995 emitcode ("inc", "dptr");
9997 aopPut (AOP (result), "a", offset++);
10000 _startLazyDPSEvaluation ();
10002 if (AOP_INDPTRn(left)) {
10003 genSetDPTR(AOP(left)->aopu.dptr);
10009 emitcode ("movx", "a,@dptr");
10010 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10011 emitcode ("inc", "dptr");
10013 aopPut (AOP (result), "a", offset++);
10015 _endLazyDPSEvaluation ();
10018 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10019 if (!AOP_INDPTRn(left)) {
10020 _startLazyDPSEvaluation ();
10021 aopPut ( AOP (left), "dpl", 0);
10022 aopPut ( AOP (left), "dph", 1);
10023 if (options.model == MODEL_FLAT24)
10024 aopPut ( AOP (left), "dpx", 2);
10025 _endLazyDPSEvaluation ();
10028 } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) &&
10029 AOP_SIZE(result) > 1 &&
10031 (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
10033 size = AOP_SIZE (result) - 1;
10034 if (AOP_INDPTRn(left)) {
10035 genSetDPTR(AOP(left)->aopu.dptr);
10037 while (size--) emitcode ("lcall","__decdptr");
10038 if (AOP_INDPTRn(left)) {
10043 freeAsmop (left, NULL, ic, TRUE);
10044 freeAsmop (result, NULL, ic, TRUE);
10047 /*-----------------------------------------------------------------*/
10048 /* genCodePointerGet - get value from code space */
10049 /*-----------------------------------------------------------------*/
10051 genCodePointerGet (operand * left,
10052 operand * result, iCode * ic, iCode *pi)
10054 int size, offset, dopi=1;
10055 sym_link *retype = getSpec (operandType (result));
10057 aopOp (left, ic, FALSE, FALSE);
10059 /* if the operand is already in dptr
10060 then we do nothing else we move the value to dptr */
10061 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
10063 /* if this is remateriazable */
10064 if (AOP_TYPE (left) == AOP_IMMD)
10066 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
10069 { /* we need to get it byte by byte */
10070 _startLazyDPSEvaluation ();
10071 if (AOP_TYPE (left) != AOP_DPTR)
10073 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10074 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10075 if (options.model == MODEL_FLAT24)
10076 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10080 /* We need to generate a load to DPTR indirect through DPTR. */
10081 D (emitcode (";", "gencodePointerGet -- indirection special case."););
10082 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
10083 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
10084 if (options.model == MODEL_FLAT24)
10085 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10086 emitcode ("pop", "dph");
10087 emitcode ("pop", "dpl");
10090 _endLazyDPSEvaluation ();
10093 /* so dptr know contains the address */
10094 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
10096 /* if bit then unpack */
10097 if (IS_BITFIELD (retype)) {
10098 if (AOP_INDPTRn(left)) {
10099 genSetDPTR(AOP(left)->aopu.dptr);
10101 genUnpackBits (result, "dptr", CPOINTER);
10102 if (AOP_INDPTRn(left)) {
10107 size = AOP_SIZE (result);
10109 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10111 genSetDPTR(AOP(left)->aopu.dptr);
10112 emitcode ("clr", "a");
10113 emitcode ("movc", "a,@a+dptr");
10114 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10115 emitcode ("inc", "dptr");
10117 aopPut (AOP (result), "a", offset++);
10120 _startLazyDPSEvaluation ();
10123 if (AOP_INDPTRn(left)) {
10124 genSetDPTR(AOP(left)->aopu.dptr);
10130 emitcode ("clr", "a");
10131 emitcode ("movc", "a,@a+dptr");
10132 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10133 emitcode ("inc", "dptr");
10134 aopPut (AOP (result), "a", offset++);
10136 _endLazyDPSEvaluation ();
10139 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10140 if (!AOP_INDPTRn(left)) {
10141 _startLazyDPSEvaluation ();
10143 aopPut ( AOP (left), "dpl", 0);
10144 aopPut ( AOP (left), "dph", 1);
10145 if (options.model == MODEL_FLAT24)
10146 aopPut ( AOP (left), "dpx", 2);
10148 _endLazyDPSEvaluation ();
10151 } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
10152 AOP_SIZE(result) > 1 &&
10153 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10155 size = AOP_SIZE (result) - 1;
10156 if (AOP_INDPTRn(left)) {
10157 genSetDPTR(AOP(left)->aopu.dptr);
10159 while (size--) emitcode ("lcall","__decdptr");
10160 if (AOP_INDPTRn(left)) {
10165 freeAsmop (left, NULL, ic, TRUE);
10166 freeAsmop (result, NULL, ic, TRUE);
10169 /*-----------------------------------------------------------------*/
10170 /* genGenPointerGet - gget value from generic pointer space */
10171 /*-----------------------------------------------------------------*/
10173 genGenPointerGet (operand * left,
10174 operand * result, iCode * ic, iCode * pi)
10177 sym_link *retype = getSpec (operandType (result));
10178 sym_link *letype = getSpec (operandType (left));
10180 D (emitcode (";", "genGenPointerGet "); );
10182 aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
10184 /* if the operand is already in dptr
10185 then we do nothing else we move the value to dptr */
10186 if (AOP_TYPE (left) != AOP_STR)
10188 /* if this is remateriazable */
10189 if (AOP_TYPE (left) == AOP_IMMD)
10191 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
10192 if (AOP(left)->aopu.aop_immd.from_cast_remat)
10194 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
10198 emitcode ("mov", "b,#%d", pointerCode (retype));
10202 { /* we need to get it byte by byte */
10203 _startLazyDPSEvaluation ();
10204 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
10205 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
10206 if (options.model == MODEL_FLAT24) {
10207 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
10208 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
10210 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
10212 _endLazyDPSEvaluation ();
10216 /* so dptr-b now contains the address */
10218 aopOp (result, ic, FALSE, TRUE);
10221 /* if bit then unpack */
10222 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10224 genUnpackBits (result, "dptr", GPOINTER);
10228 size = AOP_SIZE (result);
10235 // Get two bytes at a time, results in _AP & A.
10236 // dptr will be incremented ONCE by __gptrgetWord.
10238 // Note: any change here must be coordinated
10239 // with the implementation of __gptrgetWord
10240 // in device/lib/_gptrget.c
10241 emitcode ("lcall", "__gptrgetWord");
10242 aopPut (AOP (result), DP2_RESULT_REG, offset++);
10243 aopPut (AOP (result), "a", offset++);
10248 // Only one byte to get.
10249 emitcode ("lcall", "__gptrget");
10250 aopPut (AOP (result), "a", offset++);
10253 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
10255 emitcode ("inc", "dptr");
10260 if (pi && AOP_TYPE (left) != AOP_IMMD) {
10261 _startLazyDPSEvaluation ();
10263 aopPut ( AOP (left), "dpl", 0);
10264 aopPut ( AOP (left), "dph", 1);
10265 if (options.model == MODEL_FLAT24) {
10266 aopPut ( AOP (left), "dpx", 2);
10267 aopPut ( AOP (left), "b", 3);
10268 } else aopPut ( AOP (left), "b", 2);
10270 _endLazyDPSEvaluation ();
10273 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
10274 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10276 size = AOP_SIZE (result) - 1;
10277 while (size--) emitcode ("lcall","__decdptr");
10280 freeAsmop (left, NULL, ic, TRUE);
10281 freeAsmop (result, NULL, ic, TRUE);
10284 /*-----------------------------------------------------------------*/
10285 /* genPointerGet - generate code for pointer get */
10286 /*-----------------------------------------------------------------*/
10288 genPointerGet (iCode * ic, iCode *pi)
10290 operand *left, *result;
10291 sym_link *type, *etype;
10294 D (emitcode (";", "genPointerGet ");
10297 left = IC_LEFT (ic);
10298 result = IC_RESULT (ic);
10300 /* depending on the type of pointer we need to
10301 move it to the correct pointer register */
10302 type = operandType (left);
10303 etype = getSpec (type);
10304 /* if left is of type of pointer then it is simple */
10305 if (IS_PTR (type) && !IS_FUNC (type->next))
10306 p_type = DCL_TYPE (type);
10309 /* we have to go by the storage class */
10310 p_type = PTR_TYPE (SPEC_OCLS (etype));
10312 /* special case when cast remat */
10313 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10314 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
10315 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10316 type = operandType (left);
10317 p_type = DCL_TYPE (type);
10319 /* now that we have the pointer type we assign
10320 the pointer values */
10326 genNearPointerGet (left, result, ic, pi);
10330 genPagedPointerGet (left, result, ic, pi);
10334 genFarPointerGet (left, result, ic, pi);
10338 genCodePointerGet (left, result, ic, pi);
10342 genGenPointerGet (left, result, ic, pi);
10348 /*-----------------------------------------------------------------*/
10349 /* genPackBits - generates code for packed bit storage */
10350 /*-----------------------------------------------------------------*/
10352 genPackBits (sym_link * etype,
10354 char *rname, int p_type)
10356 int offset = 0; /* source byte offset */
10357 int rlen = 0; /* remaining bitfield length */
10358 int blen; /* bitfield length */
10359 int bstr; /* bitfield starting bit within byte */
10360 int litval; /* source literal value (if AOP_LIT) */
10361 unsigned char mask; /* bitmask within current byte */
10363 D(emitcode ("; genPackBits",""));
10365 blen = SPEC_BLEN (etype);
10366 bstr = SPEC_BSTR (etype);
10368 /* If the bitfield length is less than a byte */
10371 mask = ((unsigned char) (0xFF << (blen + bstr)) |
10372 (unsigned char) (0xFF >> (8 - bstr)));
10374 if (AOP_TYPE (right) == AOP_LIT)
10376 /* Case with a bitfield length <8 and literal source
10378 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10380 litval &= (~mask) & 0xff;
10381 emitPtrByteGet (rname, p_type, FALSE);
10382 if ((mask|litval)!=0xff)
10383 emitcode ("anl","a,#!constbyte", mask);
10385 emitcode ("orl","a,#!constbyte", litval);
10389 if ((blen==1) && (p_type!=GPOINTER))
10391 /* Case with a bitfield length == 1 and no generic pointer
10393 if (AOP_TYPE (right) == AOP_CRY)
10394 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10397 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
10398 emitcode ("rrc","a");
10400 emitPtrByteGet (rname, p_type, FALSE);
10401 emitcode ("mov","acc.%d,c",bstr);
10405 /* Case with a bitfield length < 8 and arbitrary source
10407 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
10408 /* shift and mask source value */
10410 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10412 /* transfer A to B and get next byte */
10413 emitPtrByteGet (rname, p_type, TRUE);
10415 emitcode ("anl", "a,#!constbyte", mask);
10416 emitcode ("orl", "a,b");
10417 if (p_type == GPOINTER)
10418 emitcode ("pop", "b");
10422 emitPtrByteSet (rname, p_type, "a");
10426 /* Bit length is greater than 7 bits. In this case, copy */
10427 /* all except the partial byte at the end */
10428 for (rlen=blen;rlen>=8;rlen-=8)
10430 emitPtrByteSet (rname, p_type,
10431 aopGet (AOP (right), offset++, FALSE, TRUE, NULL) );
10433 emitcode ("inc", "%s", rname);
10436 /* If there was a partial byte at the end */
10439 mask = (((unsigned char) -1 << rlen) & 0xff);
10441 if (AOP_TYPE (right) == AOP_LIT)
10443 /* Case with partial byte and literal source
10445 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10446 litval >>= (blen-rlen);
10447 litval &= (~mask) & 0xff;
10448 emitPtrByteGet (rname, p_type, FALSE);
10449 if ((mask|litval)!=0xff)
10450 emitcode ("anl","a,#!constbyte", mask);
10452 emitcode ("orl","a,#!constbyte", litval);
10456 /* Case with partial byte and arbitrary source
10458 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10459 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10461 /* transfer A to B and get next byte */
10462 emitPtrByteGet (rname, p_type, TRUE);
10464 emitcode ("anl", "a,#!constbyte", mask);
10465 emitcode ("orl", "a,b");
10466 if (p_type == GPOINTER)
10467 emitcode ("pop", "b");
10469 emitPtrByteSet (rname, p_type, "a");
10475 /*-----------------------------------------------------------------*/
10476 /* genDataPointerSet - remat pointer to data space */
10477 /*-----------------------------------------------------------------*/
10479 genDataPointerSet (operand * right,
10483 int size, offset = 0;
10484 char *l, buff[256];
10486 aopOp (right, ic, FALSE, FALSE);
10488 l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
10489 size = AOP_SIZE (right);
10494 SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
10498 SNPRINTF (buff, sizeof(buff), "%s", l + 1);
10501 emitcode ("mov", "%s,%s", buff,
10502 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10505 freeAsmop (right, NULL, ic, TRUE);
10506 freeAsmop (result, NULL, ic, TRUE);
10509 /*-----------------------------------------------------------------*/
10510 /* genNearPointerSet - emitcode for near pointer put */
10511 /*-----------------------------------------------------------------*/
10513 genNearPointerSet (operand * right,
10520 sym_link *retype, *letype;
10521 sym_link *ptype = operandType (result);
10523 retype = getSpec (operandType (right));
10524 letype = getSpec (ptype);
10526 aopOp (result, ic, FALSE, FALSE);
10528 /* if the result is rematerializable &
10529 in data space & not a bit variable */
10530 if (AOP_TYPE (result) == AOP_IMMD &&
10531 DCL_TYPE (ptype) == POINTER &&
10532 !IS_BITVAR (retype) &&
10533 !IS_BITVAR (letype))
10535 genDataPointerSet (right, result, ic);
10539 /* if the value is already in a pointer register
10540 then don't need anything more */
10541 if (!AOP_INPREG (AOP (result)))
10543 /* otherwise get a free pointer register */
10546 aop = newAsmop (0);
10547 preg = getFreePtr (ic, &aop, FALSE);
10548 emitcode ("mov", "%s,%s",
10550 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10551 rname = preg->name;
10554 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10556 aopOp (right, ic, FALSE, FALSE);
10558 /* if bitfield then unpack the bits */
10559 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10560 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10563 /* we have can just get the values */
10564 int size = AOP_SIZE (right);
10569 l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
10573 emitcode ("mov", "@%s,a", rname);
10576 emitcode ("mov", "@%s,%s", rname, l);
10578 emitcode ("inc", "%s", rname);
10583 /* now some housekeeping stuff */
10586 /* we had to allocate for this iCode */
10587 if (pi) aopPut (AOP (result),rname,0);
10588 freeAsmop (NULL, aop, ic, TRUE);
10592 /* we did not allocate which means left
10593 already in a pointer register, then
10594 if size > 0 && this could be used again
10595 we have to point it back to where it
10597 if (AOP_SIZE (right) > 1 &&
10598 !OP_SYMBOL (result)->remat &&
10599 (OP_SYMBOL (result)->liveTo > ic->seq ||
10603 int size = AOP_SIZE (right) - 1;
10605 emitcode ("dec", "%s", rname);
10610 if (pi) pi->generated = 1;
10611 freeAsmop (result, NULL, ic, TRUE);
10612 freeAsmop (right, NULL, ic, TRUE);
10617 /*-----------------------------------------------------------------*/
10618 /* genPagedPointerSet - emitcode for Paged pointer put */
10619 /*-----------------------------------------------------------------*/
10621 genPagedPointerSet (operand * right,
10628 sym_link *retype, *letype;
10630 retype = getSpec (operandType (right));
10631 letype = getSpec (operandType (result));
10633 aopOp (result, ic, FALSE, FALSE);
10635 /* if the value is already in a pointer register
10636 then don't need anything more */
10637 if (!AOP_INPREG (AOP (result)))
10639 /* otherwise get a free pointer register */
10642 aop = newAsmop (0);
10643 preg = getFreePtr (ic, &aop, FALSE);
10644 emitcode ("mov", "%s,%s",
10646 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10647 rname = preg->name;
10650 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10652 aopOp (right, ic, FALSE, FALSE);
10654 /* if bitfield then unpack the bits */
10655 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10656 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10659 /* we have can just get the values */
10660 int size = AOP_SIZE (right);
10665 MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10667 emitcode ("movx", "@%s,a", rname);
10670 emitcode ("inc", "%s", rname);
10676 /* now some housekeeping stuff */
10679 if (pi) aopPut (AOP (result),rname,0);
10680 /* we had to allocate for this iCode */
10681 freeAsmop (NULL, aop, ic, TRUE);
10685 /* we did not allocate which means left
10686 already in a pointer register, then
10687 if size > 0 && this could be used again
10688 we have to point it back to where it
10690 if (AOP_SIZE (right) > 1 &&
10691 !OP_SYMBOL (result)->remat &&
10692 (OP_SYMBOL (result)->liveTo > ic->seq ||
10696 int size = AOP_SIZE (right) - 1;
10698 emitcode ("dec", "%s", rname);
10703 if (pi) pi->generated = 1;
10704 freeAsmop (result, NULL, ic, TRUE);
10705 freeAsmop (right, NULL, ic, TRUE);
10710 /*-----------------------------------------------------------------*/
10711 /* genFarPointerSet - set value from far space */
10712 /*-----------------------------------------------------------------*/
10714 genFarPointerSet (operand * right,
10715 operand * result, iCode * ic, iCode *pi)
10717 int size, offset, dopi=1;
10718 sym_link *retype = getSpec (operandType (right));
10719 sym_link *letype = getSpec (operandType (result));
10721 aopOp (result, ic, FALSE, FALSE);
10723 /* if the operand is already in dptr
10724 then we do nothing else we move the value to dptr */
10725 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10727 /* if this is remateriazable */
10728 if (AOP_TYPE (result) == AOP_IMMD)
10729 emitcode ("mov", "dptr,%s",
10730 aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10733 /* we need to get it byte by byte */
10734 _startLazyDPSEvaluation ();
10735 if (AOP_TYPE (result) != AOP_DPTR)
10737 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10738 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10739 if (options.model == MODEL_FLAT24)
10740 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10744 /* We need to generate a load to DPTR indirect through DPTR. */
10745 D (emitcode (";", "genFarPointerSet -- indirection special case."););
10747 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10748 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10749 if (options.model == MODEL_FLAT24)
10750 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10751 emitcode ("pop", "dph");
10752 emitcode ("pop", "dpl");
10755 _endLazyDPSEvaluation ();
10758 /* so dptr know contains the address */
10759 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10761 /* if bit then unpack */
10762 if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
10763 if (AOP_INDPTRn(result)) {
10764 genSetDPTR(AOP(result)->aopu.dptr);
10766 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10767 if (AOP_INDPTRn(result)) {
10771 size = AOP_SIZE (right);
10773 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10775 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10777 genSetDPTR(AOP(result)->aopu.dptr);
10778 emitcode ("movx", "@dptr,a");
10779 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10780 emitcode ("inc", "dptr");
10784 _startLazyDPSEvaluation ();
10786 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10788 if (AOP_INDPTRn(result)) {
10789 genSetDPTR(AOP(result)->aopu.dptr);
10795 emitcode ("movx", "@dptr,a");
10796 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10797 emitcode ("inc", "dptr");
10799 _endLazyDPSEvaluation ();
10803 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10804 if (!AOP_INDPTRn(result)) {
10805 _startLazyDPSEvaluation ();
10807 aopPut (AOP(result),"dpl",0);
10808 aopPut (AOP(result),"dph",1);
10809 if (options.model == MODEL_FLAT24)
10810 aopPut (AOP(result),"dpx",2);
10812 _endLazyDPSEvaluation ();
10815 } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
10816 AOP_SIZE(right) > 1 &&
10817 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10819 size = AOP_SIZE (right) - 1;
10820 if (AOP_INDPTRn(result)) {
10821 genSetDPTR(AOP(result)->aopu.dptr);
10823 while (size--) emitcode ("lcall","__decdptr");
10824 if (AOP_INDPTRn(result)) {
10828 freeAsmop (result, NULL, ic, TRUE);
10829 freeAsmop (right, NULL, ic, TRUE);
10832 /*-----------------------------------------------------------------*/
10833 /* genGenPointerSet - set value from generic pointer space */
10834 /*-----------------------------------------------------------------*/
10836 genGenPointerSet (operand * right,
10837 operand * result, iCode * ic, iCode *pi)
10840 sym_link *retype = getSpec (operandType (right));
10841 sym_link *letype = getSpec (operandType (result));
10843 aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10845 /* if the operand is already in dptr
10846 then we do nothing else we move the value to dptr */
10847 if (AOP_TYPE (result) != AOP_STR)
10849 _startLazyDPSEvaluation ();
10850 /* if this is remateriazable */
10851 if (AOP_TYPE (result) == AOP_IMMD)
10853 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10854 if (AOP(result)->aopu.aop_immd.from_cast_remat)
10856 MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10861 "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10865 { /* we need to get it byte by byte */
10866 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10867 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10868 if (options.model == MODEL_FLAT24) {
10869 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10870 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10872 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10875 _endLazyDPSEvaluation ();
10877 /* so dptr + b now contains the address */
10879 aopOp (right, ic, FALSE, TRUE);
10883 /* if bit then unpack */
10884 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10886 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10890 size = AOP_SIZE (right);
10893 _startLazyDPSEvaluation ();
10898 // Set two bytes at a time, passed in _AP & A.
10899 // dptr will be incremented ONCE by __gptrputWord.
10901 // Note: any change here must be coordinated
10902 // with the implementation of __gptrputWord
10903 // in device/lib/_gptrput.c
10904 emitcode("mov", "_ap, %s",
10905 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10906 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10910 emitcode ("lcall", "__gptrputWord");
10915 // Only one byte to put.
10916 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10920 emitcode ("lcall", "__gptrput");
10923 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10925 emitcode ("inc", "dptr");
10928 _endLazyDPSEvaluation ();
10931 if (pi && AOP_TYPE (result) != AOP_IMMD) {
10932 _startLazyDPSEvaluation ();
10934 aopPut (AOP(result),"dpl",0);
10935 aopPut (AOP(result),"dph",1);
10936 if (options.model == MODEL_FLAT24) {
10937 aopPut (AOP(result),"dpx",2);
10938 aopPut (AOP(result),"b",3);
10940 aopPut (AOP(result),"b",2);
10942 _endLazyDPSEvaluation ();
10945 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10946 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10948 size = AOP_SIZE (right) - 1;
10949 while (size--) emitcode ("lcall","__decdptr");
10951 freeAsmop (result, NULL, ic, TRUE);
10952 freeAsmop (right, NULL, ic, TRUE);
10955 /*-----------------------------------------------------------------*/
10956 /* genPointerSet - stores the value into a pointer location */
10957 /*-----------------------------------------------------------------*/
10959 genPointerSet (iCode * ic, iCode *pi)
10961 operand *right, *result;
10962 sym_link *type, *etype;
10965 D (emitcode (";", "genPointerSet "););
10967 right = IC_RIGHT (ic);
10968 result = IC_RESULT (ic);
10970 /* depending on the type of pointer we need to
10971 move it to the correct pointer register */
10972 type = operandType (result);
10973 etype = getSpec (type);
10974 /* if left is of type of pointer then it is simple */
10975 if (IS_PTR (type) && !IS_FUNC (type->next))
10977 p_type = DCL_TYPE (type);
10981 /* we have to go by the storage class */
10982 p_type = PTR_TYPE (SPEC_OCLS (etype));
10984 /* special case when cast remat */
10985 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10986 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10987 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10988 type = operandType (result);
10989 p_type = DCL_TYPE (type);
10992 /* now that we have the pointer type we assign
10993 the pointer values */
10999 genNearPointerSet (right, result, ic, pi);
11003 genPagedPointerSet (right, result, ic, pi);
11007 genFarPointerSet (right, result, ic, pi);
11011 genGenPointerSet (right, result, ic, pi);
11015 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11016 "genPointerSet: illegal pointer type");
11021 /*-----------------------------------------------------------------*/
11022 /* genIfx - generate code for Ifx statement */
11023 /*-----------------------------------------------------------------*/
11025 genIfx (iCode * ic, iCode * popIc)
11027 operand *cond = IC_COND (ic);
11030 D (emitcode (";", "genIfx "););
11032 aopOp (cond, ic, FALSE, FALSE);
11034 /* get the value into acc */
11035 if (AOP_TYPE (cond) != AOP_CRY)
11044 /* the result is now in the accumulator */
11045 freeAsmop (cond, NULL, ic, TRUE);
11047 /* if there was something to be popped then do it */
11051 /* if the condition is a bit variable */
11052 if (isbit && IS_ITEMP (cond) &&
11055 genIfxJump (ic, SPIL_LOC (cond)->rname);
11057 else if (isbit && !IS_ITEMP (cond))
11059 genIfxJump (ic, OP_SYMBOL (cond)->rname);
11063 genIfxJump (ic, "a");
11069 /*-----------------------------------------------------------------*/
11070 /* genAddrOf - generates code for address of */
11071 /*-----------------------------------------------------------------*/
11073 genAddrOf (iCode * ic)
11075 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
11078 D (emitcode (";", "genAddrOf ");
11081 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11083 /* if the operand is on the stack then we
11084 need to get the stack offset of this
11086 if (sym->onStack) {
11088 /* if 10 bit stack */
11089 if (options.stack10bit) {
11093 tsprintf(buff, sizeof(buff),
11094 "#!constbyte",(options.stack_loc >> 16) & 0xff);
11095 /* if it has an offset then we need to compute it */
11096 /* emitcode ("subb", "a,#!constbyte", */
11097 /* -((sym->stack < 0) ? */
11098 /* ((short) (sym->stack - _G.nRegsSaved)) : */
11099 /* ((short) sym->stack)) & 0xff); */
11100 /* emitcode ("mov","b,a"); */
11101 /* emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
11102 /* ((short) (sym->stack - _G.nRegsSaved)) : */
11103 /* ((short) sym->stack)) >> 8) & 0xff); */
11105 emitcode ("mov", "a,_bpx");
11106 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
11107 ((char) (sym->stack - _G.nRegsSaved)) :
11108 ((char) sym->stack )) & 0xff);
11109 emitcode ("mov", "b,a");
11110 emitcode ("mov", "a,_bpx+1");
11112 offset = (((sym->stack < 0) ?
11113 ((short) (sym->stack - _G.nRegsSaved)) :
11114 ((short) sym->stack )) >> 8) & 0xff;
11116 emitcode ("addc","a,#!constbyte", offset);
11118 aopPut (AOP (IC_RESULT (ic)), "b", 0);
11119 aopPut (AOP (IC_RESULT (ic)), "a", 1);
11120 aopPut (AOP (IC_RESULT (ic)), buff, 2);
11122 /* we can just move _bp */
11123 aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
11124 aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
11125 aopPut (AOP (IC_RESULT (ic)), buff, 2);
11128 /* if it has an offset then we need to compute it */
11130 emitcode ("mov", "a,_bp");
11131 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
11132 aopPut (AOP (IC_RESULT (ic)), "a", 0);
11134 /* we can just move _bp */
11135 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
11137 /* fill the result with zero */
11138 size = AOP_SIZE (IC_RESULT (ic)) - 1;
11141 if (options.stack10bit && size < (FPTRSIZE - 1)) {
11143 "*** warning: pointer to stack var truncated.\n");
11148 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
11154 /* object not on stack then we need the name */
11155 size = AOP_SIZE (IC_RESULT (ic));
11160 char s[SDCC_NAME_MAX];
11164 tsprintf(s, sizeof(s), "#!his",sym->rname);
11167 tsprintf(s, sizeof(s), "#!hihis",sym->rname);
11170 tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
11172 default: /* should not need this (just in case) */
11173 SNPRINTF (s, sizeof(s), "#(%s >> %d)",
11180 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11183 aopPut (AOP (IC_RESULT (ic)), s, offset++);
11187 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11191 #if 0 // obsolete, and buggy for != xdata
11192 /*-----------------------------------------------------------------*/
11193 /* genArrayInit - generates code for address of */
11194 /*-----------------------------------------------------------------*/
11196 genArrayInit (iCode * ic)
11198 literalList *iLoop;
11200 int elementSize = 0, eIndex;
11201 unsigned val, lastVal;
11203 operand *left=IC_LEFT(ic);
11205 D (emitcode (";", "genArrayInit "););
11207 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
11209 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
11211 // Load immediate value into DPTR.
11212 emitcode("mov", "dptr, %s",
11213 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
11215 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
11218 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11219 "Unexpected operand to genArrayInit.\n");
11222 // a regression because of SDCCcse.c:1.52
11223 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
11224 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
11225 if (options.model == MODEL_FLAT24)
11226 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
11230 type = operandType(IC_LEFT(ic));
11232 if (type && type->next)
11234 elementSize = getSize(type->next);
11238 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11239 "can't determine element size in genArrayInit.\n");
11243 iLoop = IC_ARRAYILIST(ic);
11248 bool firstpass = TRUE;
11250 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
11251 iLoop->count, (int)iLoop->literalValue, elementSize);
11257 symbol *tlbl = NULL;
11259 count = ix > 256 ? 256 : ix;
11263 tlbl = newiTempLabel (NULL);
11264 if (firstpass || (count & 0xff))
11266 emitcode("mov", "b, #!constbyte", count & 0xff);
11269 emitcode ("", "!tlabeldef", tlbl->key + 100);
11274 for (eIndex = 0; eIndex < elementSize; eIndex++)
11276 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
11277 if (val != lastVal)
11279 emitcode("mov", "a, #!constbyte", val);
11283 emitcode("movx", "@dptr, a");
11284 emitcode("inc", "dptr");
11289 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
11295 iLoop = iLoop->next;
11298 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
11302 /*-----------------------------------------------------------------*/
11303 /* genFarFarAssign - assignment when both are in far space */
11304 /*-----------------------------------------------------------------*/
11306 genFarFarAssign (operand * result, operand * right, iCode * ic)
11308 int size = AOP_SIZE (right);
11310 symbol *rSym = NULL;
11314 /* quick & easy case. */
11315 D(emitcode(";","genFarFarAssign (1 byte case)"););
11316 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
11317 freeAsmop (right, NULL, ic, FALSE);
11318 /* now assign DPTR to result */
11320 aopOp(result, ic, FALSE, FALSE);
11322 aopPut(AOP(result), "a", 0);
11323 freeAsmop(result, NULL, ic, FALSE);
11327 /* See if we've got an underlying symbol to abuse. */
11328 if (IS_SYMOP(result) && OP_SYMBOL(result))
11330 if (IS_TRUE_SYMOP(result))
11332 rSym = OP_SYMBOL(result);
11334 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
11336 rSym = OP_SYMBOL(result)->usl.spillLoc;
11340 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
11342 /* We can use the '390 auto-toggle feature to good effect here. */
11344 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
11345 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11346 emitcode ("mov", "dptr,#%s", rSym->rname);
11347 /* DP2 = result, DP1 = right, DP1 is current. */
11350 emitcode("movx", "a,@dptr");
11351 emitcode("movx", "@dptr,a");
11354 emitcode("inc", "dptr");
11355 emitcode("inc", "dptr");
11358 emitcode("mov", "dps,#0");
11359 freeAsmop (right, NULL, ic, FALSE);
11361 some alternative code for processors without auto-toggle
11362 no time to test now, so later well put in...kpb
11363 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
11364 emitcode("mov", "dps,#1"); /* Select DPTR2. */
11365 emitcode ("mov", "dptr,#%s", rSym->rname);
11366 /* DP2 = result, DP1 = right, DP1 is current. */
11370 emitcode("movx", "a,@dptr");
11372 emitcode("inc", "dptr");
11373 emitcode("inc", "dps");
11374 emitcode("movx", "@dptr,a");
11376 emitcode("inc", "dptr");
11377 emitcode("inc", "dps");
11379 emitcode("mov", "dps,#0");
11380 freeAsmop (right, NULL, ic, FALSE);
11385 D (emitcode (";", "genFarFarAssign"););
11386 aopOp (result, ic, TRUE, TRUE);
11388 _startLazyDPSEvaluation ();
11392 aopPut (AOP (result),
11393 aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
11396 _endLazyDPSEvaluation ();
11397 freeAsmop (result, NULL, ic, FALSE);
11398 freeAsmop (right, NULL, ic, FALSE);
11402 /*-----------------------------------------------------------------*/
11403 /* genAssign - generate code for assignment */
11404 /*-----------------------------------------------------------------*/
11406 genAssign (iCode * ic)
11408 operand *result, *right;
11410 unsigned long lit = 0L;
11412 D (emitcode (";", "genAssign ");
11415 result = IC_RESULT (ic);
11416 right = IC_RIGHT (ic);
11418 /* if they are the same */
11419 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11422 aopOp (right, ic, FALSE, FALSE);
11424 emitcode (";", "genAssign: resultIsFar = %s",
11425 isOperandInFarSpace (result) ?
11428 /* special case both in far space */
11429 if ((AOP_TYPE (right) == AOP_DPTR ||
11430 AOP_TYPE (right) == AOP_DPTR2) &&
11431 /* IS_TRUE_SYMOP(result) && */
11432 isOperandInFarSpace (result))
11434 genFarFarAssign (result, right, ic);
11438 aopOp (result, ic, TRUE, FALSE);
11440 /* if they are the same registers */
11441 if (sameRegs (AOP (right), AOP (result)))
11444 /* if the result is a bit */
11445 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
11447 /* if the right size is a literal then
11448 we know what the value is */
11449 if (AOP_TYPE (right) == AOP_LIT)
11451 if (((int) operandLitValue (right)))
11452 aopPut (AOP (result), one, 0);
11454 aopPut (AOP (result), zero, 0);
11458 /* the right is also a bit variable */
11459 if (AOP_TYPE (right) == AOP_CRY)
11461 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11462 aopPut (AOP (result), "c", 0);
11466 /* we need to or */
11468 aopPut (AOP (result), "a", 0);
11472 /* bit variables done */
11474 size = AOP_SIZE (result);
11476 if (AOP_TYPE (right) == AOP_LIT)
11477 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11480 (AOP_TYPE (result) != AOP_REG) &&
11481 (AOP_TYPE (right) == AOP_LIT) &&
11482 !IS_FLOAT (operandType (right)))
11484 _startLazyDPSEvaluation ();
11485 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
11487 aopPut (AOP (result),
11488 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11493 /* And now fill the rest with zeros. */
11496 emitcode ("clr", "a");
11500 aopPut (AOP (result), "a", offset++);
11502 _endLazyDPSEvaluation ();
11506 _startLazyDPSEvaluation ();
11509 aopPut (AOP (result),
11510 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11514 _endLazyDPSEvaluation ();
11518 freeAsmop (right, NULL, ic, FALSE);
11519 freeAsmop (result, NULL, ic, TRUE);
11522 /*-----------------------------------------------------------------*/
11523 /* genJumpTab - generates code for jump table */
11524 /*-----------------------------------------------------------------*/
11526 genJumpTab (iCode * ic)
11531 D (emitcode (";", "genJumpTab ");
11534 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
11535 /* get the condition into accumulator */
11536 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
11538 /* multiply by four! */
11539 emitcode ("add", "a,acc");
11540 emitcode ("add", "a,acc");
11541 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11543 jtab = newiTempLabel (NULL);
11544 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
11545 emitcode ("jmp", "@a+dptr");
11546 emitcode ("", "!tlabeldef", jtab->key + 100);
11547 /* now generate the jump labels */
11548 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11549 jtab = setNextItem (IC_JTLABELS (ic)))
11550 emitcode ("ljmp", "!tlabel", jtab->key + 100);
11554 /*-----------------------------------------------------------------*/
11555 /* genCast - gen code for casting */
11556 /*-----------------------------------------------------------------*/
11558 genCast (iCode * ic)
11560 operand *result = IC_RESULT (ic);
11561 sym_link *ctype = operandType (IC_LEFT (ic));
11562 sym_link *rtype = operandType (IC_RIGHT (ic));
11563 operand *right = IC_RIGHT (ic);
11566 D (emitcode (";", "genCast "););
11568 /* if they are equivalent then do nothing */
11569 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11572 aopOp (right, ic, FALSE, AOP_IS_STR (result));
11573 aopOp (result, ic, FALSE, (AOP_TYPE(right) == AOP_DPTR));
11575 /* if the result is a bit */
11576 if (IS_BITVAR (OP_SYMBOL (result)->type)
11577 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
11579 /* if the right size is a literal then
11580 we know what the value is */
11581 if (AOP_TYPE (right) == AOP_LIT)
11583 if (((int) operandLitValue (right)))
11584 aopPut (AOP (result), one, 0);
11586 aopPut (AOP (result), zero, 0);
11591 /* the right is also a bit variable */
11592 if (AOP_TYPE (right) == AOP_CRY)
11594 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11595 aopPut (AOP (result), "c", 0);
11599 /* we need to or */
11601 aopPut (AOP (result), "a", 0);
11605 /* if they are the same size : or less */
11606 if (AOP_SIZE (result) <= AOP_SIZE (right))
11609 /* if they are in the same place */
11610 if (sameRegs (AOP (right), AOP (result)))
11613 /* if they in different places then copy */
11614 size = AOP_SIZE (result);
11616 _startLazyDPSEvaluation ();
11619 aopPut (AOP (result),
11620 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11624 _endLazyDPSEvaluation ();
11629 /* if the result is of type pointer */
11630 if (IS_PTR (ctype))
11634 sym_link *type = operandType (right);
11636 /* pointer to generic pointer */
11637 if (IS_GENPTR (ctype))
11641 p_type = DCL_TYPE (type);
11645 #if OLD_CAST_BEHAVIOR
11646 /* KV: we are converting a non-pointer type to
11647 * a generic pointer. This (ifdef'd out) code
11648 * says that the resulting generic pointer
11649 * should have the same class as the storage
11650 * location of the non-pointer variable.
11652 * For example, converting an int (which happens
11653 * to be stored in DATA space) to a pointer results
11654 * in a DATA generic pointer; if the original int
11655 * in XDATA space, so will be the resulting pointer.
11657 * I don't like that behavior, and thus this change:
11658 * all such conversions will be forced to XDATA and
11659 * throw a warning. If you want some non-XDATA
11660 * type, or you want to suppress the warning, you
11661 * must go through an intermediate cast, like so:
11663 * char _generic *gp = (char _xdata *)(intVar);
11665 sym_link *etype = getSpec (type);
11667 /* we have to go by the storage class */
11668 if (SPEC_OCLS (etype) != generic)
11670 p_type = PTR_TYPE (SPEC_OCLS (etype));
11675 /* Converting unknown class (i.e. register variable)
11676 * to generic pointer. This is not good, but
11677 * we'll make a guess (and throw a warning).
11680 werror (W_INT_TO_GEN_PTR_CAST);
11684 /* the first two bytes are known */
11685 size = GPTRSIZE - 1;
11687 _startLazyDPSEvaluation ();
11690 aopPut (AOP (result),
11691 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11695 _endLazyDPSEvaluation ();
11697 /* the last byte depending on type */
11699 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11704 // pointerTypeToGPByte will have bitched.
11708 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11709 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11714 /* just copy the pointers */
11715 size = AOP_SIZE (result);
11717 _startLazyDPSEvaluation ();
11720 aopPut (AOP (result),
11721 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11725 _endLazyDPSEvaluation ();
11729 /* so we now know that the size of destination is greater
11730 than the size of the source */
11731 /* we move to result for the size of source */
11732 size = AOP_SIZE (right);
11734 _startLazyDPSEvaluation ();
11737 aopPut (AOP (result),
11738 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11742 _endLazyDPSEvaluation ();
11744 /* now depending on the sign of the source && destination */
11745 size = AOP_SIZE (result) - AOP_SIZE (right);
11746 /* if unsigned or not an integral type */
11747 /* also, if the source is a bit, we don't need to sign extend, because
11748 * it can't possibly have set the sign bit.
11750 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
11754 aopPut (AOP (result), zero, offset++);
11759 /* we need to extend the sign :{ */
11760 MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11761 FALSE, FALSE, NULL));
11762 emitcode ("rlc", "a");
11763 emitcode ("subb", "a,acc");
11765 aopPut (AOP (result), "a", offset++);
11768 /* we are done hurray !!!! */
11771 freeAsmop (right, NULL, ic, TRUE);
11772 freeAsmop (result, NULL, ic, TRUE);
11776 /*-----------------------------------------------------------------*/
11777 /* genDjnz - generate decrement & jump if not zero instrucion */
11778 /*-----------------------------------------------------------------*/
11780 genDjnz (iCode * ic, iCode * ifx)
11782 symbol *lbl, *lbl1;
11786 /* if the if condition has a false label
11787 then we cannot save */
11788 if (IC_FALSE (ifx))
11791 /* if the minus is not of the form
11793 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11794 !IS_OP_LITERAL (IC_RIGHT (ic)))
11797 if (operandLitValue (IC_RIGHT (ic)) != 1)
11800 /* if the size of this greater than one then no
11802 if (getSize (operandType (IC_RESULT (ic))) > 1)
11805 /* otherwise we can save BIG */
11806 D(emitcode(";", "genDjnz"););
11808 lbl = newiTempLabel (NULL);
11809 lbl1 = newiTempLabel (NULL);
11811 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11813 if (AOP_NEEDSACC(IC_RESULT(ic)))
11815 /* If the result is accessed indirectly via
11816 * the accumulator, we must explicitly write
11817 * it back after the decrement.
11819 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11821 if (strcmp(rByte, "a"))
11823 /* Something is hopelessly wrong */
11824 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11825 __FILE__, __LINE__);
11826 /* We can just give up; the generated code will be inefficient,
11827 * but what the hey.
11829 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11832 emitcode ("dec", "%s", rByte);
11833 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11834 emitcode ("jnz", "!tlabel", lbl->key + 100);
11836 else if (IS_AOP_PREG (IC_RESULT (ic)))
11838 emitcode ("dec", "%s",
11839 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11840 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11841 emitcode ("jnz", "!tlabel", lbl->key + 100);
11845 emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11848 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11849 emitcode ("", "!tlabeldef", lbl->key + 100);
11850 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11851 emitcode ("", "!tlabeldef", lbl1->key + 100);
11853 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11854 ifx->generated = 1;
11858 /*-----------------------------------------------------------------*/
11859 /* genReceive - generate code for a receive iCode */
11860 /*-----------------------------------------------------------------*/
11862 genReceive (iCode * ic)
11864 int size = getSize (operandType (IC_RESULT (ic)));
11868 D (emitcode (";", "genReceive "););
11870 if (ic->argreg == 1)
11872 /* first parameter */
11873 if (AOP_IS_STR(IC_RESULT(ic)))
11875 /* Nothing to do: it's already in the proper place. */
11882 useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11883 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11884 IS_TRUE_SYMOP (IC_RESULT (ic)));
11887 aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11890 /* Sanity checking... */
11891 if (AOP_USESDPTR(IC_RESULT(ic)))
11893 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11894 "genReceive got unexpected DPTR.");
11896 assignResultValue (IC_RESULT (ic));
11901 /* second receive onwards */
11902 /* this gets a little tricky since unused recevies will be
11903 eliminated, we have saved the reg in the type field . and
11904 we use that to figure out which register to use */
11905 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11906 rb1off = ic->argreg;
11909 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11912 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11915 /*-----------------------------------------------------------------*/
11916 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
11917 /*-----------------------------------------------------------------*/
11918 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11920 operand *from , *to , *count;
11925 /* we know it has to be 3 parameters */
11926 assert (nparms == 3);
11928 rsave = newBitVect(16);
11929 /* save DPTR if it needs to be saved */
11930 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11931 if (bitVectBitValue(ic->rMask,i))
11932 rsave = bitVectSetBit(rsave,i);
11934 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11935 ds390_rUmaskForOp (IC_RESULT(ic))));
11942 aopOp (from, ic->next, FALSE, FALSE);
11944 /* get from into DPTR1 */
11945 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11946 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11947 if (options.model == MODEL_FLAT24) {
11948 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11951 freeAsmop (from, NULL, ic, FALSE);
11952 aopOp (to, ic, FALSE, FALSE);
11953 /* get "to" into DPTR */
11954 /* if the operand is already in dptr
11955 then we do nothing else we move the value to dptr */
11956 if (AOP_TYPE (to) != AOP_STR) {
11957 /* if already in DPTR then we need to push */
11958 if (AOP_TYPE(to) == AOP_DPTR) {
11959 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11960 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11961 if (options.model == MODEL_FLAT24)
11962 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11963 emitcode ("pop", "dph");
11964 emitcode ("pop", "dpl");
11966 _startLazyDPSEvaluation ();
11967 /* if this is remateriazable */
11968 if (AOP_TYPE (to) == AOP_IMMD) {
11969 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11970 } else { /* we need to get it byte by byte */
11971 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11972 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11973 if (options.model == MODEL_FLAT24) {
11974 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11977 _endLazyDPSEvaluation ();
11980 freeAsmop (to, NULL, ic, FALSE);
11981 _G.dptrInUse = _G.dptr1InUse = 1;
11982 aopOp (count, ic->next->next, FALSE,FALSE);
11983 lbl =newiTempLabel(NULL);
11985 /* now for the actual copy */
11986 if (AOP_TYPE(count) == AOP_LIT &&
11987 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11988 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11990 emitcode ("lcall","__bi_memcpyc2x_s");
11992 emitcode ("lcall","__bi_memcpyx2x_s");
11994 freeAsmop (count, NULL, ic, FALSE);
11996 symbol *lbl1 = newiTempLabel(NULL);
11998 emitcode (";"," Auto increment but no djnz");
11999 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12000 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12001 freeAsmop (count, NULL, ic, FALSE);
12002 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12003 emitcode ("","!tlabeldef",lbl->key+100);
12005 emitcode ("clr","a");
12006 emitcode ("movc", "a,@a+dptr");
12008 emitcode ("movx", "a,@dptr");
12009 emitcode ("movx", "@dptr,a");
12010 emitcode ("inc", "dptr");
12011 emitcode ("inc", "dptr");
12012 emitcode ("mov","a,b");
12013 emitcode ("orl","a,_ap");
12014 emitcode ("jz","!tlabel",lbl1->key+100);
12015 emitcode ("mov","a,_ap");
12016 emitcode ("add","a,#!constbyte",0xFF);
12017 emitcode ("mov","_ap,a");
12018 emitcode ("mov","a,b");
12019 emitcode ("addc","a,#!constbyte",0xFF);
12020 emitcode ("mov","b,a");
12021 emitcode ("sjmp","!tlabel",lbl->key+100);
12022 emitcode ("","!tlabeldef",lbl1->key+100);
12024 emitcode ("mov", "dps,#0");
12025 _G.dptrInUse = _G.dptr1InUse = 0;
12026 unsavermask(rsave);
12030 /*-----------------------------------------------------------------*/
12031 /* genMemcmpX2X - gen code for memcmp xdata to xdata */
12032 /*-----------------------------------------------------------------*/
12033 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
12035 operand *from , *to , *count;
12040 /* we know it has to be 3 parameters */
12041 assert (nparms == 3);
12043 rsave = newBitVect(16);
12044 /* save DPTR if it needs to be saved */
12045 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12046 if (bitVectBitValue(ic->rMask,i))
12047 rsave = bitVectSetBit(rsave,i);
12049 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12050 ds390_rUmaskForOp (IC_RESULT(ic))));
12057 aopOp (from, ic->next, FALSE, FALSE);
12059 /* get from into DPTR1 */
12060 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12061 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12062 if (options.model == MODEL_FLAT24) {
12063 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12066 freeAsmop (from, NULL, ic, FALSE);
12067 aopOp (to, ic, FALSE, FALSE);
12068 /* get "to" into DPTR */
12069 /* if the operand is already in dptr
12070 then we do nothing else we move the value to dptr */
12071 if (AOP_TYPE (to) != AOP_STR) {
12072 /* if already in DPTR then we need to push */
12073 if (AOP_TYPE(to) == AOP_DPTR) {
12074 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12075 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12076 if (options.model == MODEL_FLAT24)
12077 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12078 emitcode ("pop", "dph");
12079 emitcode ("pop", "dpl");
12081 _startLazyDPSEvaluation ();
12082 /* if this is remateriazable */
12083 if (AOP_TYPE (to) == AOP_IMMD) {
12084 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12085 } else { /* we need to get it byte by byte */
12086 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12087 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12088 if (options.model == MODEL_FLAT24) {
12089 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12092 _endLazyDPSEvaluation ();
12095 freeAsmop (to, NULL, ic, FALSE);
12096 _G.dptrInUse = _G.dptr1InUse = 1;
12097 aopOp (count, ic->next->next, FALSE,FALSE);
12098 lbl =newiTempLabel(NULL);
12099 lbl2 =newiTempLabel(NULL);
12101 /* now for the actual compare */
12102 if (AOP_TYPE(count) == AOP_LIT &&
12103 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12104 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12106 emitcode("lcall","__bi_memcmpc2x_s");
12108 emitcode("lcall","__bi_memcmpx2x_s");
12109 freeAsmop (count, NULL, ic, FALSE);
12110 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12111 aopPut(AOP(IC_RESULT(ic)),"a",0);
12112 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12114 symbol *lbl1 = newiTempLabel(NULL);
12116 emitcode("push","ar0");
12117 emitcode (";"," Auto increment but no djnz");
12118 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12119 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12120 freeAsmop (count, NULL, ic, FALSE);
12121 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12122 emitcode ("","!tlabeldef",lbl->key+100);
12124 emitcode ("clr","a");
12125 emitcode ("movc", "a,@a+dptr");
12127 emitcode ("movx", "a,@dptr");
12128 emitcode ("mov","r0,a");
12129 emitcode ("movx", "a,@dptr");
12130 emitcode ("clr","c");
12131 emitcode ("subb","a,r0");
12132 emitcode ("jnz","!tlabel",lbl2->key+100);
12133 emitcode ("inc", "dptr");
12134 emitcode ("inc", "dptr");
12135 emitcode ("mov","a,b");
12136 emitcode ("orl","a,_ap");
12137 emitcode ("jz","!tlabel",lbl1->key+100);
12138 emitcode ("mov","a,_ap");
12139 emitcode ("add","a,#!constbyte",0xFF);
12140 emitcode ("mov","_ap,a");
12141 emitcode ("mov","a,b");
12142 emitcode ("addc","a,#!constbyte",0xFF);
12143 emitcode ("mov","b,a");
12144 emitcode ("sjmp","!tlabel",lbl->key+100);
12145 emitcode ("","!tlabeldef",lbl1->key+100);
12146 emitcode ("clr","a");
12147 emitcode ("","!tlabeldef",lbl2->key+100);
12148 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12149 aopPut(AOP(IC_RESULT(ic)),"a",0);
12150 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12151 emitcode("pop","ar0");
12152 emitcode ("mov", "dps,#0");
12154 _G.dptrInUse = _G.dptr1InUse = 0;
12155 unsavermask(rsave);
12159 /*-----------------------------------------------------------------*/
12160 /* genInp - gen code for __builtin_inp read data from a mem mapped */
12161 /* port, first parameter output area second parameter pointer to */
12162 /* port third parameter count */
12163 /*-----------------------------------------------------------------*/
12164 static void genInp( iCode *ic, int nparms, operand **parms)
12166 operand *from , *to , *count;
12171 /* we know it has to be 3 parameters */
12172 assert (nparms == 3);
12174 rsave = newBitVect(16);
12175 /* save DPTR if it needs to be saved */
12176 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12177 if (bitVectBitValue(ic->rMask,i))
12178 rsave = bitVectSetBit(rsave,i);
12180 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12181 ds390_rUmaskForOp (IC_RESULT(ic))));
12188 aopOp (from, ic->next, FALSE, FALSE);
12190 /* get from into DPTR1 */
12191 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12192 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12193 if (options.model == MODEL_FLAT24) {
12194 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12197 freeAsmop (from, NULL, ic, FALSE);
12198 aopOp (to, ic, FALSE, FALSE);
12199 /* get "to" into DPTR */
12200 /* if the operand is already in dptr
12201 then we do nothing else we move the value to dptr */
12202 if (AOP_TYPE (to) != AOP_STR) {
12203 /* if already in DPTR then we need to push */
12204 if (AOP_TYPE(to) == AOP_DPTR) {
12205 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12206 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12207 if (options.model == MODEL_FLAT24)
12208 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12209 emitcode ("pop", "dph");
12210 emitcode ("pop", "dpl");
12212 _startLazyDPSEvaluation ();
12213 /* if this is remateriazable */
12214 if (AOP_TYPE (to) == AOP_IMMD) {
12215 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12216 } else { /* we need to get it byte by byte */
12217 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12218 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12219 if (options.model == MODEL_FLAT24) {
12220 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12223 _endLazyDPSEvaluation ();
12226 freeAsmop (to, NULL, ic, FALSE);
12228 _G.dptrInUse = _G.dptr1InUse = 1;
12229 aopOp (count, ic->next->next, FALSE,FALSE);
12230 lbl =newiTempLabel(NULL);
12232 /* now for the actual copy */
12233 if (AOP_TYPE(count) == AOP_LIT &&
12234 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12235 emitcode (";","OH JOY auto increment with djnz (very fast)");
12236 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
12237 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12238 freeAsmop (count, NULL, ic, FALSE);
12239 emitcode ("","!tlabeldef",lbl->key+100);
12240 emitcode ("movx", "a,@dptr"); /* read data from port */
12241 emitcode ("dec","dps"); /* switch to DPTR */
12242 emitcode ("movx", "@dptr,a"); /* save into location */
12243 emitcode ("inc", "dptr"); /* point to next area */
12244 emitcode ("inc","dps"); /* switch to DPTR2 */
12245 emitcode ("djnz","b,!tlabel",lbl->key+100);
12247 symbol *lbl1 = newiTempLabel(NULL);
12249 emitcode (";"," Auto increment but no djnz");
12250 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12251 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12252 freeAsmop (count, NULL, ic, FALSE);
12253 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
12254 emitcode ("","!tlabeldef",lbl->key+100);
12255 emitcode ("movx", "a,@dptr");
12256 emitcode ("dec","dps"); /* switch to DPTR */
12257 emitcode ("movx", "@dptr,a");
12258 emitcode ("inc", "dptr");
12259 emitcode ("inc","dps"); /* switch to DPTR2 */
12260 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
12261 /* emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
12262 emitcode ("mov","a,b");
12263 emitcode ("orl","a,_ap");
12264 emitcode ("jz","!tlabel",lbl1->key+100);
12265 emitcode ("mov","a,_ap");
12266 emitcode ("add","a,#!constbyte",0xFF);
12267 emitcode ("mov","_ap,a");
12268 emitcode ("mov","a,b");
12269 emitcode ("addc","a,#!constbyte",0xFF);
12270 emitcode ("mov","b,a");
12271 emitcode ("sjmp","!tlabel",lbl->key+100);
12272 emitcode ("","!tlabeldef",lbl1->key+100);
12274 emitcode ("mov", "dps,#0");
12275 _G.dptrInUse = _G.dptr1InUse = 0;
12276 unsavermask(rsave);
12280 /*-----------------------------------------------------------------*/
12281 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
12282 /* port, first parameter output area second parameter pointer to */
12283 /* port third parameter count */
12284 /*-----------------------------------------------------------------*/
12285 static void genOutp( iCode *ic, int nparms, operand **parms)
12287 operand *from , *to , *count;
12292 /* we know it has to be 3 parameters */
12293 assert (nparms == 3);
12295 rsave = newBitVect(16);
12296 /* save DPTR if it needs to be saved */
12297 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12298 if (bitVectBitValue(ic->rMask,i))
12299 rsave = bitVectSetBit(rsave,i);
12301 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12302 ds390_rUmaskForOp (IC_RESULT(ic))));
12309 aopOp (from, ic->next, FALSE, FALSE);
12311 /* get from into DPTR1 */
12312 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12313 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12314 if (options.model == MODEL_FLAT24) {
12315 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12318 freeAsmop (from, NULL, ic, FALSE);
12319 aopOp (to, ic, FALSE, FALSE);
12320 /* get "to" into DPTR */
12321 /* if the operand is already in dptr
12322 then we do nothing else we move the value to dptr */
12323 if (AOP_TYPE (to) != AOP_STR) {
12324 /* if already in DPTR then we need to push */
12325 if (AOP_TYPE(to) == AOP_DPTR) {
12326 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12327 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12328 if (options.model == MODEL_FLAT24)
12329 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12330 emitcode ("pop", "dph");
12331 emitcode ("pop", "dpl");
12333 _startLazyDPSEvaluation ();
12334 /* if this is remateriazable */
12335 if (AOP_TYPE (to) == AOP_IMMD) {
12336 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12337 } else { /* we need to get it byte by byte */
12338 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12339 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12340 if (options.model == MODEL_FLAT24) {
12341 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12344 _endLazyDPSEvaluation ();
12347 freeAsmop (to, NULL, ic, FALSE);
12349 _G.dptrInUse = _G.dptr1InUse = 1;
12350 aopOp (count, ic->next->next, FALSE,FALSE);
12351 lbl =newiTempLabel(NULL);
12353 /* now for the actual copy */
12354 if (AOP_TYPE(count) == AOP_LIT &&
12355 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12356 emitcode (";","OH JOY auto increment with djnz (very fast)");
12357 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
12358 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12359 emitcode ("","!tlabeldef",lbl->key+100);
12360 emitcode ("movx", "a,@dptr"); /* read data from port */
12361 emitcode ("inc","dps"); /* switch to DPTR2 */
12362 emitcode ("movx", "@dptr,a"); /* save into location */
12363 emitcode ("inc", "dptr"); /* point to next area */
12364 emitcode ("dec","dps"); /* switch to DPTR */
12365 emitcode ("djnz","b,!tlabel",lbl->key+100);
12366 freeAsmop (count, NULL, ic, FALSE);
12368 symbol *lbl1 = newiTempLabel(NULL);
12370 emitcode (";"," Auto increment but no djnz");
12371 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12372 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12373 freeAsmop (count, NULL, ic, FALSE);
12374 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
12375 emitcode ("","!tlabeldef",lbl->key+100);
12376 emitcode ("movx", "a,@dptr");
12377 emitcode ("inc", "dptr");
12378 emitcode ("inc","dps"); /* switch to DPTR2 */
12379 emitcode ("movx", "@dptr,a");
12380 emitcode ("dec","dps"); /* switch to DPTR */
12381 emitcode ("mov","a,b");
12382 emitcode ("orl","a,_ap");
12383 emitcode ("jz","!tlabel",lbl1->key+100);
12384 emitcode ("mov","a,_ap");
12385 emitcode ("add","a,#!constbyte",0xFF);
12386 emitcode ("mov","_ap,a");
12387 emitcode ("mov","a,b");
12388 emitcode ("addc","a,#!constbyte",0xFF);
12389 emitcode ("mov","b,a");
12390 emitcode ("sjmp","!tlabel",lbl->key+100);
12391 emitcode ("","!tlabeldef",lbl1->key+100);
12393 emitcode ("mov", "dps,#0");
12394 _G.dptrInUse = _G.dptr1InUse = 0;
12395 unsavermask(rsave);
12399 /*-----------------------------------------------------------------*/
12400 /* genSwapW - swap lower & high order bytes */
12401 /*-----------------------------------------------------------------*/
12402 static void genSwapW(iCode *ic, int nparms, operand **parms)
12406 assert (nparms==1);
12409 dest=IC_RESULT(ic);
12411 assert(getSize(operandType(src))==2);
12413 aopOp (src, ic, FALSE, FALSE);
12414 emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
12416 MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
12418 freeAsmop (src, NULL, ic, FALSE);
12420 aopOp (dest,ic, FALSE, FALSE);
12421 aopPut(AOP(dest),"b",0);
12422 aopPut(AOP(dest),"a",1);
12423 freeAsmop (dest, NULL, ic, FALSE);
12426 /*-----------------------------------------------------------------*/
12427 /* genMemsetX - gencode for memSetX data */
12428 /*-----------------------------------------------------------------*/
12429 static void genMemsetX(iCode *ic, int nparms, operand **parms)
12431 operand *to , *val , *count;
12437 /* we know it has to be 3 parameters */
12438 assert (nparms == 3);
12444 /* save DPTR if it needs to be saved */
12445 rsave = newBitVect(16);
12446 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12447 if (bitVectBitValue(ic->rMask,i))
12448 rsave = bitVectSetBit(rsave,i);
12450 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12451 ds390_rUmaskForOp (IC_RESULT(ic))));
12454 aopOp (to, ic, FALSE, FALSE);
12455 /* get "to" into DPTR */
12456 /* if the operand is already in dptr
12457 then we do nothing else we move the value to dptr */
12458 if (AOP_TYPE (to) != AOP_STR) {
12459 /* if already in DPTR then we need to push */
12460 if (AOP_TYPE(to) == AOP_DPTR) {
12461 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12462 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12463 if (options.model == MODEL_FLAT24)
12464 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12465 emitcode ("pop", "dph");
12466 emitcode ("pop", "dpl");
12468 _startLazyDPSEvaluation ();
12469 /* if this is remateriazable */
12470 if (AOP_TYPE (to) == AOP_IMMD) {
12471 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12472 } else { /* we need to get it byte by byte */
12473 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12474 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12475 if (options.model == MODEL_FLAT24) {
12476 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12479 _endLazyDPSEvaluation ();
12482 freeAsmop (to, NULL, ic, FALSE);
12484 aopOp (val, ic->next->next, FALSE,FALSE);
12485 aopOp (count, ic->next->next, FALSE,FALSE);
12486 lbl =newiTempLabel(NULL);
12487 /* now for the actual copy */
12488 if (AOP_TYPE(count) == AOP_LIT &&
12489 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12490 l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
12491 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12493 emitcode ("","!tlabeldef",lbl->key+100);
12494 emitcode ("movx", "@dptr,a");
12495 emitcode ("inc", "dptr");
12496 emitcode ("djnz","b,!tlabel",lbl->key+100);
12498 symbol *lbl1 = newiTempLabel(NULL);
12500 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12501 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12502 emitcode ("","!tlabeldef",lbl->key+100);
12503 MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
12504 emitcode ("movx", "@dptr,a");
12505 emitcode ("inc", "dptr");
12506 emitcode ("mov","a,b");
12507 emitcode ("orl","a,_ap");
12508 emitcode ("jz","!tlabel",lbl1->key+100);
12509 emitcode ("mov","a,_ap");
12510 emitcode ("add","a,#!constbyte",0xFF);
12511 emitcode ("mov","_ap,a");
12512 emitcode ("mov","a,b");
12513 emitcode ("addc","a,#!constbyte",0xFF);
12514 emitcode ("mov","b,a");
12515 emitcode ("sjmp","!tlabel",lbl->key+100);
12516 emitcode ("","!tlabeldef",lbl1->key+100);
12518 freeAsmop (count, NULL, ic, FALSE);
12519 unsavermask(rsave);
12522 /*-----------------------------------------------------------------*/
12523 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
12524 /*-----------------------------------------------------------------*/
12525 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
12528 operand *pnum, *result;
12531 assert (nparms==1);
12532 /* save registers that need to be saved */
12533 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12534 ds390_rUmaskForOp (IC_RESULT(ic))));
12537 aopOp (pnum, ic, FALSE, FALSE);
12538 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12539 freeAsmop (pnum, NULL, ic, FALSE);
12540 emitcode ("lcall","NatLib_LoadPrimitive");
12541 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12542 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
12543 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
12544 for (i = (size-1) ; i >= 0 ; i-- ) {
12545 emitcode ("push","a%s",javaRet[i]);
12547 for (i=0; i < size ; i++ ) {
12548 emitcode ("pop","a%s",
12549 aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
12552 for (i = 0 ; i < size ; i++ ) {
12553 aopPut(AOP(result),javaRet[i],i);
12556 freeAsmop (result, NULL, ic, FALSE);
12557 unsavermask(rsave);
12560 /*-----------------------------------------------------------------*/
12561 /* genNatLibLoadPointer - calls TINI api function to load pointer */
12562 /*-----------------------------------------------------------------*/
12563 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
12566 operand *pnum, *result;
12570 assert (nparms==1);
12571 /* save registers that need to be saved */
12572 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12573 ds390_rUmaskForOp (IC_RESULT(ic))));
12576 aopOp (pnum, ic, FALSE, FALSE);
12577 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12578 freeAsmop (pnum, NULL, ic, FALSE);
12579 emitcode ("lcall","NatLib_LoadPointer");
12580 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12581 if (AOP_TYPE(result)!=AOP_STR) {
12582 for (i = 0 ; i < size ; i++ ) {
12583 aopPut(AOP(result),fReturn[i],i);
12586 freeAsmop (result, NULL, ic, FALSE);
12587 unsavermask(rsave);
12590 /*-----------------------------------------------------------------*/
12591 /* genNatLibInstallStateBlock - */
12592 /*-----------------------------------------------------------------*/
12593 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
12594 operand **parms, const char *name)
12597 operand *psb, *handle;
12598 assert (nparms==2);
12600 /* save registers that need to be saved */
12601 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12602 ds390_rUmaskForOp (IC_RESULT(ic))));
12606 /* put pointer to state block into DPTR1 */
12607 aopOp (psb, ic, FALSE, FALSE);
12608 if (AOP_TYPE (psb) == AOP_IMMD) {
12609 emitcode ("mov","dps,#1");
12610 emitcode ("mov", "dptr,%s",
12611 aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12612 emitcode ("mov","dps,#0");
12614 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12615 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12616 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12618 freeAsmop (psb, NULL, ic, FALSE);
12620 /* put libraryID into DPTR */
12621 emitcode ("mov","dptr,#LibraryID");
12623 /* put handle into r3:r2 */
12624 aopOp (handle, ic, FALSE, FALSE);
12625 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12626 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12627 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12628 emitcode ("pop","ar3");
12629 emitcode ("pop","ar2");
12631 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12632 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12634 freeAsmop (psb, NULL, ic, FALSE);
12636 /* make the call */
12637 emitcode ("lcall","NatLib_Install%sStateBlock",name);
12639 /* put return value into place*/
12641 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12643 aopPut(AOP(IC_RESULT(ic)),"a",0);
12644 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12645 unsavermask(rsave);
12648 /*-----------------------------------------------------------------*/
12649 /* genNatLibRemoveStateBlock - */
12650 /*-----------------------------------------------------------------*/
12651 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12657 /* save registers that need to be saved */
12658 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12659 ds390_rUmaskForOp (IC_RESULT(ic))));
12661 /* put libraryID into DPTR */
12662 emitcode ("mov","dptr,#LibraryID");
12663 /* make the call */
12664 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12665 unsavermask(rsave);
12668 /*-----------------------------------------------------------------*/
12669 /* genNatLibGetStateBlock - */
12670 /*-----------------------------------------------------------------*/
12671 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12672 operand **parms,const char *name)
12675 symbol *lbl = newiTempLabel(NULL);
12678 /* save registers that need to be saved */
12679 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12680 ds390_rUmaskForOp (IC_RESULT(ic))));
12682 /* put libraryID into DPTR */
12683 emitcode ("mov","dptr,#LibraryID");
12684 /* make the call */
12685 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12686 emitcode ("jnz","!tlabel",lbl->key+100);
12688 /* put return value into place */
12689 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12690 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12691 emitcode ("push","ar3");
12692 emitcode ("push","ar2");
12693 emitcode ("pop","%s",
12694 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12695 emitcode ("pop","%s",
12696 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12698 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12699 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12701 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12702 emitcode ("","!tlabeldef",lbl->key+100);
12703 unsavermask(rsave);
12706 /*-----------------------------------------------------------------*/
12707 /* genMMMalloc - */
12708 /*-----------------------------------------------------------------*/
12709 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12710 int size, const char *name)
12715 symbol *lbl = newiTempLabel(NULL);
12717 assert (nparms == 1);
12718 /* save registers that need to be saved */
12719 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12720 ds390_rUmaskForOp (IC_RESULT(ic))));
12723 aopOp (bsize,ic,FALSE,FALSE);
12725 /* put the size in R4-R2 */
12726 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12727 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12728 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12730 emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12731 emitcode("pop","ar4");
12733 emitcode("pop","ar3");
12734 emitcode("pop","ar2");
12736 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12737 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12739 emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12742 freeAsmop (bsize, NULL, ic, FALSE);
12744 /* make the call */
12745 emitcode ("lcall","MM_%s",name);
12746 emitcode ("jz","!tlabel",lbl->key+100);
12747 emitcode ("mov","r2,#!constbyte",0xff);
12748 emitcode ("mov","r3,#!constbyte",0xff);
12749 emitcode ("","!tlabeldef",lbl->key+100);
12750 /* we don't care about the pointer : we just save the handle */
12751 rsym = OP_SYMBOL(IC_RESULT(ic));
12752 if (rsym->liveFrom != rsym->liveTo) {
12753 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12754 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12755 emitcode ("push","ar3");
12756 emitcode ("push","ar2");
12757 emitcode ("pop","%s",
12758 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12759 emitcode ("pop","%s",
12760 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12762 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12763 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12765 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12767 unsavermask(rsave);
12770 /*-----------------------------------------------------------------*/
12772 /*-----------------------------------------------------------------*/
12773 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12778 assert (nparms == 1);
12779 /* save registers that need to be saved */
12780 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12781 ds390_rUmaskForOp (IC_RESULT(ic))));
12784 aopOp (handle,ic,FALSE,FALSE);
12786 /* put the size in R4-R2 */
12787 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12788 emitcode("push","%s",
12789 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12790 emitcode("push","%s",
12791 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12792 emitcode("pop","ar3");
12793 emitcode("pop","ar2");
12795 emitcode ("mov","r2,%s",
12796 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12797 emitcode ("mov","r3,%s",
12798 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12800 freeAsmop (handle, NULL, ic, FALSE);
12802 /* make the call */
12803 emitcode ("lcall","MM_Deref");
12806 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12807 if (rsym->liveFrom != rsym->liveTo) {
12808 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12809 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12810 _startLazyDPSEvaluation ();
12812 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12813 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12814 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12816 _endLazyDPSEvaluation ();
12821 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12822 unsavermask(rsave);
12825 /*-----------------------------------------------------------------*/
12826 /* genMMUnrestrictedPersist - */
12827 /*-----------------------------------------------------------------*/
12828 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12833 assert (nparms == 1);
12834 /* save registers that need to be saved */
12835 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12836 ds390_rUmaskForOp (IC_RESULT(ic))));
12839 aopOp (handle,ic,FALSE,FALSE);
12841 /* put the size in R3-R2 */
12842 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12843 emitcode("push","%s",
12844 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12845 emitcode("push","%s",
12846 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12847 emitcode("pop","ar3");
12848 emitcode("pop","ar2");
12850 emitcode ("mov","r2,%s",
12851 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12852 emitcode ("mov","r3,%s",
12853 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12855 freeAsmop (handle, NULL, ic, FALSE);
12857 /* make the call */
12858 emitcode ("lcall","MM_UnrestrictedPersist");
12861 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12862 if (rsym->liveFrom != rsym->liveTo) {
12863 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12864 aopPut(AOP(IC_RESULT(ic)),"a",0);
12865 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12868 unsavermask(rsave);
12871 /*-----------------------------------------------------------------*/
12872 /* genSystemExecJavaProcess - */
12873 /*-----------------------------------------------------------------*/
12874 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12877 operand *handle, *pp;
12879 assert (nparms==2);
12880 /* save registers that need to be saved */
12881 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12882 ds390_rUmaskForOp (IC_RESULT(ic))));
12887 /* put the handle in R3-R2 */
12888 aopOp (handle,ic,FALSE,FALSE);
12889 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12890 emitcode("push","%s",
12891 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12892 emitcode("push","%s",
12893 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12894 emitcode("pop","ar3");
12895 emitcode("pop","ar2");
12897 emitcode ("mov","r2,%s",
12898 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12899 emitcode ("mov","r3,%s",
12900 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12902 freeAsmop (handle, NULL, ic, FALSE);
12904 /* put pointer in DPTR */
12905 aopOp (pp,ic,FALSE,FALSE);
12906 if (AOP_TYPE(pp) == AOP_IMMD) {
12907 emitcode ("mov", "dptr,%s",
12908 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12909 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12910 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12911 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12912 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12914 freeAsmop (handle, NULL, ic, FALSE);
12916 /* make the call */
12917 emitcode ("lcall","System_ExecJavaProcess");
12919 /* put result in place */
12921 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12922 if (rsym->liveFrom != rsym->liveTo) {
12923 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12924 aopPut(AOP(IC_RESULT(ic)),"a",0);
12925 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12929 unsavermask(rsave);
12932 /*-----------------------------------------------------------------*/
12933 /* genSystemRTCRegisters - */
12934 /*-----------------------------------------------------------------*/
12935 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12941 assert (nparms==1);
12942 /* save registers that need to be saved */
12943 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12944 ds390_rUmaskForOp (IC_RESULT(ic))));
12947 /* put pointer in DPTR */
12948 aopOp (pp,ic,FALSE,FALSE);
12949 if (AOP_TYPE (pp) == AOP_IMMD) {
12950 emitcode ("mov","dps,#1");
12951 emitcode ("mov", "dptr,%s",
12952 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12953 emitcode ("mov","dps,#0");
12955 emitcode ("mov","dpl1,%s",
12956 aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12957 emitcode ("mov","dph1,%s",
12958 aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12959 emitcode ("mov","dpx1,%s",
12960 aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12962 freeAsmop (pp, NULL, ic, FALSE);
12964 /* make the call */
12965 emitcode ("lcall","System_%sRTCRegisters",name);
12967 unsavermask(rsave);
12970 /*-----------------------------------------------------------------*/
12971 /* genSystemThreadSleep - */
12972 /*-----------------------------------------------------------------*/
12973 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12978 assert (nparms==1);
12979 /* save registers that need to be saved */
12980 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12981 ds390_rUmaskForOp (IC_RESULT(ic))));
12984 aopOp(to,ic,FALSE,FALSE);
12985 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12986 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12987 emitcode ("push","%s",
12988 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12989 emitcode ("push","%s",
12990 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12991 emitcode ("push","%s",
12992 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12993 emitcode ("push","%s",
12994 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12995 emitcode ("pop","ar3");
12996 emitcode ("pop","ar2");
12997 emitcode ("pop","ar1");
12998 emitcode ("pop","ar0");
13000 emitcode ("mov","r0,%s",
13001 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
13002 emitcode ("mov","r1,%s",
13003 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
13004 emitcode ("mov","r2,%s",
13005 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
13006 emitcode ("mov","r3,%s",
13007 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
13009 freeAsmop (to, NULL, ic, FALSE);
13011 /* suspend in acc */
13013 aopOp(s,ic,FALSE,FALSE);
13014 emitcode ("mov","a,%s",
13015 aopGet(AOP(s),0,FALSE,TRUE,NULL));
13016 freeAsmop (s, NULL, ic, FALSE);
13018 /* make the call */
13019 emitcode ("lcall","System_%s",name);
13021 unsavermask(rsave);
13024 /*-----------------------------------------------------------------*/
13025 /* genSystemThreadResume - */
13026 /*-----------------------------------------------------------------*/
13027 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
13032 assert (nparms==2);
13033 /* save registers that need to be saved */
13034 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13035 ds390_rUmaskForOp (IC_RESULT(ic))));
13041 aopOp(pid,ic,FALSE,FALSE);
13042 emitcode ("mov","r0,%s",
13043 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
13044 freeAsmop (pid, NULL, ic, FALSE);
13047 aopOp(tid,ic,FALSE,FALSE);
13048 emitcode ("mov","a,%s",
13049 aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
13050 freeAsmop (tid, NULL, ic, FALSE);
13052 emitcode ("lcall","System_ThreadResume");
13054 /* put result into place */
13056 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13057 if (rsym->liveFrom != rsym->liveTo) {
13058 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13059 aopPut(AOP(IC_RESULT(ic)),"a",0);
13060 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13063 unsavermask(rsave);
13066 /*-----------------------------------------------------------------*/
13067 /* genSystemProcessResume - */
13068 /*-----------------------------------------------------------------*/
13069 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
13074 assert (nparms==1);
13075 /* save registers that need to be saved */
13076 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13077 ds390_rUmaskForOp (IC_RESULT(ic))));
13082 aopOp(pid,ic,FALSE,FALSE);
13083 emitcode ("mov","a,%s",
13084 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
13085 freeAsmop (pid, NULL, ic, FALSE);
13087 emitcode ("lcall","System_ProcessResume");
13089 unsavermask(rsave);
13092 /*-----------------------------------------------------------------*/
13094 /*-----------------------------------------------------------------*/
13095 static void genSystem (iCode *ic,int nparms,char *name)
13097 assert(nparms == 0);
13099 emitcode ("lcall","System_%s",name);
13102 /*-----------------------------------------------------------------*/
13103 /* genSystemPoll - */
13104 /*-----------------------------------------------------------------*/
13105 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
13110 assert (nparms==1);
13111 /* save registers that need to be saved */
13112 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13113 ds390_rUmaskForOp (IC_RESULT(ic))));
13116 aopOp (fp,ic,FALSE,FALSE);
13117 if (AOP_TYPE (fp) == AOP_IMMD) {
13118 emitcode ("mov", "dptr,%s",
13119 aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
13120 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
13121 emitcode ("mov","dpl,%s",
13122 aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
13123 emitcode ("mov","dph,%s",
13124 aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
13125 emitcode ("mov","dpx,%s",
13126 aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
13128 freeAsmop (fp, NULL, ic, FALSE);
13130 emitcode ("lcall","System_%sPoll",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);
13141 unsavermask(rsave);
13144 /*-----------------------------------------------------------------*/
13145 /* genSystemGetCurrentID - */
13146 /*-----------------------------------------------------------------*/
13147 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
13149 assert (nparms==0);
13151 emitcode ("lcall","System_GetCurrent%sId",name);
13152 /* put result into place */
13154 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13155 if (rsym->liveFrom != rsym->liveTo) {
13156 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13157 aopPut(AOP(IC_RESULT(ic)),"a",0);
13158 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13163 /*-----------------------------------------------------------------*/
13164 /* genDummyRead - generate code for dummy read of volatiles */
13165 /*-----------------------------------------------------------------*/
13167 genDummyRead (iCode * ic)
13172 D(emitcode("; genDummyRead",""));
13174 op = IC_RIGHT (ic);
13175 if (op && IS_SYMOP (op))
13177 aopOp (op, ic, FALSE, FALSE);
13179 /* if the result is a bit */
13180 if (AOP_TYPE (op) == AOP_CRY)
13181 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13184 /* bit variables done */
13186 size = AOP_SIZE (op);
13190 MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
13195 freeAsmop (op, NULL, ic, TRUE);
13199 if (op && IS_SYMOP (op))
13201 aopOp (op, ic, FALSE, FALSE);
13203 /* if the result is a bit */
13204 if (AOP_TYPE (op) == AOP_CRY)
13205 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13208 /* bit variables done */
13210 size = AOP_SIZE (op);
13214 MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
13219 freeAsmop (op, NULL, ic, TRUE);
13224 /*-----------------------------------------------------------------*/
13225 /* genCritical - generate code for start of a critical sequence */
13226 /*-----------------------------------------------------------------*/
13228 genCritical (iCode *ic)
13230 symbol *tlbl = newiTempLabel (NULL);
13232 D(emitcode("; genCritical",""));
13234 if (IC_RESULT (ic))
13235 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
13237 emitcode ("setb", "c");
13238 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
13239 emitcode ("clr", "c");
13240 emitcode ("", "%05d$:", (tlbl->key + 100));
13242 if (IC_RESULT (ic))
13243 outBitC (IC_RESULT (ic)); /* save old ea in an operand */
13245 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
13247 if (IC_RESULT (ic))
13248 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13251 /*-----------------------------------------------------------------*/
13252 /* genEndCritical - generate code for end of a critical sequence */
13253 /*-----------------------------------------------------------------*/
13255 genEndCritical (iCode *ic)
13257 D(emitcode("; genEndCritical",""));
13261 aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
13262 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
13264 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
13265 emitcode ("mov", "ea,c");
13269 MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE, FALSE));
13270 emitcode ("rrc", "a");
13271 emitcode ("mov", "ea,c");
13273 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
13277 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
13278 emitcode ("mov", "ea,c");
13284 /*-----------------------------------------------------------------*/
13285 /* genBuiltIn - calls the appropriate function to generating code */
13286 /* for a built in function */
13287 /*-----------------------------------------------------------------*/
13288 static void genBuiltIn (iCode *ic)
13290 operand *bi_parms[MAX_BUILTIN_ARGS];
13295 /* get all the arguments for a built in function */
13296 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
13298 /* which function is it */
13299 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
13300 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
13301 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
13302 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
13303 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
13304 } else if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
13305 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
13306 } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
13307 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
13308 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
13309 genMemsetX(bi_iCode,nbi_parms,bi_parms);
13310 } else if (strcmp(bif->name,"__builtin_inp")==0) {
13311 genInp(bi_iCode,nbi_parms,bi_parms);
13312 } else if (strcmp(bif->name,"__builtin_outp")==0) {
13313 genOutp(bi_iCode,nbi_parms,bi_parms);
13314 } else if (strcmp(bif->name,"__builtin_swapw")==0) {
13315 genSwapW(bi_iCode,nbi_parms,bi_parms);
13316 /* JavaNative builtIns */
13317 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
13318 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
13319 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
13320 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
13321 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
13322 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
13323 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
13324 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
13325 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
13326 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
13327 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
13328 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
13329 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
13330 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
13331 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
13332 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
13333 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
13334 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
13335 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
13336 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
13337 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
13338 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
13339 } else if (strcmp(bif->name,"MM_Malloc")==0) {
13340 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
13341 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
13342 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
13343 } else if (strcmp(bif->name,"MM_Free")==0) {
13344 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
13345 } else if (strcmp(bif->name,"MM_Deref")==0) {
13346 genMMDeref(bi_iCode,nbi_parms,bi_parms);
13347 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
13348 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
13349 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
13350 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
13351 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
13352 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
13353 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
13354 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
13355 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
13356 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
13357 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
13358 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
13359 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
13360 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
13361 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
13362 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
13363 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
13364 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13365 } else if (strcmp(bif->name,"System_SaveThread")==0) {
13366 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13367 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
13368 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13369 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
13370 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
13371 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
13372 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
13373 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
13374 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
13375 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
13376 genSystem(bi_iCode,nbi_parms,"ProcessYield");
13377 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
13378 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
13379 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
13380 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
13381 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
13382 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
13383 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
13384 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
13385 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
13386 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
13388 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
13394 /*-----------------------------------------------------------------*/
13395 /* gen390Code - generate code for Dallas 390 based controllers */
13396 /*-----------------------------------------------------------------*/
13398 gen390Code (iCode * lic)
13403 lineHead = lineCurr = NULL;
13404 dptrn[1][0] = "dpl1";
13405 dptrn[1][1] = "dph1";
13406 dptrn[1][2] = "dpx1";
13408 if (options.model == MODEL_FLAT24) {
13409 fReturnSizeDS390 = 5;
13410 fReturn = fReturn24;
13412 fReturnSizeDS390 = 4;
13413 fReturn = fReturn16;
13414 options.stack10bit=0;
13417 /* print the allocation information */
13418 if (allocInfo && currFunc)
13419 printAllocInfo (currFunc, codeOutFile);
13421 /* if debug information required */
13422 if (options.debug && currFunc)
13424 debugFile->writeFunction (currFunc, lic);
13426 /* stack pointer name */
13427 if (options.useXstack)
13433 for (ic = lic; ic; ic = ic->next)
13436 _G.current_iCode = ic;
13438 if (ic->lineno && cln != ic->lineno)
13442 debugFile->writeCLine (ic);
13444 if (!options.noCcodeInAsm) {
13445 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
13446 printCLine(ic->filename, ic->lineno));
13450 if (options.iCodeInAsm) {
13451 emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
13453 /* if the result is marked as
13454 spilt and rematerializable or code for
13455 this has already been generated then
13457 if (resultRemat (ic) || ic->generated)
13460 /* depending on the operation */
13480 /* IPOP happens only when trying to restore a
13481 spilt live range, if there is an ifx statement
13482 following this pop then the if statement might
13483 be using some of the registers being popped which
13484 would destory the contents of the register so
13485 we need to check for this condition and handle it */
13487 ic->next->op == IFX &&
13488 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
13489 genIfx (ic->next, ic);
13507 genEndFunction (ic);
13527 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
13544 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
13548 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
13555 /* note these two are xlated by algebraic equivalence
13556 during parsing SDCC.y */
13557 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
13558 "got '>=' or '<=' shouldn't have come here");
13562 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
13574 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
13578 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
13582 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
13606 genRightShift (ic);
13609 case GET_VALUE_AT_ADDRESS:
13610 genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
13614 if (POINTER_SET (ic))
13615 genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
13641 if (ic->builtinSEND) genBuiltIn(ic);
13642 else addSet (&_G.sendSet, ic);
13645 case DUMMY_READ_VOLATILE:
13654 genEndCritical (ic);
13661 #if 0 // obsolete, and buggy for != xdata
13673 /* now we are ready to call the
13674 peep hole optimizer */
13675 if (!options.nopeep)
13676 peepHole (&lineHead);
13678 /* now do the actual printing */
13679 printLine (lineHead, codeOutFile);