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 unsigned fReturnSizeDS390 = 5; /* shared with ralloc.c */
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 (strcmp (sym1->rname, sym2->rname) == 0)
873 /* if left is a tmp & right is not */
874 if (IS_ITEMP (op1) &&
877 (sym1->usl.spillLoc == sym2))
880 if (IS_ITEMP (op2) &&
884 (sym2->usl.spillLoc == sym1))
887 /* are they spilt to the same location */
888 if (IS_ITEMP (op2) &&
892 (sym1->usl.spillLoc == sym2->usl.spillLoc))
898 /*-----------------------------------------------------------------*/
899 /* sameRegs - two asmops have the same registers */
900 /*-----------------------------------------------------------------*/
902 sameRegs (asmop * aop1, asmop * aop2)
908 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
915 if (aop1->type != AOP_REG ||
916 aop2->type != AOP_REG)
919 if (aop1->size != aop2->size)
922 for (i = 0; i < aop1->size; i++)
923 if (aop1->aopu.aop_reg[i] !=
924 aop2->aopu.aop_reg[i])
930 /*-----------------------------------------------------------------*/
931 /* aopOp - allocates an asmop for an operand : */
932 /*-----------------------------------------------------------------*/
934 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
943 /* if this a literal */
944 if (IS_OP_LITERAL (op))
946 op->aop = aop = newAsmop (AOP_LIT);
947 aop->aopu.aop_lit = op->operand.valOperand;
948 aop->size = getSize (operandType (op));
952 /* if already has a asmop then continue */
955 if ((op->aop->type == AOP_DPTR && useDP2)
956 || (op->aop->type == AOP_DPTR2 && !useDP2))
962 /* if the underlying symbol has a aop */
963 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
965 op->aop = OP_SYMBOL (op)->aop;
966 if ((op->aop->type == AOP_DPTR && useDP2)
967 || (op->aop->type == AOP_DPTR2 && !useDP2))
973 /* if this is a true symbol */
974 if (IS_TRUE_SYMOP (op))
976 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
980 /* this is a temporary : this has
986 e) can be a return use only */
988 sym = OP_SYMBOL (op);
991 /* if the type is a conditional */
992 if (sym->regType == REG_CND)
994 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
999 /* if it is spilt then two situations
1001 b) has a spill location */
1002 if (sym->isspilt || sym->nRegs == 0)
1005 /* rematerialize it NOW */
1008 sym->aop = op->aop = aop =
1010 aop->size = getSize (sym->type);
1017 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
1018 aop->size = getSize (sym->type);
1019 for (i = 0; i < 2; i++)
1020 aop->aopu.aop_str[i] = accUse[i];
1030 /* a AOP_STR uses DPTR, but DPTR is already in use;
1033 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"AOP_STR with DPTR in use!");
1036 aop = op->aop = sym->aop = newAsmop (AOP_STR);
1037 aop->size = getSize (sym->type);
1038 for (i = 0; i < (int) fReturnSizeDS390; i++)
1039 aop->aopu.aop_str[i] = fReturn[i];
1043 if (sym->dptr) { /* has been allocated to a DPTRn */
1044 aop = op->aop = sym->aop = newAsmop (AOP_DPTRn);
1045 aop->size = getSize (sym->type);
1046 aop->aopu.dptr = sym->dptr;
1050 if (sym->usl.spillLoc)
1052 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1054 /* force a new aop if sizes differ */
1055 sym->usl.spillLoc->aop = NULL;
1057 sym->aop = op->aop = aop =
1058 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
1059 aop->size = getSize (sym->type);
1063 /* else must be a dummy iTemp */
1064 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1065 aop->size = getSize (sym->type);
1069 /* must be in a register */
1070 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1071 aop->size = sym->nRegs;
1072 for (i = 0; i < sym->nRegs; i++)
1073 aop->aopu.aop_reg[i] = sym->regs[i];
1076 /*-----------------------------------------------------------------*/
1077 /* freeAsmop - free up the asmop given to an operand */
1078 /*----------------------------------------------------------------*/
1080 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1097 /* depending on the asmop type only three cases need work AOP_RO
1098 , AOP_R1 && AOP_STK */
1106 emitcode ("pop", "ar0");
1110 bitVectUnSetBit (ic->rUsed, R0_IDX);
1118 emitcode ("pop", "ar1");
1122 bitVectUnSetBit (ic->rUsed, R1_IDX);
1128 int stk = aop->aopu.aop_stk + aop->size;
1129 bitVectUnSetBit (ic->rUsed, R0_IDX);
1130 bitVectUnSetBit (ic->rUsed, R1_IDX);
1132 getFreePtr (ic, &aop, FALSE);
1134 if (options.stack10bit)
1136 /* I'm not sure what to do here yet... */
1139 "*** Warning: probably generating bad code for "
1140 "10 bit stack mode.\n");
1145 emitcode ("mov", "a,_bp");
1146 emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
1147 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1151 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1156 emitcode ("pop", "acc");
1157 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1160 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1163 freeAsmop (op, NULL, ic, TRUE);
1166 emitcode ("pop", "ar0");
1172 emitcode ("pop", "ar1");
1177 if (_G.dptr1InUse) {
1178 emitcode ("pop","dpx1");
1179 emitcode ("pop","dph1");
1180 emitcode ("pop","dpl1");
1185 emitcode ("pop","dpx");
1186 emitcode ("pop","dph");
1187 emitcode ("pop","dpl");
1192 /* all other cases just dealloc */
1198 OP_SYMBOL (op)->aop = NULL;
1199 /* if the symbol has a spill */
1201 SPIL_LOC (op)->aop = NULL;
1206 #define DEFAULT_ACC_WARNING 0
1207 static int saveAccWarn = DEFAULT_ACC_WARNING;
1209 /*-------------------------------------------------------------------*/
1210 /* aopGet - for fetching value of the aop */
1212 /* Set saveAcc to NULL if you are sure it is OK to clobber the value */
1213 /* in the accumulator. Set it to the name of a free register */
1214 /* if acc must be preserved; the register will be used to preserve */
1215 /* acc temporarily and to return the result byte. */
1216 /*-------------------------------------------------------------------*/
1225 /* offset is greater than
1227 if (offset > (aop->size - 1) &&
1228 aop->type != AOP_LIT)
1231 /* depending on type */
1239 /* if we need to increment it */
1240 while (offset > aop->coff)
1242 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1246 while (offset < aop->coff)
1248 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1255 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1256 return (dname ? "acc" : "a");
1258 SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1259 return Safe_strdup(buffer);
1262 assert(offset <= 3);
1263 return dptrn[aop->aopu.dptr][offset];
1268 if (aop->type == AOP_DPTR2)
1276 // if (aop->type != AOP_DPTR2)
1278 // if (saveAccWarn) { fprintf(stderr, "saveAcc for DPTR...\n"); }
1279 // emitcode(";", "spanky: saveAcc for DPTR");
1282 emitcode ("xch", "a, %s", saveAcc);
1287 while (offset > aop->coff)
1289 emitcode ("inc", "dptr");
1293 while (offset < aop->coff)
1295 emitcode ("lcall", "__decdptr");
1302 emitcode ("clr", "a");
1303 emitcode ("movc", "a,@a+dptr");
1307 emitcode ("movx", "a,@dptr");
1310 if (aop->type == AOP_DPTR2)
1318 emitcode ("xch", "a, %s", saveAcc);
1319 // if (strcmp(saveAcc, "_ap"))
1321 // emitcode(";", "spiffy: non _ap return from aopGet.");
1326 return (dname ? "acc" : "a");
1329 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1331 SNPRINTF(buffer, sizeof(buffer),
1332 "%s",aop->aopu.aop_immd.aop_immd2);
1336 SNPRINTF(buffer, sizeof(buffer),
1337 "#%s", aop->aopu.aop_immd.aop_immd1);
1343 tsprintf(buffer, sizeof(buffer),
1344 "#!his",aop->aopu.aop_immd.aop_immd1);
1347 tsprintf(buffer, sizeof(buffer),
1348 "#!hihis",aop->aopu.aop_immd.aop_immd1);
1351 tsprintf(buffer, sizeof(buffer),
1352 "#!hihihis",aop->aopu.aop_immd.aop_immd1);
1354 default: /* should not need this (just in case) */
1355 SNPRINTF (buffer, sizeof(buffer),
1357 aop->aopu.aop_immd.aop_immd1,
1363 SNPRINTF (buffer, sizeof(buffer),
1364 "#%s", aop->aopu.aop_immd.aop_immd1);
1366 return Safe_strdup(buffer);
1371 SNPRINTF (buffer, sizeof(buffer),
1378 SNPRINTF(buffer, sizeof(buffer),
1379 "%s", aop->aopu.aop_dir);
1382 return Safe_strdup(buffer);
1386 return aop->aopu.aop_reg[offset]->dname;
1388 return aop->aopu.aop_reg[offset]->name;
1391 emitcode ("clr", "a");
1392 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1393 emitcode ("rlc", "a");
1394 return (dname ? "acc" : "a");
1397 if (!offset && dname)
1399 return aop->aopu.aop_str[offset];
1402 return aopLiteral (aop->aopu.aop_lit, offset);
1406 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1410 return aop->aopu.aop_str[offset];
1414 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1415 "aopget got unsupported aop->type");
1418 return NULL; // not reached, but makes compiler happy.
1420 /*-----------------------------------------------------------------*/
1421 /* aopPut - puts a string for a aop */
1422 /*-----------------------------------------------------------------*/
1424 aopPut (asmop * aop, char *s, int offset)
1426 if (aop->size && offset > (aop->size - 1))
1428 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1429 "aopPut got offset > aop->size");
1433 /* will assign value to value */
1434 /* depending on where it is ofcourse */
1438 MOVA (s); /* read s in case it was volatile */
1444 SNPRINTF (buffer, sizeof(buffer),
1446 aop->aopu.aop_dir, offset);
1450 SNPRINTF (buffer, sizeof(buffer),
1451 "%s", aop->aopu.aop_dir);
1455 if (strcmp (buffer, s))
1457 emitcode ("mov", "%s,%s", buffer, s);
1462 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1463 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1466 strcmp (s, "r0") == 0 ||
1467 strcmp (s, "r1") == 0 ||
1468 strcmp (s, "r2") == 0 ||
1469 strcmp (s, "r3") == 0 ||
1470 strcmp (s, "r4") == 0 ||
1471 strcmp (s, "r5") == 0 ||
1472 strcmp (s, "r6") == 0 ||
1473 strcmp (s, "r7") == 0)
1475 emitcode ("mov", "%s,%s",
1476 aop->aopu.aop_reg[offset]->dname, s);
1480 emitcode ("mov", "%s,%s",
1481 aop->aopu.aop_reg[offset]->name, s);
1487 emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1493 if (aop->type == AOP_DPTR2)
1501 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1502 "aopPut writting to code space");
1506 while (offset > aop->coff)
1509 emitcode ("inc", "dptr");
1512 while (offset < aop->coff)
1515 emitcode ("lcall", "__decdptr");
1520 /* if not in accumulater */
1523 emitcode ("movx", "@dptr,a");
1525 if (aop->type == AOP_DPTR2)
1533 while (offset > aop->coff)
1536 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1538 while (offset < aop->coff)
1541 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1548 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1554 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1556 else if (strcmp (s, "r0") == 0 ||
1557 strcmp (s, "r1") == 0 ||
1558 strcmp (s, "r2") == 0 ||
1559 strcmp (s, "r3") == 0 ||
1560 strcmp (s, "r4") == 0 ||
1561 strcmp (s, "r5") == 0 ||
1562 strcmp (s, "r6") == 0 ||
1563 strcmp (s, "r7") == 0)
1566 SNPRINTF(buff, sizeof(buff),
1568 emitcode ("mov", "@%s,%s",
1569 aop->aopu.aop_ptr->name, buff);
1573 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1578 if (strcmp (s, "a") == 0)
1579 emitcode ("push", "acc");
1583 emitcode ("push", "acc");
1585 emitcode ("push", s);
1591 /* if bit variable */
1592 if (!aop->aopu.aop_dir)
1594 emitcode ("clr", "a");
1595 emitcode ("rlc", "a");
1600 emitcode ("clr", "%s", aop->aopu.aop_dir);
1602 emitcode ("setb", "%s", aop->aopu.aop_dir);
1603 else if (!strcmp (s, "c"))
1604 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1607 if (strcmp (s, "a"))
1612 /* set C, if a >= 1 */
1613 emitcode ("add", "a,#!constbyte",0xff);
1614 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1622 if (strcmp (aop->aopu.aop_str[offset], s))
1623 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1628 if (!offset && (strcmp (s, "acc") == 0))
1631 if (strcmp (aop->aopu.aop_str[offset], s))
1632 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1636 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1637 "aopPut got unsupported aop->type");
1644 /*--------------------------------------------------------------------*/
1645 /* reAdjustPreg - points a register back to where it should (coff==0) */
1646 /*--------------------------------------------------------------------*/
1648 reAdjustPreg (asmop * aop)
1650 if ((aop->coff==0) || (aop->size <= 1)) {
1659 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1663 if (aop->type == AOP_DPTR2)
1670 emitcode ("lcall", "__decdptr");
1673 if (aop->type == AOP_DPTR2)
1683 #define AOP(op) op->aop
1684 #define AOP_TYPE(op) AOP(op)->type
1685 #define AOP_SIZE(op) AOP(op)->size
1686 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1687 AOP_TYPE(x) == AOP_R0))
1689 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1690 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1693 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1694 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1695 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1696 #define AOP_INDPTRn(x) (AOP_TYPE(x) == AOP_DPTRn)
1697 #define AOP_USESDPTR(x) ((AOP_TYPE(x) == AOP_DPTR) || (AOP_TYPE(x) == AOP_STR))
1698 #define AOP_USESDPTR2(x) ((AOP_TYPE(x) == AOP_DPTR2) || (AOP_TYPE(x) == AOP_DPTRn))
1700 // The following two macros can be used even if the aop has not yet been aopOp'd.
1701 #define AOP_IS_STR(x) (IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
1702 #define AOP_IS_DPTRn(x) (IS_SYMOP(x) && OP_SYMBOL(x)->dptr)
1704 /* Workaround for DS80C390 bug: div ab may return bogus results
1705 * if A is accessed in instruction immediately before the div.
1707 * Will be fixed in B4 rev of processor, Dallas claims.
1710 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1711 if (!AOP_NEEDSACC(RIGHT)) \
1713 /* We can load A first, then B, since \
1714 * B (the RIGHT operand) won't clobber A, \
1715 * thus avoiding touching A right before the div. \
1717 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1718 L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL); \
1720 L = aopGet(AOP(RIGHT),0,FALSE,FALSE,"b"); \
1725 /* Just stuff in a nop after loading A. */ \
1726 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,NULL));\
1727 L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL); \
1729 emitcode("nop", "; workaround for DS80C390 div bug."); \
1733 /*-----------------------------------------------------------------*/
1734 /* opIsGptr: returns non-zero if the passed operand is */
1735 /* a generic pointer type. */
1736 /*-----------------------------------------------------------------*/
1738 opIsGptr (operand * op)
1740 sym_link *type = operandType (op);
1742 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1749 /*-----------------------------------------------------------------*/
1750 /* getDataSize - get the operand data size */
1751 /*-----------------------------------------------------------------*/
1753 getDataSize (operand * op)
1756 size = AOP_SIZE (op);
1757 if (size == GPTRSIZE)
1759 sym_link *type = operandType (op);
1760 if (IS_GENPTR (type))
1762 /* generic pointer; arithmetic operations
1763 * should ignore the high byte (pointer type).
1771 /*-----------------------------------------------------------------*/
1772 /* outAcc - output Acc */
1773 /*-----------------------------------------------------------------*/
1775 outAcc (operand * result)
1778 size = getDataSize (result);
1781 aopPut (AOP (result), "a", 0);
1784 /* unsigned or positive */
1787 aopPut (AOP (result), zero, offset++);
1792 /*-----------------------------------------------------------------*/
1793 /* outBitC - output a bit C */
1794 /*-----------------------------------------------------------------*/
1796 outBitC (operand * result)
1798 /* if the result is bit */
1799 if (AOP_TYPE (result) == AOP_CRY)
1801 aopPut (AOP (result), "c", 0);
1805 emitcode ("clr", "a");
1806 emitcode ("rlc", "a");
1811 /*-----------------------------------------------------------------*/
1812 /* toBoolean - emit code for orl a,operator(sizeop) */
1813 /*-----------------------------------------------------------------*/
1815 toBoolean (operand * oper)
1817 int size = AOP_SIZE (oper) - 1;
1821 /* The generic part of a generic pointer should
1822 * not participate in it's truth value.
1824 * i.e. 0x10000000 is zero.
1826 if (opIsGptr (oper))
1828 D (emitcode (";", "toBoolean: generic ptr special case."););
1832 _startLazyDPSEvaluation ();
1833 if (AOP_NEEDSACC (oper) && size)
1838 emitcode ("push", "b");
1840 MOVB (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1844 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1851 emitcode ("orl", "b,%s",
1852 aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1856 emitcode ("orl", "a,%s",
1857 aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1860 _endLazyDPSEvaluation ();
1864 emitcode ("mov", "a,b");
1867 emitcode ("pop", "b");
1874 /*-----------------------------------------------------------------*/
1875 /* genNot - generate code for ! operation */
1876 /*-----------------------------------------------------------------*/
1882 D (emitcode (";", "genNot "););
1884 /* assign asmOps to operand & result */
1885 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1886 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1888 /* if in bit space then a special case */
1889 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1891 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1892 emitcode ("cpl", "c");
1893 outBitC (IC_RESULT (ic));
1897 toBoolean (IC_LEFT (ic));
1899 tlbl = newiTempLabel (NULL);
1900 emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1901 emitcode ("", "!tlabeldef", tlbl->key + 100);
1902 outBitC (IC_RESULT (ic));
1905 /* release the aops */
1906 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1907 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1911 /*-----------------------------------------------------------------*/
1912 /* genCpl - generate code for complement */
1913 /*-----------------------------------------------------------------*/
1921 D (emitcode (";", "genCpl "););
1924 /* assign asmOps to operand & result */
1925 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1926 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1928 /* special case if in bit space */
1929 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1930 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1931 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1932 emitcode ("cpl", "c");
1933 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1936 tlbl=newiTempLabel(NULL);
1937 emitcode ("cjne", "%s,#0x01,%05d$",
1938 aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE,NULL), tlbl->key+100);
1939 emitcode ("", "%05d$:", tlbl->key+100);
1940 outBitC (IC_RESULT(ic));
1944 size = AOP_SIZE (IC_RESULT (ic));
1945 _startLazyDPSEvaluation ();
1948 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
1949 emitcode ("cpl", "a");
1950 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1952 _endLazyDPSEvaluation ();
1956 /* release the aops */
1957 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1958 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1961 /*-----------------------------------------------------------------*/
1962 /* genUminusFloat - unary minus for floating points */
1963 /*-----------------------------------------------------------------*/
1965 genUminusFloat (operand * op, operand * result)
1967 int size, offset = 0;
1969 D(emitcode (";", "genUminusFloat"););
1971 /* for this we just copy and then flip the bit */
1973 _startLazyDPSEvaluation ();
1974 size = AOP_SIZE (op) - 1;
1978 aopPut (AOP (result),
1979 aopGet (AOP (op), offset, FALSE, FALSE, NULL),
1984 MOVA(aopGet (AOP (op), offset, FALSE, FALSE, NULL));
1986 emitcode ("cpl", "acc.7");
1987 aopPut (AOP (result), "a", offset);
1988 _endLazyDPSEvaluation ();
1991 /*-----------------------------------------------------------------*/
1992 /* genUminus - unary minus code generation */
1993 /*-----------------------------------------------------------------*/
1995 genUminus (iCode * ic)
2000 D (emitcode (";", "genUminus "););
2003 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2004 aopOp (IC_RESULT (ic), ic, TRUE, (AOP_TYPE(IC_LEFT (ic)) == AOP_DPTR));
2006 /* if both in bit space then special
2008 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2009 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2012 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2013 emitcode ("cpl", "c");
2014 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2018 optype = operandType (IC_LEFT (ic));
2020 /* if float then do float stuff */
2021 if (IS_FLOAT (optype))
2023 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2027 /* otherwise subtract from zero */
2028 size = AOP_SIZE (IC_LEFT (ic));
2030 _startLazyDPSEvaluation ();
2033 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL);
2034 if (!strcmp (l, "a"))
2038 emitcode ("cpl", "a");
2039 emitcode ("addc", "a,#0");
2045 emitcode ("clr", "a");
2046 emitcode ("subb", "a,%s", l);
2048 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2050 _endLazyDPSEvaluation ();
2052 /* if any remaining bytes in the result */
2053 /* we just need to propagate the sign */
2054 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic)))) != 0)
2056 emitcode ("rlc", "a");
2057 emitcode ("subb", "a,acc");
2059 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2063 /* release the aops */
2064 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2065 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2068 /*-----------------------------------------------------------------*/
2069 /* savermask - saves registers in the mask */
2070 /*-----------------------------------------------------------------*/
2071 static void savermask(bitVect *rs_mask)
2074 if (options.useXstack) {
2075 if (bitVectBitValue (rs_mask, R0_IDX))
2076 emitcode ("mov", "b,r0");
2077 emitcode ("mov", "r0,%s", spname);
2078 for (i = 0; i < ds390_nRegs; i++) {
2079 if (bitVectBitValue (rs_mask, i)) {
2081 emitcode ("mov", "a,b");
2083 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
2084 emitcode ("movx", "@r0,a");
2085 emitcode ("inc", "r0");
2088 emitcode ("mov", "%s,r0", spname);
2089 if (bitVectBitValue (rs_mask, R0_IDX))
2090 emitcode ("mov", "r0,b");
2092 for (i = 0; i < ds390_nRegs; i++) {
2093 if (bitVectBitValue (rs_mask, i))
2094 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2099 /*-----------------------------------------------------------------*/
2100 /* saveRegisters - will look for a call and save the registers */
2101 /*-----------------------------------------------------------------*/
2103 saveRegisters (iCode * lic)
2109 for (ic = lic; ic; ic = ic->next)
2110 if (ic->op == CALL || ic->op == PCALL)
2115 fprintf (stderr, "found parameter push with no function call\n");
2119 /* if the registers have been saved already then
2122 || (IS_SYMOP(IC_LEFT(ic)) && IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))) && !TARGET_IS_DS400) )
2125 /* special case if DPTR alive across a function call then must save it
2126 even though callee saves */
2127 if (IS_SYMOP(IC_LEFT(ic)) &&
2128 IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2130 rsave = newBitVect(ic->rMask->size);
2131 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2132 if (bitVectBitValue(ic->rMask,i))
2133 rsave = bitVectSetBit(rsave,i);
2135 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2137 /* safe the registers in use at this time but skip the
2138 ones for the result */
2139 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2140 ds390_rUmaskForOp (IC_RESULT(ic)));
2146 /*-----------------------------------------------------------------*/
2147 /* usavermask - restore registers with mask */
2148 /*-----------------------------------------------------------------*/
2149 static void unsavermask(bitVect *rs_mask)
2152 if (options.useXstack) {
2153 emitcode ("mov", "r0,%s", spname);
2154 for (i = ds390_nRegs; i >= 0; i--) {
2155 if (bitVectBitValue (rs_mask, i)) {
2156 emitcode ("dec", "r0");
2157 emitcode ("movx", "a,@r0");
2159 emitcode ("mov", "b,a");
2161 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
2164 emitcode ("mov", "%s,r0", spname);
2165 if (bitVectBitValue (rs_mask, R0_IDX))
2166 emitcode ("mov", "r0,b");
2168 for (i = ds390_nRegs; i >= 0; i--) {
2169 if (bitVectBitValue (rs_mask, i))
2170 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2175 /*-----------------------------------------------------------------*/
2176 /* unsaveRegisters - pop the pushed registers */
2177 /*-----------------------------------------------------------------*/
2179 unsaveRegisters (iCode * ic)
2183 if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2185 rsave = newBitVect(ic->rMask->size);
2186 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2187 if (bitVectBitValue(ic->rMask,i))
2188 rsave = bitVectSetBit(rsave,i);
2190 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2192 /* restore the registers in use at this time but skip the
2193 ones for the result */
2194 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2195 ds390_rUmaskForOp (IC_RESULT(ic)));
2201 /*-----------------------------------------------------------------*/
2203 /*-----------------------------------------------------------------*/
2205 pushSide (operand * oper, int size)
2208 _startLazyDPSEvaluation ();
2211 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, NULL);
2212 if (AOP_TYPE (oper) != AOP_REG &&
2213 AOP_TYPE (oper) != AOP_DIR &&
2216 emitcode ("mov", "a,%s", l);
2217 emitcode ("push", "acc");
2220 emitcode ("push", "%s", l);
2222 _endLazyDPSEvaluation ();
2225 /*-----------------------------------------------------------------*/
2226 /* assignResultValue - */
2227 /*-----------------------------------------------------------------*/
2229 assignResultValue (operand * oper)
2232 int size = AOP_SIZE (oper);
2233 bool pushedAcc = FALSE;
2235 if (size == fReturnSizeDS390)
2237 /* I don't think this case can ever happen... */
2238 /* ACC is the last part of this. If writing the result
2239 * uses AC, we must preserve it.
2241 if (AOP_NEEDSACC(oper))
2243 emitcode(";", "assignResultValue special case for ACC.");
2244 emitcode("push", "acc");
2251 _startLazyDPSEvaluation ();
2254 aopPut (AOP (oper), fReturn[offset], offset);
2257 _endLazyDPSEvaluation ();
2261 emitcode("pop", "acc");
2262 aopPut(AOP(oper), "a", offset);
2267 /*-----------------------------------------------------------------*/
2268 /* genXpush - pushes onto the external stack */
2269 /*-----------------------------------------------------------------*/
2271 genXpush (iCode * ic)
2273 asmop *aop = newAsmop (0);
2275 int size, offset = 0;
2277 D (emitcode (";", "genXpush ");
2280 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2281 r = getFreePtr (ic, &aop, FALSE);
2284 emitcode ("mov", "%s,_spx", r->name);
2286 size = AOP_SIZE (IC_LEFT (ic));
2287 _startLazyDPSEvaluation ();
2291 MOVA (aopGet (AOP (IC_LEFT (ic)),
2292 offset++, FALSE, FALSE, NULL));
2293 emitcode ("movx", "@%s,a", r->name);
2294 emitcode ("inc", "%s", r->name);
2297 _endLazyDPSEvaluation ();
2300 emitcode ("mov", "_spx,%s", r->name);
2302 freeAsmop (NULL, aop, ic, TRUE);
2303 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2306 /*-----------------------------------------------------------------*/
2307 /* genIpush - generate code for pushing this gets a little complex */
2308 /*-----------------------------------------------------------------*/
2310 genIpush (iCode * ic)
2312 int size, offset = 0;
2315 D (emitcode (";", "genIpush ");
2318 /* if this is not a parm push : ie. it is spill push
2319 and spill push is always done on the local stack */
2323 /* and the item is spilt then do nothing */
2324 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2327 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2328 size = AOP_SIZE (IC_LEFT (ic));
2329 /* push it on the stack */
2330 _startLazyDPSEvaluation ();
2333 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2339 emitcode ("push", "%s", l);
2341 _endLazyDPSEvaluation ();
2345 /* this is a paramter push: in this case we call
2346 the routine to find the call and save those
2347 registers that need to be saved */
2350 /* if use external stack then call the external
2351 stack pushing routine */
2352 if (options.useXstack)
2358 /* then do the push */
2359 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2361 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2362 size = AOP_SIZE (IC_LEFT (ic));
2364 _startLazyDPSEvaluation ();
2367 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2368 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2369 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2372 emitcode ("mov", "a,%s", l);
2373 emitcode ("push", "acc");
2377 emitcode ("push", "%s", l);
2380 _endLazyDPSEvaluation ();
2382 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2385 /*-----------------------------------------------------------------*/
2386 /* genIpop - recover the registers: can happen only for spilling */
2387 /*-----------------------------------------------------------------*/
2389 genIpop (iCode * ic)
2393 D (emitcode (";", "genIpop ");
2397 /* if the temp was not pushed then */
2398 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2401 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2402 size = AOP_SIZE (IC_LEFT (ic));
2403 offset = (size - 1);
2404 _startLazyDPSEvaluation ();
2407 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2408 FALSE, TRUE, NULL));
2410 _endLazyDPSEvaluation ();
2412 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2415 /*-----------------------------------------------------------------*/
2416 /* unsaveRBank - restores the resgister bank from stack */
2417 /*-----------------------------------------------------------------*/
2419 unsaveRBank (int bank, iCode * ic, bool popPsw)
2425 if (options.useXstack)
2429 /* Assume r0 is available for use. */
2430 r = ds390_regWithIdx (R0_IDX);;
2435 r = getFreePtr (ic, &aop, FALSE);
2437 emitcode ("mov", "%s,_spx", r->name);
2442 if (options.useXstack)
2444 emitcode ("movx", "a,@%s", r->name);
2445 emitcode ("mov", "psw,a");
2446 emitcode ("dec", "%s", r->name);
2450 emitcode ("pop", "psw");
2454 for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2456 if (options.useXstack)
2458 emitcode ("movx", "a,@%s", r->name);
2459 emitcode ("mov", "(%s+%d),a",
2460 regs390[i].base, 8 * bank + regs390[i].offset);
2461 emitcode ("dec", "%s", r->name);
2465 emitcode ("pop", "(%s+%d)",
2466 regs390[i].base, 8 * bank + regs390[i].offset);
2469 if (options.useXstack)
2471 emitcode ("mov", "_spx,%s", r->name);
2476 freeAsmop (NULL, aop, ic, TRUE);
2480 /*-----------------------------------------------------------------*/
2481 /* saveRBank - saves an entire register bank on the stack */
2482 /*-----------------------------------------------------------------*/
2484 saveRBank (int bank, iCode * ic, bool pushPsw)
2490 if (options.useXstack)
2494 /* Assume r0 is available for use. */
2495 r = ds390_regWithIdx (R0_IDX);;
2500 r = getFreePtr (ic, &aop, FALSE);
2502 emitcode ("mov", "%s,_spx", r->name);
2505 for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2507 if (options.useXstack)
2509 emitcode ("inc", "%s", r->name);
2510 emitcode ("mov", "a,(%s+%d)",
2511 regs390[i].base, 8 * bank + regs390[i].offset);
2512 emitcode ("movx", "@%s,a", r->name);
2515 emitcode ("push", "(%s+%d)",
2516 regs390[i].base, 8 * bank + regs390[i].offset);
2521 if (options.useXstack)
2523 emitcode ("mov", "a,psw");
2524 emitcode ("movx", "@%s,a", r->name);
2525 emitcode ("inc", "%s", r->name);
2526 emitcode ("mov", "_spx,%s", r->name);
2530 emitcode ("push", "psw");
2533 emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2538 freeAsmop (NULL, aop, ic, TRUE);
2547 /*-----------------------------------------------------------------*/
2548 /* genSend - gen code for SEND */
2549 /*-----------------------------------------------------------------*/
2550 static void genSend(set *sendSet)
2554 static int rb1_count = 0;
2556 for (sic = setFirstItem (sendSet); sic;
2557 sic = setNextItem (sendSet)) {
2558 int size, offset = 0;
2560 size=getSize(operandType(IC_LEFT(sic)));
2561 D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2562 if (sendCount == 0) { /* first parameter */
2563 // we know that dpl(hxb) is the result, so
2565 _startLazyDPSEvaluation ();
2567 aopOp (IC_LEFT (sic), sic, FALSE,
2568 (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2570 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2573 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2574 FALSE, FALSE, NULL);
2575 if (strcmp (l, fReturn[offset])) {
2576 emitcode ("mov", "%s,%s",
2582 _endLazyDPSEvaluation ();
2583 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2585 } else { /* if more parameter in registers */
2586 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2588 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
2589 FALSE, FALSE, NULL));
2591 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2598 adjustEsp(const char *reg)
2600 emitcode ("anl","%s,#3", reg);
2601 if (TARGET_IS_DS400)
2603 emitcode ("orl","%s,#!constbyte",
2605 (options.stack_loc >> 8) & 0xff);
2609 /*-----------------------------------------------------------------*/
2610 /* genCall - generates a call statement */
2611 /*-----------------------------------------------------------------*/
2613 genCall (iCode * ic)
2616 bool restoreBank = FALSE;
2617 bool swapBanks = FALSE;
2619 D (emitcode (";", "genCall "););
2621 /* if we are calling a not _naked function that is not using
2622 the same register bank then we need to save the
2623 destination registers on the stack */
2624 dtype = operandType (IC_LEFT (ic));
2625 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2626 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2627 IFFUNC_ISISR (currFunc->type))
2631 /* This is unexpected; the bank should have been saved in
2634 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2640 /* if caller saves & we have not saved then */
2644 /* if send set is not empty the assign */
2645 /* We've saved all the registers we care about;
2646 * therefore, we may clobber any register not used
2647 * in the calling convention (i.e. anything not in
2652 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2653 genSend(reverseSet(_G.sendSet));
2655 genSend(_G.sendSet);
2662 emitcode ("mov", "psw,#!constbyte",
2663 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2667 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2668 OP_SYMBOL (IC_LEFT (ic))->rname :
2669 OP_SYMBOL (IC_LEFT (ic))->name));
2673 emitcode ("mov", "psw,#!constbyte",
2674 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2677 /* if we need assign a result value */
2678 if ((IS_ITEMP (IC_RESULT (ic)) &&
2679 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2680 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2681 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2682 IS_TRUE_SYMOP (IC_RESULT (ic)))
2684 if (isOperandInFarSpace (IC_RESULT (ic))
2685 && getSize (operandType (IC_RESULT (ic))) <= 2)
2687 int size = getSize (operandType (IC_RESULT (ic)));
2689 /* Special case for 1 or 2 byte return in far space. */
2693 emitcode ("mov", "b,%s", fReturn[1]);
2698 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2704 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2708 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2710 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2715 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2718 assignResultValue (IC_RESULT (ic));
2720 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2724 /* adjust the stack for parameters if
2726 if (ic->parmBytes) {
2728 if (options.stack10bit) {
2729 if (ic->parmBytes <= 10) {
2730 emitcode(";","stack adjustment for parms");
2731 for (i=0; i < ic->parmBytes ; i++) {
2732 emitcode("pop","acc");
2736 emitcode ("clr","c");
2737 emitcode ("mov","a,sp");
2738 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2739 emitcode ("mov","sp,a");
2740 emitcode ("mov","a,esp");
2742 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2743 emitcode ("mov","esp,a");
2747 if (ic->parmBytes > 3) {
2748 emitcode ("mov", "a,%s", spname);
2749 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2750 emitcode ("mov", "%s,a", spname);
2752 for (i = 0; i < ic->parmBytes; i++)
2753 emitcode ("dec", "%s", spname);
2757 /* if we hade saved some registers then unsave them */
2759 unsaveRegisters (ic);
2761 /* if register bank was saved then pop them */
2763 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2766 /*-----------------------------------------------------------------*/
2767 /* genPcall - generates a call by pointer statement */
2768 /*-----------------------------------------------------------------*/
2770 genPcall (iCode * ic)
2773 symbol *rlbl = newiTempLabel (NULL);
2774 bool restoreBank=FALSE;
2776 D (emitcode (";", "genPcall ");
2780 /* if caller saves & we have not saved then */
2784 /* if we are calling a function that is not using
2785 the same register bank then we need to save the
2786 destination registers on the stack */
2787 dtype = operandType (IC_LEFT (ic));
2788 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2789 IFFUNC_ISISR (currFunc->type) &&
2790 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2791 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2795 /* push the return address on to the stack */
2796 emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2797 emitcode ("push", "acc");
2798 emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2799 emitcode ("push", "acc");
2801 if (options.model == MODEL_FLAT24)
2803 emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2804 emitcode ("push", "acc");
2807 /* now push the calling address */
2808 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2810 pushSide (IC_LEFT (ic), FPTRSIZE);
2812 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2814 /* if send set is not empty the assign */
2817 genSend(reverseSet(_G.sendSet));
2821 emitcode ("ret", "");
2822 emitcode ("", "!tlabeldef", (rlbl->key + 100));
2825 /* if we need assign a result value */
2826 if ((IS_ITEMP (IC_RESULT (ic)) &&
2827 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2828 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2829 IS_TRUE_SYMOP (IC_RESULT (ic)))
2833 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2836 assignResultValue (IC_RESULT (ic));
2838 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2841 /* adjust the stack for parameters if
2846 if (options.stack10bit) {
2847 if (ic->parmBytes <= 10) {
2848 emitcode(";","stack adjustment for parms");
2849 for (i=0; i < ic->parmBytes ; i++) {
2850 emitcode("pop","acc");
2854 emitcode ("clr","c");
2855 emitcode ("mov","a,sp");
2856 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2857 emitcode ("mov","sp,a");
2858 emitcode ("mov","a,esp");
2860 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2861 emitcode ("mov","esp,a");
2865 if (ic->parmBytes > 3) {
2866 emitcode ("mov", "a,%s", spname);
2867 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2868 emitcode ("mov", "%s,a", spname);
2871 for (i = 0; i < ic->parmBytes; i++)
2872 emitcode ("dec", "%s", spname);
2876 /* if register bank was saved then unsave them */
2878 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2880 /* if we hade saved some registers then
2883 unsaveRegisters (ic);
2887 /*-----------------------------------------------------------------*/
2888 /* resultRemat - result is rematerializable */
2889 /*-----------------------------------------------------------------*/
2891 resultRemat (iCode * ic)
2893 if (SKIP_IC (ic) || ic->op == IFX)
2896 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2898 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2899 if (sym->remat && !POINTER_SET (ic))
2906 #if defined(__BORLANDC__) || defined(_MSC_VER)
2907 #define STRCASECMP stricmp
2909 #define STRCASECMP strcasecmp
2912 /*-----------------------------------------------------------------*/
2913 /* inExcludeList - return 1 if the string is in exclude Reg list */
2914 /*-----------------------------------------------------------------*/
2916 regsCmp(void *p1, void *p2)
2918 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2922 inExcludeList (char *s)
2924 const char *p = setFirstItem(options.excludeRegsSet);
2926 if (p == NULL || STRCASECMP(p, "none") == 0)
2930 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2933 /*-----------------------------------------------------------------*/
2934 /* genFunction - generated code for function entry */
2935 /*-----------------------------------------------------------------*/
2937 genFunction (iCode * ic)
2941 bool switchedPSW = FALSE;
2943 D (emitcode (";", "genFunction "););
2946 /* create the function header */
2947 emitcode (";", "-----------------------------------------");
2948 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2949 emitcode (";", "-----------------------------------------");
2951 emitcode ("", "%s:", sym->rname);
2952 ftype = operandType (IC_LEFT (ic));
2954 if (IFFUNC_ISNAKED(ftype))
2956 emitcode(";", "naked function: no prologue.");
2960 if (options.stack_probe)
2961 emitcode ("lcall","__stack_probe");
2963 /* here we need to generate the equates for the
2964 register bank if required */
2965 if (FUNC_REGBANK (ftype) != rbank)
2969 rbank = FUNC_REGBANK (ftype);
2970 for (i = 0; i < ds390_nRegs; i++)
2972 if (regs390[i].print) {
2973 if (strcmp (regs390[i].base, "0") == 0)
2974 emitcode ("", "%s !equ !constbyte",
2976 8 * rbank + regs390[i].offset);
2978 emitcode ("", "%s !equ %s + !constbyte",
2981 8 * rbank + regs390[i].offset);
2986 /* if this is an interrupt service routine then
2987 save acc, b, dpl, dph */
2988 if (IFFUNC_ISISR (sym->type))
2990 if (!inExcludeList ("acc"))
2991 emitcode ("push", "acc");
2992 if (!inExcludeList ("b"))
2993 emitcode ("push", "b");
2994 if (!inExcludeList ("dpl"))
2995 emitcode ("push", "dpl");
2996 if (!inExcludeList ("dph"))
2997 emitcode ("push", "dph");
2998 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3000 emitcode ("push", "dpx");
3001 /* Make sure we're using standard DPTR */
3002 emitcode ("push", "dps");
3003 emitcode ("mov", "dps,#0");
3004 if (options.stack10bit)
3006 /* This ISR could conceivably use DPTR2. Better save it. */
3007 emitcode ("push", "dpl1");
3008 emitcode ("push", "dph1");
3009 emitcode ("push", "dpx1");
3010 emitcode ("push", DP2_RESULT_REG);
3013 /* if this isr has no bank i.e. is going to
3014 run with bank 0 , then we need to save more
3016 if (!FUNC_REGBANK (sym->type))
3020 /* if this function does not call any other
3021 function then we can be economical and
3022 save only those registers that are used */
3023 if (!IFFUNC_HASFCALL(sym->type))
3026 /* if any registers used */
3029 /* save the registers used */
3030 for (i = 0; i < sym->regsUsed->size; i++)
3032 if (bitVectBitValue (sym->regsUsed, i))
3033 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3039 /* this function has a function call cannot
3040 determines register usage so we will have to push the
3042 saveRBank (0, ic, FALSE);
3043 if (options.parms_in_bank1) {
3044 for (i=0; i < 8 ; i++ ) {
3045 emitcode ("push","%s",rb1regs[i]);
3052 /* This ISR uses a non-zero bank.
3054 * We assume that the bank is available for our
3057 * However, if this ISR calls a function which uses some
3058 * other bank, we must save that bank entirely.
3060 unsigned long banksToSave = 0;
3062 if (IFFUNC_HASFCALL(sym->type))
3065 #define MAX_REGISTER_BANKS 4
3070 for (i = ic; i; i = i->next)
3072 if (i->op == ENDFUNCTION)
3074 /* we got to the end OK. */
3082 dtype = operandType (IC_LEFT(i));
3084 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3086 /* Mark this bank for saving. */
3087 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3089 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3093 banksToSave |= (1 << FUNC_REGBANK(dtype));
3096 /* And note that we don't need to do it in
3104 /* This is a mess; we have no idea what
3105 * register bank the called function might
3108 * The only thing I can think of to do is
3109 * throw a warning and hope.
3111 werror(W_FUNCPTR_IN_USING_ISR);
3115 if (banksToSave && options.useXstack)
3117 /* Since we aren't passing it an ic,
3118 * saveRBank will assume r0 is available to abuse.
3120 * So switch to our (trashable) bank now, so
3121 * the caller's R0 isn't trashed.
3123 emitcode ("push", "psw");
3124 emitcode ("mov", "psw,#!constbyte",
3125 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3129 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3131 if (banksToSave & (1 << ix))
3133 saveRBank(ix, NULL, FALSE);
3137 // TODO: this needs a closer look
3138 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3143 /* if callee-save to be used for this function
3144 then save the registers being used in this function */
3145 if (IFFUNC_CALLEESAVES(sym->type))
3149 /* if any registers used */
3152 /* save the registers used */
3153 for (i = 0; i < sym->regsUsed->size; i++)
3155 if (bitVectBitValue (sym->regsUsed, i))
3157 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3165 /* set the register bank to the desired value */
3166 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3169 emitcode ("push", "psw");
3170 emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3173 if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3174 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3175 if (options.stack10bit) {
3176 emitcode ("push","_bpx");
3177 emitcode ("push","_bpx+1");
3178 emitcode ("mov","_bpx,%s",spname);
3179 emitcode ("mov","_bpx+1,esp");
3180 adjustEsp("_bpx+1");
3182 if (options.useXstack) {
3183 emitcode ("mov", "r0,%s", spname);
3184 emitcode ("mov", "a,_bp");
3185 emitcode ("movx", "@r0,a");
3186 emitcode ("inc", "%s", spname);
3188 /* set up the stack */
3189 emitcode ("push", "_bp"); /* save the callers stack */
3191 emitcode ("mov", "_bp,%s", spname);
3195 /* adjust the stack for the function */
3198 if (options.stack10bit) {
3199 if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
3200 assert (sym->recvSize <= 4);
3201 if (sym->stack <= 8) {
3202 while (i--) emitcode ("push","acc");
3205 emitcode ("mov","a,sp");
3206 emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3207 emitcode ("mov","sp,a");
3208 emitcode ("mov","a,esp");
3210 emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3211 emitcode ("mov","esp,a");
3216 werror (W_STACK_OVERFLOW, sym->name);
3218 if (i > 3 && sym->recvSize < 4) {
3220 emitcode ("mov", "a,sp");
3221 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3222 emitcode ("mov", "sp,a");
3226 emitcode ("inc", "sp");
3233 emitcode ("mov", "a,_spx");
3234 emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3235 emitcode ("mov", "_spx,a");
3238 /* if critical function then turn interrupts off */
3239 if (IFFUNC_ISCRITICAL (ftype))
3241 symbol *tlbl = newiTempLabel (NULL);
3242 emitcode ("setb", "c");
3243 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3244 emitcode ("clr", "c");
3245 emitcode ("", "%05d$:", (tlbl->key + 100));
3246 emitcode ("push", "psw"); /* save old ea via c in psw */
3251 /*-----------------------------------------------------------------*/
3252 /* genEndFunction - generates epilogue for functions */
3253 /*-----------------------------------------------------------------*/
3255 genEndFunction (iCode * ic)
3257 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3258 lineNode *lnp = lineCurr;
3260 bitVect *regsUsedPrologue;
3261 bitVect *regsUnneeded;
3264 D (emitcode (";", "genEndFunction "););
3266 if (IFFUNC_ISNAKED(sym->type))
3268 emitcode(";", "naked function: no epilogue.");
3269 if (options.debug && currFunc)
3270 debugFile->writeEndFunction (currFunc, ic, 0);
3274 if (IFFUNC_ISCRITICAL (sym->type))
3276 emitcode ("pop", "psw"); /* restore ea via c in psw */
3277 emitcode ("mov", "ea,c");
3280 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3281 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3283 if (options.stack10bit) {
3285 emitcode ("mov", "sp,_bpx", spname);
3286 emitcode ("mov", "esp,_bpx+1", spname);
3289 emitcode ("mov", "%s,_bp", spname);
3293 /* if use external stack but some variables were
3294 added to the local stack then decrement the
3296 if (options.useXstack && sym->stack) {
3297 emitcode ("mov", "a,sp");
3298 emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3299 emitcode ("mov", "sp,a");
3303 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3304 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3306 if (options.useXstack) {
3307 emitcode ("mov", "r0,%s", spname);
3308 emitcode ("movx", "a,@r0");
3309 emitcode ("mov", "_bp,a");
3310 emitcode ("dec", "%s", spname);
3312 if (options.stack10bit) {
3313 emitcode ("pop", "_bpx+1");
3314 emitcode ("pop", "_bpx");
3316 emitcode ("pop", "_bp");
3321 /* restore the register bank */
3322 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3324 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3325 || !options.useXstack)
3327 /* Special case of ISR using non-zero bank with useXstack
3330 emitcode ("pop", "psw");
3334 if (IFFUNC_ISISR (sym->type))
3337 /* now we need to restore the registers */
3338 /* if this isr has no bank i.e. is going to
3339 run with bank 0 , then we need to save more
3341 if (!FUNC_REGBANK (sym->type))
3344 /* if this function does not call any other
3345 function then we can be economical and
3346 save only those registers that are used */
3347 if (!IFFUNC_HASFCALL(sym->type))
3350 /* if any registers used */
3353 /* save the registers used */
3354 for (i = sym->regsUsed->size; i >= 0; i--)
3356 if (bitVectBitValue (sym->regsUsed, i))
3357 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3363 /* this function has a function call cannot
3364 determines register usage so we will have to pop the
3366 if (options.parms_in_bank1) {
3367 for (i = 7 ; i >= 0 ; i-- ) {
3368 emitcode ("pop","%s",rb1regs[i]);
3371 unsaveRBank (0, ic, FALSE);
3376 /* This ISR uses a non-zero bank.
3378 * Restore any register banks saved by genFunction
3381 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3384 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3386 if (savedBanks & (1 << ix))
3388 unsaveRBank(ix, NULL, FALSE);
3392 if (options.useXstack)
3394 /* Restore bank AFTER calling unsaveRBank,
3395 * since it can trash r0.
3397 emitcode ("pop", "psw");
3401 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3403 if (options.stack10bit)
3405 emitcode ("pop", DP2_RESULT_REG);
3406 emitcode ("pop", "dpx1");
3407 emitcode ("pop", "dph1");
3408 emitcode ("pop", "dpl1");
3410 emitcode ("pop", "dps");
3411 emitcode ("pop", "dpx");
3413 if (!inExcludeList ("dph"))
3414 emitcode ("pop", "dph");
3415 if (!inExcludeList ("dpl"))
3416 emitcode ("pop", "dpl");
3417 if (!inExcludeList ("b"))
3418 emitcode ("pop", "b");
3419 if (!inExcludeList ("acc"))
3420 emitcode ("pop", "acc");
3422 /* if debug then send end of function */
3423 if (options.debug && currFunc) {
3424 debugFile->writeEndFunction (currFunc, ic, 1);
3427 emitcode ("reti", "");
3431 if (IFFUNC_CALLEESAVES(sym->type))
3435 /* if any registers used */
3438 /* save the registers used */
3439 for (i = sym->regsUsed->size; i >= 0; i--)
3441 if (bitVectBitValue (sym->regsUsed, i))
3442 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3447 /* if debug then send end of function */
3448 if (options.debug && currFunc)
3450 debugFile->writeEndFunction (currFunc, ic, 1);
3453 emitcode ("ret", "");
3456 if (!port->peep.getRegsRead || !port->peep.getRegsWritten)
3459 /* If this was an interrupt handler using bank 0 that called another */
3460 /* function, then all registers must be saved; nothing to optimized. */
3461 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3462 && !FUNC_REGBANK(sym->type))
3465 /* There are no push/pops to optimize if not callee-saves or ISR */
3466 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3469 /* If there were stack parameters, we cannot optimize without also */
3470 /* fixing all of the stack offsets; this is too dificult to consider. */
3471 if (FUNC_HASSTACKPARM(sym->type))
3474 /* Compute the registers actually used */
3475 regsUsed = newBitVect (ds390_nRegs);
3476 regsUsedPrologue = newBitVect (ds390_nRegs);
3479 if (lnp->ic && lnp->ic->op == FUNCTION)
3480 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3482 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3484 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3485 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3492 if (bitVectBitValue (regsUsedPrologue, DPS_IDX)
3493 && !bitVectBitValue (regsUsed, DPS_IDX))
3495 bitVectUnSetBit (regsUsedPrologue, DPS_IDX);
3498 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3499 && !bitVectBitValue (regsUsed, CND_IDX))
3501 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3502 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK(sym->type)
3504 bitVectUnSetBit (regsUsed, CND_IDX);
3507 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3509 /* If this was an interrupt handler that called another function */
3510 /* function, then assume working registers may be modified by it. */
3511 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3513 regsUsed = bitVectSetBit (regsUsed, AP_IDX);
3514 regsUsed = bitVectSetBit (regsUsed, DPX1_IDX);
3515 regsUsed = bitVectSetBit (regsUsed, DPL1_IDX);
3516 regsUsed = bitVectSetBit (regsUsed, DPH1_IDX);
3517 regsUsed = bitVectSetBit (regsUsed, DPX_IDX);
3518 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3519 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3520 regsUsed = bitVectSetBit (regsUsed, DPS_IDX);
3521 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3522 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3523 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3526 /* Remove the unneeded push/pops */
3527 regsUnneeded = newBitVect (ds390_nRegs);
3530 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3532 if (!strncmp(lnp->line, "push", 4))
3534 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3535 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3537 connectLine (lnp->prev, lnp->next);
3538 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3541 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3543 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3544 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3546 connectLine (lnp->prev, lnp->next);
3547 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3554 for (idx = 0; idx < regsUnneeded->size; idx++)
3555 if (bitVectBitValue (regsUnneeded, idx))
3556 emitcode ("", ";\teliminated unneeded push/pop %s", ds390_regWithIdx (idx)->dname);
3558 freeBitVect (regsUnneeded);
3559 freeBitVect (regsUsed);
3560 freeBitVect (regsUsedPrologue);
3563 /*-----------------------------------------------------------------*/
3564 /* genJavaNativeRet - generate code for return JavaNative */
3565 /*-----------------------------------------------------------------*/
3566 static void genJavaNativeRet(iCode *ic)
3570 aopOp (IC_LEFT (ic), ic, FALSE,
3571 AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
3572 size = AOP_SIZE (IC_LEFT (ic));
3576 /* it is assigned to GPR0-R3 then push them */
3577 if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3578 aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3579 for (i = 0 ; i < size ; i++ ) {
3580 emitcode ("push","%s",
3581 aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3583 for (i = (size-1) ; i >= 0 ; i--) {
3584 emitcode ("pop","a%s",javaRet[i]);
3587 for (i = 0 ; i < size ; i++)
3588 emitcode ("mov","%s,%s",javaRet[i],
3589 aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3591 for (i = size ; i < 4 ; i++ )
3592 emitcode ("mov","%s,#0",javaRet[i]);
3596 /*-----------------------------------------------------------------*/
3597 /* genRet - generate code for return statement */
3598 /*-----------------------------------------------------------------*/
3602 int size, offset = 0, pushed = 0;
3604 D (emitcode (";", "genRet "););
3606 /* if we have no return value then
3607 just generate the "ret" */
3611 /* if this is a JavaNative function then return
3612 value in different register */
3613 if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3614 genJavaNativeRet(ic);
3617 /* we have something to return then
3618 move the return value into place */
3619 aopOp (IC_LEFT (ic), ic, FALSE,
3620 (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
3621 size = AOP_SIZE (IC_LEFT (ic));
3623 _startLazyDPSEvaluation ();
3627 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3629 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3631 emitcode ("push", "%s", l);
3636 /* Since A is the last element of fReturn,
3637 * is is OK to clobber it in the aopGet.
3639 l = aopGet (AOP (IC_LEFT (ic)), offset,
3640 FALSE, FALSE, NULL);
3641 if (strcmp (fReturn[offset], l))
3642 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3645 _endLazyDPSEvaluation ();
3652 if (strcmp (fReturn[pushed], "a"))
3653 emitcode ("pop", fReturn[pushed]);
3655 emitcode ("pop", "acc");
3658 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3661 /* generate a jump to the return label
3662 if the next is not the return statement */
3663 if (!(ic->next && ic->next->op == LABEL &&
3664 IC_LABEL (ic->next) == returnLabel))
3666 emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3670 /*-----------------------------------------------------------------*/
3671 /* genLabel - generates a label */
3672 /*-----------------------------------------------------------------*/
3674 genLabel (iCode * ic)
3676 /* special case never generate */
3677 if (IC_LABEL (ic) == entryLabel)
3680 D (emitcode (";", "genLabel ");
3683 emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3686 /*-----------------------------------------------------------------*/
3687 /* genGoto - generates a ljmp */
3688 /*-----------------------------------------------------------------*/
3690 genGoto (iCode * ic)
3692 D (emitcode (";", "genGoto ");
3694 emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3697 /*-----------------------------------------------------------------*/
3698 /* findLabelBackwards: walks back through the iCode chain looking */
3699 /* for the given label. Returns number of iCode instructions */
3700 /* between that label and given ic. */
3701 /* Returns zero if label not found. */
3702 /*-----------------------------------------------------------------*/
3704 findLabelBackwards (iCode * ic, int key)
3713 /* If we have any pushes or pops, we cannot predict the distance.
3714 I don't like this at all, this should be dealt with in the
3716 if (ic->op == IPUSH || ic->op == IPOP) {
3720 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3722 /* printf("findLabelBackwards = %d\n", count); */
3730 /*-----------------------------------------------------------------*/
3731 /* genPlusIncr :- does addition with increment if possible */
3732 /*-----------------------------------------------------------------*/
3734 genPlusIncr (iCode * ic)
3736 unsigned int icount;
3737 unsigned int size = getDataSize (IC_RESULT (ic));
3739 /* will try to generate an increment */
3740 /* if the right side is not a literal
3742 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3745 /* if the literal value of the right hand side
3746 is greater than 4 then it is not worth it */
3747 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3750 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3751 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3753 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
3757 /* if increment 16 bits in register */
3759 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3760 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3761 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3770 /* If the next instruction is a goto and the goto target
3771 * is <= 5 instructions previous to this, we can generate
3772 * jumps straight to that target.
3774 if (ic->next && ic->next->op == GOTO
3775 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3778 D(emitcode (";", "tail increment optimized (range %d)", labelRange););
3779 tlbl = IC_LABEL (ic->next);
3784 tlbl = newiTempLabel (NULL);
3788 l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
3789 emitcode ("inc", "%s", l);
3791 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3792 IS_AOP_PREG (IC_RESULT (ic)))
3794 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3798 emitcode ("clr", "a");
3799 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3802 l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
3803 emitcode ("inc", "%s", l);
3806 if (!strcmp(l, "acc"))
3808 emitcode("jnz", "!tlabel", tlbl->key + 100);
3810 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3811 IS_AOP_PREG (IC_RESULT (ic)))
3813 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3817 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3820 l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
3821 emitcode ("inc", "%s", l);
3825 if (!strcmp(l, "acc"))
3827 emitcode("jnz", "!tlabel", tlbl->key + 100);
3829 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3830 IS_AOP_PREG (IC_RESULT (ic)))
3832 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3836 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3839 l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
3840 emitcode ("inc", "%s", l); }
3844 emitcode ("", "!tlabeldef", tlbl->key + 100);
3849 if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3850 !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 &&
3851 options.model == MODEL_FLAT24 ) {
3855 emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, NULL));
3857 emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, NULL));
3859 emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3862 while (icount--) emitcode ("inc","dptr");
3866 if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3867 AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3869 emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3870 while (icount--) emitcode ("inc","dptr");
3871 emitcode ("mov","dps,#0");
3875 /* if the sizes are greater than 1 then we cannot */
3876 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3877 AOP_SIZE (IC_LEFT (ic)) > 1)
3880 /* we can if the aops of the left & result match or
3881 if they are in registers and the registers are the
3884 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3885 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3886 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3891 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3892 emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3893 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3898 _startLazyDPSEvaluation ();
3901 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3903 _endLazyDPSEvaluation ();
3912 /*-----------------------------------------------------------------*/
3913 /* outBitAcc - output a bit in acc */
3914 /*-----------------------------------------------------------------*/
3916 outBitAcc (operand * result)
3918 symbol *tlbl = newiTempLabel (NULL);
3919 /* if the result is a bit */
3920 if (AOP_TYPE (result) == AOP_CRY)
3922 aopPut (AOP (result), "a", 0);
3926 emitcode ("jz", "!tlabel", tlbl->key + 100);
3927 emitcode ("mov", "a,%s", one);
3928 emitcode ("", "!tlabeldef", tlbl->key + 100);
3933 /*-----------------------------------------------------------------*/
3934 /* genPlusBits - generates code for addition of two bits */
3935 /*-----------------------------------------------------------------*/
3937 genPlusBits (iCode * ic)
3939 D (emitcode (";", "genPlusBits "););
3941 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3943 symbol *lbl = newiTempLabel (NULL);
3944 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3945 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3946 emitcode ("cpl", "c");
3947 emitcode ("", "!tlabeldef", (lbl->key + 100));
3948 outBitC (IC_RESULT (ic));
3952 emitcode ("clr", "a");
3953 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3954 emitcode ("rlc", "a");
3955 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3956 emitcode ("addc", "a,#0");
3957 outAcc (IC_RESULT (ic));
3962 adjustArithmeticResult (iCode * ic)
3964 if (opIsGptr (IC_RESULT (ic)) &&
3965 opIsGptr (IC_LEFT (ic)) &&
3966 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3968 aopPut (AOP (IC_RESULT (ic)),
3969 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3973 if (opIsGptr (IC_RESULT (ic)) &&
3974 opIsGptr (IC_RIGHT (ic)) &&
3975 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3977 aopPut (AOP (IC_RESULT (ic)),
3978 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3982 if (opIsGptr (IC_RESULT (ic)) &&
3983 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3984 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3985 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3986 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3989 SNPRINTF (buff, sizeof(buff),
3990 "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3991 aopPut (AOP (IC_RESULT (ic)), buff, GPTRSIZE - 1);
3995 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
3996 // generates the result if possible. If result is generated, returns TRUE; otherwise
3997 // returns false and caller must deal with fact that result isn't aopOp'd.
3998 bool aopOp3(iCode * ic)
4000 bool dp1InUse, dp2InUse;
4003 // First, generate the right opcode. DPTR may be used if neither left nor result are
4006 // D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
4007 // AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
4008 // AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
4009 // AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
4011 // D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
4012 // AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
4013 // AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
4014 // AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
4017 // Right uses DPTR unless left or result is an AOP_STR; however,
4018 // if right is an AOP_STR, it must use DPTR regardless.
4019 if ((AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)))
4020 && !AOP_IS_STR(IC_RIGHT(ic)))
4029 aopOp (IC_RIGHT(ic),ic,FALSE, useDp2);
4031 // if the right used DPTR, left MUST use DPTR2.
4032 // if the right used DPTR2, left MUST use DPTR.
4033 // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
4034 // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
4035 // enabling us to assign DPTR to result.
4037 if (AOP_USESDPTR(IC_RIGHT(ic)))
4041 else if (AOP_USESDPTR2(IC_RIGHT(ic)))
4047 if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
4057 aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
4060 // We've op'd the left & right. So, if left or right are the same operand as result,
4061 // we know aopOp will succeed, and we can just do it & bail.
4062 if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)))
4064 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4067 if (isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
4069 // D(emitcode(";", "aopOp3: (left | right) & result equal"););
4070 aopOp(IC_RESULT(ic),ic,TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4074 // Operands may be equivalent (but not equal) if they share a spill location. If
4075 // so, use the same DPTR or DPTR2.
4076 if (operandsEqu (IC_LEFT(ic), IC_RESULT(ic)))
4078 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4081 if (operandsEqu (IC_RIGHT(ic), IC_RESULT(ic)))
4083 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4087 // Note which dptrs are currently in use.
4088 dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
4089 dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
4091 // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot
4093 if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
4098 // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
4099 if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
4104 // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck
4105 if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
4110 aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
4112 // Some sanity checking...
4113 if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
4116 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
4117 __FILE__, __LINE__, ic->filename, ic->lineno);
4118 emitcode(";", ">>> unexpected DPTR here.");
4121 if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
4124 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
4125 __FILE__, __LINE__, ic->filename, ic->lineno);
4126 emitcode(";", ">>> unexpected DPTR2 here.");
4132 // Macro to aopOp all three operands of an ic. If this cannot be done,
4133 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
4134 // will be set TRUE. The caller must then handle the case specially, noting
4135 // that the IC_RESULT operand is not aopOp'd.
4137 #define AOP_OP_3_NOFATAL(ic, rc) \
4138 do { rc = !aopOp3(ic); } while (0)
4140 // aopOp the left & right operands of an ic.
4141 #define AOP_OP_2(ic) \
4142 aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
4143 aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
4145 // convienience macro.
4146 #define AOP_SET_LOCALS(ic) \
4147 left = IC_LEFT(ic); \
4148 right = IC_RIGHT(ic); \
4149 result = IC_RESULT(ic);
4152 // Given an integer value of pushedSize bytes on the stack,
4153 // adjust it to be resultSize bytes, either by discarding
4154 // the most significant bytes or by zero-padding.
4156 // On exit from this macro, pushedSize will have been adjusted to
4157 // equal resultSize, and ACC may be trashed.
4158 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
4159 /* If the pushed data is bigger than the result, \
4160 * simply discard unused bytes. Icky, but works. \
4162 while (pushedSize > resultSize) \
4164 D (emitcode (";", "discarding unused result byte."););\
4165 emitcode ("pop", "acc"); \
4168 if (pushedSize < resultSize) \
4170 emitcode ("clr", "a"); \
4171 /* Conversly, we haven't pushed enough here. \
4172 * just zero-pad, and all is well. \
4174 while (pushedSize < resultSize) \
4176 emitcode("push", "acc"); \
4180 assert(pushedSize == resultSize);
4182 /*-----------------------------------------------------------------*/
4183 /* genPlus - generates code for addition */
4184 /*-----------------------------------------------------------------*/
4186 genPlus (iCode * ic)
4188 int size, offset = 0;
4192 D (emitcode (";", "genPlus "););
4194 /* special cases :- */
4195 if ( AOP_IS_STR(IC_LEFT(ic)) &&
4196 isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
4197 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
4198 size = (int)floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
4200 while (size--) emitcode ("inc","dptr");
4202 emitcode ("mov","a,dpl");
4203 emitcode ("add","a,#!constbyte",size & 0xff);
4204 emitcode ("mov","dpl,a");
4205 emitcode ("mov","a,dph");
4206 emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
4207 emitcode ("mov","dph,a");
4208 emitcode ("mov","a,dpx");
4209 emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
4210 emitcode ("mov","dpx,a");
4212 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
4215 if ( IS_SYMOP(IC_LEFT(ic)) &&
4216 OP_SYMBOL(IC_LEFT(ic))->remat &&
4217 isOperandInFarSpace(IC_RIGHT(ic))) {
4218 operand *op = IC_RIGHT(ic);
4219 IC_RIGHT(ic) = IC_LEFT(ic);
4223 AOP_OP_3_NOFATAL (ic, pushResult);
4227 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
4232 /* if literal, literal on the right or
4233 if left requires ACC or right is already
4235 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4236 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
4237 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4239 operand *t = IC_RIGHT (ic);
4240 IC_RIGHT (ic) = IC_LEFT (ic);
4242 emitcode (";", "Swapped plus args.");
4245 /* if both left & right are in bit
4247 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4248 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4254 /* if left in bit space & right literal */
4255 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4256 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4258 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4259 /* if result in bit space */
4260 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4262 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4263 emitcode ("cpl", "c");
4264 outBitC (IC_RESULT (ic));
4268 size = getDataSize (IC_RESULT (ic));
4269 _startLazyDPSEvaluation ();
4272 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4273 emitcode ("addc", "a,#0");
4274 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4276 _endLazyDPSEvaluation ();
4281 /* if I can do an increment instead
4282 of add then GOOD for ME */
4283 if (genPlusIncr (ic) == TRUE)
4285 emitcode (";", "did genPlusIncr");
4290 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4292 _startLazyDPSEvaluation ();
4295 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4297 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4299 emitcode ("add", "a,%s",
4300 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4302 emitcode ("addc", "a,%s",
4303 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4307 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4309 /* right is going to use ACC or we would have taken the
4312 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4314 D(emitcode(";", "+ AOP_ACC special case."););
4315 emitcode("xch", "a, %s", DP2_RESULT_REG);
4317 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4320 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4323 emitcode("add", "a, %s", DP2_RESULT_REG);
4327 emitcode ("add", "a,%s",
4328 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE,
4334 emitcode ("addc", "a,%s",
4335 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE,
4341 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4345 emitcode ("push", "acc");
4349 _endLazyDPSEvaluation ();
4353 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4355 size = getDataSize (IC_LEFT (ic));
4356 rSize = getDataSize (IC_RESULT (ic));
4358 ADJUST_PUSHED_RESULT(size, rSize);
4360 _startLazyDPSEvaluation ();
4363 emitcode ("pop", "acc");
4364 aopPut (AOP (IC_RESULT (ic)), "a", size);
4366 _endLazyDPSEvaluation ();
4369 adjustArithmeticResult (ic);
4372 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4373 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4374 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4377 /*-----------------------------------------------------------------*/
4378 /* genMinusDec :- does subtraction with deccrement if possible */
4379 /*-----------------------------------------------------------------*/
4381 genMinusDec (iCode * ic)
4383 unsigned int icount;
4384 unsigned int size = getDataSize (IC_RESULT (ic));
4386 /* will try to generate an increment */
4387 /* if the right side is not a literal
4389 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4392 /* if the literal value of the right hand side
4393 is greater than 4 then it is not worth it */
4394 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4397 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4398 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4400 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
4404 /* if decrement 16 bits in register */
4405 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4406 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4407 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4416 /* If the next instruction is a goto and the goto target
4417 * is <= 5 instructions previous to this, we can generate
4418 * jumps straight to that target.
4420 if (ic->next && ic->next->op == GOTO
4421 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4424 emitcode (";", "tail decrement optimized (range %d)", labelRange);
4425 tlbl = IC_LABEL (ic->next);
4430 tlbl = newiTempLabel (NULL);
4434 l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
4435 emitcode ("dec", "%s", l);
4437 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4438 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4439 IS_AOP_PREG (IC_RESULT (ic)))
4441 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4445 emitcode ("mov", "a,#!constbyte",0xff);
4446 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4448 l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
4449 emitcode ("dec", "%s", l);
4452 if (!strcmp(l, "acc"))
4454 emitcode("jnz", "!tlabel", tlbl->key + 100);
4456 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4457 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4458 IS_AOP_PREG (IC_RESULT (ic)))
4460 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4464 emitcode ("mov", "a,#!constbyte",0xff);
4465 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4467 l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
4468 emitcode ("dec", "%s", l);
4472 if (!strcmp(l, "acc"))
4474 emitcode("jnz", "!tlabel", tlbl->key + 100);
4476 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4477 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4478 IS_AOP_PREG (IC_RESULT (ic)))
4480 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4484 emitcode ("mov", "a,#!constbyte",0xff);
4485 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4487 l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
4488 emitcode ("dec", "%s", l);
4492 emitcode ("", "!tlabeldef", tlbl->key + 100);
4497 /* if the sizes are greater than 1 then we cannot */
4498 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4499 AOP_SIZE (IC_LEFT (ic)) > 1)
4502 /* we can if the aops of the left & result match or
4503 if they are in registers and the registers are the
4506 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4507 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4508 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4511 _startLazyDPSEvaluation ();
4514 emitcode ("dec", "%s",
4515 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
4517 _endLazyDPSEvaluation ();
4525 /*-----------------------------------------------------------------*/
4526 /* addSign - complete with sign */
4527 /*-----------------------------------------------------------------*/
4529 addSign (operand * result, int offset, int sign)
4531 int size = (getDataSize (result) - offset);
4534 _startLazyDPSEvaluation();
4537 emitcode ("rlc", "a");
4538 emitcode ("subb", "a,acc");
4541 aopPut (AOP (result), "a", offset++);
4548 aopPut (AOP (result), zero, offset++);
4551 _endLazyDPSEvaluation();
4555 /*-----------------------------------------------------------------*/
4556 /* genMinusBits - generates code for subtraction of two bits */
4557 /*-----------------------------------------------------------------*/
4559 genMinusBits (iCode * ic)
4561 symbol *lbl = newiTempLabel (NULL);
4563 D (emitcode (";", "genMinusBits "););
4565 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4567 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4568 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4569 emitcode ("cpl", "c");
4570 emitcode ("", "!tlabeldef", (lbl->key + 100));
4571 outBitC (IC_RESULT (ic));
4575 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4576 emitcode ("subb", "a,acc");
4577 emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4578 emitcode ("inc", "a");
4579 emitcode ("", "!tlabeldef", (lbl->key + 100));
4580 aopPut (AOP (IC_RESULT (ic)), "a", 0);
4581 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4585 /*-----------------------------------------------------------------*/
4586 /* genMinus - generates code for subtraction */
4587 /*-----------------------------------------------------------------*/
4589 genMinus (iCode * ic)
4591 int size, offset = 0;
4596 D (emitcode (";", "genMinus "););
4598 AOP_OP_3_NOFATAL(ic, pushResult);
4602 /* special cases :- */
4603 /* if both left & right are in bit space */
4604 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4605 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4611 /* if I can do an decrement instead
4612 of subtract then GOOD for ME */
4613 if (genMinusDec (ic) == TRUE)
4618 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4620 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4626 lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4631 /* if literal, add a,#-lit, else normal subb */
4632 _startLazyDPSEvaluation ();
4634 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4635 if (AOP_USESDPTR(IC_RIGHT(ic))) {
4636 emitcode ("mov","b,%s",
4637 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4638 MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4639 emitcode ("subb","a,b");
4641 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4642 emitcode ("subb", "a,%s",
4643 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE,
4647 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4648 /* first add without previous c */
4650 if (!size && lit==-1) {
4651 emitcode ("dec", "a");
4653 emitcode ("add", "a,#!constbyte",
4654 (unsigned int) (lit & 0x0FFL));
4657 emitcode ("addc", "a,#!constbyte",
4658 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4663 emitcode ("push", "acc");
4665 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4669 _endLazyDPSEvaluation ();
4673 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4675 size = getDataSize (IC_LEFT (ic));
4676 rSize = getDataSize (IC_RESULT (ic));
4678 ADJUST_PUSHED_RESULT(size, rSize);
4680 _startLazyDPSEvaluation ();
4683 emitcode ("pop", "acc");
4684 aopPut (AOP (IC_RESULT (ic)), "a", size);
4686 _endLazyDPSEvaluation ();
4689 adjustArithmeticResult (ic);
4692 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4693 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4694 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4698 /*-----------------------------------------------------------------*/
4699 /* genMultbits :- multiplication of bits */
4700 /*-----------------------------------------------------------------*/
4702 genMultbits (operand * left,
4707 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4708 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4709 aopOp(result, ic, TRUE, FALSE);
4714 /*-----------------------------------------------------------------*/
4715 /* genMultOneByte : 8*8=8/16 bit multiplication */
4716 /*-----------------------------------------------------------------*/
4718 genMultOneByte (operand * left,
4725 bool runtimeSign, compiletimeSign;
4726 bool lUnsigned, rUnsigned;
4729 /* (if two literals: the value is computed before) */
4730 /* if one literal, literal on the right */
4731 if (AOP_TYPE (left) == AOP_LIT)
4736 emitcode (";", "swapped left and right");
4739 /* (if two literals: the value is computed before) */
4740 /* if one literal, literal on the right */
4741 if (AOP_TYPE (left) == AOP_LIT)
4746 /* emitcode (";", "swapped left and right"); */
4748 /* if no literal, unsigned on the right: shorter code */
4749 if ( AOP_TYPE (right) != AOP_LIT
4750 && SPEC_USIGN (getSpec (operandType (left))))
4757 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4758 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4760 if ((lUnsigned && rUnsigned)
4761 /* sorry, I don't know how to get size
4762 without calling aopOp (result,...);
4763 see Feature Request */
4764 /* || size == 1 */ ) /* no, this is not a bug; with a 1 byte result there's
4765 no need to take care about the signedness! */
4767 /* just an unsigned 8 * 8 = 8 multiply
4769 /* emitcode (";","unsigned"); */
4770 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4771 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4772 emitcode ("mul", "ab");
4774 _G.accInUse++; _G.bInUse++;
4775 aopOp (result, ic, TRUE, FALSE);
4776 size = AOP_SIZE (result);
4778 if (size < 1 || size > 2)
4780 /* this should never happen */
4781 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4782 size, __FILE__, lineno);
4786 aopPut (AOP (result), "a", 0);
4787 _G.accInUse--; _G.bInUse--;
4789 aopPut (AOP (result), "b", 1);
4793 /* we have to do a signed multiply */
4794 /* emitcode (";", "signed"); */
4796 /* now sign adjust for both left & right */
4798 /* let's see what's needed: */
4799 /* apply negative sign during runtime */
4800 runtimeSign = FALSE;
4801 /* negative sign from literals */
4802 compiletimeSign = FALSE;
4806 if (AOP_TYPE(left) == AOP_LIT)
4808 /* signed literal */
4809 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4811 compiletimeSign = TRUE;
4814 /* signed but not literal */
4820 if (AOP_TYPE(right) == AOP_LIT)
4822 /* signed literal */
4823 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4825 compiletimeSign ^= TRUE;
4828 /* signed but not literal */
4832 /* initialize F0, which stores the runtime sign */
4835 if (compiletimeSign)
4836 emitcode ("setb", "F0"); /* set sign flag */
4838 emitcode ("clr", "F0"); /* reset sign flag */
4841 /* save the signs of the operands */
4842 if (AOP_TYPE(right) == AOP_LIT)
4844 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4846 if (!rUnsigned && val < 0)
4847 emitcode ("mov", "b,#!constbyte", -val);
4849 emitcode ("mov", "b,#!constbyte", (unsigned char) val);
4851 else /* ! literal */
4853 if (rUnsigned) /* emitcode (";", "signed"); */
4854 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4857 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4858 lbl = newiTempLabel (NULL);
4859 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
4860 emitcode ("cpl", "F0"); /* complement sign flag */
4861 emitcode ("cpl", "a"); /* 2's complement */
4862 emitcode ("inc", "a");
4863 emitcode ("", "!tlabeldef", lbl->key + 100);
4864 emitcode ("mov", "b,a");
4868 if (AOP_TYPE(left) == AOP_LIT)
4870 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4872 if (!lUnsigned && val < 0)
4873 emitcode ("mov", "a,#!constbyte", -val);
4875 emitcode ("mov", "a,#!constbyte", (unsigned char) val);
4877 else /* ! literal */
4879 if (lUnsigned) /* emitcode (";", "signed"); */
4881 emitcode ("mov", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4884 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4885 lbl = newiTempLabel (NULL);
4886 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
4887 emitcode ("cpl", "F0"); /* complement sign flag */
4888 emitcode ("cpl", "a"); /* 2's complement */
4889 emitcode ("inc", "a");
4890 emitcode ("", "!tlabeldef", lbl->key + 100);
4894 /* now the multiplication */
4895 emitcode ("mul", "ab");
4896 _G.accInUse++;_G.bInUse++;
4897 aopOp(result, ic, TRUE, FALSE);
4898 size = AOP_SIZE (result);
4900 if (size < 1 || size > 2)
4902 /* this should never happen */
4903 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4904 size, __FILE__, lineno);
4908 if (runtimeSign || compiletimeSign)
4910 lbl = newiTempLabel (NULL);
4912 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
4913 emitcode ("cpl", "a"); /* lsb 2's complement */
4915 emitcode ("inc", "a"); /* inc doesn't set carry flag */
4918 emitcode ("add", "a,#1"); /* this sets carry flag */
4919 emitcode ("xch", "a,b");
4920 emitcode ("cpl", "a"); /* msb 2's complement */
4921 emitcode ("addc", "a,#0");
4922 emitcode ("xch", "a,b");
4924 emitcode ("", "!tlabeldef", lbl->key + 100);
4926 aopPut (AOP (result), "a", 0);
4927 _G.accInUse--;_G.bInUse--;
4929 aopPut (AOP (result), "b", 1);
4932 /*-----------------------------------------------------------------*/
4933 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
4934 /*-----------------------------------------------------------------*/
4935 static void genMultTwoByte (operand *left, operand *right,
4936 operand *result, iCode *ic)
4938 sym_link *retype = getSpec(operandType(right));
4939 sym_link *letype = getSpec(operandType(left));
4940 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4943 if (AOP_TYPE (left) == AOP_LIT) {
4948 /* save EA bit in F1 */
4949 lbl = newiTempLabel(NULL);
4950 emitcode ("setb","F1");
4951 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4952 emitcode ("clr","F1");
4953 emitcode("","!tlabeldef",lbl->key+100);
4955 /* load up MB with right */
4957 emitcode("clr","F0");
4958 if (AOP_TYPE(right) == AOP_LIT) {
4959 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
4961 emitcode("setb","F0");
4964 emitcode ("mov","mb,#!constbyte",val & 0xff);
4965 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4967 lbl = newiTempLabel(NULL);
4968 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4969 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4970 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4971 emitcode ("xch", "a,b");
4972 emitcode ("cpl","a");
4973 emitcode ("add", "a,#1");
4974 emitcode ("xch", "a,b");
4975 emitcode ("cpl", "a"); // msb
4976 emitcode ("addc", "a,#0");
4977 emitcode ("setb","F0");
4978 emitcode ("","!tlabeldef",lbl->key+100);
4979 emitcode ("mov","mb,b");
4980 emitcode ("mov","mb,a");
4983 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4984 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4986 /* load up MA with left */
4988 lbl = newiTempLabel(NULL);
4989 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4990 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4991 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4992 emitcode ("xch", "a,b");
4993 emitcode ("cpl","a");
4994 emitcode ("add", "a,#1");
4995 emitcode ("xch", "a,b");
4996 emitcode ("cpl", "a"); // msb
4997 emitcode ("addc","a,#0");
4998 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4999 emitcode ("setb","F0");
5000 emitcode ("","!tlabeldef",lbl->key+100);
5001 emitcode ("mov","ma,b");
5002 emitcode ("mov","ma,a");
5004 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5005 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5007 /* wait for multiplication to finish */
5008 lbl = newiTempLabel(NULL);
5009 emitcode("","!tlabeldef", lbl->key+100);
5010 emitcode("mov","a,mcnt1");
5011 emitcode("anl","a,#!constbyte",0x80);
5012 emitcode("jnz","!tlabel",lbl->key+100);
5014 freeAsmop (left, NULL, ic, TRUE);
5015 freeAsmop (right, NULL, ic,TRUE);
5016 aopOp(result, ic, TRUE, FALSE);
5018 /* if unsigned then simple */
5020 emitcode ("mov","a,ma");
5021 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
5022 emitcode ("mov","a,ma");
5023 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
5024 aopPut(AOP(result),"ma",1);
5025 aopPut(AOP(result),"ma",0);
5027 emitcode("push","ma");
5028 emitcode("push","ma");
5029 emitcode("push","ma");
5031 /* negate result if needed */
5032 lbl = newiTempLabel(NULL);
5033 emitcode("jnb","F0,!tlabel",lbl->key+100);
5034 emitcode("cpl","a");
5035 emitcode("add","a,#1");
5036 emitcode("","!tlabeldef", lbl->key+100);
5037 if (AOP_TYPE(result) == AOP_ACC)
5039 D(emitcode(";", "ACC special case."););
5040 /* We know result is the only live aop, and
5041 * it's obviously not a DPTR2, so AP is available.
5043 emitcode("mov", "%s,acc", DP2_RESULT_REG);
5047 aopPut(AOP(result),"a",0);
5050 emitcode("pop","acc");
5051 lbl = newiTempLabel(NULL);
5052 emitcode("jnb","F0,!tlabel",lbl->key+100);
5053 emitcode("cpl","a");
5054 emitcode("addc","a,#0");
5055 emitcode("","!tlabeldef", lbl->key+100);
5056 aopPut(AOP(result),"a",1);
5057 emitcode("pop","acc");
5058 if (AOP_SIZE(result) >= 3) {
5059 lbl = newiTempLabel(NULL);
5060 emitcode("jnb","F0,!tlabel",lbl->key+100);
5061 emitcode("cpl","a");
5062 emitcode("addc","a,#0");
5063 emitcode("","!tlabeldef", lbl->key+100);
5064 aopPut(AOP(result),"a",2);
5066 emitcode("pop","acc");
5067 if (AOP_SIZE(result) >= 4) {
5068 lbl = newiTempLabel(NULL);
5069 emitcode("jnb","F0,!tlabel",lbl->key+100);
5070 emitcode("cpl","a");
5071 emitcode("addc","a,#0");
5072 emitcode("","!tlabeldef", lbl->key+100);
5073 aopPut(AOP(result),"a",3);
5075 if (AOP_TYPE(result) == AOP_ACC)
5077 /* We stashed the result away above. */
5078 emitcode("mov", "acc,%s", DP2_RESULT_REG);
5082 freeAsmop (result, NULL, ic, TRUE);
5084 /* restore EA bit in F1 */
5085 lbl = newiTempLabel(NULL);
5086 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5087 emitcode ("setb","EA");
5088 emitcode("","!tlabeldef",lbl->key+100);
5092 /*-----------------------------------------------------------------*/
5093 /* genMult - generates code for multiplication */
5094 /*-----------------------------------------------------------------*/
5096 genMult (iCode * ic)
5098 operand *left = IC_LEFT (ic);
5099 operand *right = IC_RIGHT (ic);
5100 operand *result = IC_RESULT (ic);
5102 D (emitcode (";", "genMult "););
5104 /* assign the amsops */
5107 /* special cases first */
5109 if (AOP_TYPE (left) == AOP_CRY &&
5110 AOP_TYPE (right) == AOP_CRY)
5112 genMultbits (left, right, result, ic);
5116 /* if both are of size == 1 */
5117 if (AOP_SIZE (left) == 1 &&
5118 AOP_SIZE (right) == 1)
5120 genMultOneByte (left, right, result, ic);
5124 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5125 /* use the ds390 ARITHMETIC accel UNIT */
5126 genMultTwoByte (left, right, result, ic);
5129 /* should have been converted to function call */
5133 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5134 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5135 freeAsmop (result, NULL, ic, TRUE);
5138 /*-----------------------------------------------------------------*/
5139 /* genDivbits :- division of bits */
5140 /*-----------------------------------------------------------------*/
5142 genDivbits (operand * left,
5150 /* the result must be bit */
5151 LOAD_AB_FOR_DIV (left, right, l);
5152 emitcode ("div", "ab");
5153 emitcode ("rrc", "a");
5154 aopOp(result, ic, TRUE, FALSE);
5156 aopPut (AOP (result), "c", 0);
5159 /*-----------------------------------------------------------------*/
5160 /* genDivOneByte : 8 bit division */
5161 /*-----------------------------------------------------------------*/
5163 genDivOneByte (operand * left,
5168 bool lUnsigned, rUnsigned;
5169 bool runtimeSign, compiletimeSign;
5175 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5176 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5178 /* signed or unsigned */
5179 if (lUnsigned && rUnsigned)
5181 /* unsigned is easy */
5182 LOAD_AB_FOR_DIV (left, right, l);
5183 emitcode ("div", "ab");
5186 aopOp (result, ic, TRUE, FALSE);
5187 aopPut (AOP (result), "a", 0);
5190 size = AOP_SIZE (result) - 1;
5193 aopPut (AOP (result), zero, offset++);
5197 /* signed is a little bit more difficult */
5199 /* now sign adjust for both left & right */
5201 /* let's see what's needed: */
5202 /* apply negative sign during runtime */
5203 runtimeSign = FALSE;
5204 /* negative sign from literals */
5205 compiletimeSign = FALSE;
5209 if (AOP_TYPE(left) == AOP_LIT)
5211 /* signed literal */
5212 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5214 compiletimeSign = TRUE;
5217 /* signed but not literal */
5223 if (AOP_TYPE(right) == AOP_LIT)
5225 /* signed literal */
5226 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5228 compiletimeSign ^= TRUE;
5231 /* signed but not literal */
5235 /* initialize F0, which stores the runtime sign */
5238 if (compiletimeSign)
5239 emitcode ("setb", "F0"); /* set sign flag */
5241 emitcode ("clr", "F0"); /* reset sign flag */
5244 /* save the signs of the operands */
5245 if (AOP_TYPE(right) == AOP_LIT)
5247 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5249 if (!rUnsigned && val < 0)
5250 emitcode ("mov", "b,#0x%02x", -val);
5252 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5254 else /* ! literal */
5257 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5260 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5261 lbl = newiTempLabel (NULL);
5262 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5263 emitcode ("cpl", "F0"); /* complement sign flag */
5264 emitcode ("cpl", "a"); /* 2's complement */
5265 emitcode ("inc", "a");
5266 emitcode ("", "!tlabeldef", lbl->key + 100);
5267 emitcode ("mov", "b,a");
5271 if (AOP_TYPE(left) == AOP_LIT)
5273 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5275 if (!lUnsigned && val < 0)
5276 emitcode ("mov", "a,#0x%02x", -val);
5278 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5280 else /* ! literal */
5283 emitcode ("mov", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5286 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5287 lbl = newiTempLabel (NULL);
5288 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5289 emitcode ("cpl", "F0"); /* complement sign flag */
5290 emitcode ("cpl", "a"); /* 2's complement */
5291 emitcode ("inc", "a");
5292 emitcode ("", "!tlabeldef", lbl->key + 100);
5296 /* now the division */
5297 emitcode ("nop", "; workaround for DS80C390 div bug.");
5298 emitcode ("div", "ab");
5300 if (runtimeSign || compiletimeSign)
5302 lbl = newiTempLabel (NULL);
5304 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5305 emitcode ("cpl", "a"); /* lsb 2's complement */
5306 emitcode ("inc", "a");
5307 emitcode ("", "!tlabeldef", lbl->key + 100);
5309 _G.accInUse++; _G.bInUse++;
5310 aopOp (result, ic, TRUE, FALSE);
5311 size = AOP_SIZE (result) - 1;
5315 /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
5316 then the result will be in b, a */
5317 emitcode ("mov", "b,a"); /* 1 */
5318 /* msb is 0x00 or 0xff depending on the sign */
5321 emitcode ("mov", "c,F0");
5322 emitcode ("subb", "a,acc");
5323 emitcode ("xch", "a,b"); /* 2 */
5325 aopPut (AOP (result), "b", offset++); /* write msb's */
5327 else /* compiletimeSign */
5329 aopPut (AOP (result), "#0xff", offset++); /* write msb's */
5331 aopPut (AOP (result), "a", 0); /* 3: write lsb */
5335 _G.accInUse++; _G.bInUse++;
5336 aopOp(result, ic, TRUE, FALSE);
5337 size = AOP_SIZE (result) - 1;
5339 aopPut (AOP (result), "a", 0);
5341 aopPut (AOP (result), zero, offset++);
5343 _G.accInUse--; _G.bInUse--;
5347 /*-----------------------------------------------------------------*/
5348 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
5349 /*-----------------------------------------------------------------*/
5350 static void genDivTwoByte (operand *left, operand *right,
5351 operand *result, iCode *ic)
5353 sym_link *retype = getSpec(operandType(right));
5354 sym_link *letype = getSpec(operandType(left));
5355 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5358 /* save EA bit in F1 */
5359 lbl = newiTempLabel(NULL);
5360 emitcode ("setb","F1");
5361 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5362 emitcode ("clr","F1");
5363 emitcode("","!tlabeldef",lbl->key+100);
5365 /* load up MA with left */
5367 emitcode("clr","F0");
5368 lbl = newiTempLabel(NULL);
5369 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5370 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5371 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5372 emitcode ("xch", "a,b");
5373 emitcode ("cpl","a");
5374 emitcode ("add", "a,#1");
5375 emitcode ("xch", "a,b");
5376 emitcode ("cpl", "a"); // msb
5377 emitcode ("addc","a,#0");
5378 emitcode ("setb","F0");
5379 emitcode ("","!tlabeldef",lbl->key+100);
5380 emitcode ("mov","ma,b");
5381 emitcode ("mov","ma,a");
5383 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5384 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5387 /* load up MB with right */
5389 if (AOP_TYPE(right) == AOP_LIT) {
5390 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5392 lbl = newiTempLabel(NULL);
5393 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5394 emitcode("setb","F0");
5395 emitcode ("","!tlabeldef",lbl->key+100);
5398 emitcode ("mov","mb,#!constbyte",val & 0xff);
5399 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5401 lbl = newiTempLabel(NULL);
5402 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5403 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5404 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5405 emitcode ("xch", "a,b");
5406 emitcode ("cpl","a");
5407 emitcode ("add", "a,#1");
5408 emitcode ("xch", "a,b");
5409 emitcode ("cpl", "a"); // msb
5410 emitcode ("addc", "a,#0");
5411 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5412 emitcode ("setb","F0");
5413 emitcode ("","!tlabeldef",lbl->key+100);
5414 emitcode ("mov","mb,b");
5415 emitcode ("mov","mb,a");
5418 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5419 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5422 /* wait for multiplication to finish */
5423 lbl = newiTempLabel(NULL);
5424 emitcode("","!tlabeldef", lbl->key+100);
5425 emitcode("mov","a,mcnt1");
5426 emitcode("anl","a,#!constbyte",0x80);
5427 emitcode("jnz","!tlabel",lbl->key+100);
5429 freeAsmop (left, NULL, ic, TRUE);
5430 freeAsmop (right, NULL, ic,TRUE);
5431 aopOp(result, ic, TRUE, FALSE);
5433 /* if unsigned then simple */
5435 aopPut(AOP(result),"ma",1);
5436 aopPut(AOP(result),"ma",0);
5438 emitcode("push","ma");
5440 /* negate result if needed */
5441 lbl = newiTempLabel(NULL);
5442 emitcode("jnb","F0,!tlabel",lbl->key+100);
5443 emitcode("cpl","a");
5444 emitcode("add","a,#1");
5445 emitcode("","!tlabeldef", lbl->key+100);
5446 aopPut(AOP(result),"a",0);
5447 emitcode("pop","acc");
5448 lbl = newiTempLabel(NULL);
5449 emitcode("jnb","F0,!tlabel",lbl->key+100);
5450 emitcode("cpl","a");
5451 emitcode("addc","a,#0");
5452 emitcode("","!tlabeldef", lbl->key+100);
5453 aopPut(AOP(result),"a",1);
5455 freeAsmop (result, NULL, ic, TRUE);
5456 /* restore EA bit in F1 */
5457 lbl = newiTempLabel(NULL);
5458 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5459 emitcode ("setb","EA");
5460 emitcode("","!tlabeldef",lbl->key+100);
5464 /*-----------------------------------------------------------------*/
5465 /* genDiv - generates code for division */
5466 /*-----------------------------------------------------------------*/
5470 operand *left = IC_LEFT (ic);
5471 operand *right = IC_RIGHT (ic);
5472 operand *result = IC_RESULT (ic);
5474 D (emitcode (";", "genDiv "););
5476 /* assign the amsops */
5479 /* special cases first */
5481 if (AOP_TYPE (left) == AOP_CRY &&
5482 AOP_TYPE (right) == AOP_CRY)
5484 genDivbits (left, right, result, ic);
5488 /* if both are of size == 1 */
5489 if (AOP_SIZE (left) == 1 &&
5490 AOP_SIZE (right) == 1)
5492 genDivOneByte (left, right, result, ic);
5496 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5497 /* use the ds390 ARITHMETIC accel UNIT */
5498 genDivTwoByte (left, right, result, ic);
5501 /* should have been converted to function call */
5504 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5505 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5506 freeAsmop (result, NULL, ic, TRUE);
5509 /*-----------------------------------------------------------------*/
5510 /* genModbits :- modulus of bits */
5511 /*-----------------------------------------------------------------*/
5513 genModbits (operand * left,
5521 /* the result must be bit */
5522 LOAD_AB_FOR_DIV (left, right, l);
5523 emitcode ("div", "ab");
5524 emitcode ("mov", "a,b");
5525 emitcode ("rrc", "a");
5526 aopOp(result, ic, TRUE, FALSE);
5527 aopPut (AOP (result), "c", 0);
5530 /*-----------------------------------------------------------------*/
5531 /* genModOneByte : 8 bit modulus */
5532 /*-----------------------------------------------------------------*/
5534 genModOneByte (operand * left,
5539 bool lUnsigned, rUnsigned;
5540 bool runtimeSign, compiletimeSign;
5546 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5547 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5549 /* signed or unsigned */
5550 if (lUnsigned && rUnsigned)
5552 /* unsigned is easy */
5553 LOAD_AB_FOR_DIV (left, right, l);
5554 emitcode ("div", "ab");
5555 aopOp (result, ic, TRUE, FALSE);
5556 aopPut (AOP (result), "b", 0);
5558 for (size = AOP_SIZE (result) - 1; size--;)
5559 aopPut (AOP (result), zero, offset++);
5563 /* signed is a little bit more difficult */
5565 /* now sign adjust for both left & right */
5567 /* modulus: sign of the right operand has no influence on the result! */
5568 if (AOP_TYPE(right) == AOP_LIT)
5570 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5572 if (!rUnsigned && val < 0)
5573 emitcode ("mov", "b,#0x%02x", -val);
5575 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5577 else /* ! literal */
5580 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5583 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5584 lbl = newiTempLabel (NULL);
5585 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5586 emitcode ("cpl", "a"); /* 2's complement */
5587 emitcode ("inc", "a");
5588 emitcode ("", "!tlabeldef", lbl->key + 100);
5589 emitcode ("mov", "b,a");
5593 /* let's see what's needed: */
5594 /* apply negative sign during runtime */
5595 runtimeSign = FALSE;
5596 /* negative sign from literals */
5597 compiletimeSign = FALSE;
5599 /* sign adjust left side */
5600 if (AOP_TYPE(left) == AOP_LIT)
5602 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5604 if (!lUnsigned && val < 0)
5606 compiletimeSign = TRUE; /* set sign flag */
5607 emitcode ("mov", "a,#0x%02x", -val);
5610 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5612 else /* ! literal */
5614 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5619 emitcode ("clr", "F0"); /* clear sign flag */
5621 lbl = newiTempLabel (NULL);
5622 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5623 emitcode ("setb", "F0"); /* set sign flag */
5624 emitcode ("cpl", "a"); /* 2's complement */
5625 emitcode ("inc", "a");
5626 emitcode ("", "!tlabeldef", lbl->key + 100);
5630 /* now the modulus */
5631 emitcode ("nop", "; workaround for DS80C390 div bug.");
5632 emitcode ("div", "ab");
5634 if (runtimeSign || compiletimeSign)
5636 emitcode ("mov", "a,b");
5637 lbl = newiTempLabel (NULL);
5639 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5640 emitcode ("cpl", "a"); /* lsb 2's complement */
5641 emitcode ("inc", "a");
5642 emitcode ("", "!tlabeldef", lbl->key + 100);
5644 _G.accInUse++; _G.bInUse++;
5645 aopOp (result, ic, TRUE, FALSE);
5646 size = AOP_SIZE (result) - 1;
5650 /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
5651 then the result will be in b, a */
5652 emitcode ("mov", "b,a"); /* 1 */
5653 /* msb is 0x00 or 0xff depending on the sign */
5656 emitcode ("mov", "c,F0");
5657 emitcode ("subb", "a,acc");
5658 emitcode ("xch", "a,b"); /* 2 */
5660 aopPut (AOP (result), "b", offset++); /* write msb's */
5662 else /* compiletimeSign */
5664 aopPut (AOP (result), "#0xff", offset++); /* write msb's */
5666 aopPut (AOP (result), "a", 0); /* 3: write lsb */
5670 _G.accInUse++; _G.bInUse++;
5671 aopOp(result, ic, TRUE, FALSE);
5672 size = AOP_SIZE (result) - 1;
5674 aopPut (AOP (result), "b", 0);
5676 aopPut (AOP (result), zero, offset++);
5678 _G.accInUse--; _G.bInUse--;
5682 /*-----------------------------------------------------------------*/
5683 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
5684 /*-----------------------------------------------------------------*/
5685 static void genModTwoByte (operand *left, operand *right,
5686 operand *result, iCode *ic)
5688 sym_link *retype = getSpec(operandType(right));
5689 sym_link *letype = getSpec(operandType(left));
5690 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5693 /* load up MA with left */
5694 /* save EA bit in F1 */
5695 lbl = newiTempLabel(NULL);
5696 emitcode ("setb","F1");
5697 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5698 emitcode ("clr","F1");
5699 emitcode("","!tlabeldef",lbl->key+100);
5702 lbl = newiTempLabel(NULL);
5703 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5704 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5705 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5706 emitcode ("xch", "a,b");
5707 emitcode ("cpl","a");
5708 emitcode ("add", "a,#1");
5709 emitcode ("xch", "a,b");
5710 emitcode ("cpl", "a"); // msb
5711 emitcode ("addc","a,#0");
5712 emitcode ("","!tlabeldef",lbl->key+100);
5713 emitcode ("mov","ma,b");
5714 emitcode ("mov","ma,a");
5716 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5717 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5720 /* load up MB with right */
5722 if (AOP_TYPE(right) == AOP_LIT) {
5723 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5727 emitcode ("mov","mb,#!constbyte",val & 0xff);
5728 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5730 lbl = newiTempLabel(NULL);
5731 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5732 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5733 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5734 emitcode ("xch", "a,b");
5735 emitcode ("cpl","a");
5736 emitcode ("add", "a,#1");
5737 emitcode ("xch", "a,b");
5738 emitcode ("cpl", "a"); // msb
5739 emitcode ("addc", "a,#0");
5740 emitcode ("","!tlabeldef",lbl->key+100);
5741 emitcode ("mov","mb,b");
5742 emitcode ("mov","mb,a");
5745 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5746 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5749 /* wait for multiplication to finish */
5750 lbl = newiTempLabel(NULL);
5751 emitcode("","!tlabeldef", lbl->key+100);
5752 emitcode("mov","a,mcnt1");
5753 emitcode("anl","a,#!constbyte",0x80);
5754 emitcode("jnz","!tlabel",lbl->key+100);
5756 freeAsmop (left, NULL, ic, TRUE);
5757 freeAsmop (right, NULL, ic,TRUE);
5758 aopOp(result, ic, TRUE, FALSE);
5760 aopPut(AOP(result),"mb",1);
5761 aopPut(AOP(result),"mb",0);
5762 freeAsmop (result, NULL, ic, TRUE);
5764 /* restore EA bit in F1 */
5765 lbl = newiTempLabel(NULL);
5766 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5767 emitcode ("setb","EA");
5768 emitcode("","!tlabeldef",lbl->key+100);
5772 /*-----------------------------------------------------------------*/
5773 /* genMod - generates code for division */
5774 /*-----------------------------------------------------------------*/
5778 operand *left = IC_LEFT (ic);
5779 operand *right = IC_RIGHT (ic);
5780 operand *result = IC_RESULT (ic);
5782 D (emitcode (";", "genMod "); );
5784 /* assign the amsops */
5787 /* special cases first */
5789 if (AOP_TYPE (left) == AOP_CRY &&
5790 AOP_TYPE (right) == AOP_CRY)
5792 genModbits (left, right, result, ic);
5796 /* if both are of size == 1 */
5797 if (AOP_SIZE (left) == 1 &&
5798 AOP_SIZE (right) == 1)
5800 genModOneByte (left, right, result, ic);
5804 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5805 /* use the ds390 ARITHMETIC accel UNIT */
5806 genModTwoByte (left, right, result, ic);
5810 /* should have been converted to function call */
5814 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5815 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5816 freeAsmop (result, NULL, ic, TRUE);
5819 /*-----------------------------------------------------------------*/
5820 /* genIfxJump :- will create a jump depending on the ifx */
5821 /*-----------------------------------------------------------------*/
5823 genIfxJump (iCode * ic, char *jval)
5826 symbol *tlbl = newiTempLabel (NULL);
5829 D (emitcode (";", "genIfxJump"););
5831 /* if true label then we jump if condition
5835 jlbl = IC_TRUE (ic);
5836 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5837 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5841 /* false label is present */
5842 jlbl = IC_FALSE (ic);
5843 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5844 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5846 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5847 emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5849 emitcode (inst, "!tlabel", tlbl->key + 100);
5850 emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5851 emitcode ("", "!tlabeldef", tlbl->key + 100);
5853 /* mark the icode as generated */
5857 /*-----------------------------------------------------------------*/
5858 /* genCmp :- greater or less than comparison */
5859 /*-----------------------------------------------------------------*/
5861 genCmp (operand * left, operand * right,
5862 iCode * ic, iCode * ifx, int sign)
5864 int size, offset = 0;
5865 unsigned long lit = 0L;
5868 D (emitcode (";", "genCmp"););
5870 result = IC_RESULT (ic);
5872 /* if left & right are bit variables */
5873 if (AOP_TYPE (left) == AOP_CRY &&
5874 AOP_TYPE (right) == AOP_CRY)
5876 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5877 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5881 /* subtract right from left if at the
5882 end the carry flag is set then we know that
5883 left is greater than right */
5884 size = max (AOP_SIZE (left), AOP_SIZE (right));
5886 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5887 if ((size == 1) && !sign
5888 && (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5890 symbol *lbl = newiTempLabel (NULL);
5891 emitcode ("cjne", "%s,%s,!tlabel",
5892 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
5893 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5895 emitcode ("", "!tlabeldef", lbl->key + 100);
5899 if (AOP_TYPE (right) == AOP_LIT)
5901 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5902 /* optimize if(x < 0) or if(x >= 0) */
5911 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
5913 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5914 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5916 aopOp (result, ic, FALSE, FALSE);
5918 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5920 freeAsmop (result, NULL, ic, TRUE);
5921 genIfxJump (ifx, "acc.7");
5926 emitcode ("rlc", "a");
5928 goto release_freedLR;
5936 // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5937 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5938 // emitcode (";", "genCmp #2");
5939 if (sign && (size == 0))
5941 // emitcode (";", "genCmp #3");
5942 emitcode ("xrl", "a,#!constbyte",0x80);
5943 if (AOP_TYPE (right) == AOP_LIT)
5945 unsigned long lit = (unsigned long)
5946 floatFromVal (AOP (right)->aopu.aop_lit);
5947 // emitcode (";", "genCmp #3.1");
5948 emitcode ("subb", "a,#!constbyte",
5949 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5953 // emitcode (";", "genCmp #3.2");
5955 MOVB(aopGet (AOP (right), offset++, FALSE, FALSE, "b"));
5956 saveAccWarn = DEFAULT_ACC_WARNING;
5957 emitcode ("xrl", "b,#!constbyte",0x80);
5958 emitcode ("subb", "a,b");
5965 // emitcode (";", "genCmp #4");
5967 s = aopGet (AOP (right), offset++, FALSE, FALSE, "b");
5968 saveAccWarn = DEFAULT_ACC_WARNING;
5970 emitcode ("subb", "a,%s", s);
5977 /* Don't need the left & right operands any more; do need the result. */
5978 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5979 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5981 aopOp (result, ic, FALSE, FALSE);
5985 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5991 /* if the result is used in the next
5992 ifx conditional branch then generate
5993 code a little differently */
5996 genIfxJump (ifx, "c");
6002 /* leave the result in acc */
6004 freeAsmop (result, NULL, ic, TRUE);
6007 /*-----------------------------------------------------------------*/
6008 /* genCmpGt :- greater than comparison */
6009 /*-----------------------------------------------------------------*/
6011 genCmpGt (iCode * ic, iCode * ifx)
6013 operand *left, *right;
6014 sym_link *letype, *retype;
6017 D (emitcode (";", "genCmpGt ");
6020 left = IC_LEFT (ic);
6021 right = IC_RIGHT (ic);
6023 letype = getSpec (operandType (left));
6024 retype = getSpec (operandType (right));
6025 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6027 /* assign the left & right amsops */
6030 genCmp (right, left, ic, ifx, sign);
6033 /*-----------------------------------------------------------------*/
6034 /* genCmpLt - less than comparisons */
6035 /*-----------------------------------------------------------------*/
6037 genCmpLt (iCode * ic, iCode * ifx)
6039 operand *left, *right;
6040 sym_link *letype, *retype;
6043 D (emitcode (";", "genCmpLt "););
6045 left = IC_LEFT (ic);
6046 right = IC_RIGHT (ic);
6048 letype = getSpec (operandType (left));
6049 retype = getSpec (operandType (right));
6050 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6052 /* assign the left & right amsops */
6055 genCmp (left, right, ic, ifx, sign);
6058 /*-----------------------------------------------------------------*/
6059 /* gencjneshort - compare and jump if not equal */
6060 /*-----------------------------------------------------------------*/
6062 gencjneshort (operand * left, operand * right, symbol * lbl)
6064 int size = max (AOP_SIZE (left), AOP_SIZE (right));
6066 unsigned long lit = 0L;
6068 D (emitcode (";", "gencjneshort");
6071 /* if the left side is a literal or
6072 if the right is in a pointer register and left
6074 if ((AOP_TYPE (left) == AOP_LIT) ||
6075 (AOP_TYPE (left) == AOP_IMMD) ||
6076 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6083 if (AOP_TYPE (right) == AOP_LIT)
6084 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6086 if (opIsGptr (left) || opIsGptr (right))
6088 /* We are comparing a generic pointer to something.
6089 * Exclude the generic type byte from the comparison.
6092 D (emitcode (";", "cjneshort: generic ptr special case."););
6096 /* if the right side is a literal then anything goes */
6097 if (AOP_TYPE (right) == AOP_LIT &&
6098 AOP_TYPE (left) != AOP_DIR)
6102 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6103 emitcode ("cjne", "a,%s,!tlabel",
6104 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
6110 /* if the right side is in a register or in direct space or
6111 if the left is a pointer register & right is not */
6112 else if (AOP_TYPE (right) == AOP_REG ||
6113 AOP_TYPE (right) == AOP_DIR ||
6114 AOP_TYPE (right) == AOP_LIT ||
6115 AOP_TYPE (right) == AOP_IMMD ||
6116 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6117 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6121 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6122 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6123 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6124 emitcode ("jnz", "!tlabel", lbl->key + 100);
6126 emitcode ("cjne", "a,%s,!tlabel",
6127 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
6134 /* right is a pointer reg need both a & b */
6137 MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6138 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6139 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
6145 /*-----------------------------------------------------------------*/
6146 /* gencjne - compare and jump if not equal */
6147 /*-----------------------------------------------------------------*/
6149 gencjne (operand * left, operand * right, symbol * lbl)
6151 symbol *tlbl = newiTempLabel (NULL);
6153 D (emitcode (";", "gencjne");
6156 gencjneshort (left, right, lbl);
6158 emitcode ("mov", "a,%s", one);
6159 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
6160 emitcode ("", "!tlabeldef", lbl->key + 100);
6161 emitcode ("clr", "a");
6162 emitcode ("", "!tlabeldef", tlbl->key + 100);
6165 /*-----------------------------------------------------------------*/
6166 /* genCmpEq - generates code for equal to */
6167 /*-----------------------------------------------------------------*/
6169 genCmpEq (iCode * ic, iCode * ifx)
6171 operand *left, *right, *result;
6173 D (emitcode (";", "genCmpEq ");
6177 AOP_SET_LOCALS (ic);
6179 /* if literal, literal on the right or
6180 if the right is in a pointer register and left
6182 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6183 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6185 operand *t = IC_RIGHT (ic);
6186 IC_RIGHT (ic) = IC_LEFT (ic);
6190 if (ifx && /* !AOP_SIZE(result) */
6191 OP_SYMBOL (result) &&
6192 OP_SYMBOL (result)->regType == REG_CND)
6195 /* if they are both bit variables */
6196 if (AOP_TYPE (left) == AOP_CRY &&
6197 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6199 if (AOP_TYPE (right) == AOP_LIT)
6201 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6204 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6205 emitcode ("cpl", "c");
6209 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6213 emitcode ("clr", "c");
6215 /* AOP_TYPE(right) == AOP_CRY */
6219 symbol *lbl = newiTempLabel (NULL);
6220 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6221 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6222 emitcode ("cpl", "c");
6223 emitcode ("", "!tlabeldef", (lbl->key + 100));
6225 /* if true label then we jump if condition
6227 tlbl = newiTempLabel (NULL);
6230 emitcode ("jnc", "!tlabel", tlbl->key + 100);
6231 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6235 emitcode ("jc", "!tlabel", tlbl->key + 100);
6236 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6238 emitcode ("", "!tlabeldef", tlbl->key + 100);
6242 tlbl = newiTempLabel (NULL);
6243 gencjneshort (left, right, tlbl);
6246 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6247 emitcode ("", "!tlabeldef", tlbl->key + 100);
6251 symbol *lbl = newiTempLabel (NULL);
6252 emitcode ("sjmp", "!tlabel", lbl->key + 100);
6253 emitcode ("", "!tlabeldef", tlbl->key + 100);
6254 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6255 emitcode ("", "!tlabeldef", lbl->key + 100);
6258 /* mark the icode as generated */
6261 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6262 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6266 /* if they are both bit variables */
6267 if (AOP_TYPE (left) == AOP_CRY &&
6268 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6270 if (AOP_TYPE (right) == AOP_LIT)
6272 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6275 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6276 emitcode ("cpl", "c");
6280 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6284 emitcode ("clr", "c");
6286 /* AOP_TYPE(right) == AOP_CRY */
6290 symbol *lbl = newiTempLabel (NULL);
6291 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6292 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6293 emitcode ("cpl", "c");
6294 emitcode ("", "!tlabeldef", (lbl->key + 100));
6297 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6298 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6300 aopOp (result, ic, TRUE, FALSE);
6303 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6310 genIfxJump (ifx, "c");
6313 /* if the result is used in an arithmetic operation
6314 then put the result in place */
6319 gencjne (left, right, newiTempLabel (NULL));
6321 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6322 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6324 aopOp (result, ic, TRUE, FALSE);
6326 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6328 aopPut (AOP (result), "a", 0);
6333 genIfxJump (ifx, "a");
6336 /* if the result is used in an arithmetic operation
6337 then put the result in place */
6338 if (AOP_TYPE (result) != AOP_CRY)
6340 /* leave the result in acc */
6344 freeAsmop (result, NULL, ic, TRUE);
6347 /*-----------------------------------------------------------------*/
6348 /* ifxForOp - returns the icode containing the ifx for operand */
6349 /*-----------------------------------------------------------------*/
6351 ifxForOp (operand * op, iCode * ic)
6353 /* if true symbol then needs to be assigned */
6354 if (IS_TRUE_SYMOP (op))
6357 /* if this has register type condition and
6358 the next instruction is ifx with the same operand
6359 and live to of the operand is upto the ifx only then */
6361 ic->next->op == IFX &&
6362 IC_COND (ic->next)->key == op->key &&
6363 OP_SYMBOL (op)->liveTo <= ic->next->seq)
6368 /*-----------------------------------------------------------------*/
6369 /* hasInc - operand is incremented before any other use */
6370 /*-----------------------------------------------------------------*/
6372 hasInc (operand *op, iCode *ic, int osize)
6374 sym_link *type = operandType(op);
6375 sym_link *retype = getSpec (type);
6376 iCode *lic = ic->next;
6379 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6380 if (!IS_SYMOP(op)) return NULL;
6382 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6383 if (IS_AGGREGATE(type->next)) return NULL;
6384 if (osize != (isize = getSize(type->next))) return NULL;
6387 /* if operand of the form op = op + <sizeof *op> */
6388 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6389 isOperandEqual(IC_RESULT(lic),op) &&
6390 isOperandLiteral(IC_RIGHT(lic)) &&
6391 operandLitValue(IC_RIGHT(lic)) == isize) {
6394 /* if the operand used or deffed */
6395 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
6398 /* if GOTO or IFX */
6399 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6405 /*-----------------------------------------------------------------*/
6406 /* genAndOp - for && operation */
6407 /*-----------------------------------------------------------------*/
6409 genAndOp (iCode * ic)
6411 operand *left, *right, *result;
6414 D (emitcode (";", "genAndOp "););
6416 /* note here that && operations that are in an
6417 if statement are taken away by backPatchLabels
6418 only those used in arthmetic operations remain */
6420 AOP_SET_LOCALS (ic);
6422 /* if both are bit variables */
6423 if (AOP_TYPE (left) == AOP_CRY &&
6424 AOP_TYPE (right) == AOP_CRY)
6426 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6427 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6428 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6429 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6431 aopOp (result,ic,FALSE, FALSE);
6436 tlbl = newiTempLabel (NULL);
6438 emitcode ("jz", "!tlabel", tlbl->key + 100);
6440 emitcode ("", "!tlabeldef", tlbl->key + 100);
6441 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6442 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6444 aopOp (result,ic,FALSE, FALSE);
6447 freeAsmop (result, NULL, ic, TRUE);
6451 /*-----------------------------------------------------------------*/
6452 /* genOrOp - for || operation */
6453 /*-----------------------------------------------------------------*/
6455 genOrOp (iCode * ic)
6457 operand *left, *right, *result;
6460 D (emitcode (";", "genOrOp "););
6462 /* note here that || operations that are in an
6463 if statement are taken away by backPatchLabels
6464 only those used in arthmetic operations remain */
6466 AOP_SET_LOCALS (ic);
6468 /* if both are bit variables */
6469 if (AOP_TYPE (left) == AOP_CRY &&
6470 AOP_TYPE (right) == AOP_CRY)
6472 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6473 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6474 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6475 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6477 aopOp (result,ic,FALSE, FALSE);
6483 tlbl = newiTempLabel (NULL);
6485 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6487 emitcode ("", "!tlabeldef", tlbl->key + 100);
6488 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6489 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6491 aopOp (result,ic,FALSE, FALSE);
6496 freeAsmop (result, NULL, ic, TRUE);
6499 /*-----------------------------------------------------------------*/
6500 /* isLiteralBit - test if lit == 2^n */
6501 /*-----------------------------------------------------------------*/
6503 isLiteralBit (unsigned long lit)
6505 unsigned long pw[32] =
6506 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6507 0x100L, 0x200L, 0x400L, 0x800L,
6508 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6509 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6510 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6511 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6512 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6515 for (idx = 0; idx < 32; idx++)
6521 /*-----------------------------------------------------------------*/
6522 /* continueIfTrue - */
6523 /*-----------------------------------------------------------------*/
6525 continueIfTrue (iCode * ic)
6528 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6532 /*-----------------------------------------------------------------*/
6534 /*-----------------------------------------------------------------*/
6536 jumpIfTrue (iCode * ic)
6539 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6543 /*-----------------------------------------------------------------*/
6544 /* jmpTrueOrFalse - */
6545 /*-----------------------------------------------------------------*/
6547 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6549 // ugly but optimized by peephole
6552 symbol *nlbl = newiTempLabel (NULL);
6553 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6554 emitcode ("", "!tlabeldef", tlbl->key + 100);
6555 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6556 emitcode ("", "!tlabeldef", nlbl->key + 100);
6560 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6561 emitcode ("", "!tlabeldef", tlbl->key + 100);
6566 // Generate code to perform a bit-wise logic operation
6567 // on two operands in far space (assumed to already have been
6568 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6569 // in far space. This requires pushing the result on the stack
6570 // then popping it into the result.
6572 genFarFarLogicOp(iCode *ic, char *logicOp)
6574 int size, resultSize, compSize;
6578 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6579 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
6580 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6582 _startLazyDPSEvaluation();
6583 for (size = compSize; (size--); offset++)
6585 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6586 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6587 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6589 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6590 emitcode ("push", "acc");
6592 _endLazyDPSEvaluation();
6594 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6595 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6596 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6598 resultSize = AOP_SIZE(IC_RESULT(ic));
6600 ADJUST_PUSHED_RESULT(compSize, resultSize);
6602 _startLazyDPSEvaluation();
6605 emitcode ("pop", "acc");
6606 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6608 _endLazyDPSEvaluation();
6609 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6613 /*-----------------------------------------------------------------*/
6614 /* genAnd - code for and */
6615 /*-----------------------------------------------------------------*/
6617 genAnd (iCode * ic, iCode * ifx)
6619 operand *left, *right, *result;
6620 int size, offset = 0;
6621 unsigned long lit = 0L;
6626 D (emitcode (";", "genAnd "););
6628 AOP_OP_3_NOFATAL (ic, pushResult);
6629 AOP_SET_LOCALS (ic);
6633 genFarFarLogicOp(ic, "anl");
6638 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6640 AOP_TYPE (left), AOP_TYPE (right));
6641 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6643 AOP_SIZE (left), AOP_SIZE (right));
6646 /* if left is a literal & right is not then exchange them */
6647 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6648 #ifdef LOGIC_OPS_BROKEN
6649 || AOP_NEEDSACC (left)
6653 operand *tmp = right;
6658 /* if result = right then exchange them */
6659 if (sameRegs (AOP (result), AOP (right)))
6661 operand *tmp = right;
6666 /* if right is bit then exchange them */
6667 if (AOP_TYPE (right) == AOP_CRY &&
6668 AOP_TYPE (left) != AOP_CRY)
6670 operand *tmp = right;
6674 if (AOP_TYPE (right) == AOP_LIT)
6675 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6677 size = AOP_SIZE (result);
6680 // result = bit & yy;
6681 if (AOP_TYPE (left) == AOP_CRY)
6683 // c = bit & literal;
6684 if (AOP_TYPE (right) == AOP_LIT)
6688 if (size && sameRegs (AOP (result), AOP (left)))
6691 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6696 if (size && (AOP_TYPE (result) == AOP_CRY))
6698 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6701 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6706 emitcode ("clr", "c");
6711 if (AOP_TYPE (right) == AOP_CRY)
6714 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6715 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6720 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6722 emitcode ("rrc", "a");
6723 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6731 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6732 genIfxJump (ifx, "c");
6736 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6737 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6738 if ((AOP_TYPE (right) == AOP_LIT) &&
6739 (AOP_TYPE (result) == AOP_CRY) &&
6740 (AOP_TYPE (left) != AOP_CRY))
6742 int posbit = isLiteralBit (lit);
6747 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6750 emitcode ("mov", "c,acc.%d", posbit & 0x07);
6756 SNPRINTF (buff, sizeof(buff),
6757 "acc.%d", posbit & 0x07);
6758 genIfxJump (ifx, buff);
6762 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6769 symbol *tlbl = newiTempLabel (NULL);
6770 int sizel = AOP_SIZE (left);
6772 emitcode ("setb", "c");
6775 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6777 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6779 if ((posbit = isLiteralBit (bytelit)) != 0)
6780 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6783 if (bytelit != 0x0FFL)
6784 emitcode ("anl", "a,%s",
6785 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6786 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6791 // bit = left & literal
6794 emitcode ("clr", "c");
6795 emitcode ("", "!tlabeldef", tlbl->key + 100);
6797 // if(left & literal)
6801 jmpTrueOrFalse (ifx, tlbl);
6803 emitcode ("", "!tlabeldef", tlbl->key + 100);
6811 /* if left is same as result */
6812 if (sameRegs (AOP (result), AOP (left)))
6814 for (; size--; offset++)
6816 if (AOP_TYPE (right) == AOP_LIT)
6818 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6820 else if (bytelit == 0)
6821 aopPut (AOP (result), zero, offset);
6822 else if (IS_AOP_PREG (result))
6824 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6825 emitcode ("anl", "a,%s",
6826 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6827 aopPut (AOP (result), "a", offset);
6830 emitcode ("anl", "%s,%s",
6831 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6832 aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6836 if (AOP_TYPE (left) == AOP_ACC)
6837 emitcode ("anl", "a,%s",
6838 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6841 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6842 if (IS_AOP_PREG (result))
6844 emitcode ("anl", "a,%s",
6845 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6846 aopPut (AOP (result), "a", offset);
6849 emitcode ("anl", "%s,a",
6850 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6857 // left & result in different registers
6858 if (AOP_TYPE (result) == AOP_CRY)
6861 // if(size), result in bit
6862 // if(!size && ifx), conditional oper: if(left & right)
6863 symbol *tlbl = newiTempLabel (NULL);
6864 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6866 emitcode ("setb", "c");
6869 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6870 emitcode ("anl", "a,%s",
6871 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6873 if (AOP_TYPE(left)==AOP_ACC) {
6874 emitcode("mov", "b,a");
6875 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6876 emitcode("anl", "a,b");
6878 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6879 emitcode ("anl", "a,%s",
6880 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6883 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6889 emitcode ("", "!tlabeldef", tlbl->key + 100);
6893 jmpTrueOrFalse (ifx, tlbl);
6895 emitcode ("", "!tlabeldef", tlbl->key + 100);
6899 for (; (size--); offset++)
6902 // result = left & right
6903 if (AOP_TYPE (right) == AOP_LIT)
6905 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6907 aopPut (AOP (result),
6908 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6912 else if (bytelit == 0)
6914 aopPut (AOP (result), zero, offset);
6917 D (emitcode (";", "better literal AND."););
6918 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6919 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6920 FALSE, FALSE, DP2_RESULT_REG));
6925 // faster than result <- left, anl result,right
6926 // and better if result is SFR
6927 if (AOP_TYPE (left) == AOP_ACC)
6929 emitcode ("anl", "a,%s",
6930 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6934 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6935 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6937 emitcode("mov", "b,a");
6941 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6942 emitcode ("anl", "a,%s", rOp);
6945 aopPut (AOP (result), "a", offset);
6951 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6952 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6953 freeAsmop (result, NULL, ic, TRUE);
6957 /*-----------------------------------------------------------------*/
6958 /* genOr - code for or */
6959 /*-----------------------------------------------------------------*/
6961 genOr (iCode * ic, iCode * ifx)
6963 operand *left, *right, *result;
6964 int size, offset = 0;
6965 unsigned long lit = 0L;
6968 D (emitcode (";", "genOr "););
6970 AOP_OP_3_NOFATAL (ic, pushResult);
6971 AOP_SET_LOCALS (ic);
6975 genFarFarLogicOp(ic, "orl");
6981 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6983 AOP_TYPE (left), AOP_TYPE (right));
6984 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6986 AOP_SIZE (left), AOP_SIZE (right));
6989 /* if left is a literal & right is not then exchange them */
6990 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6991 #ifdef LOGIC_OPS_BROKEN
6992 || AOP_NEEDSACC (left) // I think this is a net loss now.
6996 operand *tmp = right;
7001 /* if result = right then exchange them */
7002 if (sameRegs (AOP (result), AOP (right)))
7004 operand *tmp = right;
7009 /* if right is bit then exchange them */
7010 if (AOP_TYPE (right) == AOP_CRY &&
7011 AOP_TYPE (left) != AOP_CRY)
7013 operand *tmp = right;
7017 if (AOP_TYPE (right) == AOP_LIT)
7018 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7020 size = AOP_SIZE (result);
7024 if (AOP_TYPE (left) == AOP_CRY)
7026 if (AOP_TYPE (right) == AOP_LIT)
7028 // c = bit & literal;
7031 // lit != 0 => result = 1
7032 if (AOP_TYPE (result) == AOP_CRY)
7035 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7037 continueIfTrue (ifx);
7040 emitcode ("setb", "c");
7044 // lit == 0 => result = left
7045 if (size && sameRegs (AOP (result), AOP (left)))
7047 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7052 if (AOP_TYPE (right) == AOP_CRY)
7055 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7056 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7061 symbol *tlbl = newiTempLabel (NULL);
7062 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
7063 emitcode ("setb", "c");
7064 emitcode ("jb", "%s,!tlabel",
7065 AOP (left)->aopu.aop_dir, tlbl->key + 100);
7067 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7068 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7070 jmpTrueOrFalse (ifx, tlbl);
7076 emitcode ("", "!tlabeldef", tlbl->key + 100);
7085 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7086 genIfxJump (ifx, "c");
7090 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7091 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7092 if ((AOP_TYPE (right) == AOP_LIT) &&
7093 (AOP_TYPE (result) == AOP_CRY) &&
7094 (AOP_TYPE (left) != AOP_CRY))
7100 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7102 continueIfTrue (ifx);
7107 // lit = 0, result = boolean(left)
7109 emitcode ("setb", "c");
7113 symbol *tlbl = newiTempLabel (NULL);
7114 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7116 emitcode ("", "!tlabeldef", tlbl->key + 100);
7120 genIfxJump (ifx, "a");
7128 /* if left is same as result */
7129 if (sameRegs (AOP (result), AOP (left)))
7131 for (; size--; offset++)
7133 if (AOP_TYPE (right) == AOP_LIT)
7135 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7141 if (IS_AOP_PREG (left))
7143 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7144 emitcode ("orl", "a,%s",
7145 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7146 aopPut (AOP (result), "a", offset);
7150 emitcode ("orl", "%s,%s",
7151 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
7152 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7158 if (AOP_TYPE (left) == AOP_ACC)
7160 emitcode ("orl", "a,%s",
7161 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7165 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7166 if (IS_AOP_PREG (left))
7168 emitcode ("orl", "a,%s",
7169 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7170 aopPut (AOP (result), "a", offset);
7174 emitcode ("orl", "%s,a",
7175 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7183 // left & result in different registers
7184 if (AOP_TYPE (result) == AOP_CRY)
7187 // if(size), result in bit
7188 // if(!size && ifx), conditional oper: if(left | right)
7189 symbol *tlbl = newiTempLabel (NULL);
7190 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7192 emitcode ("setb", "c");
7195 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7196 emitcode ("orl", "a,%s",
7197 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7199 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7200 emitcode ("orl", "a,%s",
7201 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
7203 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7209 emitcode ("", "!tlabeldef", tlbl->key + 100);
7213 jmpTrueOrFalse (ifx, tlbl);
7215 emitcode ("", "!tlabeldef", tlbl->key + 100);
7219 _startLazyDPSEvaluation();
7220 for (; (size--); offset++)
7223 // result = left & right
7224 if (AOP_TYPE (right) == AOP_LIT)
7226 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7228 aopPut (AOP (result),
7229 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7233 D (emitcode (";", "better literal OR."););
7234 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7235 emitcode ("orl", "a, %s",
7236 aopGet (AOP (right), offset,
7237 FALSE, FALSE, DP2_RESULT_REG));
7242 // faster than result <- left, anl result,right
7243 // and better if result is SFR
7244 if (AOP_TYPE (left) == AOP_ACC)
7246 emitcode ("orl", "a,%s",
7247 aopGet (AOP (right), offset,
7248 FALSE, FALSE, DP2_RESULT_REG));
7252 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7254 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7256 emitcode("mov", "b,a");
7260 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7261 emitcode ("orl", "a,%s", rOp);
7264 aopPut (AOP (result), "a", offset);
7266 _endLazyDPSEvaluation();
7271 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7272 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7273 freeAsmop (result, NULL, ic, TRUE);
7276 /*-----------------------------------------------------------------*/
7277 /* genXor - code for xclusive or */
7278 /*-----------------------------------------------------------------*/
7280 genXor (iCode * ic, iCode * ifx)
7282 operand *left, *right, *result;
7283 int size, offset = 0;
7284 unsigned long lit = 0L;
7287 D (emitcode (";", "genXor "););
7289 AOP_OP_3_NOFATAL (ic, pushResult);
7290 AOP_SET_LOCALS (ic);
7294 genFarFarLogicOp(ic, "xrl");
7299 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7301 AOP_TYPE (left), AOP_TYPE (right));
7302 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7304 AOP_SIZE (left), AOP_SIZE (right));
7307 /* if left is a literal & right is not ||
7308 if left needs acc & right does not */
7309 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7310 #ifdef LOGIC_OPS_BROKEN
7311 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
7315 operand *tmp = right;
7320 /* if result = right then exchange them */
7321 if (sameRegs (AOP (result), AOP (right)))
7323 operand *tmp = right;
7328 /* if right is bit then exchange them */
7329 if (AOP_TYPE (right) == AOP_CRY &&
7330 AOP_TYPE (left) != AOP_CRY)
7332 operand *tmp = right;
7336 if (AOP_TYPE (right) == AOP_LIT)
7337 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7339 size = AOP_SIZE (result);
7343 if (AOP_TYPE (left) == AOP_CRY)
7345 if (AOP_TYPE (right) == AOP_LIT)
7347 // c = bit & literal;
7350 // lit>>1 != 0 => result = 1
7351 if (AOP_TYPE (result) == AOP_CRY)
7354 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7356 continueIfTrue (ifx);
7359 emitcode ("setb", "c");
7366 // lit == 0, result = left
7367 if (size && sameRegs (AOP (result), AOP (left)))
7369 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7373 // lit == 1, result = not(left)
7374 if (size && sameRegs (AOP (result), AOP (left)))
7376 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7381 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7382 emitcode ("cpl", "c");
7391 symbol *tlbl = newiTempLabel (NULL);
7392 if (AOP_TYPE (right) == AOP_CRY)
7395 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7399 int sizer = AOP_SIZE (right);
7401 // if val>>1 != 0, result = 1
7402 emitcode ("setb", "c");
7405 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
7407 // test the msb of the lsb
7408 emitcode ("anl", "a,#!constbyte",0xfe);
7409 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7413 emitcode ("rrc", "a");
7415 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7416 emitcode ("cpl", "c");
7417 emitcode ("", "!tlabeldef", (tlbl->key + 100));
7424 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7425 genIfxJump (ifx, "c");
7429 if (sameRegs (AOP (result), AOP (left)))
7431 /* if left is same as result */
7432 for (; size--; offset++)
7434 if (AOP_TYPE (right) == AOP_LIT)
7436 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7438 else if (IS_AOP_PREG (left))
7440 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7441 emitcode ("xrl", "a,%s",
7442 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7443 aopPut (AOP (result), "a", offset);
7446 emitcode ("xrl", "%s,%s",
7447 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
7448 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7452 if (AOP_TYPE (left) == AOP_ACC)
7453 emitcode ("xrl", "a,%s",
7454 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7457 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7458 if (IS_AOP_PREG (left))
7460 emitcode ("xrl", "a,%s",
7461 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7462 aopPut (AOP (result), "a", offset);
7465 emitcode ("xrl", "%s,a",
7466 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7473 // left & result in different registers
7474 if (AOP_TYPE (result) == AOP_CRY)
7477 // if(size), result in bit
7478 // if(!size && ifx), conditional oper: if(left ^ right)
7479 symbol *tlbl = newiTempLabel (NULL);
7480 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7483 emitcode ("setb", "c");
7486 if ((AOP_TYPE (right) == AOP_LIT) &&
7487 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7489 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7493 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7494 emitcode ("xrl", "a,%s",
7495 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7497 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7498 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7500 emitcode("mov", "b,a");
7504 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7505 emitcode ("xrl", "a,%s", rOp);
7508 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7514 emitcode ("", "!tlabeldef", tlbl->key + 100);
7518 jmpTrueOrFalse (ifx, tlbl);
7522 for (; (size--); offset++)
7525 // result = left & right
7526 if (AOP_TYPE (right) == AOP_LIT)
7528 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7530 aopPut (AOP (result),
7531 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7535 D (emitcode (";", "better literal XOR."););
7536 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7537 emitcode ("xrl", "a, %s",
7538 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7542 // faster than result <- left, anl result,right
7543 // and better if result is SFR
7544 if (AOP_TYPE (left) == AOP_ACC)
7546 emitcode ("xrl", "a,%s",
7547 aopGet (AOP (right), offset,
7548 FALSE, FALSE, DP2_RESULT_REG));
7552 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7553 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7555 emitcode("mov", "b,a");
7559 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7560 emitcode ("xrl", "a,%s", rOp);
7563 aopPut (AOP (result), "a", offset);
7570 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7571 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7572 freeAsmop (result, NULL, ic, TRUE);
7575 /*-----------------------------------------------------------------*/
7576 /* genInline - write the inline code out */
7577 /*-----------------------------------------------------------------*/
7579 genInline (iCode * ic)
7581 char *buffer, *bp, *bp1;
7583 D (emitcode (";", "genInline "); );
7585 _G.inLine += (!options.asmpeep);
7587 buffer = Safe_strdup(IC_INLINE(ic));
7591 /* emit each line as a code */
7616 /* emitcode("",buffer); */
7617 _G.inLine -= (!options.asmpeep);
7620 /*-----------------------------------------------------------------*/
7621 /* genRRC - rotate right with carry */
7622 /*-----------------------------------------------------------------*/
7626 operand *left, *result;
7629 D (emitcode (";", "genRRC "););
7631 /* rotate right with carry */
7632 left = IC_LEFT (ic);
7633 result = IC_RESULT (ic);
7634 aopOp (left, ic, FALSE, FALSE);
7635 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7637 /* move it to the result */
7638 size = AOP_SIZE (result);
7642 _startLazyDPSEvaluation ();
7645 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7646 emitcode ("rrc", "a");
7647 if (AOP_SIZE (result) > 1)
7648 aopPut (AOP (result), "a", offset--);
7650 _endLazyDPSEvaluation ();
7652 /* now we need to put the carry into the
7653 highest order byte of the result */
7654 if (AOP_SIZE (result) > 1)
7656 MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7658 emitcode ("mov", "acc.7,c");
7659 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7660 freeAsmop (left, NULL, ic, TRUE);
7661 freeAsmop (result, NULL, ic, TRUE);
7664 /*-----------------------------------------------------------------*/
7665 /* genRLC - generate code for rotate left with carry */
7666 /*-----------------------------------------------------------------*/
7670 operand *left, *result;
7674 D (emitcode (";", "genRLC "););
7676 /* rotate right with carry */
7677 left = IC_LEFT (ic);
7678 result = IC_RESULT (ic);
7679 aopOp (left, ic, FALSE, FALSE);
7680 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7682 /* move it to the result */
7683 size = AOP_SIZE (result);
7687 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7689 emitcode ("add", "a,acc");
7690 if (AOP_SIZE (result) > 1)
7692 aopPut (AOP (result), "a", offset++);
7695 _startLazyDPSEvaluation ();
7698 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7700 emitcode ("rlc", "a");
7701 if (AOP_SIZE (result) > 1)
7702 aopPut (AOP (result), "a", offset++);
7704 _endLazyDPSEvaluation ();
7706 /* now we need to put the carry into the
7707 highest order byte of the result */
7708 if (AOP_SIZE (result) > 1)
7710 l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7713 emitcode ("mov", "acc.0,c");
7714 aopPut (AOP (result), "a", 0);
7715 freeAsmop (left, NULL, ic, TRUE);
7716 freeAsmop (result, NULL, ic, TRUE);
7719 /*-----------------------------------------------------------------*/
7720 /* genGetHbit - generates code get highest order bit */
7721 /*-----------------------------------------------------------------*/
7723 genGetHbit (iCode * ic)
7725 operand *left, *result;
7726 left = IC_LEFT (ic);
7727 result = IC_RESULT (ic);
7728 aopOp (left, ic, FALSE, FALSE);
7729 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7731 D (emitcode (";", "genGetHbit "););
7733 /* get the highest order byte into a */
7734 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7735 if (AOP_TYPE (result) == AOP_CRY)
7737 emitcode ("rlc", "a");
7742 emitcode ("rl", "a");
7743 emitcode ("anl", "a,#1");
7748 freeAsmop (left, NULL, ic, TRUE);
7749 freeAsmop (result, NULL, ic, TRUE);
7752 /*-----------------------------------------------------------------*/
7753 /* genSwap - generates code to swap nibbles or bytes */
7754 /*-----------------------------------------------------------------*/
7756 genSwap (iCode * ic)
7758 operand *left, *result;
7760 D(emitcode ("; genSwap",""));
7762 left = IC_LEFT (ic);
7763 result = IC_RESULT (ic);
7764 aopOp (left, ic, FALSE, FALSE);
7765 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7767 _startLazyDPSEvaluation ();
7768 switch (AOP_SIZE (left))
7770 case 1: /* swap nibbles in byte */
7771 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7772 emitcode ("swap", "a");
7773 aopPut (AOP (result), "a", 0);
7775 case 2: /* swap bytes in word */
7776 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7778 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7779 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7780 aopPut (AOP (result), "a", 1);
7782 else if (operandsEqu (left, result))
7785 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7786 if (AOP_NEEDSACC (left) || AOP_NEEDSACC (result))
7788 emitcode ("mov", "b,a");
7792 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7793 aopPut (AOP (result), reg, 1);
7798 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7799 aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE, NULL), 1);
7803 wassertl(FALSE, "unsupported SWAP operand size");
7805 _endLazyDPSEvaluation ();
7807 freeAsmop (left, NULL, ic, TRUE);
7808 freeAsmop (result, NULL, ic, TRUE);
7811 /*-----------------------------------------------------------------*/
7812 /* AccRol - rotate left accumulator by known count */
7813 /*-----------------------------------------------------------------*/
7815 AccRol (int shCount)
7817 shCount &= 0x0007; // shCount : 0..7
7824 emitcode ("rl", "a");
7827 emitcode ("rl", "a");
7828 emitcode ("rl", "a");
7831 emitcode ("swap", "a");
7832 emitcode ("rr", "a");
7835 emitcode ("swap", "a");
7838 emitcode ("swap", "a");
7839 emitcode ("rl", "a");
7842 emitcode ("rr", "a");
7843 emitcode ("rr", "a");
7846 emitcode ("rr", "a");
7851 /*-----------------------------------------------------------------*/
7852 /* AccLsh - left shift accumulator by known count */
7853 /*-----------------------------------------------------------------*/
7855 AccLsh (int shCount)
7860 emitcode ("add", "a,acc");
7861 else if (shCount == 2)
7863 emitcode ("add", "a,acc");
7864 emitcode ("add", "a,acc");
7868 /* rotate left accumulator */
7870 /* and kill the lower order bits */
7871 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7876 /*-----------------------------------------------------------------*/
7877 /* AccRsh - right shift accumulator by known count */
7878 /*-----------------------------------------------------------------*/
7880 AccRsh (int shCount)
7887 emitcode ("rrc", "a");
7891 /* rotate right accumulator */
7892 AccRol (8 - shCount);
7893 /* and kill the higher order bits */
7894 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7899 #ifdef BETTER_LITERAL_SHIFT
7900 /*-----------------------------------------------------------------*/
7901 /* AccSRsh - signed right shift accumulator by known count */
7902 /*-----------------------------------------------------------------*/
7904 AccSRsh (int shCount)
7911 emitcode ("mov", "c,acc.7");
7912 emitcode ("rrc", "a");
7914 else if (shCount == 2)
7916 emitcode ("mov", "c,acc.7");
7917 emitcode ("rrc", "a");
7918 emitcode ("mov", "c,acc.7");
7919 emitcode ("rrc", "a");
7923 tlbl = newiTempLabel (NULL);
7924 /* rotate right accumulator */
7925 AccRol (8 - shCount);
7926 /* and kill the higher order bits */
7927 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7928 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7929 emitcode ("orl", "a,#!constbyte",
7930 (unsigned char) ~SRMask[shCount]);
7931 emitcode ("", "!tlabeldef", tlbl->key + 100);
7937 #ifdef BETTER_LITERAL_SHIFT
7938 /*-----------------------------------------------------------------*/
7939 /* shiftR1Left2Result - shift right one byte from left to result */
7940 /*-----------------------------------------------------------------*/
7942 shiftR1Left2Result (operand * left, int offl,
7943 operand * result, int offr,
7944 int shCount, int sign)
7946 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7947 /* shift right accumulator */
7952 aopPut (AOP (result), "a", offr);
7956 #ifdef BETTER_LITERAL_SHIFT
7957 /*-----------------------------------------------------------------*/
7958 /* shiftL1Left2Result - shift left one byte from left to result */
7959 /*-----------------------------------------------------------------*/
7961 shiftL1Left2Result (operand * left, int offl,
7962 operand * result, int offr, int shCount)
7964 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7965 /* shift left accumulator */
7967 aopPut (AOP (result), "a", offr);
7971 #ifdef BETTER_LITERAL_SHIFT
7972 /*-----------------------------------------------------------------*/
7973 /* movLeft2Result - move byte from left to result */
7974 /*-----------------------------------------------------------------*/
7976 movLeft2Result (operand * left, int offl,
7977 operand * result, int offr, int sign)
7980 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7982 l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
7984 if (*l == '@' && (IS_AOP_PREG (result)))
7986 emitcode ("mov", "a,%s", l);
7987 aopPut (AOP (result), "a", offr);
7993 aopPut (AOP (result), l, offr);
7997 /* MSB sign in acc.7 ! */
7998 if (getDataSize (left) == offl + 1)
8000 emitcode ("mov", "a,%s", l);
8001 aopPut (AOP (result), "a", offr);
8009 #ifdef BETTER_LITERAL_SHIFT
8010 /*-----------------------------------------------------------------*/
8011 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
8012 /*-----------------------------------------------------------------*/
8016 emitcode ("rrc", "a");
8017 emitcode ("xch", "a,%s", x);
8018 emitcode ("rrc", "a");
8019 emitcode ("xch", "a,%s", x);
8023 #ifdef BETTER_LITERAL_SHIFT
8025 /*-----------------------------------------------------------------*/
8026 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
8027 /*-----------------------------------------------------------------*/
8031 emitcode ("xch", "a,%s", x);
8032 emitcode ("rlc", "a");
8033 emitcode ("xch", "a,%s", x);
8034 emitcode ("rlc", "a");
8038 #ifdef BETTER_LITERAL_SHIFT
8039 /*-----------------------------------------------------------------*/
8040 /* AccAXLsh1 - left shift a:x<-0 by 1 */
8041 /*-----------------------------------------------------------------*/
8045 emitcode ("xch", "a,%s", x);
8046 emitcode ("add", "a,acc");
8047 emitcode ("xch", "a,%s", x);
8048 emitcode ("rlc", "a");
8052 #ifdef BETTER_LITERAL_SHIFT
8053 /*-----------------------------------------------------------------*/
8054 /* AccAXLsh - left shift a:x by known count (0..7) */
8055 /*-----------------------------------------------------------------*/
8057 AccAXLsh (char *x, int shCount)
8072 case 5: // AAAAABBB:CCCCCDDD
8074 AccRol (shCount); // BBBAAAAA:CCCCCDDD
8076 emitcode ("anl", "a,#!constbyte",
8077 SLMask[shCount]); // BBB00000:CCCCCDDD
8079 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
8081 AccRol (shCount); // DDDCCCCC:BBB00000
8083 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8085 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8087 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8089 emitcode ("anl", "a,#!constbyte",
8090 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8092 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8094 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8097 case 6: // AAAAAABB:CCCCCCDD
8098 emitcode ("anl", "a,#!constbyte",
8099 SRMask[shCount]); // 000000BB:CCCCCCDD
8100 emitcode ("mov", "c,acc.0"); // c = B
8101 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8103 AccAXRrl1 (x); // BCCCCCCD:D000000B
8104 AccAXRrl1 (x); // BBCCCCCC:DD000000
8106 emitcode("rrc","a");
8107 emitcode("xch","a,%s", x);
8108 emitcode("rrc","a");
8109 emitcode("mov","c,acc.0"); //<< get correct bit
8110 emitcode("xch","a,%s", x);
8112 emitcode("rrc","a");
8113 emitcode("xch","a,%s", x);
8114 emitcode("rrc","a");
8115 emitcode("xch","a,%s", x);
8118 case 7: // a:x <<= 7
8120 emitcode ("anl", "a,#!constbyte",
8121 SRMask[shCount]); // 0000000B:CCCCCCCD
8123 emitcode ("mov", "c,acc.0"); // c = B
8125 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
8127 AccAXRrl1 (x); // BCCCCCCC:D0000000
8136 #ifdef BETTER_LITERAL_SHIFT
8138 /*-----------------------------------------------------------------*/
8139 /* AccAXRsh - right shift a:x known count (0..7) */
8140 /*-----------------------------------------------------------------*/
8142 AccAXRsh (char *x, int shCount)
8150 AccAXRrl1 (x); // 0->a:x
8155 AccAXRrl1 (x); // 0->a:x
8158 AccAXRrl1 (x); // 0->a:x
8163 case 5: // AAAAABBB:CCCCCDDD = a:x
8165 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8167 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8169 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8171 emitcode ("anl", "a,#!constbyte",
8172 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8174 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8176 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8178 emitcode ("anl", "a,#!constbyte",
8179 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8181 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8183 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8185 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8188 case 6: // AABBBBBB:CCDDDDDD
8190 emitcode ("mov", "c,acc.7");
8191 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8193 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8195 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8197 emitcode ("anl", "a,#!constbyte",
8198 SRMask[shCount]); // 000000AA:BBBBBBCC
8201 case 7: // ABBBBBBB:CDDDDDDD
8203 emitcode ("mov", "c,acc.7"); // c = A
8205 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8207 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8209 emitcode ("anl", "a,#!constbyte",
8210 SRMask[shCount]); // 0000000A:BBBBBBBC
8219 #ifdef BETTER_LITERAL_SHIFT
8220 /*-----------------------------------------------------------------*/
8221 /* AccAXRshS - right shift signed a:x known count (0..7) */
8222 /*-----------------------------------------------------------------*/
8224 AccAXRshS (char *x, int shCount)
8232 emitcode ("mov", "c,acc.7");
8233 AccAXRrl1 (x); // s->a:x
8237 emitcode ("mov", "c,acc.7");
8238 AccAXRrl1 (x); // s->a:x
8240 emitcode ("mov", "c,acc.7");
8241 AccAXRrl1 (x); // s->a:x
8246 case 5: // AAAAABBB:CCCCCDDD = a:x
8248 tlbl = newiTempLabel (NULL);
8249 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8251 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8253 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8255 emitcode ("anl", "a,#!constbyte",
8256 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8258 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8260 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8262 emitcode ("anl", "a,#!constbyte",
8263 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8265 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8267 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8269 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
8271 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8272 emitcode ("orl", "a,#!constbyte",
8273 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
8275 emitcode ("", "!tlabeldef", tlbl->key + 100);
8276 break; // SSSSAAAA:BBBCCCCC
8278 case 6: // AABBBBBB:CCDDDDDD
8280 tlbl = newiTempLabel (NULL);
8281 emitcode ("mov", "c,acc.7");
8282 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8284 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8286 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8288 emitcode ("anl", "a,#!constbyte",
8289 SRMask[shCount]); // 000000AA:BBBBBBCC
8291 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8292 emitcode ("orl", "a,#!constbyte",
8293 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
8295 emitcode ("", "!tlabeldef", tlbl->key + 100);
8297 case 7: // ABBBBBBB:CDDDDDDD
8299 tlbl = newiTempLabel (NULL);
8300 emitcode ("mov", "c,acc.7"); // c = A
8302 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8304 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8306 emitcode ("anl", "a,#!constbyte",
8307 SRMask[shCount]); // 0000000A:BBBBBBBC
8309 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8310 emitcode ("orl", "a,#!constbyte",
8311 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
8313 emitcode ("", "!tlabeldef", tlbl->key + 100);
8321 #ifdef BETTER_LITERAL_SHIFT
8323 _loadLeftIntoAx(char **lsb,
8329 // Get the initial value from left into a pair of registers.
8330 // MSB must be in A, LSB can be any register.
8332 // If the result is held in registers, it is an optimization
8333 // if the LSB can be held in the register which will hold the,
8334 // result LSB since this saves us from having to copy it into
8335 // the result following AccAXLsh.
8337 // If the result is addressed indirectly, this is not a gain.
8338 if (AOP_NEEDSACC(result))
8342 _startLazyDPSEvaluation();
8343 if (AOP_TYPE(left) == AOP_DPTR2)
8346 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
8347 // get LSB in DP2_RESULT_REG.
8348 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
8349 assert(!strcmp(leftByte, DP2_RESULT_REG));
8353 // get LSB into DP2_RESULT_REG
8354 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
8355 if (strcmp(leftByte, DP2_RESULT_REG))
8358 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
8361 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
8362 assert(strcmp(leftByte, DP2_RESULT_REG));
8365 _endLazyDPSEvaluation();
8366 *lsb = DP2_RESULT_REG;
8370 if (sameRegs (AOP (result), AOP (left)) &&
8371 ((offl + MSB16) == offr))
8373 /* don't crash result[offr] */
8374 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
8375 emitcode ("xch", "a,%s",
8376 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
8380 movLeft2Result (left, offl, result, offr, 0);
8381 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
8383 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
8384 assert(strcmp(*lsb,"a"));
8389 _storeAxResults(char *lsb,
8393 _startLazyDPSEvaluation();
8394 if (AOP_NEEDSACC(result))
8396 /* We have to explicitly update the result LSB.
8398 emitcode("xch","a,%s", lsb);
8399 aopPut(AOP(result), "a", offr);
8400 emitcode("mov","a,%s", lsb);
8402 if (getDataSize (result) > 1)
8404 aopPut (AOP (result), "a", offr + MSB16);
8406 _endLazyDPSEvaluation();
8409 /*-----------------------------------------------------------------*/
8410 /* shiftL2Left2Result - shift left two bytes from left to result */
8411 /*-----------------------------------------------------------------*/
8413 shiftL2Left2Result (operand * left, int offl,
8414 operand * result, int offr, int shCount)
8418 _loadLeftIntoAx(&lsb, left, result, offl, offr);
8420 AccAXLsh (lsb, shCount);
8422 _storeAxResults(lsb, result, offr);
8426 #ifdef BETTER_LITERAL_SHIFT
8427 /*-----------------------------------------------------------------*/
8428 /* shiftR2Left2Result - shift right two bytes from left to result */
8429 /*-----------------------------------------------------------------*/
8431 shiftR2Left2Result (operand * left, int offl,
8432 operand * result, int offr,
8433 int shCount, int sign)
8437 _loadLeftIntoAx(&lsb, left, result, offl, offr);
8439 /* a:x >> shCount (x = lsb(result)) */
8442 AccAXRshS(lsb, shCount);
8446 AccAXRsh(lsb, shCount);
8449 _storeAxResults(lsb, result, offr);
8453 /*-----------------------------------------------------------------*/
8454 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8455 /*-----------------------------------------------------------------*/
8457 shiftLLeftOrResult (operand * left, int offl,
8458 operand * result, int offr, int shCount)
8460 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8461 /* shift left accumulator */
8463 /* or with result */
8464 emitcode ("orl", "a,%s",
8465 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8466 /* back to result */
8467 aopPut (AOP (result), "a", offr);
8472 /*-----------------------------------------------------------------*/
8473 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8474 /*-----------------------------------------------------------------*/
8476 shiftRLeftOrResult (operand * left, int offl,
8477 operand * result, int offr, int shCount)
8479 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8480 /* shift right accumulator */
8482 /* or with result */
8483 emitcode ("orl", "a,%s",
8484 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8485 /* back to result */
8486 aopPut (AOP (result), "a", offr);
8490 #ifdef BETTER_LITERAL_SHIFT
8491 /*-----------------------------------------------------------------*/
8492 /* genlshOne - left shift a one byte quantity by known count */
8493 /*-----------------------------------------------------------------*/
8495 genlshOne (operand * result, operand * left, int shCount)
8497 D (emitcode (";", "genlshOne "););
8498 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8502 #ifdef BETTER_LITERAL_SHIFT
8503 /*-----------------------------------------------------------------*/
8504 /* genlshTwo - left shift two bytes by known amount != 0 */
8505 /*-----------------------------------------------------------------*/
8507 genlshTwo (operand * result, operand * left, int shCount)
8511 D (emitcode (";", "genlshTwo "););
8513 size = getDataSize (result);
8515 /* if shCount >= 8 */
8520 _startLazyDPSEvaluation();
8526 _endLazyDPSEvaluation();
8527 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8528 aopPut (AOP (result), zero, LSB);
8532 movLeft2Result (left, LSB, result, MSB16, 0);
8533 aopPut (AOP (result), zero, LSB);
8534 _endLazyDPSEvaluation();
8539 aopPut (AOP (result), zero, LSB);
8540 _endLazyDPSEvaluation();
8544 /* 1 <= shCount <= 7 */
8549 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8553 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8561 /*-----------------------------------------------------------------*/
8562 /* shiftLLong - shift left one long from left to result */
8563 /* offl = LSB or MSB16 */
8564 /*-----------------------------------------------------------------*/
8566 shiftLLong (operand * left, operand * result, int offr)
8569 int size = AOP_SIZE (result);
8571 if (size >= LSB + offr)
8573 l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8575 emitcode ("add", "a,acc");
8576 if (sameRegs (AOP (left), AOP (result)) &&
8577 size >= MSB16 + offr && offr != LSB)
8578 emitcode ("xch", "a,%s",
8579 aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8581 aopPut (AOP (result), "a", LSB + offr);
8584 if (size >= MSB16 + offr)
8586 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8588 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8590 emitcode ("rlc", "a");
8591 if (sameRegs (AOP (left), AOP (result)) &&
8592 size >= MSB24 + offr && offr != LSB)
8593 emitcode ("xch", "a,%s",
8594 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8596 aopPut (AOP (result), "a", MSB16 + offr);
8599 if (size >= MSB24 + offr)
8601 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8603 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8605 emitcode ("rlc", "a");
8606 if (sameRegs (AOP (left), AOP (result)) &&
8607 size >= MSB32 + offr && offr != LSB)
8608 emitcode ("xch", "a,%s",
8609 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8611 aopPut (AOP (result), "a", MSB24 + offr);
8614 if (size > MSB32 + offr)
8616 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8618 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8620 emitcode ("rlc", "a");
8621 aopPut (AOP (result), "a", MSB32 + offr);
8624 aopPut (AOP (result), zero, LSB);
8630 /*-----------------------------------------------------------------*/
8631 /* genlshFour - shift four byte by a known amount != 0 */
8632 /*-----------------------------------------------------------------*/
8634 genlshFour (operand * result, operand * left, int shCount)
8638 D (emitcode (";", "genlshFour ");
8641 size = AOP_SIZE (result);
8643 /* if shifting more that 3 bytes */
8648 /* lowest order of left goes to the highest
8649 order of the destination */
8650 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8652 movLeft2Result (left, LSB, result, MSB32, 0);
8653 aopPut (AOP (result), zero, LSB);
8654 aopPut (AOP (result), zero, MSB16);
8655 aopPut (AOP (result), zero, MSB24);
8659 /* more than two bytes */
8660 else if (shCount >= 16)
8662 /* lower order two bytes goes to higher order two bytes */
8664 /* if some more remaining */
8666 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8669 movLeft2Result (left, MSB16, result, MSB32, 0);
8670 movLeft2Result (left, LSB, result, MSB24, 0);
8672 aopPut (AOP (result), zero, MSB16);
8673 aopPut (AOP (result), zero, LSB);
8677 /* if more than 1 byte */
8678 else if (shCount >= 8)
8680 /* lower order three bytes goes to higher order three bytes */
8685 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8687 movLeft2Result (left, LSB, result, MSB16, 0);
8693 movLeft2Result (left, MSB24, result, MSB32, 0);
8694 movLeft2Result (left, MSB16, result, MSB24, 0);
8695 movLeft2Result (left, LSB, result, MSB16, 0);
8696 aopPut (AOP (result), zero, LSB);
8698 else if (shCount == 1)
8699 shiftLLong (left, result, MSB16);
8702 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8703 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8704 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8705 aopPut (AOP (result), zero, LSB);
8710 /* 1 <= shCount <= 7 */
8711 else if (shCount <= 2)
8713 shiftLLong (left, result, LSB);
8715 shiftLLong (result, result, LSB);
8717 /* 3 <= shCount <= 7, optimize */
8720 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8721 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8722 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8727 #ifdef BETTER_LITERAL_SHIFT
8728 /*-----------------------------------------------------------------*/
8729 /* genLeftShiftLiteral - left shifting by known count */
8730 /*-----------------------------------------------------------------*/
8732 genLeftShiftLiteral (operand * left,
8737 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8740 size = getSize (operandType (result));
8742 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8744 /* We only handle certain easy cases so far. */
8746 && (shCount < (size * 8))
8750 D(emitcode (";", "genLeftShiftLiteral wimping out"););
8754 freeAsmop (right, NULL, ic, TRUE);
8756 aopOp(left, ic, FALSE, FALSE);
8757 aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8760 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8762 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8763 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8765 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8768 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8770 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8771 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8773 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8779 emitcode ("; shift left ", "result %d, left %d", size,
8783 /* I suppose that the left size >= result size */
8786 _startLazyDPSEvaluation();
8789 movLeft2Result (left, size, result, size, 0);
8791 _endLazyDPSEvaluation();
8793 else if (shCount >= (size * 8))
8795 _startLazyDPSEvaluation();
8798 aopPut (AOP (result), zero, size);
8800 _endLazyDPSEvaluation();
8807 genlshOne (result, left, shCount);
8811 genlshTwo (result, left, shCount);
8815 genlshFour (result, left, shCount);
8819 fprintf(stderr, "*** ack! mystery literal shift!\n");
8823 freeAsmop (left, NULL, ic, TRUE);
8824 freeAsmop (result, NULL, ic, TRUE);
8829 /*-----------------------------------------------------------------*/
8830 /* genLeftShift - generates code for left shifting */
8831 /*-----------------------------------------------------------------*/
8833 genLeftShift (iCode * ic)
8835 operand *left, *right, *result;
8838 symbol *tlbl, *tlbl1;
8840 D (emitcode (";", "genLeftShift "););
8842 right = IC_RIGHT (ic);
8843 left = IC_LEFT (ic);
8844 result = IC_RESULT (ic);
8846 aopOp (right, ic, FALSE, FALSE);
8849 #ifdef BETTER_LITERAL_SHIFT
8850 /* if the shift count is known then do it
8851 as efficiently as possible */
8852 if (AOP_TYPE (right) == AOP_LIT)
8854 if (genLeftShiftLiteral (left, right, result, ic))
8861 /* shift count is unknown then we have to form
8862 a loop get the loop count in B : Note: we take
8863 only the lower order byte since shifting
8864 more that 32 bits make no sense anyway, ( the
8865 largest size of an object can be only 32 bits ) */
8867 if (AOP_TYPE (right) == AOP_LIT)
8869 /* Really should be handled by genLeftShiftLiteral,
8870 * but since I'm too lazy to fix that today, at least we can make
8871 * some small improvement.
8873 emitcode("mov", "b,#!constbyte",
8874 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8878 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8879 emitcode ("inc", "b");
8881 freeAsmop (right, NULL, ic, TRUE);
8882 aopOp (left, ic, FALSE, FALSE);
8883 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8885 /* now move the left to the result if they are not the
8887 if (!sameRegs (AOP (left), AOP (result)) &&
8888 AOP_SIZE (result) > 1)
8891 size = AOP_SIZE (result);
8893 _startLazyDPSEvaluation ();
8896 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8897 if (*l == '@' && (IS_AOP_PREG (result)))
8900 emitcode ("mov", "a,%s", l);
8901 aopPut (AOP (result), "a", offset);
8904 aopPut (AOP (result), l, offset);
8907 _endLazyDPSEvaluation ();
8910 tlbl = newiTempLabel (NULL);
8911 size = AOP_SIZE (result);
8913 tlbl1 = newiTempLabel (NULL);
8915 /* if it is only one byte then */
8918 symbol *tlbl1 = newiTempLabel (NULL);
8920 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8921 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8922 emitcode ("", "!tlabeldef", tlbl->key + 100);
8923 emitcode ("add", "a,acc");
8924 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8925 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8926 aopPut (AOP (result), "a", 0);
8930 reAdjustPreg (AOP (result));
8932 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8933 emitcode ("", "!tlabeldef", tlbl->key + 100);
8934 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8935 emitcode ("add", "a,acc");
8936 aopPut (AOP (result), "a", offset++);
8937 _startLazyDPSEvaluation ();
8940 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8941 emitcode ("rlc", "a");
8942 aopPut (AOP (result), "a", offset++);
8944 _endLazyDPSEvaluation ();
8945 reAdjustPreg (AOP (result));
8947 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8948 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8950 freeAsmop (left, NULL, ic, TRUE);
8951 freeAsmop (result, NULL, ic, TRUE);
8954 #ifdef BETTER_LITERAL_SHIFT
8955 /*-----------------------------------------------------------------*/
8956 /* genrshOne - right shift a one byte quantity by known count */
8957 /*-----------------------------------------------------------------*/
8959 genrshOne (operand * result, operand * left,
8960 int shCount, int sign)
8962 D (emitcode (";", "genrshOne"););
8963 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8967 #ifdef BETTER_LITERAL_SHIFT
8968 /*-----------------------------------------------------------------*/
8969 /* genrshTwo - right shift two bytes by known amount != 0 */
8970 /*-----------------------------------------------------------------*/
8972 genrshTwo (operand * result, operand * left,
8973 int shCount, int sign)
8975 D (emitcode (";", "genrshTwo"););
8977 /* if shCount >= 8 */
8981 _startLazyDPSEvaluation();
8984 shiftR1Left2Result (left, MSB16, result, LSB,
8989 movLeft2Result (left, MSB16, result, LSB, sign);
8991 addSign (result, MSB16, sign);
8992 _endLazyDPSEvaluation();
8995 /* 1 <= shCount <= 7 */
8998 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9003 /*-----------------------------------------------------------------*/
9004 /* shiftRLong - shift right one long from left to result */
9005 /* offl = LSB or MSB16 */
9006 /*-----------------------------------------------------------------*/
9008 shiftRLong (operand * left, int offl,
9009 operand * result, int sign)
9011 int isSameRegs=sameRegs(AOP(left),AOP(result));
9013 if (isSameRegs && offl>1) {
9014 // we are in big trouble, but this shouldn't happen
9015 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9018 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
9023 emitcode ("rlc", "a");
9024 emitcode ("subb", "a,acc");
9025 emitcode ("xch", "a,%s",
9026 aopGet(AOP(left), MSB32, FALSE, FALSE, DP2_RESULT_REG));
9028 aopPut (AOP(result), zero, MSB32);
9033 emitcode ("clr", "c");
9035 emitcode ("mov", "c,acc.7");
9038 emitcode ("rrc", "a");
9040 if (isSameRegs && offl==MSB16) {
9042 "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE, DP2_RESULT_REG));
9044 aopPut (AOP (result), "a", MSB32);
9045 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
9048 emitcode ("rrc", "a");
9049 if (isSameRegs && offl==1) {
9050 emitcode ("xch", "a,%s",
9051 aopGet (AOP (left), MSB16, FALSE, FALSE, DP2_RESULT_REG));
9053 aopPut (AOP (result), "a", MSB24);
9054 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, NULL));
9056 emitcode ("rrc", "a");
9057 aopPut (AOP (result), "a", MSB16 - offl);
9061 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, NULL));
9062 emitcode ("rrc", "a");
9063 aopPut (AOP (result), "a", LSB);
9067 /*-----------------------------------------------------------------*/
9068 /* genrshFour - shift four byte by a known amount != 0 */
9069 /*-----------------------------------------------------------------*/
9071 genrshFour (operand * result, operand * left,
9072 int shCount, int sign)
9074 D (emitcode (";", "genrshFour"););
9076 /* if shifting more that 3 bytes */
9080 _startLazyDPSEvaluation();
9082 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9084 movLeft2Result (left, MSB32, result, LSB, sign);
9085 addSign (result, MSB16, sign);
9086 _endLazyDPSEvaluation();
9088 else if (shCount >= 16)
9091 _startLazyDPSEvaluation();
9093 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9096 movLeft2Result (left, MSB24, result, LSB, 0);
9097 movLeft2Result (left, MSB32, result, MSB16, sign);
9099 addSign (result, MSB24, sign);
9100 _endLazyDPSEvaluation();
9102 else if (shCount >= 8)
9105 _startLazyDPSEvaluation();
9108 shiftRLong (left, MSB16, result, sign);
9110 else if (shCount == 0)
9112 movLeft2Result (left, MSB16, result, LSB, 0);
9113 movLeft2Result (left, MSB24, result, MSB16, 0);
9114 movLeft2Result (left, MSB32, result, MSB24, sign);
9115 addSign (result, MSB32, sign);
9119 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9120 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9121 /* the last shift is signed */
9122 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9123 addSign (result, MSB32, sign);
9125 _endLazyDPSEvaluation();
9129 /* 1 <= shCount <= 7 */
9132 shiftRLong (left, LSB, result, sign);
9134 shiftRLong (result, LSB, result, sign);
9138 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9139 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9140 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9145 #ifdef BETTER_LITERAL_SHIFT
9146 /*-----------------------------------------------------------------*/
9147 /* genRightShiftLiteral - right shifting by known count */
9148 /*-----------------------------------------------------------------*/
9150 genRightShiftLiteral (operand * left,
9156 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9159 size = getSize (operandType (result));
9161 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
9163 /* We only handle certain easy cases so far. */
9165 && (shCount < (size * 8))
9170 D(emitcode (";", "genRightShiftLiteral wimping out"););
9174 freeAsmop (right, NULL, ic, TRUE);
9176 aopOp (left, ic, FALSE, FALSE);
9177 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9180 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9184 /* test the LEFT size !!! */
9186 /* I suppose that the left size >= result size */
9189 size = getDataSize (result);
9190 _startLazyDPSEvaluation();
9193 movLeft2Result (left, size, result, size, 0);
9195 _endLazyDPSEvaluation();
9197 else if (shCount >= (size * 8))
9201 /* get sign in acc.7 */
9202 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
9204 addSign (result, LSB, sign);
9211 genrshOne (result, left, shCount, sign);
9215 genrshTwo (result, left, shCount, sign);
9219 genrshFour (result, left, shCount, sign);
9226 freeAsmop (left, NULL, ic, TRUE);
9227 freeAsmop (result, NULL, ic, TRUE);
9233 /*-----------------------------------------------------------------*/
9234 /* genSignedRightShift - right shift of signed number */
9235 /*-----------------------------------------------------------------*/
9237 genSignedRightShift (iCode * ic)
9239 operand *right, *left, *result;
9242 symbol *tlbl, *tlbl1;
9244 D (emitcode (";", "genSignedRightShift "););
9246 /* we do it the hard way put the shift count in b
9247 and loop thru preserving the sign */
9249 right = IC_RIGHT (ic);
9250 left = IC_LEFT (ic);
9251 result = IC_RESULT (ic);
9253 aopOp (right, ic, FALSE, FALSE);
9255 #ifdef BETTER_LITERAL_SHIFT
9256 if (AOP_TYPE (right) == AOP_LIT)
9258 if (genRightShiftLiteral (left, right, result, ic, 1))
9264 /* shift count is unknown then we have to form
9265 a loop get the loop count in B : Note: we take
9266 only the lower order byte since shifting
9267 more that 32 bits make no sense anyway, ( the
9268 largest size of an object can be only 32 bits ) */
9270 if (AOP_TYPE (right) == AOP_LIT)
9272 /* Really should be handled by genRightShiftLiteral,
9273 * but since I'm too lazy to fix that today, at least we can make
9274 * some small improvement.
9276 emitcode("mov", "b,#!constbyte",
9277 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9281 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
9282 emitcode ("inc", "b");
9284 freeAsmop (right, NULL, ic, TRUE);
9285 aopOp (left, ic, FALSE, FALSE);
9286 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9288 /* now move the left to the result if they are not the
9290 if (!sameRegs (AOP (left), AOP (result)) &&
9291 AOP_SIZE (result) > 1)
9294 size = AOP_SIZE (result);
9296 _startLazyDPSEvaluation ();
9299 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
9300 if (*l == '@' && IS_AOP_PREG (result))
9303 emitcode ("mov", "a,%s", l);
9304 aopPut (AOP (result), "a", offset);
9307 aopPut (AOP (result), l, offset);
9310 _endLazyDPSEvaluation ();
9313 /* mov the highest order bit to OVR */
9314 tlbl = newiTempLabel (NULL);
9315 tlbl1 = newiTempLabel (NULL);
9317 size = AOP_SIZE (result);
9319 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
9320 emitcode ("rlc", "a");
9321 emitcode ("mov", "ov,c");
9322 /* if it is only one byte then */
9325 MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9326 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9327 emitcode ("", "!tlabeldef", tlbl->key + 100);
9328 emitcode ("mov", "c,ov");
9329 emitcode ("rrc", "a");
9330 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9331 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9332 aopPut (AOP (result), "a", 0);
9336 reAdjustPreg (AOP (result));
9337 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9338 emitcode ("", "!tlabeldef", tlbl->key + 100);
9339 emitcode ("mov", "c,ov");
9340 _startLazyDPSEvaluation ();
9343 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
9344 emitcode ("rrc", "a");
9345 aopPut (AOP (result), "a", offset--);
9347 _endLazyDPSEvaluation ();
9348 reAdjustPreg (AOP (result));
9349 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9350 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9353 freeAsmop (left, NULL, ic, TRUE);
9354 freeAsmop (result, NULL, ic, TRUE);
9357 /*-----------------------------------------------------------------*/
9358 /* genRightShift - generate code for right shifting */
9359 /*-----------------------------------------------------------------*/
9361 genRightShift (iCode * ic)
9363 operand *right, *left, *result;
9367 symbol *tlbl, *tlbl1;
9369 D (emitcode (";", "genRightShift "););
9371 /* if signed then we do it the hard way preserve the
9372 sign bit moving it inwards */
9373 letype = getSpec (operandType (IC_LEFT (ic)));
9375 if (!SPEC_USIGN (letype))
9377 genSignedRightShift (ic);
9381 /* signed & unsigned types are treated the same : i.e. the
9382 signed is NOT propagated inwards : quoting from the
9383 ANSI - standard : "for E1 >> E2, is equivalent to division
9384 by 2**E2 if unsigned or if it has a non-negative value,
9385 otherwise the result is implementation defined ", MY definition
9386 is that the sign does not get propagated */
9388 right = IC_RIGHT (ic);
9389 left = IC_LEFT (ic);
9390 result = IC_RESULT (ic);
9392 aopOp (right, ic, FALSE, FALSE);
9394 #ifdef BETTER_LITERAL_SHIFT
9395 /* if the shift count is known then do it
9396 as efficiently as possible */
9397 if (AOP_TYPE (right) == AOP_LIT)
9399 if (genRightShiftLiteral (left, right, result, ic, 0))
9406 /* shift count is unknown then we have to form
9407 a loop get the loop count in B : Note: we take
9408 only the lower order byte since shifting
9409 more that 32 bits make no sense anyway, ( the
9410 largest size of an object can be only 32 bits ) */
9412 if (AOP_TYPE (right) == AOP_LIT)
9414 /* Really should be handled by genRightShiftLiteral,
9415 * but since I'm too lazy to fix that today, at least we can make
9416 * some small improvement.
9418 emitcode("mov", "b,#!constbyte",
9419 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9423 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
9424 emitcode ("inc", "b");
9426 freeAsmop (right, NULL, ic, TRUE);
9427 aopOp (left, ic, FALSE, FALSE);
9428 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9430 /* now move the left to the result if they are not the
9432 if (!sameRegs (AOP (left), AOP (result)) &&
9433 AOP_SIZE (result) > 1)
9436 size = AOP_SIZE (result);
9438 _startLazyDPSEvaluation ();
9441 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
9442 if (*l == '@' && IS_AOP_PREG (result))
9445 emitcode ("mov", "a,%s", l);
9446 aopPut (AOP (result), "a", offset);
9449 aopPut (AOP (result), l, offset);
9452 _endLazyDPSEvaluation ();
9455 tlbl = newiTempLabel (NULL);
9456 tlbl1 = newiTempLabel (NULL);
9457 size = AOP_SIZE (result);
9460 /* if it is only one byte then */
9463 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9464 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9465 emitcode ("", "!tlabeldef", tlbl->key + 100);
9467 emitcode ("rrc", "a");
9468 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9469 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9470 aopPut (AOP (result), "a", 0);
9474 reAdjustPreg (AOP (result));
9475 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9476 emitcode ("", "!tlabeldef", tlbl->key + 100);
9478 _startLazyDPSEvaluation ();
9481 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
9482 emitcode ("rrc", "a");
9483 aopPut (AOP (result), "a", offset--);
9485 _endLazyDPSEvaluation ();
9486 reAdjustPreg (AOP (result));
9488 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9489 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9492 freeAsmop (left, NULL, ic, TRUE);
9493 freeAsmop (result, NULL, ic, TRUE);
9497 /*-----------------------------------------------------------------*/
9498 /* emitPtrByteGet - emits code to get a byte into A through a */
9499 /* pointer register (R0, R1, or DPTR). The */
9500 /* original value of A can be preserved in B. */
9501 /*-----------------------------------------------------------------*/
9503 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9510 emitcode ("mov", "b,a");
9511 emitcode ("mov", "a,@%s", rname);
9516 emitcode ("mov", "b,a");
9517 emitcode ("movx", "a,@%s", rname);
9522 emitcode ("mov", "b,a");
9523 emitcode ("movx", "a,@dptr");
9528 emitcode ("mov", "b,a");
9529 emitcode ("clr", "a");
9530 emitcode ("movc", "a,@a+dptr");
9536 emitcode ("push", "b");
9537 emitcode ("push", "acc");
9539 emitcode ("lcall", "__gptrget");
9541 emitcode ("pop", "b");
9546 /*-----------------------------------------------------------------*/
9547 /* emitPtrByteSet - emits code to set a byte from src through a */
9548 /* pointer register (R0, R1, or DPTR). */
9549 /*-----------------------------------------------------------------*/
9551 emitPtrByteSet (char *rname, int p_type, char *src)
9560 emitcode ("mov", "@%s,a", rname);
9563 emitcode ("mov", "@%s,%s", rname, src);
9568 emitcode ("movx", "@%s,a", rname);
9573 emitcode ("movx", "@dptr,a");
9578 emitcode ("lcall", "__gptrput");
9583 /*-----------------------------------------------------------------*/
9584 /* genUnpackBits - generates code for unpacking bits */
9585 /*-----------------------------------------------------------------*/
9587 genUnpackBits (operand * result, char *rname, int ptype)
9589 int offset = 0; /* result byte offset */
9590 int rsize; /* result size */
9591 int rlen = 0; /* remaining bitfield length */
9592 sym_link *etype; /* bitfield type information */
9593 int blen; /* bitfield length */
9594 int bstr; /* bitfield starting bit within byte */
9596 D(emitcode ("; genUnpackBits",""));
9598 etype = getSpec (operandType (result));
9599 rsize = getSize (operandType (result));
9600 blen = SPEC_BLEN (etype);
9601 bstr = SPEC_BSTR (etype);
9603 /* If the bitfield length is less than a byte */
9606 emitPtrByteGet (rname, ptype, FALSE);
9608 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
9609 aopPut (AOP (result), "a", offset++);
9613 /* Bit field did not fit in a byte. Copy all
9614 but the partial byte at the end. */
9615 for (rlen=blen;rlen>=8;rlen-=8)
9617 emitPtrByteGet (rname, ptype, FALSE);
9618 aopPut (AOP (result), "a", offset++);
9620 emitcode ("inc", "%s", rname);
9623 /* Handle the partial byte at the end */
9626 emitPtrByteGet (rname, ptype, FALSE);
9627 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
9628 aopPut (AOP (result), "a", offset++);
9636 aopPut (AOP (result), zero, offset++);
9641 /*-----------------------------------------------------------------*/
9642 /* genDataPointerGet - generates code when ptr offset is known */
9643 /*-----------------------------------------------------------------*/
9645 genDataPointerGet (operand * left,
9651 int size, offset = 0;
9652 aopOp (result, ic, TRUE, FALSE);
9654 /* get the string representation of the name */
9655 l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9656 size = AOP_SIZE (result);
9657 _startLazyDPSEvaluation ();
9662 SNPRINTF (buff, sizeof(buff),
9663 "(%s + %d)", l + 1, offset);
9667 SNPRINTF (buff, sizeof(buff),
9670 aopPut (AOP (result), buff, offset++);
9672 _endLazyDPSEvaluation ();
9674 freeAsmop (left, NULL, ic, TRUE);
9675 freeAsmop (result, NULL, ic, TRUE);
9678 /*-----------------------------------------------------------------*/
9679 /* genNearPointerGet - emitcode for near pointer fetch */
9680 /*-----------------------------------------------------------------*/
9682 genNearPointerGet (operand * left,
9690 sym_link *rtype, *retype, *letype;
9691 sym_link *ltype = operandType (left);
9694 rtype = operandType (result);
9695 retype = getSpec (rtype);
9696 letype = getSpec (ltype);
9698 aopOp (left, ic, FALSE, FALSE);
9700 /* if left is rematerialisable and
9701 result is not bitfield variable type and
9702 the left is pointer to data space i.e
9703 lower 128 bytes of space */
9704 if (AOP_TYPE (left) == AOP_IMMD &&
9705 !IS_BITFIELD (retype) &&
9706 !IS_BITFIELD (letype) &&
9707 DCL_TYPE (ltype) == POINTER)
9709 genDataPointerGet (left, result, ic);
9713 /* if the value is already in a pointer register
9714 then don't need anything more */
9715 if (!AOP_INPREG (AOP (left)))
9717 /* otherwise get a free pointer register */
9719 preg = getFreePtr (ic, &aop, FALSE);
9720 emitcode ("mov", "%s,%s",
9722 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9726 rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9728 freeAsmop (left, NULL, ic, TRUE);
9729 aopOp (result, ic, FALSE, FALSE);
9731 /* if bitfield then unpack the bits */
9732 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9733 genUnpackBits (result, rname, POINTER);
9736 /* we have can just get the values */
9737 int size = AOP_SIZE (result);
9742 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9745 emitcode ("mov", "a,@%s", rname);
9746 aopPut (AOP (result), "a", offset);
9750 SNPRINTF (buff, sizeof(buff), "@%s", rname);
9751 aopPut (AOP (result), buff, offset);
9756 emitcode ("inc", "%s", rname);
9761 /* now some housekeeping stuff */
9764 /* we had to allocate for this iCode */
9765 if (pi) { /* post increment present */
9766 aopPut(AOP ( left ),rname,0);
9768 freeAsmop (NULL, aop, ic, TRUE);
9772 /* we did not allocate which means left
9773 already in a pointer register, then
9774 if size > 0 && this could be used again
9775 we have to point it back to where it
9777 if (AOP_SIZE (result) > 1 &&
9778 !OP_SYMBOL (left)->remat &&
9779 (OP_SYMBOL (left)->liveTo > ic->seq ||
9783 int size = AOP_SIZE (result) - 1;
9785 emitcode ("dec", "%s", rname);
9790 freeAsmop (result, NULL, ic, TRUE);
9791 if (pi) pi->generated = 1;
9794 /*-----------------------------------------------------------------*/
9795 /* genPagedPointerGet - emitcode for paged pointer fetch */
9796 /*-----------------------------------------------------------------*/
9798 genPagedPointerGet (operand * left,
9806 sym_link *rtype, *retype, *letype;
9808 rtype = operandType (result);
9809 retype = getSpec (rtype);
9810 letype = getSpec (operandType (left));
9811 aopOp (left, ic, FALSE, FALSE);
9813 /* if the value is already in a pointer register
9814 then don't need anything more */
9815 if (!AOP_INPREG (AOP (left)))
9817 /* otherwise get a free pointer register */
9819 preg = getFreePtr (ic, &aop, FALSE);
9820 emitcode ("mov", "%s,%s",
9822 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9826 rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9828 freeAsmop (left, NULL, ic, TRUE);
9829 aopOp (result, ic, FALSE, FALSE);
9831 /* if bitfield then unpack the bits */
9832 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9833 genUnpackBits (result, rname, PPOINTER);
9836 /* we have can just get the values */
9837 int size = AOP_SIZE (result);
9843 emitcode ("movx", "a,@%s", rname);
9844 aopPut (AOP (result), "a", offset);
9849 emitcode ("inc", "%s", rname);
9853 /* now some housekeeping stuff */
9856 /* we had to allocate for this iCode */
9857 if (pi) aopPut ( AOP (left), rname, 0);
9858 freeAsmop (NULL, aop, ic, TRUE);
9862 /* we did not allocate which means left
9863 already in a pointer register, then
9864 if size > 0 && this could be used again
9865 we have to point it back to where it
9867 if (AOP_SIZE (result) > 1 &&
9868 !OP_SYMBOL (left)->remat &&
9869 (OP_SYMBOL (left)->liveTo > ic->seq ||
9873 int size = AOP_SIZE (result) - 1;
9875 emitcode ("dec", "%s", rname);
9880 freeAsmop (result, NULL, ic, TRUE);
9881 if (pi) pi->generated = 1;
9884 /*-----------------------------------------------------------------*/
9885 /* genFarPointerGet - gget value from far space */
9886 /*-----------------------------------------------------------------*/
9888 genFarPointerGet (operand * left,
9889 operand * result, iCode * ic, iCode *pi)
9891 int size, offset, dopi=1;
9892 sym_link *retype = getSpec (operandType (result));
9893 sym_link *letype = getSpec (operandType (left));
9894 D (emitcode (";", "genFarPointerGet"););
9896 aopOp (left, ic, FALSE, FALSE);
9898 /* if the operand is already in dptr
9899 then we do nothing else we move the value to dptr */
9900 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9902 /* if this is remateriazable */
9903 if (AOP_TYPE (left) == AOP_IMMD)
9905 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9909 /* we need to get it byte by byte */
9910 _startLazyDPSEvaluation ();
9911 if (AOP_TYPE (left) != AOP_DPTR)
9913 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9914 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9915 if (options.model == MODEL_FLAT24)
9916 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9920 /* We need to generate a load to DPTR indirect through DPTR. */
9921 D (emitcode (";", "genFarPointerGet -- indirection special case."););
9922 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9923 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9924 if (options.model == MODEL_FLAT24)
9925 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9926 emitcode ("pop", "dph");
9927 emitcode ("pop", "dpl");
9930 _endLazyDPSEvaluation ();
9933 /* so dptr know contains the address */
9934 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9936 /* if bit then unpack */
9937 if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
9938 if (AOP_INDPTRn(left)) {
9939 genSetDPTR(AOP(left)->aopu.dptr);
9941 genUnpackBits (result, "dptr", FPOINTER);
9942 if (AOP_INDPTRn(left)) {
9947 size = AOP_SIZE (result);
9950 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9952 genSetDPTR(AOP(left)->aopu.dptr);
9953 emitcode ("movx", "a,@dptr");
9954 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9955 emitcode ("inc", "dptr");
9957 aopPut (AOP (result), "a", offset++);
9960 _startLazyDPSEvaluation ();
9962 if (AOP_INDPTRn(left)) {
9963 genSetDPTR(AOP(left)->aopu.dptr);
9969 emitcode ("movx", "a,@dptr");
9970 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9971 emitcode ("inc", "dptr");
9973 aopPut (AOP (result), "a", offset++);
9975 _endLazyDPSEvaluation ();
9978 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9979 if (!AOP_INDPTRn(left)) {
9980 _startLazyDPSEvaluation ();
9981 aopPut ( AOP (left), "dpl", 0);
9982 aopPut ( AOP (left), "dph", 1);
9983 if (options.model == MODEL_FLAT24)
9984 aopPut ( AOP (left), "dpx", 2);
9985 _endLazyDPSEvaluation ();
9988 } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) &&
9989 AOP_SIZE(result) > 1 &&
9991 (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
9993 size = AOP_SIZE (result) - 1;
9994 if (AOP_INDPTRn(left)) {
9995 genSetDPTR(AOP(left)->aopu.dptr);
9997 while (size--) emitcode ("lcall","__decdptr");
9998 if (AOP_INDPTRn(left)) {
10003 freeAsmop (left, NULL, ic, TRUE);
10004 freeAsmop (result, NULL, ic, TRUE);
10007 /*-----------------------------------------------------------------*/
10008 /* genCodePointerGet - get value from code space */
10009 /*-----------------------------------------------------------------*/
10011 genCodePointerGet (operand * left,
10012 operand * result, iCode * ic, iCode *pi)
10014 int size, offset, dopi=1;
10015 sym_link *retype = getSpec (operandType (result));
10017 aopOp (left, ic, FALSE, FALSE);
10019 /* if the operand is already in dptr
10020 then we do nothing else we move the value to dptr */
10021 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
10023 /* if this is remateriazable */
10024 if (AOP_TYPE (left) == AOP_IMMD)
10026 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
10029 { /* we need to get it byte by byte */
10030 _startLazyDPSEvaluation ();
10031 if (AOP_TYPE (left) != AOP_DPTR)
10033 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10034 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10035 if (options.model == MODEL_FLAT24)
10036 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10040 /* We need to generate a load to DPTR indirect through DPTR. */
10041 D (emitcode (";", "gencodePointerGet -- indirection special case."););
10042 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
10043 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
10044 if (options.model == MODEL_FLAT24)
10045 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10046 emitcode ("pop", "dph");
10047 emitcode ("pop", "dpl");
10050 _endLazyDPSEvaluation ();
10053 /* so dptr know contains the address */
10054 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
10056 /* if bit then unpack */
10057 if (IS_BITFIELD (retype)) {
10058 if (AOP_INDPTRn(left)) {
10059 genSetDPTR(AOP(left)->aopu.dptr);
10061 genUnpackBits (result, "dptr", CPOINTER);
10062 if (AOP_INDPTRn(left)) {
10067 size = AOP_SIZE (result);
10069 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10071 genSetDPTR(AOP(left)->aopu.dptr);
10072 emitcode ("clr", "a");
10073 emitcode ("movc", "a,@a+dptr");
10074 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10075 emitcode ("inc", "dptr");
10077 aopPut (AOP (result), "a", offset++);
10080 _startLazyDPSEvaluation ();
10083 if (AOP_INDPTRn(left)) {
10084 genSetDPTR(AOP(left)->aopu.dptr);
10090 emitcode ("clr", "a");
10091 emitcode ("movc", "a,@a+dptr");
10092 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10093 emitcode ("inc", "dptr");
10094 aopPut (AOP (result), "a", offset++);
10096 _endLazyDPSEvaluation ();
10099 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10100 if (!AOP_INDPTRn(left)) {
10101 _startLazyDPSEvaluation ();
10103 aopPut ( AOP (left), "dpl", 0);
10104 aopPut ( AOP (left), "dph", 1);
10105 if (options.model == MODEL_FLAT24)
10106 aopPut ( AOP (left), "dpx", 2);
10108 _endLazyDPSEvaluation ();
10111 } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
10112 AOP_SIZE(result) > 1 &&
10113 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10115 size = AOP_SIZE (result) - 1;
10116 if (AOP_INDPTRn(left)) {
10117 genSetDPTR(AOP(left)->aopu.dptr);
10119 while (size--) emitcode ("lcall","__decdptr");
10120 if (AOP_INDPTRn(left)) {
10125 freeAsmop (left, NULL, ic, TRUE);
10126 freeAsmop (result, NULL, ic, TRUE);
10129 /*-----------------------------------------------------------------*/
10130 /* genGenPointerGet - gget value from generic pointer space */
10131 /*-----------------------------------------------------------------*/
10133 genGenPointerGet (operand * left,
10134 operand * result, iCode * ic, iCode * pi)
10137 sym_link *retype = getSpec (operandType (result));
10138 sym_link *letype = getSpec (operandType (left));
10140 D (emitcode (";", "genGenPointerGet "); );
10142 aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
10144 /* if the operand is already in dptr
10145 then we do nothing else we move the value to dptr */
10146 if (AOP_TYPE (left) != AOP_STR)
10148 /* if this is remateriazable */
10149 if (AOP_TYPE (left) == AOP_IMMD)
10151 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
10152 if (AOP(left)->aopu.aop_immd.from_cast_remat)
10154 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
10158 emitcode ("mov", "b,#%d", pointerCode (retype));
10162 { /* we need to get it byte by byte */
10163 _startLazyDPSEvaluation ();
10164 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
10165 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
10166 if (options.model == MODEL_FLAT24) {
10167 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
10168 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
10170 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
10172 _endLazyDPSEvaluation ();
10176 /* so dptr-b now contains the address */
10178 aopOp (result, ic, FALSE, TRUE);
10181 /* if bit then unpack */
10182 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10184 genUnpackBits (result, "dptr", GPOINTER);
10188 size = AOP_SIZE (result);
10195 // Get two bytes at a time, results in _AP & A.
10196 // dptr will be incremented ONCE by __gptrgetWord.
10198 // Note: any change here must be coordinated
10199 // with the implementation of __gptrgetWord
10200 // in device/lib/_gptrget.c
10201 emitcode ("lcall", "__gptrgetWord");
10202 aopPut (AOP (result), DP2_RESULT_REG, offset++);
10203 aopPut (AOP (result), "a", offset++);
10208 // Only one byte to get.
10209 emitcode ("lcall", "__gptrget");
10210 aopPut (AOP (result), "a", offset++);
10213 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
10215 emitcode ("inc", "dptr");
10220 if (pi && AOP_TYPE (left) != AOP_IMMD) {
10221 _startLazyDPSEvaluation ();
10223 aopPut ( AOP (left), "dpl", 0);
10224 aopPut ( AOP (left), "dph", 1);
10225 if (options.model == MODEL_FLAT24) {
10226 aopPut ( AOP (left), "dpx", 2);
10227 aopPut ( AOP (left), "b", 3);
10228 } else aopPut ( AOP (left), "b", 2);
10230 _endLazyDPSEvaluation ();
10233 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
10234 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10236 size = AOP_SIZE (result) - 1;
10237 while (size--) emitcode ("lcall","__decdptr");
10240 freeAsmop (left, NULL, ic, TRUE);
10241 freeAsmop (result, NULL, ic, TRUE);
10244 /*-----------------------------------------------------------------*/
10245 /* genPointerGet - generate code for pointer get */
10246 /*-----------------------------------------------------------------*/
10248 genPointerGet (iCode * ic, iCode *pi)
10250 operand *left, *result;
10251 sym_link *type, *etype;
10254 D (emitcode (";", "genPointerGet ");
10257 left = IC_LEFT (ic);
10258 result = IC_RESULT (ic);
10260 /* depending on the type of pointer we need to
10261 move it to the correct pointer register */
10262 type = operandType (left);
10263 etype = getSpec (type);
10264 /* if left is of type of pointer then it is simple */
10265 if (IS_PTR (type) && !IS_FUNC (type->next))
10266 p_type = DCL_TYPE (type);
10269 /* we have to go by the storage class */
10270 p_type = PTR_TYPE (SPEC_OCLS (etype));
10272 /* special case when cast remat */
10273 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10274 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
10275 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10276 type = operandType (left);
10277 p_type = DCL_TYPE (type);
10279 /* now that we have the pointer type we assign
10280 the pointer values */
10286 genNearPointerGet (left, result, ic, pi);
10290 genPagedPointerGet (left, result, ic, pi);
10294 genFarPointerGet (left, result, ic, pi);
10298 genCodePointerGet (left, result, ic, pi);
10302 genGenPointerGet (left, result, ic, pi);
10308 /*-----------------------------------------------------------------*/
10309 /* genPackBits - generates code for packed bit storage */
10310 /*-----------------------------------------------------------------*/
10312 genPackBits (sym_link * etype,
10314 char *rname, int p_type)
10316 int offset = 0; /* source byte offset */
10317 int rlen = 0; /* remaining bitfield length */
10318 int blen; /* bitfield length */
10319 int bstr; /* bitfield starting bit within byte */
10320 int litval; /* source literal value (if AOP_LIT) */
10321 unsigned char mask; /* bitmask within current byte */
10323 D(emitcode ("; genPackBits",""));
10325 blen = SPEC_BLEN (etype);
10326 bstr = SPEC_BSTR (etype);
10328 /* If the bitfield length is less than a byte */
10331 mask = ((unsigned char) (0xFF << (blen + bstr)) |
10332 (unsigned char) (0xFF >> (8 - bstr)));
10334 if (AOP_TYPE (right) == AOP_LIT)
10336 /* Case with a bitfield length <8 and literal source
10338 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10340 litval &= (~mask) & 0xff;
10341 emitPtrByteGet (rname, p_type, FALSE);
10342 if ((mask|litval)!=0xff)
10343 emitcode ("anl","a,#!constbyte", mask);
10345 emitcode ("orl","a,#!constbyte", litval);
10349 if ((blen==1) && (p_type!=GPOINTER))
10351 /* Case with a bitfield length == 1 and no generic pointer
10353 if (AOP_TYPE (right) == AOP_CRY)
10354 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10357 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
10358 emitcode ("rrc","a");
10360 emitPtrByteGet (rname, p_type, FALSE);
10361 emitcode ("mov","acc.%d,c",bstr);
10365 /* Case with a bitfield length < 8 and arbitrary source
10367 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
10368 /* shift and mask source value */
10370 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10372 /* transfer A to B and get next byte */
10373 emitPtrByteGet (rname, p_type, TRUE);
10375 emitcode ("anl", "a,#!constbyte", mask);
10376 emitcode ("orl", "a,b");
10377 if (p_type == GPOINTER)
10378 emitcode ("pop", "b");
10382 emitPtrByteSet (rname, p_type, "a");
10386 /* Bit length is greater than 7 bits. In this case, copy */
10387 /* all except the partial byte at the end */
10388 for (rlen=blen;rlen>=8;rlen-=8)
10390 emitPtrByteSet (rname, p_type,
10391 aopGet (AOP (right), offset++, FALSE, TRUE, NULL) );
10393 emitcode ("inc", "%s", rname);
10396 /* If there was a partial byte at the end */
10399 mask = (((unsigned char) -1 << rlen) & 0xff);
10401 if (AOP_TYPE (right) == AOP_LIT)
10403 /* Case with partial byte and literal source
10405 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10406 litval >>= (blen-rlen);
10407 litval &= (~mask) & 0xff;
10408 emitPtrByteGet (rname, p_type, FALSE);
10409 if ((mask|litval)!=0xff)
10410 emitcode ("anl","a,#!constbyte", mask);
10412 emitcode ("orl","a,#!constbyte", litval);
10416 /* Case with partial byte and arbitrary source
10418 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10419 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10421 /* transfer A to B and get next byte */
10422 emitPtrByteGet (rname, p_type, TRUE);
10424 emitcode ("anl", "a,#!constbyte", mask);
10425 emitcode ("orl", "a,b");
10426 if (p_type == GPOINTER)
10427 emitcode ("pop", "b");
10429 emitPtrByteSet (rname, p_type, "a");
10435 /*-----------------------------------------------------------------*/
10436 /* genDataPointerSet - remat pointer to data space */
10437 /*-----------------------------------------------------------------*/
10439 genDataPointerSet (operand * right,
10443 int size, offset = 0;
10444 char *l, buff[256];
10446 aopOp (right, ic, FALSE, FALSE);
10448 l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
10449 size = AOP_SIZE (right);
10454 SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
10458 SNPRINTF (buff, sizeof(buff), "%s", l + 1);
10461 emitcode ("mov", "%s,%s", buff,
10462 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10465 freeAsmop (right, NULL, ic, TRUE);
10466 freeAsmop (result, NULL, ic, TRUE);
10469 /*-----------------------------------------------------------------*/
10470 /* genNearPointerSet - emitcode for near pointer put */
10471 /*-----------------------------------------------------------------*/
10473 genNearPointerSet (operand * right,
10480 sym_link *retype, *letype;
10481 sym_link *ptype = operandType (result);
10483 retype = getSpec (operandType (right));
10484 letype = getSpec (ptype);
10486 aopOp (result, ic, FALSE, FALSE);
10488 /* if the result is rematerializable &
10489 in data space & not a bit variable */
10490 if (AOP_TYPE (result) == AOP_IMMD &&
10491 DCL_TYPE (ptype) == POINTER &&
10492 !IS_BITVAR (retype) &&
10493 !IS_BITVAR (letype))
10495 genDataPointerSet (right, result, ic);
10499 /* if the value is already in a pointer register
10500 then don't need anything more */
10501 if (!AOP_INPREG (AOP (result)))
10503 /* otherwise get a free pointer register */
10506 aop = newAsmop (0);
10507 preg = getFreePtr (ic, &aop, FALSE);
10508 emitcode ("mov", "%s,%s",
10510 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10511 rname = preg->name;
10514 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10516 aopOp (right, ic, FALSE, FALSE);
10518 /* if bitfield then unpack the bits */
10519 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10520 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10523 /* we have can just get the values */
10524 int size = AOP_SIZE (right);
10529 l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
10533 emitcode ("mov", "@%s,a", rname);
10536 emitcode ("mov", "@%s,%s", rname, l);
10538 emitcode ("inc", "%s", rname);
10543 /* now some housekeeping stuff */
10546 /* we had to allocate for this iCode */
10547 if (pi) aopPut (AOP (result),rname,0);
10548 freeAsmop (NULL, aop, ic, TRUE);
10552 /* we did not allocate which means left
10553 already in a pointer register, then
10554 if size > 0 && this could be used again
10555 we have to point it back to where it
10557 if (AOP_SIZE (right) > 1 &&
10558 !OP_SYMBOL (result)->remat &&
10559 (OP_SYMBOL (result)->liveTo > ic->seq ||
10563 int size = AOP_SIZE (right) - 1;
10565 emitcode ("dec", "%s", rname);
10570 if (pi) pi->generated = 1;
10571 freeAsmop (result, NULL, ic, TRUE);
10572 freeAsmop (right, NULL, ic, TRUE);
10577 /*-----------------------------------------------------------------*/
10578 /* genPagedPointerSet - emitcode for Paged pointer put */
10579 /*-----------------------------------------------------------------*/
10581 genPagedPointerSet (operand * right,
10588 sym_link *retype, *letype;
10590 retype = getSpec (operandType (right));
10591 letype = getSpec (operandType (result));
10593 aopOp (result, ic, FALSE, FALSE);
10595 /* if the value is already in a pointer register
10596 then don't need anything more */
10597 if (!AOP_INPREG (AOP (result)))
10599 /* otherwise get a free pointer register */
10602 aop = newAsmop (0);
10603 preg = getFreePtr (ic, &aop, FALSE);
10604 emitcode ("mov", "%s,%s",
10606 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10607 rname = preg->name;
10610 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10612 aopOp (right, ic, FALSE, FALSE);
10614 /* if bitfield then unpack the bits */
10615 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10616 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10619 /* we have can just get the values */
10620 int size = AOP_SIZE (right);
10625 MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10627 emitcode ("movx", "@%s,a", rname);
10630 emitcode ("inc", "%s", rname);
10636 /* now some housekeeping stuff */
10639 if (pi) aopPut (AOP (result),rname,0);
10640 /* we had to allocate for this iCode */
10641 freeAsmop (NULL, aop, ic, TRUE);
10645 /* we did not allocate which means left
10646 already in a pointer register, then
10647 if size > 0 && this could be used again
10648 we have to point it back to where it
10650 if (AOP_SIZE (right) > 1 &&
10651 !OP_SYMBOL (result)->remat &&
10652 (OP_SYMBOL (result)->liveTo > ic->seq ||
10656 int size = AOP_SIZE (right) - 1;
10658 emitcode ("dec", "%s", rname);
10663 if (pi) pi->generated = 1;
10664 freeAsmop (result, NULL, ic, TRUE);
10665 freeAsmop (right, NULL, ic, TRUE);
10670 /*-----------------------------------------------------------------*/
10671 /* genFarPointerSet - set value from far space */
10672 /*-----------------------------------------------------------------*/
10674 genFarPointerSet (operand * right,
10675 operand * result, iCode * ic, iCode *pi)
10677 int size, offset, dopi=1;
10678 sym_link *retype = getSpec (operandType (right));
10679 sym_link *letype = getSpec (operandType (result));
10681 aopOp (result, ic, FALSE, FALSE);
10683 /* if the operand is already in dptr
10684 then we do nothing else we move the value to dptr */
10685 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10687 /* if this is remateriazable */
10688 if (AOP_TYPE (result) == AOP_IMMD)
10689 emitcode ("mov", "dptr,%s",
10690 aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10693 /* we need to get it byte by byte */
10694 _startLazyDPSEvaluation ();
10695 if (AOP_TYPE (result) != AOP_DPTR)
10697 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10698 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10699 if (options.model == MODEL_FLAT24)
10700 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10704 /* We need to generate a load to DPTR indirect through DPTR. */
10705 D (emitcode (";", "genFarPointerSet -- indirection special case."););
10707 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10708 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10709 if (options.model == MODEL_FLAT24)
10710 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10711 emitcode ("pop", "dph");
10712 emitcode ("pop", "dpl");
10715 _endLazyDPSEvaluation ();
10718 /* so dptr know contains the address */
10719 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10721 /* if bit then unpack */
10722 if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
10723 if (AOP_INDPTRn(result)) {
10724 genSetDPTR(AOP(result)->aopu.dptr);
10726 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10727 if (AOP_INDPTRn(result)) {
10731 size = AOP_SIZE (right);
10733 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10735 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10737 genSetDPTR(AOP(result)->aopu.dptr);
10738 emitcode ("movx", "@dptr,a");
10739 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10740 emitcode ("inc", "dptr");
10744 _startLazyDPSEvaluation ();
10746 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10748 if (AOP_INDPTRn(result)) {
10749 genSetDPTR(AOP(result)->aopu.dptr);
10755 emitcode ("movx", "@dptr,a");
10756 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10757 emitcode ("inc", "dptr");
10759 _endLazyDPSEvaluation ();
10763 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10764 if (!AOP_INDPTRn(result)) {
10765 _startLazyDPSEvaluation ();
10767 aopPut (AOP(result),"dpl",0);
10768 aopPut (AOP(result),"dph",1);
10769 if (options.model == MODEL_FLAT24)
10770 aopPut (AOP(result),"dpx",2);
10772 _endLazyDPSEvaluation ();
10775 } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
10776 AOP_SIZE(right) > 1 &&
10777 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10779 size = AOP_SIZE (right) - 1;
10780 if (AOP_INDPTRn(result)) {
10781 genSetDPTR(AOP(result)->aopu.dptr);
10783 while (size--) emitcode ("lcall","__decdptr");
10784 if (AOP_INDPTRn(result)) {
10788 freeAsmop (result, NULL, ic, TRUE);
10789 freeAsmop (right, NULL, ic, TRUE);
10792 /*-----------------------------------------------------------------*/
10793 /* genGenPointerSet - set value from generic pointer space */
10794 /*-----------------------------------------------------------------*/
10796 genGenPointerSet (operand * right,
10797 operand * result, iCode * ic, iCode *pi)
10800 sym_link *retype = getSpec (operandType (right));
10801 sym_link *letype = getSpec (operandType (result));
10803 aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10805 /* if the operand is already in dptr
10806 then we do nothing else we move the value to dptr */
10807 if (AOP_TYPE (result) != AOP_STR)
10809 _startLazyDPSEvaluation ();
10810 /* if this is remateriazable */
10811 if (AOP_TYPE (result) == AOP_IMMD)
10813 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10814 if (AOP(result)->aopu.aop_immd.from_cast_remat)
10816 MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10821 "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10825 { /* we need to get it byte by byte */
10826 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10827 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10828 if (options.model == MODEL_FLAT24) {
10829 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10830 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10832 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10835 _endLazyDPSEvaluation ();
10837 /* so dptr + b now contains the address */
10839 aopOp (right, ic, FALSE, TRUE);
10843 /* if bit then unpack */
10844 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10846 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10850 size = AOP_SIZE (right);
10853 _startLazyDPSEvaluation ();
10858 // Set two bytes at a time, passed in _AP & A.
10859 // dptr will be incremented ONCE by __gptrputWord.
10861 // Note: any change here must be coordinated
10862 // with the implementation of __gptrputWord
10863 // in device/lib/_gptrput.c
10864 emitcode("mov", "_ap, %s",
10865 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10866 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10870 emitcode ("lcall", "__gptrputWord");
10875 // Only one byte to put.
10876 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10880 emitcode ("lcall", "__gptrput");
10883 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10885 emitcode ("inc", "dptr");
10888 _endLazyDPSEvaluation ();
10891 if (pi && AOP_TYPE (result) != AOP_IMMD) {
10892 _startLazyDPSEvaluation ();
10894 aopPut (AOP(result),"dpl",0);
10895 aopPut (AOP(result),"dph",1);
10896 if (options.model == MODEL_FLAT24) {
10897 aopPut (AOP(result),"dpx",2);
10898 aopPut (AOP(result),"b",3);
10900 aopPut (AOP(result),"b",2);
10902 _endLazyDPSEvaluation ();
10905 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10906 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10908 size = AOP_SIZE (right) - 1;
10909 while (size--) emitcode ("lcall","__decdptr");
10911 freeAsmop (result, NULL, ic, TRUE);
10912 freeAsmop (right, NULL, ic, TRUE);
10915 /*-----------------------------------------------------------------*/
10916 /* genPointerSet - stores the value into a pointer location */
10917 /*-----------------------------------------------------------------*/
10919 genPointerSet (iCode * ic, iCode *pi)
10921 operand *right, *result;
10922 sym_link *type, *etype;
10925 D (emitcode (";", "genPointerSet "););
10927 right = IC_RIGHT (ic);
10928 result = IC_RESULT (ic);
10930 /* depending on the type of pointer we need to
10931 move it to the correct pointer register */
10932 type = operandType (result);
10933 etype = getSpec (type);
10934 /* if left is of type of pointer then it is simple */
10935 if (IS_PTR (type) && !IS_FUNC (type->next))
10937 p_type = DCL_TYPE (type);
10941 /* we have to go by the storage class */
10942 p_type = PTR_TYPE (SPEC_OCLS (etype));
10944 /* special case when cast remat */
10945 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10946 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10947 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10948 type = operandType (result);
10949 p_type = DCL_TYPE (type);
10952 /* now that we have the pointer type we assign
10953 the pointer values */
10959 genNearPointerSet (right, result, ic, pi);
10963 genPagedPointerSet (right, result, ic, pi);
10967 genFarPointerSet (right, result, ic, pi);
10971 genGenPointerSet (right, result, ic, pi);
10975 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10976 "genPointerSet: illegal pointer type");
10981 /*-----------------------------------------------------------------*/
10982 /* genIfx - generate code for Ifx statement */
10983 /*-----------------------------------------------------------------*/
10985 genIfx (iCode * ic, iCode * popIc)
10987 operand *cond = IC_COND (ic);
10990 D (emitcode (";", "genIfx "););
10992 aopOp (cond, ic, FALSE, FALSE);
10994 /* get the value into acc */
10995 if (AOP_TYPE (cond) != AOP_CRY)
11004 /* the result is now in the accumulator */
11005 freeAsmop (cond, NULL, ic, TRUE);
11007 /* if there was something to be popped then do it */
11011 /* if the condition is a bit variable */
11012 if (isbit && IS_ITEMP (cond) &&
11015 genIfxJump (ic, SPIL_LOC (cond)->rname);
11017 else if (isbit && !IS_ITEMP (cond))
11019 genIfxJump (ic, OP_SYMBOL (cond)->rname);
11023 genIfxJump (ic, "a");
11029 /*-----------------------------------------------------------------*/
11030 /* genAddrOf - generates code for address of */
11031 /*-----------------------------------------------------------------*/
11033 genAddrOf (iCode * ic)
11035 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
11038 D (emitcode (";", "genAddrOf ");
11041 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11043 /* if the operand is on the stack then we
11044 need to get the stack offset of this
11046 if (sym->onStack) {
11048 /* if 10 bit stack */
11049 if (options.stack10bit) {
11053 tsprintf(buff, sizeof(buff),
11054 "#!constbyte",(options.stack_loc >> 16) & 0xff);
11055 /* if it has an offset then we need to compute it */
11056 /* emitcode ("subb", "a,#!constbyte", */
11057 /* -((sym->stack < 0) ? */
11058 /* ((short) (sym->stack - _G.nRegsSaved)) : */
11059 /* ((short) sym->stack)) & 0xff); */
11060 /* emitcode ("mov","b,a"); */
11061 /* emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
11062 /* ((short) (sym->stack - _G.nRegsSaved)) : */
11063 /* ((short) sym->stack)) >> 8) & 0xff); */
11065 emitcode ("mov", "a,_bpx");
11066 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
11067 ((char) (sym->stack - _G.nRegsSaved)) :
11068 ((char) sym->stack )) & 0xff);
11069 emitcode ("mov", "b,a");
11070 emitcode ("mov", "a,_bpx+1");
11072 offset = (((sym->stack < 0) ?
11073 ((short) (sym->stack - _G.nRegsSaved)) :
11074 ((short) sym->stack )) >> 8) & 0xff;
11076 emitcode ("addc","a,#!constbyte", offset);
11078 aopPut (AOP (IC_RESULT (ic)), "b", 0);
11079 aopPut (AOP (IC_RESULT (ic)), "a", 1);
11080 aopPut (AOP (IC_RESULT (ic)), buff, 2);
11082 /* we can just move _bp */
11083 aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
11084 aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
11085 aopPut (AOP (IC_RESULT (ic)), buff, 2);
11088 /* if it has an offset then we need to compute it */
11090 emitcode ("mov", "a,_bp");
11091 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
11092 aopPut (AOP (IC_RESULT (ic)), "a", 0);
11094 /* we can just move _bp */
11095 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
11097 /* fill the result with zero */
11098 size = AOP_SIZE (IC_RESULT (ic)) - 1;
11101 if (options.stack10bit && size < (FPTRSIZE - 1)) {
11103 "*** warning: pointer to stack var truncated.\n");
11108 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
11114 /* object not on stack then we need the name */
11115 size = AOP_SIZE (IC_RESULT (ic));
11120 char s[SDCC_NAME_MAX];
11124 tsprintf(s, sizeof(s), "#!his",sym->rname);
11127 tsprintf(s, sizeof(s), "#!hihis",sym->rname);
11130 tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
11132 default: /* should not need this (just in case) */
11133 SNPRINTF (s, sizeof(s), "#(%s >> %d)",
11140 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11143 aopPut (AOP (IC_RESULT (ic)), s, offset++);
11147 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11151 #if 0 // obsolete, and buggy for != xdata
11152 /*-----------------------------------------------------------------*/
11153 /* genArrayInit - generates code for address of */
11154 /*-----------------------------------------------------------------*/
11156 genArrayInit (iCode * ic)
11158 literalList *iLoop;
11160 int elementSize = 0, eIndex;
11161 unsigned val, lastVal;
11163 operand *left=IC_LEFT(ic);
11165 D (emitcode (";", "genArrayInit "););
11167 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
11169 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
11171 // Load immediate value into DPTR.
11172 emitcode("mov", "dptr, %s",
11173 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
11175 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
11178 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11179 "Unexpected operand to genArrayInit.\n");
11182 // a regression because of SDCCcse.c:1.52
11183 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
11184 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
11185 if (options.model == MODEL_FLAT24)
11186 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
11190 type = operandType(IC_LEFT(ic));
11192 if (type && type->next)
11194 elementSize = getSize(type->next);
11198 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11199 "can't determine element size in genArrayInit.\n");
11203 iLoop = IC_ARRAYILIST(ic);
11208 bool firstpass = TRUE;
11210 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
11211 iLoop->count, (int)iLoop->literalValue, elementSize);
11217 symbol *tlbl = NULL;
11219 count = ix > 256 ? 256 : ix;
11223 tlbl = newiTempLabel (NULL);
11224 if (firstpass || (count & 0xff))
11226 emitcode("mov", "b, #!constbyte", count & 0xff);
11229 emitcode ("", "!tlabeldef", tlbl->key + 100);
11234 for (eIndex = 0; eIndex < elementSize; eIndex++)
11236 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
11237 if (val != lastVal)
11239 emitcode("mov", "a, #!constbyte", val);
11243 emitcode("movx", "@dptr, a");
11244 emitcode("inc", "dptr");
11249 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
11255 iLoop = iLoop->next;
11258 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
11262 /*-----------------------------------------------------------------*/
11263 /* genFarFarAssign - assignment when both are in far space */
11264 /*-----------------------------------------------------------------*/
11266 genFarFarAssign (operand * result, operand * right, iCode * ic)
11268 int size = AOP_SIZE (right);
11270 symbol *rSym = NULL;
11274 /* quick & easy case. */
11275 D(emitcode(";","genFarFarAssign (1 byte case)"););
11276 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
11277 freeAsmop (right, NULL, ic, FALSE);
11278 /* now assign DPTR to result */
11280 aopOp(result, ic, FALSE, FALSE);
11282 aopPut(AOP(result), "a", 0);
11283 freeAsmop(result, NULL, ic, FALSE);
11287 /* See if we've got an underlying symbol to abuse. */
11288 if (IS_SYMOP(result) && OP_SYMBOL(result))
11290 if (IS_TRUE_SYMOP(result))
11292 rSym = OP_SYMBOL(result);
11294 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
11296 rSym = OP_SYMBOL(result)->usl.spillLoc;
11300 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
11302 /* We can use the '390 auto-toggle feature to good effect here. */
11304 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
11305 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11306 emitcode ("mov", "dptr,#%s", rSym->rname);
11307 /* DP2 = result, DP1 = right, DP1 is current. */
11310 emitcode("movx", "a,@dptr");
11311 emitcode("movx", "@dptr,a");
11314 emitcode("inc", "dptr");
11315 emitcode("inc", "dptr");
11318 emitcode("mov", "dps,#0");
11319 freeAsmop (right, NULL, ic, FALSE);
11321 some alternative code for processors without auto-toggle
11322 no time to test now, so later well put in...kpb
11323 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
11324 emitcode("mov", "dps,#1"); /* Select DPTR2. */
11325 emitcode ("mov", "dptr,#%s", rSym->rname);
11326 /* DP2 = result, DP1 = right, DP1 is current. */
11330 emitcode("movx", "a,@dptr");
11332 emitcode("inc", "dptr");
11333 emitcode("inc", "dps");
11334 emitcode("movx", "@dptr,a");
11336 emitcode("inc", "dptr");
11337 emitcode("inc", "dps");
11339 emitcode("mov", "dps,#0");
11340 freeAsmop (right, NULL, ic, FALSE);
11345 D (emitcode (";", "genFarFarAssign"););
11346 aopOp (result, ic, TRUE, TRUE);
11348 _startLazyDPSEvaluation ();
11352 aopPut (AOP (result),
11353 aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
11356 _endLazyDPSEvaluation ();
11357 freeAsmop (result, NULL, ic, FALSE);
11358 freeAsmop (right, NULL, ic, FALSE);
11362 /*-----------------------------------------------------------------*/
11363 /* genAssign - generate code for assignment */
11364 /*-----------------------------------------------------------------*/
11366 genAssign (iCode * ic)
11368 operand *result, *right;
11370 unsigned long lit = 0L;
11372 D (emitcode (";", "genAssign ");
11375 result = IC_RESULT (ic);
11376 right = IC_RIGHT (ic);
11378 /* if they are the same */
11379 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11382 aopOp (right, ic, FALSE, FALSE);
11384 emitcode (";", "genAssign: resultIsFar = %s",
11385 isOperandInFarSpace (result) ?
11388 /* special case both in far space */
11389 if ((AOP_TYPE (right) == AOP_DPTR ||
11390 AOP_TYPE (right) == AOP_DPTR2) &&
11391 /* IS_TRUE_SYMOP(result) && */
11392 isOperandInFarSpace (result))
11394 genFarFarAssign (result, right, ic);
11398 aopOp (result, ic, TRUE, FALSE);
11400 /* if they are the same registers */
11401 if (sameRegs (AOP (right), AOP (result)))
11404 /* if the result is a bit */
11405 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
11407 /* if the right size is a literal then
11408 we know what the value is */
11409 if (AOP_TYPE (right) == AOP_LIT)
11411 if (((int) operandLitValue (right)))
11412 aopPut (AOP (result), one, 0);
11414 aopPut (AOP (result), zero, 0);
11418 /* the right is also a bit variable */
11419 if (AOP_TYPE (right) == AOP_CRY)
11421 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11422 aopPut (AOP (result), "c", 0);
11426 /* we need to or */
11428 aopPut (AOP (result), "a", 0);
11432 /* bit variables done */
11434 size = AOP_SIZE (result);
11436 if (AOP_TYPE (right) == AOP_LIT)
11437 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11440 (AOP_TYPE (result) != AOP_REG) &&
11441 (AOP_TYPE (right) == AOP_LIT) &&
11442 !IS_FLOAT (operandType (right)))
11444 _startLazyDPSEvaluation ();
11445 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
11447 aopPut (AOP (result),
11448 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11453 /* And now fill the rest with zeros. */
11456 emitcode ("clr", "a");
11460 aopPut (AOP (result), "a", offset++);
11462 _endLazyDPSEvaluation ();
11466 _startLazyDPSEvaluation ();
11469 aopPut (AOP (result),
11470 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11474 _endLazyDPSEvaluation ();
11478 freeAsmop (right, NULL, ic, FALSE);
11479 freeAsmop (result, NULL, ic, TRUE);
11482 /*-----------------------------------------------------------------*/
11483 /* genJumpTab - generates code for jump table */
11484 /*-----------------------------------------------------------------*/
11486 genJumpTab (iCode * ic)
11491 D (emitcode (";", "genJumpTab ");
11494 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
11495 /* get the condition into accumulator */
11496 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
11498 /* multiply by four! */
11499 emitcode ("add", "a,acc");
11500 emitcode ("add", "a,acc");
11501 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11503 jtab = newiTempLabel (NULL);
11504 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
11505 emitcode ("jmp", "@a+dptr");
11506 emitcode ("", "!tlabeldef", jtab->key + 100);
11507 /* now generate the jump labels */
11508 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11509 jtab = setNextItem (IC_JTLABELS (ic)))
11510 emitcode ("ljmp", "!tlabel", jtab->key + 100);
11514 /*-----------------------------------------------------------------*/
11515 /* genCast - gen code for casting */
11516 /*-----------------------------------------------------------------*/
11518 genCast (iCode * ic)
11520 operand *result = IC_RESULT (ic);
11521 sym_link *ctype = operandType (IC_LEFT (ic));
11522 sym_link *rtype = operandType (IC_RIGHT (ic));
11523 operand *right = IC_RIGHT (ic);
11526 D (emitcode (";", "genCast "););
11528 /* if they are equivalent then do nothing */
11529 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11532 aopOp (right, ic, FALSE, AOP_IS_STR (result));
11533 aopOp (result, ic, FALSE, (AOP_TYPE(right) == AOP_DPTR));
11535 /* if the result is a bit */
11536 if (IS_BITVAR (OP_SYMBOL (result)->type)
11537 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
11539 /* if the right size is a literal then
11540 we know what the value is */
11541 if (AOP_TYPE (right) == AOP_LIT)
11543 if (((int) operandLitValue (right)))
11544 aopPut (AOP (result), one, 0);
11546 aopPut (AOP (result), zero, 0);
11551 /* the right is also a bit variable */
11552 if (AOP_TYPE (right) == AOP_CRY)
11554 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11555 aopPut (AOP (result), "c", 0);
11559 /* we need to or */
11561 aopPut (AOP (result), "a", 0);
11565 /* if they are the same size : or less */
11566 if (AOP_SIZE (result) <= AOP_SIZE (right))
11569 /* if they are in the same place */
11570 if (sameRegs (AOP (right), AOP (result)))
11573 /* if they in different places then copy */
11574 size = AOP_SIZE (result);
11576 _startLazyDPSEvaluation ();
11579 aopPut (AOP (result),
11580 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11584 _endLazyDPSEvaluation ();
11589 /* if the result is of type pointer */
11590 if (IS_PTR (ctype))
11594 sym_link *type = operandType (right);
11596 /* pointer to generic pointer */
11597 if (IS_GENPTR (ctype))
11601 p_type = DCL_TYPE (type);
11605 #if OLD_CAST_BEHAVIOR
11606 /* KV: we are converting a non-pointer type to
11607 * a generic pointer. This (ifdef'd out) code
11608 * says that the resulting generic pointer
11609 * should have the same class as the storage
11610 * location of the non-pointer variable.
11612 * For example, converting an int (which happens
11613 * to be stored in DATA space) to a pointer results
11614 * in a DATA generic pointer; if the original int
11615 * in XDATA space, so will be the resulting pointer.
11617 * I don't like that behavior, and thus this change:
11618 * all such conversions will be forced to XDATA and
11619 * throw a warning. If you want some non-XDATA
11620 * type, or you want to suppress the warning, you
11621 * must go through an intermediate cast, like so:
11623 * char _generic *gp = (char _xdata *)(intVar);
11625 sym_link *etype = getSpec (type);
11627 /* we have to go by the storage class */
11628 if (SPEC_OCLS (etype) != generic)
11630 p_type = PTR_TYPE (SPEC_OCLS (etype));
11635 /* Converting unknown class (i.e. register variable)
11636 * to generic pointer. This is not good, but
11637 * we'll make a guess (and throw a warning).
11640 werror (W_INT_TO_GEN_PTR_CAST);
11644 /* the first two bytes are known */
11645 size = GPTRSIZE - 1;
11647 _startLazyDPSEvaluation ();
11650 aopPut (AOP (result),
11651 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11655 _endLazyDPSEvaluation ();
11657 /* the last byte depending on type */
11659 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11664 // pointerTypeToGPByte will have bitched.
11668 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11669 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11674 /* just copy the pointers */
11675 size = AOP_SIZE (result);
11677 _startLazyDPSEvaluation ();
11680 aopPut (AOP (result),
11681 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11685 _endLazyDPSEvaluation ();
11689 /* so we now know that the size of destination is greater
11690 than the size of the source */
11691 /* we move to result for the size of source */
11692 size = AOP_SIZE (right);
11694 _startLazyDPSEvaluation ();
11697 aopPut (AOP (result),
11698 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11702 _endLazyDPSEvaluation ();
11704 /* now depending on the sign of the source && destination */
11705 size = AOP_SIZE (result) - AOP_SIZE (right);
11706 /* if unsigned or not an integral type */
11707 /* also, if the source is a bit, we don't need to sign extend, because
11708 * it can't possibly have set the sign bit.
11710 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
11714 aopPut (AOP (result), zero, offset++);
11719 /* we need to extend the sign :{ */
11720 MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11721 FALSE, FALSE, NULL));
11722 emitcode ("rlc", "a");
11723 emitcode ("subb", "a,acc");
11725 aopPut (AOP (result), "a", offset++);
11728 /* we are done hurray !!!! */
11731 freeAsmop (right, NULL, ic, TRUE);
11732 freeAsmop (result, NULL, ic, TRUE);
11736 /*-----------------------------------------------------------------*/
11737 /* genDjnz - generate decrement & jump if not zero instrucion */
11738 /*-----------------------------------------------------------------*/
11740 genDjnz (iCode * ic, iCode * ifx)
11742 symbol *lbl, *lbl1;
11746 /* if the if condition has a false label
11747 then we cannot save */
11748 if (IC_FALSE (ifx))
11751 /* if the minus is not of the form
11753 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11754 !IS_OP_LITERAL (IC_RIGHT (ic)))
11757 if (operandLitValue (IC_RIGHT (ic)) != 1)
11760 /* if the size of this greater than one then no
11762 if (getSize (operandType (IC_RESULT (ic))) > 1)
11765 /* otherwise we can save BIG */
11766 D(emitcode(";", "genDjnz"););
11768 lbl = newiTempLabel (NULL);
11769 lbl1 = newiTempLabel (NULL);
11771 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11773 if (AOP_NEEDSACC(IC_RESULT(ic)))
11775 /* If the result is accessed indirectly via
11776 * the accumulator, we must explicitly write
11777 * it back after the decrement.
11779 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11781 if (strcmp(rByte, "a"))
11783 /* Something is hopelessly wrong */
11784 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11785 __FILE__, __LINE__);
11786 /* We can just give up; the generated code will be inefficient,
11787 * but what the hey.
11789 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11792 emitcode ("dec", "%s", rByte);
11793 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11794 emitcode ("jnz", "!tlabel", lbl->key + 100);
11796 else if (IS_AOP_PREG (IC_RESULT (ic)))
11798 emitcode ("dec", "%s",
11799 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11800 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11801 emitcode ("jnz", "!tlabel", lbl->key + 100);
11805 emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11808 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11809 emitcode ("", "!tlabeldef", lbl->key + 100);
11810 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11811 emitcode ("", "!tlabeldef", lbl1->key + 100);
11813 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11814 ifx->generated = 1;
11818 /*-----------------------------------------------------------------*/
11819 /* genReceive - generate code for a receive iCode */
11820 /*-----------------------------------------------------------------*/
11822 genReceive (iCode * ic)
11824 int size = getSize (operandType (IC_RESULT (ic)));
11828 D (emitcode (";", "genReceive "););
11830 if (ic->argreg == 1)
11832 /* first parameter */
11833 if (AOP_IS_STR(IC_RESULT(ic)))
11835 /* Nothing to do: it's already in the proper place. */
11842 useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11843 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11844 IS_TRUE_SYMOP (IC_RESULT (ic)));
11847 aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11850 /* Sanity checking... */
11851 if (AOP_USESDPTR(IC_RESULT(ic)))
11853 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11854 "genReceive got unexpected DPTR.");
11856 assignResultValue (IC_RESULT (ic));
11861 /* second receive onwards */
11862 /* this gets a little tricky since unused recevies will be
11863 eliminated, we have saved the reg in the type field . and
11864 we use that to figure out which register to use */
11865 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11866 rb1off = ic->argreg;
11869 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11872 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11875 /*-----------------------------------------------------------------*/
11876 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
11877 /*-----------------------------------------------------------------*/
11878 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11880 operand *from , *to , *count;
11885 /* we know it has to be 3 parameters */
11886 assert (nparms == 3);
11888 rsave = newBitVect(16);
11889 /* save DPTR if it needs to be saved */
11890 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11891 if (bitVectBitValue(ic->rMask,i))
11892 rsave = bitVectSetBit(rsave,i);
11894 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11895 ds390_rUmaskForOp (IC_RESULT(ic))));
11902 aopOp (from, ic->next, FALSE, FALSE);
11904 /* get from into DPTR1 */
11905 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11906 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11907 if (options.model == MODEL_FLAT24) {
11908 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11911 freeAsmop (from, NULL, ic, FALSE);
11912 aopOp (to, ic, FALSE, FALSE);
11913 /* get "to" into DPTR */
11914 /* if the operand is already in dptr
11915 then we do nothing else we move the value to dptr */
11916 if (AOP_TYPE (to) != AOP_STR) {
11917 /* if already in DPTR then we need to push */
11918 if (AOP_TYPE(to) == AOP_DPTR) {
11919 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11920 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11921 if (options.model == MODEL_FLAT24)
11922 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11923 emitcode ("pop", "dph");
11924 emitcode ("pop", "dpl");
11926 _startLazyDPSEvaluation ();
11927 /* if this is remateriazable */
11928 if (AOP_TYPE (to) == AOP_IMMD) {
11929 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11930 } else { /* we need to get it byte by byte */
11931 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11932 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11933 if (options.model == MODEL_FLAT24) {
11934 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11937 _endLazyDPSEvaluation ();
11940 freeAsmop (to, NULL, ic, FALSE);
11941 _G.dptrInUse = _G.dptr1InUse = 1;
11942 aopOp (count, ic->next->next, FALSE,FALSE);
11943 lbl =newiTempLabel(NULL);
11945 /* now for the actual copy */
11946 if (AOP_TYPE(count) == AOP_LIT &&
11947 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11948 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11950 emitcode ("lcall","__bi_memcpyc2x_s");
11952 emitcode ("lcall","__bi_memcpyx2x_s");
11954 freeAsmop (count, NULL, ic, FALSE);
11956 symbol *lbl1 = newiTempLabel(NULL);
11958 emitcode (";"," Auto increment but no djnz");
11959 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11960 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11961 freeAsmop (count, NULL, ic, FALSE);
11962 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11963 emitcode ("","!tlabeldef",lbl->key+100);
11965 emitcode ("clr","a");
11966 emitcode ("movc", "a,@a+dptr");
11968 emitcode ("movx", "a,@dptr");
11969 emitcode ("movx", "@dptr,a");
11970 emitcode ("inc", "dptr");
11971 emitcode ("inc", "dptr");
11972 emitcode ("mov","a,b");
11973 emitcode ("orl","a,_ap");
11974 emitcode ("jz","!tlabel",lbl1->key+100);
11975 emitcode ("mov","a,_ap");
11976 emitcode ("add","a,#!constbyte",0xFF);
11977 emitcode ("mov","_ap,a");
11978 emitcode ("mov","a,b");
11979 emitcode ("addc","a,#!constbyte",0xFF);
11980 emitcode ("mov","b,a");
11981 emitcode ("sjmp","!tlabel",lbl->key+100);
11982 emitcode ("","!tlabeldef",lbl1->key+100);
11984 emitcode ("mov", "dps,#0");
11985 _G.dptrInUse = _G.dptr1InUse = 0;
11986 unsavermask(rsave);
11990 /*-----------------------------------------------------------------*/
11991 /* genMemcmpX2X - gen code for memcmp xdata to xdata */
11992 /*-----------------------------------------------------------------*/
11993 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11995 operand *from , *to , *count;
12000 /* we know it has to be 3 parameters */
12001 assert (nparms == 3);
12003 rsave = newBitVect(16);
12004 /* save DPTR if it needs to be saved */
12005 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12006 if (bitVectBitValue(ic->rMask,i))
12007 rsave = bitVectSetBit(rsave,i);
12009 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12010 ds390_rUmaskForOp (IC_RESULT(ic))));
12017 aopOp (from, ic->next, FALSE, FALSE);
12019 /* get from into DPTR1 */
12020 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12021 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12022 if (options.model == MODEL_FLAT24) {
12023 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12026 freeAsmop (from, NULL, ic, FALSE);
12027 aopOp (to, ic, FALSE, FALSE);
12028 /* get "to" into DPTR */
12029 /* if the operand is already in dptr
12030 then we do nothing else we move the value to dptr */
12031 if (AOP_TYPE (to) != AOP_STR) {
12032 /* if already in DPTR then we need to push */
12033 if (AOP_TYPE(to) == AOP_DPTR) {
12034 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12035 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12036 if (options.model == MODEL_FLAT24)
12037 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12038 emitcode ("pop", "dph");
12039 emitcode ("pop", "dpl");
12041 _startLazyDPSEvaluation ();
12042 /* if this is remateriazable */
12043 if (AOP_TYPE (to) == AOP_IMMD) {
12044 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12045 } else { /* we need to get it byte by byte */
12046 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12047 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12048 if (options.model == MODEL_FLAT24) {
12049 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12052 _endLazyDPSEvaluation ();
12055 freeAsmop (to, NULL, ic, FALSE);
12056 _G.dptrInUse = _G.dptr1InUse = 1;
12057 aopOp (count, ic->next->next, FALSE,FALSE);
12058 lbl =newiTempLabel(NULL);
12059 lbl2 =newiTempLabel(NULL);
12061 /* now for the actual compare */
12062 if (AOP_TYPE(count) == AOP_LIT &&
12063 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12064 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12066 emitcode("lcall","__bi_memcmpc2x_s");
12068 emitcode("lcall","__bi_memcmpx2x_s");
12069 freeAsmop (count, NULL, ic, FALSE);
12070 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12071 aopPut(AOP(IC_RESULT(ic)),"a",0);
12072 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12074 symbol *lbl1 = newiTempLabel(NULL);
12076 emitcode("push","ar0");
12077 emitcode (";"," Auto increment but no djnz");
12078 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12079 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12080 freeAsmop (count, NULL, ic, FALSE);
12081 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12082 emitcode ("","!tlabeldef",lbl->key+100);
12084 emitcode ("clr","a");
12085 emitcode ("movc", "a,@a+dptr");
12087 emitcode ("movx", "a,@dptr");
12088 emitcode ("mov","r0,a");
12089 emitcode ("movx", "a,@dptr");
12090 emitcode ("clr","c");
12091 emitcode ("subb","a,r0");
12092 emitcode ("jnz","!tlabel",lbl2->key+100);
12093 emitcode ("inc", "dptr");
12094 emitcode ("inc", "dptr");
12095 emitcode ("mov","a,b");
12096 emitcode ("orl","a,_ap");
12097 emitcode ("jz","!tlabel",lbl1->key+100);
12098 emitcode ("mov","a,_ap");
12099 emitcode ("add","a,#!constbyte",0xFF);
12100 emitcode ("mov","_ap,a");
12101 emitcode ("mov","a,b");
12102 emitcode ("addc","a,#!constbyte",0xFF);
12103 emitcode ("mov","b,a");
12104 emitcode ("sjmp","!tlabel",lbl->key+100);
12105 emitcode ("","!tlabeldef",lbl1->key+100);
12106 emitcode ("clr","a");
12107 emitcode ("","!tlabeldef",lbl2->key+100);
12108 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12109 aopPut(AOP(IC_RESULT(ic)),"a",0);
12110 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12111 emitcode("pop","ar0");
12112 emitcode ("mov", "dps,#0");
12114 _G.dptrInUse = _G.dptr1InUse = 0;
12115 unsavermask(rsave);
12119 /*-----------------------------------------------------------------*/
12120 /* genInp - gen code for __builtin_inp read data from a mem mapped */
12121 /* port, first parameter output area second parameter pointer to */
12122 /* port third parameter count */
12123 /*-----------------------------------------------------------------*/
12124 static void genInp( iCode *ic, int nparms, operand **parms)
12126 operand *from , *to , *count;
12131 /* we know it has to be 3 parameters */
12132 assert (nparms == 3);
12134 rsave = newBitVect(16);
12135 /* save DPTR if it needs to be saved */
12136 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12137 if (bitVectBitValue(ic->rMask,i))
12138 rsave = bitVectSetBit(rsave,i);
12140 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12141 ds390_rUmaskForOp (IC_RESULT(ic))));
12148 aopOp (from, ic->next, FALSE, FALSE);
12150 /* get from into DPTR1 */
12151 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12152 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12153 if (options.model == MODEL_FLAT24) {
12154 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12157 freeAsmop (from, NULL, ic, FALSE);
12158 aopOp (to, ic, FALSE, FALSE);
12159 /* get "to" into DPTR */
12160 /* if the operand is already in dptr
12161 then we do nothing else we move the value to dptr */
12162 if (AOP_TYPE (to) != AOP_STR) {
12163 /* if already in DPTR then we need to push */
12164 if (AOP_TYPE(to) == AOP_DPTR) {
12165 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12166 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12167 if (options.model == MODEL_FLAT24)
12168 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12169 emitcode ("pop", "dph");
12170 emitcode ("pop", "dpl");
12172 _startLazyDPSEvaluation ();
12173 /* if this is remateriazable */
12174 if (AOP_TYPE (to) == AOP_IMMD) {
12175 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12176 } else { /* we need to get it byte by byte */
12177 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12178 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12179 if (options.model == MODEL_FLAT24) {
12180 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12183 _endLazyDPSEvaluation ();
12186 freeAsmop (to, NULL, ic, FALSE);
12188 _G.dptrInUse = _G.dptr1InUse = 1;
12189 aopOp (count, ic->next->next, FALSE,FALSE);
12190 lbl =newiTempLabel(NULL);
12192 /* now for the actual copy */
12193 if (AOP_TYPE(count) == AOP_LIT &&
12194 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12195 emitcode (";","OH JOY auto increment with djnz (very fast)");
12196 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
12197 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12198 freeAsmop (count, NULL, ic, FALSE);
12199 emitcode ("","!tlabeldef",lbl->key+100);
12200 emitcode ("movx", "a,@dptr"); /* read data from port */
12201 emitcode ("dec","dps"); /* switch to DPTR */
12202 emitcode ("movx", "@dptr,a"); /* save into location */
12203 emitcode ("inc", "dptr"); /* point to next area */
12204 emitcode ("inc","dps"); /* switch to DPTR2 */
12205 emitcode ("djnz","b,!tlabel",lbl->key+100);
12207 symbol *lbl1 = newiTempLabel(NULL);
12209 emitcode (";"," Auto increment but no djnz");
12210 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12211 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12212 freeAsmop (count, NULL, ic, FALSE);
12213 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
12214 emitcode ("","!tlabeldef",lbl->key+100);
12215 emitcode ("movx", "a,@dptr");
12216 emitcode ("dec","dps"); /* switch to DPTR */
12217 emitcode ("movx", "@dptr,a");
12218 emitcode ("inc", "dptr");
12219 emitcode ("inc","dps"); /* switch to DPTR2 */
12220 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
12221 /* emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
12222 emitcode ("mov","a,b");
12223 emitcode ("orl","a,_ap");
12224 emitcode ("jz","!tlabel",lbl1->key+100);
12225 emitcode ("mov","a,_ap");
12226 emitcode ("add","a,#!constbyte",0xFF);
12227 emitcode ("mov","_ap,a");
12228 emitcode ("mov","a,b");
12229 emitcode ("addc","a,#!constbyte",0xFF);
12230 emitcode ("mov","b,a");
12231 emitcode ("sjmp","!tlabel",lbl->key+100);
12232 emitcode ("","!tlabeldef",lbl1->key+100);
12234 emitcode ("mov", "dps,#0");
12235 _G.dptrInUse = _G.dptr1InUse = 0;
12236 unsavermask(rsave);
12240 /*-----------------------------------------------------------------*/
12241 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
12242 /* port, first parameter output area second parameter pointer to */
12243 /* port third parameter count */
12244 /*-----------------------------------------------------------------*/
12245 static void genOutp( iCode *ic, int nparms, operand **parms)
12247 operand *from , *to , *count;
12252 /* we know it has to be 3 parameters */
12253 assert (nparms == 3);
12255 rsave = newBitVect(16);
12256 /* save DPTR if it needs to be saved */
12257 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12258 if (bitVectBitValue(ic->rMask,i))
12259 rsave = bitVectSetBit(rsave,i);
12261 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12262 ds390_rUmaskForOp (IC_RESULT(ic))));
12269 aopOp (from, ic->next, FALSE, FALSE);
12271 /* get from into DPTR1 */
12272 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12273 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12274 if (options.model == MODEL_FLAT24) {
12275 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12278 freeAsmop (from, NULL, ic, FALSE);
12279 aopOp (to, ic, FALSE, FALSE);
12280 /* get "to" into DPTR */
12281 /* if the operand is already in dptr
12282 then we do nothing else we move the value to dptr */
12283 if (AOP_TYPE (to) != AOP_STR) {
12284 /* if already in DPTR then we need to push */
12285 if (AOP_TYPE(to) == AOP_DPTR) {
12286 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12287 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12288 if (options.model == MODEL_FLAT24)
12289 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12290 emitcode ("pop", "dph");
12291 emitcode ("pop", "dpl");
12293 _startLazyDPSEvaluation ();
12294 /* if this is remateriazable */
12295 if (AOP_TYPE (to) == AOP_IMMD) {
12296 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12297 } else { /* we need to get it byte by byte */
12298 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12299 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12300 if (options.model == MODEL_FLAT24) {
12301 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12304 _endLazyDPSEvaluation ();
12307 freeAsmop (to, NULL, ic, FALSE);
12309 _G.dptrInUse = _G.dptr1InUse = 1;
12310 aopOp (count, ic->next->next, FALSE,FALSE);
12311 lbl =newiTempLabel(NULL);
12313 /* now for the actual copy */
12314 if (AOP_TYPE(count) == AOP_LIT &&
12315 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12316 emitcode (";","OH JOY auto increment with djnz (very fast)");
12317 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
12318 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12319 emitcode ("","!tlabeldef",lbl->key+100);
12320 emitcode ("movx", "a,@dptr"); /* read data from port */
12321 emitcode ("inc","dps"); /* switch to DPTR2 */
12322 emitcode ("movx", "@dptr,a"); /* save into location */
12323 emitcode ("inc", "dptr"); /* point to next area */
12324 emitcode ("dec","dps"); /* switch to DPTR */
12325 emitcode ("djnz","b,!tlabel",lbl->key+100);
12326 freeAsmop (count, NULL, ic, FALSE);
12328 symbol *lbl1 = newiTempLabel(NULL);
12330 emitcode (";"," Auto increment but no djnz");
12331 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12332 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12333 freeAsmop (count, NULL, ic, FALSE);
12334 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
12335 emitcode ("","!tlabeldef",lbl->key+100);
12336 emitcode ("movx", "a,@dptr");
12337 emitcode ("inc", "dptr");
12338 emitcode ("inc","dps"); /* switch to DPTR2 */
12339 emitcode ("movx", "@dptr,a");
12340 emitcode ("dec","dps"); /* switch to DPTR */
12341 emitcode ("mov","a,b");
12342 emitcode ("orl","a,_ap");
12343 emitcode ("jz","!tlabel",lbl1->key+100);
12344 emitcode ("mov","a,_ap");
12345 emitcode ("add","a,#!constbyte",0xFF);
12346 emitcode ("mov","_ap,a");
12347 emitcode ("mov","a,b");
12348 emitcode ("addc","a,#!constbyte",0xFF);
12349 emitcode ("mov","b,a");
12350 emitcode ("sjmp","!tlabel",lbl->key+100);
12351 emitcode ("","!tlabeldef",lbl1->key+100);
12353 emitcode ("mov", "dps,#0");
12354 _G.dptrInUse = _G.dptr1InUse = 0;
12355 unsavermask(rsave);
12359 /*-----------------------------------------------------------------*/
12360 /* genSwapW - swap lower & high order bytes */
12361 /*-----------------------------------------------------------------*/
12362 static void genSwapW(iCode *ic, int nparms, operand **parms)
12366 assert (nparms==1);
12369 dest=IC_RESULT(ic);
12371 assert(getSize(operandType(src))==2);
12373 aopOp (src, ic, FALSE, FALSE);
12374 emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
12376 MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
12378 freeAsmop (src, NULL, ic, FALSE);
12380 aopOp (dest,ic, FALSE, FALSE);
12381 aopPut(AOP(dest),"b",0);
12382 aopPut(AOP(dest),"a",1);
12383 freeAsmop (dest, NULL, ic, FALSE);
12386 /*-----------------------------------------------------------------*/
12387 /* genMemsetX - gencode for memSetX data */
12388 /*-----------------------------------------------------------------*/
12389 static void genMemsetX(iCode *ic, int nparms, operand **parms)
12391 operand *to , *val , *count;
12397 /* we know it has to be 3 parameters */
12398 assert (nparms == 3);
12404 /* save DPTR if it needs to be saved */
12405 rsave = newBitVect(16);
12406 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12407 if (bitVectBitValue(ic->rMask,i))
12408 rsave = bitVectSetBit(rsave,i);
12410 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12411 ds390_rUmaskForOp (IC_RESULT(ic))));
12414 aopOp (to, ic, FALSE, FALSE);
12415 /* get "to" into DPTR */
12416 /* if the operand is already in dptr
12417 then we do nothing else we move the value to dptr */
12418 if (AOP_TYPE (to) != AOP_STR) {
12419 /* if already in DPTR then we need to push */
12420 if (AOP_TYPE(to) == AOP_DPTR) {
12421 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12422 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12423 if (options.model == MODEL_FLAT24)
12424 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12425 emitcode ("pop", "dph");
12426 emitcode ("pop", "dpl");
12428 _startLazyDPSEvaluation ();
12429 /* if this is remateriazable */
12430 if (AOP_TYPE (to) == AOP_IMMD) {
12431 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12432 } else { /* we need to get it byte by byte */
12433 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12434 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12435 if (options.model == MODEL_FLAT24) {
12436 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12439 _endLazyDPSEvaluation ();
12442 freeAsmop (to, NULL, ic, FALSE);
12444 aopOp (val, ic->next->next, FALSE,FALSE);
12445 aopOp (count, ic->next->next, FALSE,FALSE);
12446 lbl =newiTempLabel(NULL);
12447 /* now for the actual copy */
12448 if (AOP_TYPE(count) == AOP_LIT &&
12449 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12450 l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
12451 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12453 emitcode ("","!tlabeldef",lbl->key+100);
12454 emitcode ("movx", "@dptr,a");
12455 emitcode ("inc", "dptr");
12456 emitcode ("djnz","b,!tlabel",lbl->key+100);
12458 symbol *lbl1 = newiTempLabel(NULL);
12460 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12461 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12462 emitcode ("","!tlabeldef",lbl->key+100);
12463 MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
12464 emitcode ("movx", "@dptr,a");
12465 emitcode ("inc", "dptr");
12466 emitcode ("mov","a,b");
12467 emitcode ("orl","a,_ap");
12468 emitcode ("jz","!tlabel",lbl1->key+100);
12469 emitcode ("mov","a,_ap");
12470 emitcode ("add","a,#!constbyte",0xFF);
12471 emitcode ("mov","_ap,a");
12472 emitcode ("mov","a,b");
12473 emitcode ("addc","a,#!constbyte",0xFF);
12474 emitcode ("mov","b,a");
12475 emitcode ("sjmp","!tlabel",lbl->key+100);
12476 emitcode ("","!tlabeldef",lbl1->key+100);
12478 freeAsmop (count, NULL, ic, FALSE);
12479 unsavermask(rsave);
12482 /*-----------------------------------------------------------------*/
12483 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
12484 /*-----------------------------------------------------------------*/
12485 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
12488 operand *pnum, *result;
12491 assert (nparms==1);
12492 /* save registers that need to be saved */
12493 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12494 ds390_rUmaskForOp (IC_RESULT(ic))));
12497 aopOp (pnum, ic, FALSE, FALSE);
12498 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12499 freeAsmop (pnum, NULL, ic, FALSE);
12500 emitcode ("lcall","NatLib_LoadPrimitive");
12501 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12502 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
12503 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
12504 for (i = (size-1) ; i >= 0 ; i-- ) {
12505 emitcode ("push","a%s",javaRet[i]);
12507 for (i=0; i < size ; i++ ) {
12508 emitcode ("pop","a%s",
12509 aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
12512 for (i = 0 ; i < size ; i++ ) {
12513 aopPut(AOP(result),javaRet[i],i);
12516 freeAsmop (result, NULL, ic, FALSE);
12517 unsavermask(rsave);
12520 /*-----------------------------------------------------------------*/
12521 /* genNatLibLoadPointer - calls TINI api function to load pointer */
12522 /*-----------------------------------------------------------------*/
12523 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
12526 operand *pnum, *result;
12530 assert (nparms==1);
12531 /* save registers that need to be saved */
12532 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12533 ds390_rUmaskForOp (IC_RESULT(ic))));
12536 aopOp (pnum, ic, FALSE, FALSE);
12537 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12538 freeAsmop (pnum, NULL, ic, FALSE);
12539 emitcode ("lcall","NatLib_LoadPointer");
12540 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12541 if (AOP_TYPE(result)!=AOP_STR) {
12542 for (i = 0 ; i < size ; i++ ) {
12543 aopPut(AOP(result),fReturn[i],i);
12546 freeAsmop (result, NULL, ic, FALSE);
12547 unsavermask(rsave);
12550 /*-----------------------------------------------------------------*/
12551 /* genNatLibInstallStateBlock - */
12552 /*-----------------------------------------------------------------*/
12553 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
12554 operand **parms, const char *name)
12557 operand *psb, *handle;
12558 assert (nparms==2);
12560 /* save registers that need to be saved */
12561 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12562 ds390_rUmaskForOp (IC_RESULT(ic))));
12566 /* put pointer to state block into DPTR1 */
12567 aopOp (psb, ic, FALSE, FALSE);
12568 if (AOP_TYPE (psb) == AOP_IMMD) {
12569 emitcode ("mov","dps,#1");
12570 emitcode ("mov", "dptr,%s",
12571 aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12572 emitcode ("mov","dps,#0");
12574 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12575 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12576 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12578 freeAsmop (psb, NULL, ic, FALSE);
12580 /* put libraryID into DPTR */
12581 emitcode ("mov","dptr,#LibraryID");
12583 /* put handle into r3:r2 */
12584 aopOp (handle, ic, FALSE, FALSE);
12585 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12586 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12587 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12588 emitcode ("pop","ar3");
12589 emitcode ("pop","ar2");
12591 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12592 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12594 freeAsmop (psb, NULL, ic, FALSE);
12596 /* make the call */
12597 emitcode ("lcall","NatLib_Install%sStateBlock",name);
12599 /* put return value into place*/
12601 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12603 aopPut(AOP(IC_RESULT(ic)),"a",0);
12604 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12605 unsavermask(rsave);
12608 /*-----------------------------------------------------------------*/
12609 /* genNatLibRemoveStateBlock - */
12610 /*-----------------------------------------------------------------*/
12611 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12617 /* save registers that need to be saved */
12618 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12619 ds390_rUmaskForOp (IC_RESULT(ic))));
12621 /* put libraryID into DPTR */
12622 emitcode ("mov","dptr,#LibraryID");
12623 /* make the call */
12624 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12625 unsavermask(rsave);
12628 /*-----------------------------------------------------------------*/
12629 /* genNatLibGetStateBlock - */
12630 /*-----------------------------------------------------------------*/
12631 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12632 operand **parms,const char *name)
12635 symbol *lbl = newiTempLabel(NULL);
12638 /* save registers that need to be saved */
12639 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12640 ds390_rUmaskForOp (IC_RESULT(ic))));
12642 /* put libraryID into DPTR */
12643 emitcode ("mov","dptr,#LibraryID");
12644 /* make the call */
12645 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12646 emitcode ("jnz","!tlabel",lbl->key+100);
12648 /* put return value into place */
12649 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12650 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12651 emitcode ("push","ar3");
12652 emitcode ("push","ar2");
12653 emitcode ("pop","%s",
12654 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12655 emitcode ("pop","%s",
12656 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12658 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12659 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12661 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12662 emitcode ("","!tlabeldef",lbl->key+100);
12663 unsavermask(rsave);
12666 /*-----------------------------------------------------------------*/
12667 /* genMMMalloc - */
12668 /*-----------------------------------------------------------------*/
12669 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12670 int size, const char *name)
12675 symbol *lbl = newiTempLabel(NULL);
12677 assert (nparms == 1);
12678 /* save registers that need to be saved */
12679 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12680 ds390_rUmaskForOp (IC_RESULT(ic))));
12683 aopOp (bsize,ic,FALSE,FALSE);
12685 /* put the size in R4-R2 */
12686 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12687 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12688 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12690 emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12691 emitcode("pop","ar4");
12693 emitcode("pop","ar3");
12694 emitcode("pop","ar2");
12696 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12697 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12699 emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12702 freeAsmop (bsize, NULL, ic, FALSE);
12704 /* make the call */
12705 emitcode ("lcall","MM_%s",name);
12706 emitcode ("jz","!tlabel",lbl->key+100);
12707 emitcode ("mov","r2,#!constbyte",0xff);
12708 emitcode ("mov","r3,#!constbyte",0xff);
12709 emitcode ("","!tlabeldef",lbl->key+100);
12710 /* we don't care about the pointer : we just save the handle */
12711 rsym = OP_SYMBOL(IC_RESULT(ic));
12712 if (rsym->liveFrom != rsym->liveTo) {
12713 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12714 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12715 emitcode ("push","ar3");
12716 emitcode ("push","ar2");
12717 emitcode ("pop","%s",
12718 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12719 emitcode ("pop","%s",
12720 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12722 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12723 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12725 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12727 unsavermask(rsave);
12730 /*-----------------------------------------------------------------*/
12732 /*-----------------------------------------------------------------*/
12733 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12738 assert (nparms == 1);
12739 /* save registers that need to be saved */
12740 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12741 ds390_rUmaskForOp (IC_RESULT(ic))));
12744 aopOp (handle,ic,FALSE,FALSE);
12746 /* put the size in R4-R2 */
12747 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12748 emitcode("push","%s",
12749 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12750 emitcode("push","%s",
12751 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12752 emitcode("pop","ar3");
12753 emitcode("pop","ar2");
12755 emitcode ("mov","r2,%s",
12756 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12757 emitcode ("mov","r3,%s",
12758 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12760 freeAsmop (handle, NULL, ic, FALSE);
12762 /* make the call */
12763 emitcode ("lcall","MM_Deref");
12766 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12767 if (rsym->liveFrom != rsym->liveTo) {
12768 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12769 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12770 _startLazyDPSEvaluation ();
12772 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12773 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12774 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12776 _endLazyDPSEvaluation ();
12781 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12782 unsavermask(rsave);
12785 /*-----------------------------------------------------------------*/
12786 /* genMMUnrestrictedPersist - */
12787 /*-----------------------------------------------------------------*/
12788 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12793 assert (nparms == 1);
12794 /* save registers that need to be saved */
12795 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12796 ds390_rUmaskForOp (IC_RESULT(ic))));
12799 aopOp (handle,ic,FALSE,FALSE);
12801 /* put the size in R3-R2 */
12802 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12803 emitcode("push","%s",
12804 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12805 emitcode("push","%s",
12806 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12807 emitcode("pop","ar3");
12808 emitcode("pop","ar2");
12810 emitcode ("mov","r2,%s",
12811 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12812 emitcode ("mov","r3,%s",
12813 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12815 freeAsmop (handle, NULL, ic, FALSE);
12817 /* make the call */
12818 emitcode ("lcall","MM_UnrestrictedPersist");
12821 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12822 if (rsym->liveFrom != rsym->liveTo) {
12823 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12824 aopPut(AOP(IC_RESULT(ic)),"a",0);
12825 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12828 unsavermask(rsave);
12831 /*-----------------------------------------------------------------*/
12832 /* genSystemExecJavaProcess - */
12833 /*-----------------------------------------------------------------*/
12834 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12837 operand *handle, *pp;
12839 assert (nparms==2);
12840 /* save registers that need to be saved */
12841 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12842 ds390_rUmaskForOp (IC_RESULT(ic))));
12847 /* put the handle in R3-R2 */
12848 aopOp (handle,ic,FALSE,FALSE);
12849 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12850 emitcode("push","%s",
12851 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12852 emitcode("push","%s",
12853 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12854 emitcode("pop","ar3");
12855 emitcode("pop","ar2");
12857 emitcode ("mov","r2,%s",
12858 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12859 emitcode ("mov","r3,%s",
12860 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12862 freeAsmop (handle, NULL, ic, FALSE);
12864 /* put pointer in DPTR */
12865 aopOp (pp,ic,FALSE,FALSE);
12866 if (AOP_TYPE(pp) == AOP_IMMD) {
12867 emitcode ("mov", "dptr,%s",
12868 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12869 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12870 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12871 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12872 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12874 freeAsmop (handle, NULL, ic, FALSE);
12876 /* make the call */
12877 emitcode ("lcall","System_ExecJavaProcess");
12879 /* put result in place */
12881 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12882 if (rsym->liveFrom != rsym->liveTo) {
12883 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12884 aopPut(AOP(IC_RESULT(ic)),"a",0);
12885 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12889 unsavermask(rsave);
12892 /*-----------------------------------------------------------------*/
12893 /* genSystemRTCRegisters - */
12894 /*-----------------------------------------------------------------*/
12895 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12901 assert (nparms==1);
12902 /* save registers that need to be saved */
12903 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12904 ds390_rUmaskForOp (IC_RESULT(ic))));
12907 /* put pointer in DPTR */
12908 aopOp (pp,ic,FALSE,FALSE);
12909 if (AOP_TYPE (pp) == AOP_IMMD) {
12910 emitcode ("mov","dps,#1");
12911 emitcode ("mov", "dptr,%s",
12912 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12913 emitcode ("mov","dps,#0");
12915 emitcode ("mov","dpl1,%s",
12916 aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12917 emitcode ("mov","dph1,%s",
12918 aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12919 emitcode ("mov","dpx1,%s",
12920 aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12922 freeAsmop (pp, NULL, ic, FALSE);
12924 /* make the call */
12925 emitcode ("lcall","System_%sRTCRegisters",name);
12927 unsavermask(rsave);
12930 /*-----------------------------------------------------------------*/
12931 /* genSystemThreadSleep - */
12932 /*-----------------------------------------------------------------*/
12933 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12938 assert (nparms==1);
12939 /* save registers that need to be saved */
12940 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12941 ds390_rUmaskForOp (IC_RESULT(ic))));
12944 aopOp(to,ic,FALSE,FALSE);
12945 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12946 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12947 emitcode ("push","%s",
12948 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12949 emitcode ("push","%s",
12950 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12951 emitcode ("push","%s",
12952 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12953 emitcode ("push","%s",
12954 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12955 emitcode ("pop","ar3");
12956 emitcode ("pop","ar2");
12957 emitcode ("pop","ar1");
12958 emitcode ("pop","ar0");
12960 emitcode ("mov","r0,%s",
12961 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12962 emitcode ("mov","r1,%s",
12963 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12964 emitcode ("mov","r2,%s",
12965 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12966 emitcode ("mov","r3,%s",
12967 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12969 freeAsmop (to, NULL, ic, FALSE);
12971 /* suspend in acc */
12973 aopOp(s,ic,FALSE,FALSE);
12974 emitcode ("mov","a,%s",
12975 aopGet(AOP(s),0,FALSE,TRUE,NULL));
12976 freeAsmop (s, NULL, ic, FALSE);
12978 /* make the call */
12979 emitcode ("lcall","System_%s",name);
12981 unsavermask(rsave);
12984 /*-----------------------------------------------------------------*/
12985 /* genSystemThreadResume - */
12986 /*-----------------------------------------------------------------*/
12987 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12992 assert (nparms==2);
12993 /* save registers that need to be saved */
12994 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12995 ds390_rUmaskForOp (IC_RESULT(ic))));
13001 aopOp(pid,ic,FALSE,FALSE);
13002 emitcode ("mov","r0,%s",
13003 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
13004 freeAsmop (pid, NULL, ic, FALSE);
13007 aopOp(tid,ic,FALSE,FALSE);
13008 emitcode ("mov","a,%s",
13009 aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
13010 freeAsmop (tid, NULL, ic, FALSE);
13012 emitcode ("lcall","System_ThreadResume");
13014 /* put result into place */
13016 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13017 if (rsym->liveFrom != rsym->liveTo) {
13018 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13019 aopPut(AOP(IC_RESULT(ic)),"a",0);
13020 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13023 unsavermask(rsave);
13026 /*-----------------------------------------------------------------*/
13027 /* genSystemProcessResume - */
13028 /*-----------------------------------------------------------------*/
13029 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
13034 assert (nparms==1);
13035 /* save registers that need to be saved */
13036 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13037 ds390_rUmaskForOp (IC_RESULT(ic))));
13042 aopOp(pid,ic,FALSE,FALSE);
13043 emitcode ("mov","a,%s",
13044 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
13045 freeAsmop (pid, NULL, ic, FALSE);
13047 emitcode ("lcall","System_ProcessResume");
13049 unsavermask(rsave);
13052 /*-----------------------------------------------------------------*/
13054 /*-----------------------------------------------------------------*/
13055 static void genSystem (iCode *ic,int nparms,char *name)
13057 assert(nparms == 0);
13059 emitcode ("lcall","System_%s",name);
13062 /*-----------------------------------------------------------------*/
13063 /* genSystemPoll - */
13064 /*-----------------------------------------------------------------*/
13065 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
13070 assert (nparms==1);
13071 /* save registers that need to be saved */
13072 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13073 ds390_rUmaskForOp (IC_RESULT(ic))));
13076 aopOp (fp,ic,FALSE,FALSE);
13077 if (AOP_TYPE (fp) == AOP_IMMD) {
13078 emitcode ("mov", "dptr,%s",
13079 aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
13080 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
13081 emitcode ("mov","dpl,%s",
13082 aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
13083 emitcode ("mov","dph,%s",
13084 aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
13085 emitcode ("mov","dpx,%s",
13086 aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
13088 freeAsmop (fp, NULL, ic, FALSE);
13090 emitcode ("lcall","System_%sPoll",name);
13092 /* put result into place */
13094 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13095 if (rsym->liveFrom != rsym->liveTo) {
13096 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13097 aopPut(AOP(IC_RESULT(ic)),"a",0);
13098 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13101 unsavermask(rsave);
13104 /*-----------------------------------------------------------------*/
13105 /* genSystemGetCurrentID - */
13106 /*-----------------------------------------------------------------*/
13107 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
13109 assert (nparms==0);
13111 emitcode ("lcall","System_GetCurrent%sId",name);
13112 /* put result into place */
13114 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13115 if (rsym->liveFrom != rsym->liveTo) {
13116 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13117 aopPut(AOP(IC_RESULT(ic)),"a",0);
13118 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13123 /*-----------------------------------------------------------------*/
13124 /* genDummyRead - generate code for dummy read of volatiles */
13125 /*-----------------------------------------------------------------*/
13127 genDummyRead (iCode * ic)
13132 D(emitcode("; genDummyRead",""));
13134 op = IC_RIGHT (ic);
13135 if (op && IS_SYMOP (op))
13137 aopOp (op, ic, FALSE, FALSE);
13139 /* if the result is a bit */
13140 if (AOP_TYPE (op) == AOP_CRY)
13141 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13144 /* bit variables done */
13146 size = AOP_SIZE (op);
13150 MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
13155 freeAsmop (op, NULL, ic, TRUE);
13159 if (op && IS_SYMOP (op))
13161 aopOp (op, ic, FALSE, FALSE);
13163 /* if the result is a bit */
13164 if (AOP_TYPE (op) == AOP_CRY)
13165 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13168 /* bit variables done */
13170 size = AOP_SIZE (op);
13174 MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
13179 freeAsmop (op, NULL, ic, TRUE);
13184 /*-----------------------------------------------------------------*/
13185 /* genCritical - generate code for start of a critical sequence */
13186 /*-----------------------------------------------------------------*/
13188 genCritical (iCode *ic)
13190 symbol *tlbl = newiTempLabel (NULL);
13192 D(emitcode("; genCritical",""));
13194 if (IC_RESULT (ic))
13195 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
13197 emitcode ("setb", "c");
13198 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
13199 emitcode ("clr", "c");
13200 emitcode ("", "%05d$:", (tlbl->key + 100));
13202 if (IC_RESULT (ic))
13203 outBitC (IC_RESULT (ic)); /* save old ea in an operand */
13205 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
13207 if (IC_RESULT (ic))
13208 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13211 /*-----------------------------------------------------------------*/
13212 /* genEndCritical - generate code for end of a critical sequence */
13213 /*-----------------------------------------------------------------*/
13215 genEndCritical (iCode *ic)
13217 D(emitcode("; genEndCritical",""));
13221 aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
13222 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
13224 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
13225 emitcode ("mov", "ea,c");
13229 MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE, FALSE));
13230 emitcode ("rrc", "a");
13231 emitcode ("mov", "ea,c");
13233 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
13237 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
13238 emitcode ("mov", "ea,c");
13244 /*-----------------------------------------------------------------*/
13245 /* genBuiltIn - calls the appropriate function to generating code */
13246 /* for a built in function */
13247 /*-----------------------------------------------------------------*/
13248 static void genBuiltIn (iCode *ic)
13250 operand *bi_parms[MAX_BUILTIN_ARGS];
13255 /* get all the arguments for a built in function */
13256 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
13258 /* which function is it */
13259 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
13260 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
13261 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
13262 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
13263 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
13264 } else if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
13265 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
13266 } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
13267 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
13268 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
13269 genMemsetX(bi_iCode,nbi_parms,bi_parms);
13270 } else if (strcmp(bif->name,"__builtin_inp")==0) {
13271 genInp(bi_iCode,nbi_parms,bi_parms);
13272 } else if (strcmp(bif->name,"__builtin_outp")==0) {
13273 genOutp(bi_iCode,nbi_parms,bi_parms);
13274 } else if (strcmp(bif->name,"__builtin_swapw")==0) {
13275 genSwapW(bi_iCode,nbi_parms,bi_parms);
13276 /* JavaNative builtIns */
13277 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
13278 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
13279 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
13280 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
13281 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
13282 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
13283 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
13284 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
13285 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
13286 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
13287 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
13288 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
13289 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
13290 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
13291 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
13292 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
13293 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
13294 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
13295 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
13296 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
13297 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
13298 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
13299 } else if (strcmp(bif->name,"MM_Malloc")==0) {
13300 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
13301 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
13302 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
13303 } else if (strcmp(bif->name,"MM_Free")==0) {
13304 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
13305 } else if (strcmp(bif->name,"MM_Deref")==0) {
13306 genMMDeref(bi_iCode,nbi_parms,bi_parms);
13307 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
13308 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
13309 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
13310 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
13311 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
13312 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
13313 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
13314 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
13315 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
13316 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
13317 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
13318 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
13319 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
13320 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
13321 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
13322 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
13323 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
13324 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13325 } else if (strcmp(bif->name,"System_SaveThread")==0) {
13326 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13327 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
13328 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13329 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
13330 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
13331 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
13332 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
13333 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
13334 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
13335 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
13336 genSystem(bi_iCode,nbi_parms,"ProcessYield");
13337 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
13338 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
13339 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
13340 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
13341 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
13342 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
13343 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
13344 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
13345 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
13346 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
13348 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
13354 /*-----------------------------------------------------------------*/
13355 /* gen390Code - generate code for Dallas 390 based controllers */
13356 /*-----------------------------------------------------------------*/
13358 gen390Code (iCode * lic)
13363 lineHead = lineCurr = NULL;
13364 dptrn[1][0] = "dpl1";
13365 dptrn[1][1] = "dph1";
13366 dptrn[1][2] = "dpx1";
13368 if (options.model == MODEL_FLAT24) {
13369 fReturnSizeDS390 = 5;
13370 fReturn = fReturn24;
13372 fReturnSizeDS390 = 4;
13373 fReturn = fReturn16;
13374 options.stack10bit=0;
13377 /* print the allocation information */
13378 if (allocInfo && currFunc)
13379 printAllocInfo (currFunc, codeOutFile);
13381 /* if debug information required */
13382 if (options.debug && currFunc)
13384 debugFile->writeFunction (currFunc, lic);
13386 /* stack pointer name */
13387 if (options.useXstack)
13393 for (ic = lic; ic; ic = ic->next)
13396 _G.current_iCode = ic;
13398 if (ic->lineno && cln != ic->lineno)
13402 debugFile->writeCLine (ic);
13404 if (!options.noCcodeInAsm) {
13405 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
13406 printCLine(ic->filename, ic->lineno));
13410 if (options.iCodeInAsm) {
13411 emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
13413 /* if the result is marked as
13414 spilt and rematerializable or code for
13415 this has already been generated then
13417 if (resultRemat (ic) || ic->generated)
13420 /* depending on the operation */
13440 /* IPOP happens only when trying to restore a
13441 spilt live range, if there is an ifx statement
13442 following this pop then the if statement might
13443 be using some of the registers being popped which
13444 would destory the contents of the register so
13445 we need to check for this condition and handle it */
13447 ic->next->op == IFX &&
13448 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
13449 genIfx (ic->next, ic);
13467 genEndFunction (ic);
13487 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
13504 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
13508 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
13515 /* note these two are xlated by algebraic equivalence
13516 during parsing SDCC.y */
13517 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
13518 "got '>=' or '<=' shouldn't have come here");
13522 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
13534 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
13538 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
13542 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
13566 genRightShift (ic);
13569 case GET_VALUE_AT_ADDRESS:
13570 genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
13574 if (POINTER_SET (ic))
13575 genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
13601 if (ic->builtinSEND) genBuiltIn(ic);
13602 else addSet (&_G.sendSet, ic);
13605 case DUMMY_READ_VOLATILE:
13614 genEndCritical (ic);
13621 #if 0 // obsolete, and buggy for != xdata
13633 /* now we are ready to call the
13634 peep hole optimizer */
13635 if (!options.nopeep)
13636 peepHole (&lineHead);
13638 /* now do the actual printing */
13639 printLine (lineHead, codeOutFile);