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 (sym1->rname[0] && sym2->rname[0]
870 && strcmp (sym1->rname, sym2->rname) == 0)
874 /* if left is a tmp & right is not */
875 if (IS_ITEMP (op1) &&
878 (sym1->usl.spillLoc == sym2))
881 if (IS_ITEMP (op2) &&
885 (sym2->usl.spillLoc == sym1))
888 /* are they spilt to the same location */
889 if (IS_ITEMP (op2) &&
893 (sym1->usl.spillLoc == sym2->usl.spillLoc))
899 /*-----------------------------------------------------------------*/
900 /* sameRegs - two asmops have the same registers */
901 /*-----------------------------------------------------------------*/
903 sameRegs (asmop * aop1, asmop * aop2)
909 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
916 if (aop1->type != AOP_REG ||
917 aop2->type != AOP_REG)
920 if (aop1->size != aop2->size)
923 for (i = 0; i < aop1->size; i++)
924 if (aop1->aopu.aop_reg[i] !=
925 aop2->aopu.aop_reg[i])
931 /*-----------------------------------------------------------------*/
932 /* aopOp - allocates an asmop for an operand : */
933 /*-----------------------------------------------------------------*/
935 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
944 /* if this a literal */
945 if (IS_OP_LITERAL (op))
947 op->aop = aop = newAsmop (AOP_LIT);
948 aop->aopu.aop_lit = op->operand.valOperand;
949 aop->size = getSize (operandType (op));
953 /* if already has a asmop then continue */
956 if ((op->aop->type == AOP_DPTR && useDP2)
957 || (op->aop->type == AOP_DPTR2 && !useDP2))
963 /* if the underlying symbol has a aop */
964 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
966 op->aop = OP_SYMBOL (op)->aop;
967 if ((op->aop->type == AOP_DPTR && useDP2)
968 || (op->aop->type == AOP_DPTR2 && !useDP2))
974 /* if this is a true symbol */
975 if (IS_TRUE_SYMOP (op))
977 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
981 /* this is a temporary : this has
987 e) can be a return use only */
989 sym = OP_SYMBOL (op);
992 /* if the type is a conditional */
993 if (sym->regType == REG_CND)
995 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
1000 /* if it is spilt then two situations
1002 b) has a spill location */
1003 if (sym->isspilt || sym->nRegs == 0)
1006 /* rematerialize it NOW */
1009 sym->aop = op->aop = aop =
1011 aop->size = getSize (sym->type);
1018 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
1019 aop->size = getSize (sym->type);
1020 for (i = 0; i < 2; i++)
1021 aop->aopu.aop_str[i] = accUse[i];
1031 /* a AOP_STR uses DPTR, but DPTR is already in use;
1034 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"AOP_STR with DPTR in use!");
1037 aop = op->aop = sym->aop = newAsmop (AOP_STR);
1038 aop->size = getSize (sym->type);
1039 for (i = 0; i < (int) fReturnSizeDS390; i++)
1040 aop->aopu.aop_str[i] = fReturn[i];
1044 if (sym->dptr) { /* has been allocated to a DPTRn */
1045 aop = op->aop = sym->aop = newAsmop (AOP_DPTRn);
1046 aop->size = getSize (sym->type);
1047 aop->aopu.dptr = sym->dptr;
1051 if (sym->usl.spillLoc)
1053 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1055 /* force a new aop if sizes differ */
1056 sym->usl.spillLoc->aop = NULL;
1058 sym->aop = op->aop = aop =
1059 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
1060 aop->size = getSize (sym->type);
1064 /* else must be a dummy iTemp */
1065 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1066 aop->size = getSize (sym->type);
1070 /* must be in a register */
1071 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1072 aop->size = sym->nRegs;
1073 for (i = 0; i < sym->nRegs; i++)
1074 aop->aopu.aop_reg[i] = sym->regs[i];
1077 /*-----------------------------------------------------------------*/
1078 /* freeAsmop - free up the asmop given to an operand */
1079 /*----------------------------------------------------------------*/
1081 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1098 /* depending on the asmop type only three cases need work AOP_RO
1099 , AOP_R1 && AOP_STK */
1107 emitcode ("pop", "ar0");
1111 bitVectUnSetBit (ic->rUsed, R0_IDX);
1119 emitcode ("pop", "ar1");
1123 bitVectUnSetBit (ic->rUsed, R1_IDX);
1129 int stk = aop->aopu.aop_stk + aop->size;
1130 bitVectUnSetBit (ic->rUsed, R0_IDX);
1131 bitVectUnSetBit (ic->rUsed, R1_IDX);
1133 getFreePtr (ic, &aop, FALSE);
1135 if (options.stack10bit)
1137 /* I'm not sure what to do here yet... */
1140 "*** Warning: probably generating bad code for "
1141 "10 bit stack mode.\n");
1146 emitcode ("mov", "a,_bp");
1147 emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
1148 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1152 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1157 emitcode ("pop", "acc");
1158 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1161 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1164 freeAsmop (op, NULL, ic, TRUE);
1167 emitcode ("pop", "ar0");
1173 emitcode ("pop", "ar1");
1178 if (_G.dptr1InUse) {
1179 emitcode ("pop","dpx1");
1180 emitcode ("pop","dph1");
1181 emitcode ("pop","dpl1");
1186 emitcode ("pop","dpx");
1187 emitcode ("pop","dph");
1188 emitcode ("pop","dpl");
1193 /* all other cases just dealloc */
1199 OP_SYMBOL (op)->aop = NULL;
1200 /* if the symbol has a spill */
1202 SPIL_LOC (op)->aop = NULL;
1207 #define DEFAULT_ACC_WARNING 0
1208 static int saveAccWarn = DEFAULT_ACC_WARNING;
1210 /*-------------------------------------------------------------------*/
1211 /* aopGet - for fetching value of the aop */
1213 /* Set saveAcc to NULL if you are sure it is OK to clobber the value */
1214 /* in the accumulator. Set it to the name of a free register */
1215 /* if acc must be preserved; the register will be used to preserve */
1216 /* acc temporarily and to return the result byte. */
1217 /*-------------------------------------------------------------------*/
1226 /* offset is greater than
1228 if (offset > (aop->size - 1) &&
1229 aop->type != AOP_LIT)
1232 /* depending on type */
1240 /* if we need to increment it */
1241 while (offset > aop->coff)
1243 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1247 while (offset < aop->coff)
1249 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1256 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1257 return (dname ? "acc" : "a");
1259 SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1260 return Safe_strdup(buffer);
1263 assert(offset <= 3);
1264 return dptrn[aop->aopu.dptr][offset];
1269 if (aop->type == AOP_DPTR2)
1277 // if (aop->type != AOP_DPTR2)
1279 // if (saveAccWarn) { fprintf(stderr, "saveAcc for DPTR...\n"); }
1280 // emitcode(";", "spanky: saveAcc for DPTR");
1283 emitcode ("xch", "a, %s", saveAcc);
1288 while (offset > aop->coff)
1290 emitcode ("inc", "dptr");
1294 while (offset < aop->coff)
1296 emitcode ("lcall", "__decdptr");
1303 emitcode ("clr", "a");
1304 emitcode ("movc", "a,@a+dptr");
1308 emitcode ("movx", "a,@dptr");
1311 if (aop->type == AOP_DPTR2)
1319 emitcode ("xch", "a, %s", saveAcc);
1320 // if (strcmp(saveAcc, "_ap"))
1322 // emitcode(";", "spiffy: non _ap return from aopGet.");
1327 return (dname ? "acc" : "a");
1330 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1332 SNPRINTF(buffer, sizeof(buffer),
1333 "%s",aop->aopu.aop_immd.aop_immd2);
1337 SNPRINTF(buffer, sizeof(buffer),
1338 "#%s", aop->aopu.aop_immd.aop_immd1);
1344 tsprintf(buffer, sizeof(buffer),
1345 "#!his",aop->aopu.aop_immd.aop_immd1);
1348 tsprintf(buffer, sizeof(buffer),
1349 "#!hihis",aop->aopu.aop_immd.aop_immd1);
1352 tsprintf(buffer, sizeof(buffer),
1353 "#!hihihis",aop->aopu.aop_immd.aop_immd1);
1355 default: /* should not need this (just in case) */
1356 SNPRINTF (buffer, sizeof(buffer),
1358 aop->aopu.aop_immd.aop_immd1,
1364 SNPRINTF (buffer, sizeof(buffer),
1365 "#%s", aop->aopu.aop_immd.aop_immd1);
1367 return Safe_strdup(buffer);
1372 SNPRINTF (buffer, sizeof(buffer),
1379 SNPRINTF(buffer, sizeof(buffer),
1380 "%s", aop->aopu.aop_dir);
1383 return Safe_strdup(buffer);
1387 return aop->aopu.aop_reg[offset]->dname;
1389 return aop->aopu.aop_reg[offset]->name;
1392 emitcode ("clr", "a");
1393 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1394 emitcode ("rlc", "a");
1395 return (dname ? "acc" : "a");
1398 if (!offset && dname)
1400 return aop->aopu.aop_str[offset];
1403 return aopLiteral (aop->aopu.aop_lit, offset);
1407 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1411 return aop->aopu.aop_str[offset];
1415 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1416 "aopget got unsupported aop->type");
1419 return NULL; // not reached, but makes compiler happy.
1421 /*-----------------------------------------------------------------*/
1422 /* aopPut - puts a string for a aop */
1423 /*-----------------------------------------------------------------*/
1425 aopPut (asmop * aop, char *s, int offset)
1427 if (aop->size && offset > (aop->size - 1))
1429 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1430 "aopPut got offset > aop->size");
1434 /* will assign value to value */
1435 /* depending on where it is ofcourse */
1439 MOVA (s); /* read s in case it was volatile */
1445 SNPRINTF (buffer, sizeof(buffer),
1447 aop->aopu.aop_dir, offset);
1451 SNPRINTF (buffer, sizeof(buffer),
1452 "%s", aop->aopu.aop_dir);
1456 if (strcmp (buffer, s))
1458 emitcode ("mov", "%s,%s", buffer, s);
1463 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1464 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1467 strcmp (s, "r0") == 0 ||
1468 strcmp (s, "r1") == 0 ||
1469 strcmp (s, "r2") == 0 ||
1470 strcmp (s, "r3") == 0 ||
1471 strcmp (s, "r4") == 0 ||
1472 strcmp (s, "r5") == 0 ||
1473 strcmp (s, "r6") == 0 ||
1474 strcmp (s, "r7") == 0)
1476 emitcode ("mov", "%s,%s",
1477 aop->aopu.aop_reg[offset]->dname, s);
1481 emitcode ("mov", "%s,%s",
1482 aop->aopu.aop_reg[offset]->name, s);
1488 emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1494 if (aop->type == AOP_DPTR2)
1502 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1503 "aopPut writting to code space");
1507 while (offset > aop->coff)
1510 emitcode ("inc", "dptr");
1513 while (offset < aop->coff)
1516 emitcode ("lcall", "__decdptr");
1521 /* if not in accumulater */
1524 emitcode ("movx", "@dptr,a");
1526 if (aop->type == AOP_DPTR2)
1534 while (offset > aop->coff)
1537 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1539 while (offset < aop->coff)
1542 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1549 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1555 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1557 else if (strcmp (s, "r0") == 0 ||
1558 strcmp (s, "r1") == 0 ||
1559 strcmp (s, "r2") == 0 ||
1560 strcmp (s, "r3") == 0 ||
1561 strcmp (s, "r4") == 0 ||
1562 strcmp (s, "r5") == 0 ||
1563 strcmp (s, "r6") == 0 ||
1564 strcmp (s, "r7") == 0)
1567 SNPRINTF(buff, sizeof(buff),
1569 emitcode ("mov", "@%s,%s",
1570 aop->aopu.aop_ptr->name, buff);
1574 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1579 if (strcmp (s, "a") == 0)
1580 emitcode ("push", "acc");
1584 emitcode ("push", "acc");
1586 emitcode ("push", s);
1592 /* if bit variable */
1593 if (!aop->aopu.aop_dir)
1595 emitcode ("clr", "a");
1596 emitcode ("rlc", "a");
1601 emitcode ("clr", "%s", aop->aopu.aop_dir);
1603 emitcode ("setb", "%s", aop->aopu.aop_dir);
1604 else if (!strcmp (s, "c"))
1605 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1608 if (strcmp (s, "a"))
1613 /* set C, if a >= 1 */
1614 emitcode ("add", "a,#!constbyte",0xff);
1615 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1623 if (strcmp (aop->aopu.aop_str[offset], s))
1624 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1629 if (!offset && (strcmp (s, "acc") == 0))
1632 if (strcmp (aop->aopu.aop_str[offset], s))
1633 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1637 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1638 "aopPut got unsupported aop->type");
1645 /*--------------------------------------------------------------------*/
1646 /* reAdjustPreg - points a register back to where it should (coff==0) */
1647 /*--------------------------------------------------------------------*/
1649 reAdjustPreg (asmop * aop)
1651 if ((aop->coff==0) || (aop->size <= 1)) {
1660 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1664 if (aop->type == AOP_DPTR2)
1671 emitcode ("lcall", "__decdptr");
1674 if (aop->type == AOP_DPTR2)
1684 #define AOP(op) op->aop
1685 #define AOP_TYPE(op) AOP(op)->type
1686 #define AOP_SIZE(op) AOP(op)->size
1687 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1688 AOP_TYPE(x) == AOP_R0))
1690 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1691 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1694 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1695 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1696 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1697 #define AOP_INDPTRn(x) (AOP_TYPE(x) == AOP_DPTRn)
1698 #define AOP_USESDPTR(x) ((AOP_TYPE(x) == AOP_DPTR) || (AOP_TYPE(x) == AOP_STR))
1699 #define AOP_USESDPTR2(x) ((AOP_TYPE(x) == AOP_DPTR2) || (AOP_TYPE(x) == AOP_DPTRn))
1701 // The following two macros can be used even if the aop has not yet been aopOp'd.
1702 #define AOP_IS_STR(x) (IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
1703 #define AOP_IS_DPTRn(x) (IS_SYMOP(x) && OP_SYMBOL(x)->dptr)
1705 /* Workaround for DS80C390 bug: div ab may return bogus results
1706 * if A is accessed in instruction immediately before the div.
1708 * Will be fixed in B4 rev of processor, Dallas claims.
1711 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1712 if (!AOP_NEEDSACC(RIGHT)) \
1714 /* We can load A first, then B, since \
1715 * B (the RIGHT operand) won't clobber A, \
1716 * thus avoiding touching A right before the div. \
1718 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1719 L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL); \
1721 L = aopGet(AOP(RIGHT),0,FALSE,FALSE,"b"); \
1726 /* Just stuff in a nop after loading A. */ \
1727 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,NULL));\
1728 L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL); \
1730 emitcode("nop", "; workaround for DS80C390 div bug."); \
1734 /*-----------------------------------------------------------------*/
1735 /* opIsGptr: returns non-zero if the passed operand is */
1736 /* a generic pointer type. */
1737 /*-----------------------------------------------------------------*/
1739 opIsGptr (operand * op)
1741 sym_link *type = operandType (op);
1743 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1750 /*-----------------------------------------------------------------*/
1751 /* getDataSize - get the operand data size */
1752 /*-----------------------------------------------------------------*/
1754 getDataSize (operand * op)
1757 size = AOP_SIZE (op);
1758 if (size == GPTRSIZE)
1760 sym_link *type = operandType (op);
1761 if (IS_GENPTR (type))
1763 /* generic pointer; arithmetic operations
1764 * should ignore the high byte (pointer type).
1772 /*-----------------------------------------------------------------*/
1773 /* outAcc - output Acc */
1774 /*-----------------------------------------------------------------*/
1776 outAcc (operand * result)
1779 size = getDataSize (result);
1782 aopPut (AOP (result), "a", 0);
1785 /* unsigned or positive */
1788 aopPut (AOP (result), zero, offset++);
1793 /*-----------------------------------------------------------------*/
1794 /* outBitC - output a bit C */
1795 /*-----------------------------------------------------------------*/
1797 outBitC (operand * result)
1799 /* if the result is bit */
1800 if (AOP_TYPE (result) == AOP_CRY)
1802 aopPut (AOP (result), "c", 0);
1806 emitcode ("clr", "a");
1807 emitcode ("rlc", "a");
1812 /*-----------------------------------------------------------------*/
1813 /* toBoolean - emit code for orl a,operator(sizeop) */
1814 /*-----------------------------------------------------------------*/
1816 toBoolean (operand * oper)
1818 int size = AOP_SIZE (oper) - 1;
1822 /* The generic part of a generic pointer should
1823 * not participate in it's truth value.
1825 * i.e. 0x10000000 is zero.
1827 if (opIsGptr (oper))
1829 D (emitcode (";", "toBoolean: generic ptr special case."););
1833 _startLazyDPSEvaluation ();
1834 if (AOP_NEEDSACC (oper) && size)
1839 emitcode ("push", "b");
1841 MOVB (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1845 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1852 emitcode ("orl", "b,%s",
1853 aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1857 emitcode ("orl", "a,%s",
1858 aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1861 _endLazyDPSEvaluation ();
1865 emitcode ("mov", "a,b");
1868 emitcode ("pop", "b");
1875 /*-----------------------------------------------------------------*/
1876 /* genNot - generate code for ! operation */
1877 /*-----------------------------------------------------------------*/
1883 D (emitcode (";", "genNot "););
1885 /* assign asmOps to operand & result */
1886 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1887 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1889 /* if in bit space then a special case */
1890 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1892 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1893 emitcode ("cpl", "c");
1894 outBitC (IC_RESULT (ic));
1898 toBoolean (IC_LEFT (ic));
1900 tlbl = newiTempLabel (NULL);
1901 emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1902 emitcode ("", "!tlabeldef", tlbl->key + 100);
1903 outBitC (IC_RESULT (ic));
1906 /* release the aops */
1907 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1908 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1912 /*-----------------------------------------------------------------*/
1913 /* genCpl - generate code for complement */
1914 /*-----------------------------------------------------------------*/
1922 D (emitcode (";", "genCpl "););
1925 /* assign asmOps to operand & result */
1926 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1927 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1929 /* special case if in bit space */
1930 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1931 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1932 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1933 emitcode ("cpl", "c");
1934 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1937 tlbl=newiTempLabel(NULL);
1938 emitcode ("cjne", "%s,#0x01,%05d$",
1939 aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE,NULL), tlbl->key+100);
1940 emitcode ("", "%05d$:", tlbl->key+100);
1941 outBitC (IC_RESULT(ic));
1945 size = AOP_SIZE (IC_RESULT (ic));
1946 _startLazyDPSEvaluation ();
1949 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
1950 emitcode ("cpl", "a");
1951 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1953 _endLazyDPSEvaluation ();
1957 /* release the aops */
1958 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1959 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1962 /*-----------------------------------------------------------------*/
1963 /* genUminusFloat - unary minus for floating points */
1964 /*-----------------------------------------------------------------*/
1966 genUminusFloat (operand * op, operand * result)
1968 int size, offset = 0;
1970 D(emitcode (";", "genUminusFloat"););
1972 /* for this we just copy and then flip the bit */
1974 _startLazyDPSEvaluation ();
1975 size = AOP_SIZE (op) - 1;
1979 aopPut (AOP (result),
1980 aopGet (AOP (op), offset, FALSE, FALSE, NULL),
1985 MOVA(aopGet (AOP (op), offset, FALSE, FALSE, NULL));
1987 emitcode ("cpl", "acc.7");
1988 aopPut (AOP (result), "a", offset);
1989 _endLazyDPSEvaluation ();
1992 /*-----------------------------------------------------------------*/
1993 /* genUminus - unary minus code generation */
1994 /*-----------------------------------------------------------------*/
1996 genUminus (iCode * ic)
2001 D (emitcode (";", "genUminus "););
2004 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2005 aopOp (IC_RESULT (ic), ic, TRUE, (AOP_TYPE(IC_LEFT (ic)) == AOP_DPTR));
2007 /* if both in bit space then special
2009 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2010 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2013 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2014 emitcode ("cpl", "c");
2015 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2019 optype = operandType (IC_LEFT (ic));
2021 /* if float then do float stuff */
2022 if (IS_FLOAT (optype))
2024 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2028 /* otherwise subtract from zero */
2029 size = AOP_SIZE (IC_LEFT (ic));
2031 _startLazyDPSEvaluation ();
2034 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL);
2035 if (!strcmp (l, "a"))
2039 emitcode ("cpl", "a");
2040 emitcode ("addc", "a,#0");
2046 emitcode ("clr", "a");
2047 emitcode ("subb", "a,%s", l);
2049 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2051 _endLazyDPSEvaluation ();
2053 /* if any remaining bytes in the result */
2054 /* we just need to propagate the sign */
2055 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic)))) != 0)
2057 emitcode ("rlc", "a");
2058 emitcode ("subb", "a,acc");
2060 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2064 /* release the aops */
2065 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2066 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2069 /*-----------------------------------------------------------------*/
2070 /* savermask - saves registers in the mask */
2071 /*-----------------------------------------------------------------*/
2072 static void savermask(bitVect *rs_mask)
2075 if (options.useXstack) {
2076 if (bitVectBitValue (rs_mask, R0_IDX))
2077 emitcode ("mov", "b,r0");
2078 emitcode ("mov", "r0,%s", spname);
2079 for (i = 0; i < ds390_nRegs; i++) {
2080 if (bitVectBitValue (rs_mask, i)) {
2082 emitcode ("mov", "a,b");
2084 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
2085 emitcode ("movx", "@r0,a");
2086 emitcode ("inc", "r0");
2089 emitcode ("mov", "%s,r0", spname);
2090 if (bitVectBitValue (rs_mask, R0_IDX))
2091 emitcode ("mov", "r0,b");
2093 for (i = 0; i < ds390_nRegs; i++) {
2094 if (bitVectBitValue (rs_mask, i))
2095 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2100 /*-----------------------------------------------------------------*/
2101 /* saveRegisters - will look for a call and save the registers */
2102 /*-----------------------------------------------------------------*/
2104 saveRegisters (iCode * lic)
2110 for (ic = lic; ic; ic = ic->next)
2111 if (ic->op == CALL || ic->op == PCALL)
2116 fprintf (stderr, "found parameter push with no function call\n");
2120 /* if the registers have been saved already then
2123 || (IS_SYMOP(IC_LEFT(ic)) && IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))) && !TARGET_IS_DS400) )
2126 /* special case if DPTR alive across a function call then must save it
2127 even though callee saves */
2128 if (IS_SYMOP(IC_LEFT(ic)) &&
2129 IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2131 rsave = newBitVect(ic->rMask->size);
2132 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2133 if (bitVectBitValue(ic->rMask,i))
2134 rsave = bitVectSetBit(rsave,i);
2136 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2138 /* safe the registers in use at this time but skip the
2139 ones for the result */
2140 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2141 ds390_rUmaskForOp (IC_RESULT(ic)));
2147 /*-----------------------------------------------------------------*/
2148 /* usavermask - restore registers with mask */
2149 /*-----------------------------------------------------------------*/
2150 static void unsavermask(bitVect *rs_mask)
2153 if (options.useXstack) {
2154 emitcode ("mov", "r0,%s", spname);
2155 for (i = ds390_nRegs; i >= 0; i--) {
2156 if (bitVectBitValue (rs_mask, i)) {
2157 emitcode ("dec", "r0");
2158 emitcode ("movx", "a,@r0");
2160 emitcode ("mov", "b,a");
2162 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
2165 emitcode ("mov", "%s,r0", spname);
2166 if (bitVectBitValue (rs_mask, R0_IDX))
2167 emitcode ("mov", "r0,b");
2169 for (i = ds390_nRegs; i >= 0; i--) {
2170 if (bitVectBitValue (rs_mask, i))
2171 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2176 /*-----------------------------------------------------------------*/
2177 /* unsaveRegisters - pop the pushed registers */
2178 /*-----------------------------------------------------------------*/
2180 unsaveRegisters (iCode * ic)
2184 if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2186 rsave = newBitVect(ic->rMask->size);
2187 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2188 if (bitVectBitValue(ic->rMask,i))
2189 rsave = bitVectSetBit(rsave,i);
2191 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2193 /* restore the registers in use at this time but skip the
2194 ones for the result */
2195 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2196 ds390_rUmaskForOp (IC_RESULT(ic)));
2202 /*-----------------------------------------------------------------*/
2204 /*-----------------------------------------------------------------*/
2206 pushSide (operand * oper, int size)
2209 _startLazyDPSEvaluation ();
2212 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, NULL);
2213 if (AOP_TYPE (oper) != AOP_REG &&
2214 AOP_TYPE (oper) != AOP_DIR &&
2217 emitcode ("mov", "a,%s", l);
2218 emitcode ("push", "acc");
2221 emitcode ("push", "%s", l);
2223 _endLazyDPSEvaluation ();
2226 /*-----------------------------------------------------------------*/
2227 /* assignResultValue - */
2228 /*-----------------------------------------------------------------*/
2230 assignResultValue (operand * oper)
2233 int size = AOP_SIZE (oper);
2234 bool pushedAcc = FALSE;
2236 if (size == fReturnSizeDS390)
2238 /* I don't think this case can ever happen... */
2239 /* ACC is the last part of this. If writing the result
2240 * uses AC, we must preserve it.
2242 if (AOP_NEEDSACC(oper))
2244 emitcode(";", "assignResultValue special case for ACC.");
2245 emitcode("push", "acc");
2252 _startLazyDPSEvaluation ();
2255 aopPut (AOP (oper), fReturn[offset], offset);
2258 _endLazyDPSEvaluation ();
2262 emitcode("pop", "acc");
2263 aopPut(AOP(oper), "a", offset);
2268 /*-----------------------------------------------------------------*/
2269 /* genXpush - pushes onto the external stack */
2270 /*-----------------------------------------------------------------*/
2272 genXpush (iCode * ic)
2274 asmop *aop = newAsmop (0);
2276 int size, offset = 0;
2278 D (emitcode (";", "genXpush ");
2281 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2282 r = getFreePtr (ic, &aop, FALSE);
2285 emitcode ("mov", "%s,_spx", r->name);
2287 size = AOP_SIZE (IC_LEFT (ic));
2288 _startLazyDPSEvaluation ();
2292 MOVA (aopGet (AOP (IC_LEFT (ic)),
2293 offset++, FALSE, FALSE, NULL));
2294 emitcode ("movx", "@%s,a", r->name);
2295 emitcode ("inc", "%s", r->name);
2298 _endLazyDPSEvaluation ();
2301 emitcode ("mov", "_spx,%s", r->name);
2303 freeAsmop (NULL, aop, ic, TRUE);
2304 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2307 /*-----------------------------------------------------------------*/
2308 /* genIpush - generate code for pushing this gets a little complex */
2309 /*-----------------------------------------------------------------*/
2311 genIpush (iCode * ic)
2313 int size, offset = 0;
2316 D (emitcode (";", "genIpush ");
2319 /* if this is not a parm push : ie. it is spill push
2320 and spill push is always done on the local stack */
2324 /* and the item is spilt then do nothing */
2325 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2328 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2329 size = AOP_SIZE (IC_LEFT (ic));
2330 /* push it on the stack */
2331 _startLazyDPSEvaluation ();
2334 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2340 emitcode ("push", "%s", l);
2342 _endLazyDPSEvaluation ();
2346 /* this is a paramter push: in this case we call
2347 the routine to find the call and save those
2348 registers that need to be saved */
2351 /* if use external stack then call the external
2352 stack pushing routine */
2353 if (options.useXstack)
2359 /* then do the push */
2360 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2362 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2363 size = AOP_SIZE (IC_LEFT (ic));
2365 _startLazyDPSEvaluation ();
2368 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2369 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2370 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2373 emitcode ("mov", "a,%s", l);
2374 emitcode ("push", "acc");
2378 emitcode ("push", "%s", l);
2381 _endLazyDPSEvaluation ();
2383 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2386 /*-----------------------------------------------------------------*/
2387 /* genIpop - recover the registers: can happen only for spilling */
2388 /*-----------------------------------------------------------------*/
2390 genIpop (iCode * ic)
2394 D (emitcode (";", "genIpop ");
2398 /* if the temp was not pushed then */
2399 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2402 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2403 size = AOP_SIZE (IC_LEFT (ic));
2404 offset = (size - 1);
2405 _startLazyDPSEvaluation ();
2408 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2409 FALSE, TRUE, NULL));
2411 _endLazyDPSEvaluation ();
2413 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2416 /*-----------------------------------------------------------------*/
2417 /* unsaveRBank - restores the resgister bank from stack */
2418 /*-----------------------------------------------------------------*/
2420 unsaveRBank (int bank, iCode * ic, bool popPsw)
2426 if (options.useXstack)
2430 /* Assume r0 is available for use. */
2431 r = ds390_regWithIdx (R0_IDX);;
2436 r = getFreePtr (ic, &aop, FALSE);
2438 emitcode ("mov", "%s,_spx", r->name);
2443 if (options.useXstack)
2445 emitcode ("movx", "a,@%s", r->name);
2446 emitcode ("mov", "psw,a");
2447 emitcode ("dec", "%s", r->name);
2451 emitcode ("pop", "psw");
2455 for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2457 if (options.useXstack)
2459 emitcode ("movx", "a,@%s", r->name);
2460 emitcode ("mov", "(%s+%d),a",
2461 regs390[i].base, 8 * bank + regs390[i].offset);
2462 emitcode ("dec", "%s", r->name);
2466 emitcode ("pop", "(%s+%d)",
2467 regs390[i].base, 8 * bank + regs390[i].offset);
2470 if (options.useXstack)
2472 emitcode ("mov", "_spx,%s", r->name);
2477 freeAsmop (NULL, aop, ic, TRUE);
2481 /*-----------------------------------------------------------------*/
2482 /* saveRBank - saves an entire register bank on the stack */
2483 /*-----------------------------------------------------------------*/
2485 saveRBank (int bank, iCode * ic, bool pushPsw)
2491 if (options.useXstack)
2495 /* Assume r0 is available for use. */
2496 r = ds390_regWithIdx (R0_IDX);;
2501 r = getFreePtr (ic, &aop, FALSE);
2503 emitcode ("mov", "%s,_spx", r->name);
2506 for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2508 if (options.useXstack)
2510 emitcode ("inc", "%s", r->name);
2511 emitcode ("mov", "a,(%s+%d)",
2512 regs390[i].base, 8 * bank + regs390[i].offset);
2513 emitcode ("movx", "@%s,a", r->name);
2516 emitcode ("push", "(%s+%d)",
2517 regs390[i].base, 8 * bank + regs390[i].offset);
2522 if (options.useXstack)
2524 emitcode ("mov", "a,psw");
2525 emitcode ("movx", "@%s,a", r->name);
2526 emitcode ("inc", "%s", r->name);
2527 emitcode ("mov", "_spx,%s", r->name);
2531 emitcode ("push", "psw");
2534 emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2539 freeAsmop (NULL, aop, ic, TRUE);
2548 /*-----------------------------------------------------------------*/
2549 /* genSend - gen code for SEND */
2550 /*-----------------------------------------------------------------*/
2551 static void genSend(set *sendSet)
2555 static int rb1_count = 0;
2557 for (sic = setFirstItem (sendSet); sic;
2558 sic = setNextItem (sendSet)) {
2559 int size, offset = 0;
2561 size=getSize(operandType(IC_LEFT(sic)));
2562 D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2563 if (sendCount == 0) { /* first parameter */
2564 // we know that dpl(hxb) is the result, so
2566 _startLazyDPSEvaluation ();
2568 aopOp (IC_LEFT (sic), sic, FALSE,
2569 (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2571 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2574 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2575 FALSE, FALSE, NULL);
2576 if (strcmp (l, fReturn[offset])) {
2577 emitcode ("mov", "%s,%s",
2583 _endLazyDPSEvaluation ();
2584 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2586 } else { /* if more parameter in registers */
2587 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2589 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
2590 FALSE, FALSE, NULL));
2592 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2599 adjustEsp(const char *reg)
2601 emitcode ("anl","%s,#3", reg);
2602 if (TARGET_IS_DS400)
2604 emitcode ("orl","%s,#!constbyte",
2606 (options.stack_loc >> 8) & 0xff);
2610 /*-----------------------------------------------------------------*/
2611 /* genCall - generates a call statement */
2612 /*-----------------------------------------------------------------*/
2614 genCall (iCode * ic)
2617 bool restoreBank = FALSE;
2618 bool swapBanks = FALSE;
2620 D (emitcode (";", "genCall "););
2622 /* if we are calling a not _naked function that is not using
2623 the same register bank then we need to save the
2624 destination registers on the stack */
2625 dtype = operandType (IC_LEFT (ic));
2626 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2627 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2628 IFFUNC_ISISR (currFunc->type))
2632 /* This is unexpected; the bank should have been saved in
2635 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2641 /* if caller saves & we have not saved then */
2645 /* if send set is not empty the assign */
2646 /* We've saved all the registers we care about;
2647 * therefore, we may clobber any register not used
2648 * in the calling convention (i.e. anything not in
2653 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2654 genSend(reverseSet(_G.sendSet));
2656 genSend(_G.sendSet);
2663 emitcode ("mov", "psw,#!constbyte",
2664 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2668 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2669 OP_SYMBOL (IC_LEFT (ic))->rname :
2670 OP_SYMBOL (IC_LEFT (ic))->name));
2674 emitcode ("mov", "psw,#!constbyte",
2675 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2678 /* if we need assign a result value */
2679 if ((IS_ITEMP (IC_RESULT (ic)) &&
2680 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2681 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2682 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2683 IS_TRUE_SYMOP (IC_RESULT (ic)))
2685 if (isOperandInFarSpace (IC_RESULT (ic))
2686 && getSize (operandType (IC_RESULT (ic))) <= 2)
2688 int size = getSize (operandType (IC_RESULT (ic)));
2690 /* Special case for 1 or 2 byte return in far space. */
2694 emitcode ("mov", "b,%s", fReturn[1]);
2699 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2705 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2709 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2711 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2716 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2719 assignResultValue (IC_RESULT (ic));
2721 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2725 /* adjust the stack for parameters if
2727 if (ic->parmBytes) {
2729 if (options.stack10bit) {
2730 if (ic->parmBytes <= 10) {
2731 emitcode(";","stack adjustment for parms");
2732 for (i=0; i < ic->parmBytes ; i++) {
2733 emitcode("pop","acc");
2737 emitcode ("clr","c");
2738 emitcode ("mov","a,sp");
2739 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2740 emitcode ("mov","sp,a");
2741 emitcode ("mov","a,esp");
2743 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2744 emitcode ("mov","esp,a");
2748 if (ic->parmBytes > 3) {
2749 emitcode ("mov", "a,%s", spname);
2750 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2751 emitcode ("mov", "%s,a", spname);
2753 for (i = 0; i < ic->parmBytes; i++)
2754 emitcode ("dec", "%s", spname);
2758 /* if we hade saved some registers then unsave them */
2760 unsaveRegisters (ic);
2762 /* if register bank was saved then pop them */
2764 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2767 /*-----------------------------------------------------------------*/
2768 /* genPcall - generates a call by pointer statement */
2769 /*-----------------------------------------------------------------*/
2771 genPcall (iCode * ic)
2774 symbol *rlbl = newiTempLabel (NULL);
2775 bool restoreBank=FALSE;
2777 D (emitcode (";", "genPcall ");
2781 /* if caller saves & we have not saved then */
2785 /* if we are calling a function that is not using
2786 the same register bank then we need to save the
2787 destination registers on the stack */
2788 dtype = operandType (IC_LEFT (ic));
2789 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2790 IFFUNC_ISISR (currFunc->type) &&
2791 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2792 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2796 /* push the return address on to the stack */
2797 emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2798 emitcode ("push", "acc");
2799 emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2800 emitcode ("push", "acc");
2802 if (options.model == MODEL_FLAT24)
2804 emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2805 emitcode ("push", "acc");
2808 /* now push the calling address */
2809 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2811 pushSide (IC_LEFT (ic), FPTRSIZE);
2813 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2815 /* if send set is not empty the assign */
2818 genSend(reverseSet(_G.sendSet));
2822 emitcode ("ret", "");
2823 emitcode ("", "!tlabeldef", (rlbl->key + 100));
2826 /* if we need assign a result value */
2827 if ((IS_ITEMP (IC_RESULT (ic)) &&
2828 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2829 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2830 IS_TRUE_SYMOP (IC_RESULT (ic)))
2834 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2837 assignResultValue (IC_RESULT (ic));
2839 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2842 /* adjust the stack for parameters if
2847 if (options.stack10bit) {
2848 if (ic->parmBytes <= 10) {
2849 emitcode(";","stack adjustment for parms");
2850 for (i=0; i < ic->parmBytes ; i++) {
2851 emitcode("pop","acc");
2855 emitcode ("clr","c");
2856 emitcode ("mov","a,sp");
2857 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2858 emitcode ("mov","sp,a");
2859 emitcode ("mov","a,esp");
2861 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2862 emitcode ("mov","esp,a");
2866 if (ic->parmBytes > 3) {
2867 emitcode ("mov", "a,%s", spname);
2868 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2869 emitcode ("mov", "%s,a", spname);
2872 for (i = 0; i < ic->parmBytes; i++)
2873 emitcode ("dec", "%s", spname);
2877 /* if register bank was saved then unsave them */
2879 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2881 /* if we hade saved some registers then
2884 unsaveRegisters (ic);
2888 /*-----------------------------------------------------------------*/
2889 /* resultRemat - result is rematerializable */
2890 /*-----------------------------------------------------------------*/
2892 resultRemat (iCode * ic)
2894 if (SKIP_IC (ic) || ic->op == IFX)
2897 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2899 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2900 if (sym->remat && !POINTER_SET (ic))
2907 #if defined(__BORLANDC__) || defined(_MSC_VER)
2908 #define STRCASECMP stricmp
2910 #define STRCASECMP strcasecmp
2913 /*-----------------------------------------------------------------*/
2914 /* inExcludeList - return 1 if the string is in exclude Reg list */
2915 /*-----------------------------------------------------------------*/
2917 regsCmp(void *p1, void *p2)
2919 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2923 inExcludeList (char *s)
2925 const char *p = setFirstItem(options.excludeRegsSet);
2927 if (p == NULL || STRCASECMP(p, "none") == 0)
2931 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2934 /*-----------------------------------------------------------------*/
2935 /* genFunction - generated code for function entry */
2936 /*-----------------------------------------------------------------*/
2938 genFunction (iCode * ic)
2942 bool switchedPSW = FALSE;
2944 D (emitcode (";", "genFunction "););
2947 /* create the function header */
2948 emitcode (";", "-----------------------------------------");
2949 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2950 emitcode (";", "-----------------------------------------");
2952 emitcode ("", "%s:", sym->rname);
2953 ftype = operandType (IC_LEFT (ic));
2955 if (IFFUNC_ISNAKED(ftype))
2957 emitcode(";", "naked function: no prologue.");
2961 if (options.stack_probe)
2962 emitcode ("lcall","__stack_probe");
2964 /* here we need to generate the equates for the
2965 register bank if required */
2966 if (FUNC_REGBANK (ftype) != rbank)
2970 rbank = FUNC_REGBANK (ftype);
2971 for (i = 0; i < ds390_nRegs; i++)
2973 if (regs390[i].print) {
2974 if (strcmp (regs390[i].base, "0") == 0)
2975 emitcode ("", "%s !equ !constbyte",
2977 8 * rbank + regs390[i].offset);
2979 emitcode ("", "%s !equ %s + !constbyte",
2982 8 * rbank + regs390[i].offset);
2987 /* if this is an interrupt service routine then
2988 save acc, b, dpl, dph */
2989 if (IFFUNC_ISISR (sym->type))
2991 if (!inExcludeList ("acc"))
2992 emitcode ("push", "acc");
2993 if (!inExcludeList ("b"))
2994 emitcode ("push", "b");
2995 if (!inExcludeList ("dpl"))
2996 emitcode ("push", "dpl");
2997 if (!inExcludeList ("dph"))
2998 emitcode ("push", "dph");
2999 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3001 emitcode ("push", "dpx");
3002 /* Make sure we're using standard DPTR */
3003 emitcode ("push", "dps");
3004 emitcode ("mov", "dps,#0");
3005 if (options.stack10bit)
3007 /* This ISR could conceivably use DPTR2. Better save it. */
3008 emitcode ("push", "dpl1");
3009 emitcode ("push", "dph1");
3010 emitcode ("push", "dpx1");
3011 emitcode ("push", DP2_RESULT_REG);
3014 /* if this isr has no bank i.e. is going to
3015 run with bank 0 , then we need to save more
3017 if (!FUNC_REGBANK (sym->type))
3021 /* if this function does not call any other
3022 function then we can be economical and
3023 save only those registers that are used */
3024 if (!IFFUNC_HASFCALL(sym->type))
3027 /* if any registers used */
3030 /* save the registers used */
3031 for (i = 0; i < sym->regsUsed->size; i++)
3033 if (bitVectBitValue (sym->regsUsed, i))
3034 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3040 /* this function has a function call cannot
3041 determines register usage so we will have to push the
3043 saveRBank (0, ic, FALSE);
3044 if (options.parms_in_bank1) {
3045 for (i=0; i < 8 ; i++ ) {
3046 emitcode ("push","%s",rb1regs[i]);
3053 /* This ISR uses a non-zero bank.
3055 * We assume that the bank is available for our
3058 * However, if this ISR calls a function which uses some
3059 * other bank, we must save that bank entirely.
3061 unsigned long banksToSave = 0;
3063 if (IFFUNC_HASFCALL(sym->type))
3066 #define MAX_REGISTER_BANKS 4
3071 for (i = ic; i; i = i->next)
3073 if (i->op == ENDFUNCTION)
3075 /* we got to the end OK. */
3083 dtype = operandType (IC_LEFT(i));
3085 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3087 /* Mark this bank for saving. */
3088 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3090 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3094 banksToSave |= (1 << FUNC_REGBANK(dtype));
3097 /* And note that we don't need to do it in
3105 /* This is a mess; we have no idea what
3106 * register bank the called function might
3109 * The only thing I can think of to do is
3110 * throw a warning and hope.
3112 werror(W_FUNCPTR_IN_USING_ISR);
3116 if (banksToSave && options.useXstack)
3118 /* Since we aren't passing it an ic,
3119 * saveRBank will assume r0 is available to abuse.
3121 * So switch to our (trashable) bank now, so
3122 * the caller's R0 isn't trashed.
3124 emitcode ("push", "psw");
3125 emitcode ("mov", "psw,#!constbyte",
3126 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3130 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3132 if (banksToSave & (1 << ix))
3134 saveRBank(ix, NULL, FALSE);
3138 // TODO: this needs a closer look
3139 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3144 /* if callee-save to be used for this function
3145 then save the registers being used in this function */
3146 if (IFFUNC_CALLEESAVES(sym->type))
3150 /* if any registers used */
3153 /* save the registers used */
3154 for (i = 0; i < sym->regsUsed->size; i++)
3156 if (bitVectBitValue (sym->regsUsed, i))
3158 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3166 /* set the register bank to the desired value */
3167 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3170 emitcode ("push", "psw");
3171 emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3174 if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3175 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3176 if (options.stack10bit) {
3177 emitcode ("push","_bpx");
3178 emitcode ("push","_bpx+1");
3179 emitcode ("mov","_bpx,%s",spname);
3180 emitcode ("mov","_bpx+1,esp");
3181 adjustEsp("_bpx+1");
3183 if (options.useXstack) {
3184 emitcode ("mov", "r0,%s", spname);
3185 emitcode ("mov", "a,_bp");
3186 emitcode ("movx", "@r0,a");
3187 emitcode ("inc", "%s", spname);
3189 /* set up the stack */
3190 emitcode ("push", "_bp"); /* save the callers stack */
3192 emitcode ("mov", "_bp,%s", spname);
3196 /* adjust the stack for the function */
3199 if (options.stack10bit) {
3200 if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
3201 assert (sym->recvSize <= 4);
3202 if (sym->stack <= 8) {
3203 while (i--) emitcode ("push","acc");
3206 emitcode ("mov","a,sp");
3207 emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3208 emitcode ("mov","sp,a");
3209 emitcode ("mov","a,esp");
3211 emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3212 emitcode ("mov","esp,a");
3217 werror (W_STACK_OVERFLOW, sym->name);
3219 if (i > 3 && sym->recvSize < 4) {
3221 emitcode ("mov", "a,sp");
3222 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3223 emitcode ("mov", "sp,a");
3227 emitcode ("inc", "sp");
3234 emitcode ("mov", "a,_spx");
3235 emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3236 emitcode ("mov", "_spx,a");
3239 /* if critical function then turn interrupts off */
3240 if (IFFUNC_ISCRITICAL (ftype))
3242 symbol *tlbl = newiTempLabel (NULL);
3243 emitcode ("setb", "c");
3244 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3245 emitcode ("clr", "c");
3246 emitcode ("", "%05d$:", (tlbl->key + 100));
3247 emitcode ("push", "psw"); /* save old ea via c in psw */
3252 /*-----------------------------------------------------------------*/
3253 /* genEndFunction - generates epilogue for functions */
3254 /*-----------------------------------------------------------------*/
3256 genEndFunction (iCode * ic)
3258 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3259 lineNode *lnp = lineCurr;
3261 bitVect *regsUsedPrologue;
3262 bitVect *regsUnneeded;
3265 D (emitcode (";", "genEndFunction "););
3267 if (IFFUNC_ISNAKED(sym->type))
3269 emitcode(";", "naked function: no epilogue.");
3270 if (options.debug && currFunc)
3271 debugFile->writeEndFunction (currFunc, ic, 0);
3275 if (IFFUNC_ISCRITICAL (sym->type))
3277 emitcode ("pop", "psw"); /* restore ea via c in psw */
3278 emitcode ("mov", "ea,c");
3281 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3282 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3284 if (options.stack10bit) {
3286 emitcode ("mov", "sp,_bpx", spname);
3287 emitcode ("mov", "esp,_bpx+1", spname);
3290 emitcode ("mov", "%s,_bp", spname);
3294 /* if use external stack but some variables were
3295 added to the local stack then decrement the
3297 if (options.useXstack && sym->stack) {
3298 emitcode ("mov", "a,sp");
3299 emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3300 emitcode ("mov", "sp,a");
3304 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3305 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3307 if (options.useXstack) {
3308 emitcode ("mov", "r0,%s", spname);
3309 emitcode ("movx", "a,@r0");
3310 emitcode ("mov", "_bp,a");
3311 emitcode ("dec", "%s", spname);
3313 if (options.stack10bit) {
3314 emitcode ("pop", "_bpx+1");
3315 emitcode ("pop", "_bpx");
3317 emitcode ("pop", "_bp");
3322 /* restore the register bank */
3323 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3325 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3326 || !options.useXstack)
3328 /* Special case of ISR using non-zero bank with useXstack
3331 emitcode ("pop", "psw");
3335 if (IFFUNC_ISISR (sym->type))
3338 /* now we need to restore the registers */
3339 /* if this isr has no bank i.e. is going to
3340 run with bank 0 , then we need to save more
3342 if (!FUNC_REGBANK (sym->type))
3345 /* if this function does not call any other
3346 function then we can be economical and
3347 save only those registers that are used */
3348 if (!IFFUNC_HASFCALL(sym->type))
3351 /* if any registers used */
3354 /* save the registers used */
3355 for (i = sym->regsUsed->size; i >= 0; i--)
3357 if (bitVectBitValue (sym->regsUsed, i))
3358 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3364 /* this function has a function call cannot
3365 determines register usage so we will have to pop the
3367 if (options.parms_in_bank1) {
3368 for (i = 7 ; i >= 0 ; i-- ) {
3369 emitcode ("pop","%s",rb1regs[i]);
3372 unsaveRBank (0, ic, FALSE);
3377 /* This ISR uses a non-zero bank.
3379 * Restore any register banks saved by genFunction
3382 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3385 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3387 if (savedBanks & (1 << ix))
3389 unsaveRBank(ix, NULL, FALSE);
3393 if (options.useXstack)
3395 /* Restore bank AFTER calling unsaveRBank,
3396 * since it can trash r0.
3398 emitcode ("pop", "psw");
3402 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3404 if (options.stack10bit)
3406 emitcode ("pop", DP2_RESULT_REG);
3407 emitcode ("pop", "dpx1");
3408 emitcode ("pop", "dph1");
3409 emitcode ("pop", "dpl1");
3411 emitcode ("pop", "dps");
3412 emitcode ("pop", "dpx");
3414 if (!inExcludeList ("dph"))
3415 emitcode ("pop", "dph");
3416 if (!inExcludeList ("dpl"))
3417 emitcode ("pop", "dpl");
3418 if (!inExcludeList ("b"))
3419 emitcode ("pop", "b");
3420 if (!inExcludeList ("acc"))
3421 emitcode ("pop", "acc");
3423 /* if debug then send end of function */
3424 if (options.debug && currFunc) {
3425 debugFile->writeEndFunction (currFunc, ic, 1);
3428 emitcode ("reti", "");
3432 if (IFFUNC_CALLEESAVES(sym->type))
3436 /* if any registers used */
3439 /* save the registers used */
3440 for (i = sym->regsUsed->size; i >= 0; i--)
3442 if (bitVectBitValue (sym->regsUsed, i))
3443 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3448 /* if debug then send end of function */
3449 if (options.debug && currFunc)
3451 debugFile->writeEndFunction (currFunc, ic, 1);
3454 emitcode ("ret", "");
3457 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3460 /* If this was an interrupt handler using bank 0 that called another */
3461 /* function, then all registers must be saved; nothing to optimized. */
3462 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3463 && !FUNC_REGBANK(sym->type))
3466 /* There are no push/pops to optimize if not callee-saves or ISR */
3467 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3470 /* If there were stack parameters, we cannot optimize without also */
3471 /* fixing all of the stack offsets; this is too dificult to consider. */
3472 if (FUNC_HASSTACKPARM(sym->type))
3475 /* Compute the registers actually used */
3476 regsUsed = newBitVect (ds390_nRegs);
3477 regsUsedPrologue = newBitVect (ds390_nRegs);
3480 if (lnp->ic && lnp->ic->op == FUNCTION)
3481 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3483 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3485 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3486 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3493 if (bitVectBitValue (regsUsedPrologue, DPS_IDX)
3494 && !bitVectBitValue (regsUsed, DPS_IDX))
3496 bitVectUnSetBit (regsUsedPrologue, DPS_IDX);
3499 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3500 && !bitVectBitValue (regsUsed, CND_IDX))
3502 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3503 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3504 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3505 bitVectUnSetBit (regsUsed, CND_IDX);
3508 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3510 /* If this was an interrupt handler that called another function */
3511 /* function, then assume working registers may be modified by it. */
3512 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3514 regsUsed = bitVectSetBit (regsUsed, AP_IDX);
3515 regsUsed = bitVectSetBit (regsUsed, DPX1_IDX);
3516 regsUsed = bitVectSetBit (regsUsed, DPL1_IDX);
3517 regsUsed = bitVectSetBit (regsUsed, DPH1_IDX);
3518 regsUsed = bitVectSetBit (regsUsed, DPX_IDX);
3519 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3520 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3521 regsUsed = bitVectSetBit (regsUsed, DPS_IDX);
3522 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3523 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3524 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3527 /* Remove the unneeded push/pops */
3528 regsUnneeded = newBitVect (ds390_nRegs);
3531 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3533 if (!strncmp(lnp->line, "push", 4))
3535 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3536 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3538 connectLine (lnp->prev, lnp->next);
3539 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3542 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3544 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3545 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3547 connectLine (lnp->prev, lnp->next);
3548 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3555 for (idx = 0; idx < regsUnneeded->size; idx++)
3556 if (bitVectBitValue (regsUnneeded, idx))
3557 emitcode ("", ";\teliminated unneeded push/pop %s", ds390_regWithIdx (idx)->dname);
3559 freeBitVect (regsUnneeded);
3560 freeBitVect (regsUsed);
3561 freeBitVect (regsUsedPrologue);
3564 /*-----------------------------------------------------------------*/
3565 /* genJavaNativeRet - generate code for return JavaNative */
3566 /*-----------------------------------------------------------------*/
3567 static void genJavaNativeRet(iCode *ic)
3571 aopOp (IC_LEFT (ic), ic, FALSE,
3572 AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
3573 size = AOP_SIZE (IC_LEFT (ic));
3577 /* it is assigned to GPR0-R3 then push them */
3578 if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3579 aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3580 for (i = 0 ; i < size ; i++ ) {
3581 emitcode ("push","%s",
3582 aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3584 for (i = (size-1) ; i >= 0 ; i--) {
3585 emitcode ("pop","a%s",javaRet[i]);
3588 for (i = 0 ; i < size ; i++)
3589 emitcode ("mov","%s,%s",javaRet[i],
3590 aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3592 for (i = size ; i < 4 ; i++ )
3593 emitcode ("mov","%s,#0",javaRet[i]);
3597 /*-----------------------------------------------------------------*/
3598 /* genRet - generate code for return statement */
3599 /*-----------------------------------------------------------------*/
3603 int size, offset = 0, pushed = 0;
3605 D (emitcode (";", "genRet "););
3607 /* if we have no return value then
3608 just generate the "ret" */
3612 /* if this is a JavaNative function then return
3613 value in different register */
3614 if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3615 genJavaNativeRet(ic);
3618 /* we have something to return then
3619 move the return value into place */
3620 aopOp (IC_LEFT (ic), ic, FALSE,
3621 (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
3622 size = AOP_SIZE (IC_LEFT (ic));
3624 _startLazyDPSEvaluation ();
3628 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3630 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3632 emitcode ("push", "%s", l);
3637 /* Since A is the last element of fReturn,
3638 * is is OK to clobber it in the aopGet.
3640 l = aopGet (AOP (IC_LEFT (ic)), offset,
3641 FALSE, FALSE, NULL);
3642 if (strcmp (fReturn[offset], l))
3643 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3646 _endLazyDPSEvaluation ();
3653 if (strcmp (fReturn[pushed], "a"))
3654 emitcode ("pop", fReturn[pushed]);
3656 emitcode ("pop", "acc");
3659 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3662 /* generate a jump to the return label
3663 if the next is not the return statement */
3664 if (!(ic->next && ic->next->op == LABEL &&
3665 IC_LABEL (ic->next) == returnLabel))
3667 emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3671 /*-----------------------------------------------------------------*/
3672 /* genLabel - generates a label */
3673 /*-----------------------------------------------------------------*/
3675 genLabel (iCode * ic)
3677 /* special case never generate */
3678 if (IC_LABEL (ic) == entryLabel)
3681 D (emitcode (";", "genLabel ");
3684 emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3687 /*-----------------------------------------------------------------*/
3688 /* genGoto - generates a ljmp */
3689 /*-----------------------------------------------------------------*/
3691 genGoto (iCode * ic)
3693 D (emitcode (";", "genGoto ");
3695 emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3698 /*-----------------------------------------------------------------*/
3699 /* findLabelBackwards: walks back through the iCode chain looking */
3700 /* for the given label. Returns number of iCode instructions */
3701 /* between that label and given ic. */
3702 /* Returns zero if label not found. */
3703 /*-----------------------------------------------------------------*/
3705 findLabelBackwards (iCode * ic, int key)
3714 /* If we have any pushes or pops, we cannot predict the distance.
3715 I don't like this at all, this should be dealt with in the
3717 if (ic->op == IPUSH || ic->op == IPOP) {
3721 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3723 /* printf("findLabelBackwards = %d\n", count); */
3731 /*-----------------------------------------------------------------*/
3732 /* genPlusIncr :- does addition with increment if possible */
3733 /*-----------------------------------------------------------------*/
3735 genPlusIncr (iCode * ic)
3737 unsigned int icount;
3738 unsigned int size = getDataSize (IC_RESULT (ic));
3740 /* will try to generate an increment */
3741 /* if the right side is not a literal
3743 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3746 /* if the literal value of the right hand side
3747 is greater than 4 then it is not worth it */
3748 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3751 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3752 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3754 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
3758 /* if increment 16 bits in register */
3760 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3761 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3762 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3771 /* If the next instruction is a goto and the goto target
3772 * is <= 5 instructions previous to this, we can generate
3773 * jumps straight to that target.
3775 if (ic->next && ic->next->op == GOTO
3776 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3779 D(emitcode (";", "tail increment optimized (range %d)", labelRange););
3780 tlbl = IC_LABEL (ic->next);
3785 tlbl = newiTempLabel (NULL);
3789 l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
3790 emitcode ("inc", "%s", l);
3792 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3793 IS_AOP_PREG (IC_RESULT (ic)))
3795 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3799 emitcode ("clr", "a");
3800 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3803 l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
3804 emitcode ("inc", "%s", l);
3807 if (!strcmp(l, "acc"))
3809 emitcode("jnz", "!tlabel", tlbl->key + 100);
3811 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3812 IS_AOP_PREG (IC_RESULT (ic)))
3814 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3818 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3821 l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
3822 emitcode ("inc", "%s", l);
3826 if (!strcmp(l, "acc"))
3828 emitcode("jnz", "!tlabel", tlbl->key + 100);
3830 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3831 IS_AOP_PREG (IC_RESULT (ic)))
3833 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3837 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3840 l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
3841 emitcode ("inc", "%s", l); }
3845 emitcode ("", "!tlabeldef", tlbl->key + 100);
3850 if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3851 !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 &&
3852 options.model == MODEL_FLAT24 ) {
3856 emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, NULL));
3858 emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, NULL));
3860 emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3863 while (icount--) emitcode ("inc","dptr");
3867 if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3868 AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3870 emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3871 while (icount--) emitcode ("inc","dptr");
3872 emitcode ("mov","dps,#0");
3876 /* if the sizes are greater than 1 then we cannot */
3877 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3878 AOP_SIZE (IC_LEFT (ic)) > 1)
3881 /* we can if the aops of the left & result match or
3882 if they are in registers and the registers are the
3885 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3886 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3887 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3892 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3893 emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3894 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3899 _startLazyDPSEvaluation ();
3902 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3904 _endLazyDPSEvaluation ();
3913 /*-----------------------------------------------------------------*/
3914 /* outBitAcc - output a bit in acc */
3915 /*-----------------------------------------------------------------*/
3917 outBitAcc (operand * result)
3919 symbol *tlbl = newiTempLabel (NULL);
3920 /* if the result is a bit */
3921 if (AOP_TYPE (result) == AOP_CRY)
3923 aopPut (AOP (result), "a", 0);
3927 emitcode ("jz", "!tlabel", tlbl->key + 100);
3928 emitcode ("mov", "a,%s", one);
3929 emitcode ("", "!tlabeldef", tlbl->key + 100);
3934 /*-----------------------------------------------------------------*/
3935 /* genPlusBits - generates code for addition of two bits */
3936 /*-----------------------------------------------------------------*/
3938 genPlusBits (iCode * ic)
3940 D (emitcode (";", "genPlusBits "););
3942 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3944 symbol *lbl = newiTempLabel (NULL);
3945 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3946 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3947 emitcode ("cpl", "c");
3948 emitcode ("", "!tlabeldef", (lbl->key + 100));
3949 outBitC (IC_RESULT (ic));
3953 emitcode ("clr", "a");
3954 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3955 emitcode ("rlc", "a");
3956 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3957 emitcode ("addc", "a,#0");
3958 outAcc (IC_RESULT (ic));
3963 adjustArithmeticResult (iCode * ic)
3965 if (opIsGptr (IC_RESULT (ic)) &&
3966 opIsGptr (IC_LEFT (ic)) &&
3967 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3969 aopPut (AOP (IC_RESULT (ic)),
3970 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3974 if (opIsGptr (IC_RESULT (ic)) &&
3975 opIsGptr (IC_RIGHT (ic)) &&
3976 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3978 aopPut (AOP (IC_RESULT (ic)),
3979 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3983 if (opIsGptr (IC_RESULT (ic)) &&
3984 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3985 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3986 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3987 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3990 SNPRINTF (buff, sizeof(buff),
3991 "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3992 aopPut (AOP (IC_RESULT (ic)), buff, GPTRSIZE - 1);
3996 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
3997 // generates the result if possible. If result is generated, returns TRUE; otherwise
3998 // returns false and caller must deal with fact that result isn't aopOp'd.
3999 bool aopOp3(iCode * ic)
4001 bool dp1InUse, dp2InUse;
4004 // First, generate the right opcode. DPTR may be used if neither left nor result are
4007 // D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
4008 // AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
4009 // AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
4010 // AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
4012 // D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
4013 // AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
4014 // AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
4015 // AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
4018 // Right uses DPTR unless left or result is an AOP_STR; however,
4019 // if right is an AOP_STR, it must use DPTR regardless.
4020 if ((AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)))
4021 && !AOP_IS_STR(IC_RIGHT(ic)))
4030 aopOp (IC_RIGHT(ic),ic,FALSE, useDp2);
4032 // if the right used DPTR, left MUST use DPTR2.
4033 // if the right used DPTR2, left MUST use DPTR.
4034 // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
4035 // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
4036 // enabling us to assign DPTR to result.
4038 if (AOP_USESDPTR(IC_RIGHT(ic)))
4042 else if (AOP_USESDPTR2(IC_RIGHT(ic)))
4048 if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
4058 aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
4061 // We've op'd the left & right. So, if left or right are the same operand as result,
4062 // we know aopOp will succeed, and we can just do it & bail.
4063 if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)))
4065 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4068 if (isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
4070 // D(emitcode(";", "aopOp3: (left | right) & result equal"););
4071 aopOp(IC_RESULT(ic),ic,TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4075 // Operands may be equivalent (but not equal) if they share a spill location. If
4076 // so, use the same DPTR or DPTR2.
4077 if (operandsEqu (IC_LEFT(ic), IC_RESULT(ic)))
4079 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4082 if (operandsEqu (IC_RIGHT(ic), IC_RESULT(ic)))
4084 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4088 // Note which dptrs are currently in use.
4089 dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
4090 dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
4092 // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot
4094 if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
4099 // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
4100 if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
4105 // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck
4106 if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
4111 aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
4113 // Some sanity checking...
4114 if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
4117 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
4118 __FILE__, __LINE__, ic->filename, ic->lineno);
4119 emitcode(";", ">>> unexpected DPTR here.");
4122 if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
4125 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
4126 __FILE__, __LINE__, ic->filename, ic->lineno);
4127 emitcode(";", ">>> unexpected DPTR2 here.");
4133 // Macro to aopOp all three operands of an ic. If this cannot be done,
4134 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
4135 // will be set TRUE. The caller must then handle the case specially, noting
4136 // that the IC_RESULT operand is not aopOp'd.
4138 #define AOP_OP_3_NOFATAL(ic, rc) \
4139 do { rc = !aopOp3(ic); } while (0)
4141 // aopOp the left & right operands of an ic.
4142 #define AOP_OP_2(ic) \
4143 aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
4144 aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
4146 // convienience macro.
4147 #define AOP_SET_LOCALS(ic) \
4148 left = IC_LEFT(ic); \
4149 right = IC_RIGHT(ic); \
4150 result = IC_RESULT(ic);
4153 // Given an integer value of pushedSize bytes on the stack,
4154 // adjust it to be resultSize bytes, either by discarding
4155 // the most significant bytes or by zero-padding.
4157 // On exit from this macro, pushedSize will have been adjusted to
4158 // equal resultSize, and ACC may be trashed.
4159 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
4160 /* If the pushed data is bigger than the result, \
4161 * simply discard unused bytes. Icky, but works. \
4163 while (pushedSize > resultSize) \
4165 D (emitcode (";", "discarding unused result byte."););\
4166 emitcode ("pop", "acc"); \
4169 if (pushedSize < resultSize) \
4171 emitcode ("clr", "a"); \
4172 /* Conversly, we haven't pushed enough here. \
4173 * just zero-pad, and all is well. \
4175 while (pushedSize < resultSize) \
4177 emitcode("push", "acc"); \
4181 assert(pushedSize == resultSize);
4183 /*-----------------------------------------------------------------*/
4184 /* genPlus - generates code for addition */
4185 /*-----------------------------------------------------------------*/
4187 genPlus (iCode * ic)
4189 int size, offset = 0;
4193 D (emitcode (";", "genPlus "););
4195 /* special cases :- */
4196 if ( AOP_IS_STR(IC_LEFT(ic)) &&
4197 isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
4198 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
4199 size = (int)floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
4201 while (size--) emitcode ("inc","dptr");
4203 emitcode ("mov","a,dpl");
4204 emitcode ("add","a,#!constbyte",size & 0xff);
4205 emitcode ("mov","dpl,a");
4206 emitcode ("mov","a,dph");
4207 emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
4208 emitcode ("mov","dph,a");
4209 emitcode ("mov","a,dpx");
4210 emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
4211 emitcode ("mov","dpx,a");
4213 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
4216 if ( IS_SYMOP(IC_LEFT(ic)) &&
4217 OP_SYMBOL(IC_LEFT(ic))->remat &&
4218 isOperandInFarSpace(IC_RIGHT(ic))) {
4219 operand *op = IC_RIGHT(ic);
4220 IC_RIGHT(ic) = IC_LEFT(ic);
4224 AOP_OP_3_NOFATAL (ic, pushResult);
4228 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
4233 /* if literal, literal on the right or
4234 if left requires ACC or right is already
4236 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4237 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
4238 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4240 operand *t = IC_RIGHT (ic);
4241 IC_RIGHT (ic) = IC_LEFT (ic);
4243 emitcode (";", "Swapped plus args.");
4246 /* if both left & right are in bit
4248 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4249 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4255 /* if left in bit space & right literal */
4256 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4257 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4259 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4260 /* if result in bit space */
4261 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4263 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4264 emitcode ("cpl", "c");
4265 outBitC (IC_RESULT (ic));
4269 size = getDataSize (IC_RESULT (ic));
4270 _startLazyDPSEvaluation ();
4273 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4274 emitcode ("addc", "a,#0");
4275 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4277 _endLazyDPSEvaluation ();
4282 /* if I can do an increment instead
4283 of add then GOOD for ME */
4284 if (genPlusIncr (ic) == TRUE)
4286 emitcode (";", "did genPlusIncr");
4291 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4293 _startLazyDPSEvaluation ();
4296 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4298 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4300 emitcode ("add", "a,%s",
4301 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4303 emitcode ("addc", "a,%s",
4304 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4308 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4310 /* right is going to use ACC or we would have taken the
4313 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4315 D(emitcode(";", "+ AOP_ACC special case."););
4316 emitcode("xch", "a, %s", DP2_RESULT_REG);
4318 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4321 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4324 emitcode("add", "a, %s", DP2_RESULT_REG);
4328 emitcode ("add", "a,%s",
4329 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE,
4335 emitcode ("addc", "a,%s",
4336 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE,
4342 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4346 emitcode ("push", "acc");
4350 _endLazyDPSEvaluation ();
4354 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4356 size = getDataSize (IC_LEFT (ic));
4357 rSize = getDataSize (IC_RESULT (ic));
4359 ADJUST_PUSHED_RESULT(size, rSize);
4361 _startLazyDPSEvaluation ();
4364 emitcode ("pop", "acc");
4365 aopPut (AOP (IC_RESULT (ic)), "a", size);
4367 _endLazyDPSEvaluation ();
4370 adjustArithmeticResult (ic);
4373 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4374 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4375 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4378 /*-----------------------------------------------------------------*/
4379 /* genMinusDec :- does subtraction with deccrement if possible */
4380 /*-----------------------------------------------------------------*/
4382 genMinusDec (iCode * ic)
4384 unsigned int icount;
4385 unsigned int size = getDataSize (IC_RESULT (ic));
4387 /* will try to generate an increment */
4388 /* if the right side is not a literal
4390 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4393 /* if the literal value of the right hand side
4394 is greater than 4 then it is not worth it */
4395 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4398 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4399 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4401 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
4405 /* if decrement 16 bits in register */
4406 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4407 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4408 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4417 /* If the next instruction is a goto and the goto target
4418 * is <= 5 instructions previous to this, we can generate
4419 * jumps straight to that target.
4421 if (ic->next && ic->next->op == GOTO
4422 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4425 emitcode (";", "tail decrement optimized (range %d)", labelRange);
4426 tlbl = IC_LABEL (ic->next);
4431 tlbl = newiTempLabel (NULL);
4435 l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
4436 emitcode ("dec", "%s", l);
4438 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4439 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4440 IS_AOP_PREG (IC_RESULT (ic)))
4442 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4446 emitcode ("mov", "a,#!constbyte",0xff);
4447 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4449 l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
4450 emitcode ("dec", "%s", l);
4453 if (!strcmp(l, "acc"))
4455 emitcode("jnz", "!tlabel", tlbl->key + 100);
4457 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4458 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4459 IS_AOP_PREG (IC_RESULT (ic)))
4461 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4465 emitcode ("mov", "a,#!constbyte",0xff);
4466 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4468 l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
4469 emitcode ("dec", "%s", l);
4473 if (!strcmp(l, "acc"))
4475 emitcode("jnz", "!tlabel", tlbl->key + 100);
4477 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4478 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4479 IS_AOP_PREG (IC_RESULT (ic)))
4481 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4485 emitcode ("mov", "a,#!constbyte",0xff);
4486 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4488 l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
4489 emitcode ("dec", "%s", l);
4493 emitcode ("", "!tlabeldef", tlbl->key + 100);
4498 /* if the sizes are greater than 1 then we cannot */
4499 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4500 AOP_SIZE (IC_LEFT (ic)) > 1)
4503 /* we can if the aops of the left & result match or
4504 if they are in registers and the registers are the
4507 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4508 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4509 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4512 _startLazyDPSEvaluation ();
4515 emitcode ("dec", "%s",
4516 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
4518 _endLazyDPSEvaluation ();
4526 /*-----------------------------------------------------------------*/
4527 /* addSign - complete with sign */
4528 /*-----------------------------------------------------------------*/
4530 addSign (operand * result, int offset, int sign)
4532 int size = (getDataSize (result) - offset);
4535 _startLazyDPSEvaluation();
4538 emitcode ("rlc", "a");
4539 emitcode ("subb", "a,acc");
4542 aopPut (AOP (result), "a", offset++);
4549 aopPut (AOP (result), zero, offset++);
4552 _endLazyDPSEvaluation();
4556 /*-----------------------------------------------------------------*/
4557 /* genMinusBits - generates code for subtraction of two bits */
4558 /*-----------------------------------------------------------------*/
4560 genMinusBits (iCode * ic)
4562 symbol *lbl = newiTempLabel (NULL);
4564 D (emitcode (";", "genMinusBits "););
4566 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4568 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4569 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4570 emitcode ("cpl", "c");
4571 emitcode ("", "!tlabeldef", (lbl->key + 100));
4572 outBitC (IC_RESULT (ic));
4576 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4577 emitcode ("subb", "a,acc");
4578 emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4579 emitcode ("inc", "a");
4580 emitcode ("", "!tlabeldef", (lbl->key + 100));
4581 aopPut (AOP (IC_RESULT (ic)), "a", 0);
4582 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4586 /*-----------------------------------------------------------------*/
4587 /* genMinus - generates code for subtraction */
4588 /*-----------------------------------------------------------------*/
4590 genMinus (iCode * ic)
4592 int size, offset = 0;
4597 D (emitcode (";", "genMinus "););
4599 AOP_OP_3_NOFATAL(ic, pushResult);
4603 /* special cases :- */
4604 /* if both left & right are in bit space */
4605 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4606 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4612 /* if I can do an decrement instead
4613 of subtract then GOOD for ME */
4614 if (genMinusDec (ic) == TRUE)
4619 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4621 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4627 lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4632 /* if literal, add a,#-lit, else normal subb */
4633 _startLazyDPSEvaluation ();
4635 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4636 if (AOP_USESDPTR(IC_RIGHT(ic))) {
4637 emitcode ("mov","b,%s",
4638 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4639 MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4640 emitcode ("subb","a,b");
4642 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4643 emitcode ("subb", "a,%s",
4644 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE,
4648 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4649 /* first add without previous c */
4651 if (!size && lit==-1) {
4652 emitcode ("dec", "a");
4654 emitcode ("add", "a,#!constbyte",
4655 (unsigned int) (lit & 0x0FFL));
4658 emitcode ("addc", "a,#!constbyte",
4659 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4664 emitcode ("push", "acc");
4666 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4670 _endLazyDPSEvaluation ();
4674 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4676 size = getDataSize (IC_LEFT (ic));
4677 rSize = getDataSize (IC_RESULT (ic));
4679 ADJUST_PUSHED_RESULT(size, rSize);
4681 _startLazyDPSEvaluation ();
4684 emitcode ("pop", "acc");
4685 aopPut (AOP (IC_RESULT (ic)), "a", size);
4687 _endLazyDPSEvaluation ();
4690 adjustArithmeticResult (ic);
4693 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4694 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4695 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4699 /*-----------------------------------------------------------------*/
4700 /* genMultbits :- multiplication of bits */
4701 /*-----------------------------------------------------------------*/
4703 genMultbits (operand * left,
4708 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4709 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4710 aopOp(result, ic, TRUE, FALSE);
4715 /*-----------------------------------------------------------------*/
4716 /* genMultOneByte : 8*8=8/16 bit multiplication */
4717 /*-----------------------------------------------------------------*/
4719 genMultOneByte (operand * left,
4726 bool runtimeSign, compiletimeSign;
4727 bool lUnsigned, rUnsigned;
4730 /* (if two literals: the value is computed before) */
4731 /* if one literal, literal on the right */
4732 if (AOP_TYPE (left) == AOP_LIT)
4737 emitcode (";", "swapped left and right");
4740 /* (if two literals: the value is computed before) */
4741 /* if one literal, literal on the right */
4742 if (AOP_TYPE (left) == AOP_LIT)
4747 /* emitcode (";", "swapped left and right"); */
4749 /* if no literal, unsigned on the right: shorter code */
4750 if ( AOP_TYPE (right) != AOP_LIT
4751 && SPEC_USIGN (getSpec (operandType (left))))
4758 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4759 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4761 if ((lUnsigned && rUnsigned)
4762 /* sorry, I don't know how to get size
4763 without calling aopOp (result,...);
4764 see Feature Request */
4765 /* || size == 1 */ ) /* no, this is not a bug; with a 1 byte result there's
4766 no need to take care about the signedness! */
4768 /* just an unsigned 8 * 8 = 8 multiply
4770 /* emitcode (";","unsigned"); */
4771 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4772 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4773 emitcode ("mul", "ab");
4775 _G.accInUse++; _G.bInUse++;
4776 aopOp (result, ic, TRUE, FALSE);
4777 size = AOP_SIZE (result);
4779 if (size < 1 || size > 2)
4781 /* this should never happen */
4782 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4783 size, __FILE__, lineno);
4787 aopPut (AOP (result), "a", 0);
4788 _G.accInUse--; _G.bInUse--;
4790 aopPut (AOP (result), "b", 1);
4794 /* we have to do a signed multiply */
4795 /* emitcode (";", "signed"); */
4797 /* now sign adjust for both left & right */
4799 /* let's see what's needed: */
4800 /* apply negative sign during runtime */
4801 runtimeSign = FALSE;
4802 /* negative sign from literals */
4803 compiletimeSign = FALSE;
4807 if (AOP_TYPE(left) == AOP_LIT)
4809 /* signed literal */
4810 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4812 compiletimeSign = TRUE;
4815 /* signed but not literal */
4821 if (AOP_TYPE(right) == AOP_LIT)
4823 /* signed literal */
4824 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4826 compiletimeSign ^= TRUE;
4829 /* signed but not literal */
4833 /* initialize F0, which stores the runtime sign */
4836 if (compiletimeSign)
4837 emitcode ("setb", "F0"); /* set sign flag */
4839 emitcode ("clr", "F0"); /* reset sign flag */
4842 /* save the signs of the operands */
4843 if (AOP_TYPE(right) == AOP_LIT)
4845 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4847 if (!rUnsigned && val < 0)
4848 emitcode ("mov", "b,#!constbyte", -val);
4850 emitcode ("mov", "b,#!constbyte", (unsigned char) val);
4852 else /* ! literal */
4854 if (rUnsigned) /* emitcode (";", "signed"); */
4855 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4858 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4859 lbl = newiTempLabel (NULL);
4860 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
4861 emitcode ("cpl", "F0"); /* complement sign flag */
4862 emitcode ("cpl", "a"); /* 2's complement */
4863 emitcode ("inc", "a");
4864 emitcode ("", "!tlabeldef", lbl->key + 100);
4865 emitcode ("mov", "b,a");
4869 if (AOP_TYPE(left) == AOP_LIT)
4871 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4873 if (!lUnsigned && val < 0)
4874 emitcode ("mov", "a,#!constbyte", -val);
4876 emitcode ("mov", "a,#!constbyte", (unsigned char) val);
4878 else /* ! literal */
4880 if (lUnsigned) /* emitcode (";", "signed"); */
4882 emitcode ("mov", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4885 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4886 lbl = newiTempLabel (NULL);
4887 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
4888 emitcode ("cpl", "F0"); /* complement sign flag */
4889 emitcode ("cpl", "a"); /* 2's complement */
4890 emitcode ("inc", "a");
4891 emitcode ("", "!tlabeldef", lbl->key + 100);
4895 /* now the multiplication */
4896 emitcode ("mul", "ab");
4897 _G.accInUse++;_G.bInUse++;
4898 aopOp(result, ic, TRUE, FALSE);
4899 size = AOP_SIZE (result);
4901 if (size < 1 || size > 2)
4903 /* this should never happen */
4904 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4905 size, __FILE__, lineno);
4909 if (runtimeSign || compiletimeSign)
4911 lbl = newiTempLabel (NULL);
4913 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
4914 emitcode ("cpl", "a"); /* lsb 2's complement */
4916 emitcode ("inc", "a"); /* inc doesn't set carry flag */
4919 emitcode ("add", "a,#1"); /* this sets carry flag */
4920 emitcode ("xch", "a,b");
4921 emitcode ("cpl", "a"); /* msb 2's complement */
4922 emitcode ("addc", "a,#0");
4923 emitcode ("xch", "a,b");
4925 emitcode ("", "!tlabeldef", lbl->key + 100);
4927 aopPut (AOP (result), "a", 0);
4928 _G.accInUse--;_G.bInUse--;
4930 aopPut (AOP (result), "b", 1);
4933 /*-----------------------------------------------------------------*/
4934 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
4935 /*-----------------------------------------------------------------*/
4936 static void genMultTwoByte (operand *left, operand *right,
4937 operand *result, iCode *ic)
4939 sym_link *retype = getSpec(operandType(right));
4940 sym_link *letype = getSpec(operandType(left));
4941 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4944 if (AOP_TYPE (left) == AOP_LIT) {
4949 /* save EA bit in F1 */
4950 lbl = newiTempLabel(NULL);
4951 emitcode ("setb","F1");
4952 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4953 emitcode ("clr","F1");
4954 emitcode("","!tlabeldef",lbl->key+100);
4956 /* load up MB with right */
4958 emitcode("clr","F0");
4959 if (AOP_TYPE(right) == AOP_LIT) {
4960 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
4962 emitcode("setb","F0");
4965 emitcode ("mov","mb,#!constbyte",val & 0xff);
4966 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4968 lbl = newiTempLabel(NULL);
4969 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4970 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4971 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4972 emitcode ("xch", "a,b");
4973 emitcode ("cpl","a");
4974 emitcode ("add", "a,#1");
4975 emitcode ("xch", "a,b");
4976 emitcode ("cpl", "a"); // msb
4977 emitcode ("addc", "a,#0");
4978 emitcode ("setb","F0");
4979 emitcode ("","!tlabeldef",lbl->key+100);
4980 emitcode ("mov","mb,b");
4981 emitcode ("mov","mb,a");
4984 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4985 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4987 /* load up MA with left */
4989 lbl = newiTempLabel(NULL);
4990 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4991 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4992 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4993 emitcode ("xch", "a,b");
4994 emitcode ("cpl","a");
4995 emitcode ("add", "a,#1");
4996 emitcode ("xch", "a,b");
4997 emitcode ("cpl", "a"); // msb
4998 emitcode ("addc","a,#0");
4999 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5000 emitcode ("setb","F0");
5001 emitcode ("","!tlabeldef",lbl->key+100);
5002 emitcode ("mov","ma,b");
5003 emitcode ("mov","ma,a");
5005 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5006 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5008 /* wait for multiplication to finish */
5009 lbl = newiTempLabel(NULL);
5010 emitcode("","!tlabeldef", lbl->key+100);
5011 emitcode("mov","a,mcnt1");
5012 emitcode("anl","a,#!constbyte",0x80);
5013 emitcode("jnz","!tlabel",lbl->key+100);
5015 freeAsmop (left, NULL, ic, TRUE);
5016 freeAsmop (right, NULL, ic,TRUE);
5017 aopOp(result, ic, TRUE, FALSE);
5019 /* if unsigned then simple */
5021 emitcode ("mov","a,ma");
5022 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
5023 emitcode ("mov","a,ma");
5024 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
5025 aopPut(AOP(result),"ma",1);
5026 aopPut(AOP(result),"ma",0);
5028 emitcode("push","ma");
5029 emitcode("push","ma");
5030 emitcode("push","ma");
5032 /* negate result if needed */
5033 lbl = newiTempLabel(NULL);
5034 emitcode("jnb","F0,!tlabel",lbl->key+100);
5035 emitcode("cpl","a");
5036 emitcode("add","a,#1");
5037 emitcode("","!tlabeldef", lbl->key+100);
5038 if (AOP_TYPE(result) == AOP_ACC)
5040 D(emitcode(";", "ACC special case."););
5041 /* We know result is the only live aop, and
5042 * it's obviously not a DPTR2, so AP is available.
5044 emitcode("mov", "%s,acc", DP2_RESULT_REG);
5048 aopPut(AOP(result),"a",0);
5051 emitcode("pop","acc");
5052 lbl = newiTempLabel(NULL);
5053 emitcode("jnb","F0,!tlabel",lbl->key+100);
5054 emitcode("cpl","a");
5055 emitcode("addc","a,#0");
5056 emitcode("","!tlabeldef", lbl->key+100);
5057 aopPut(AOP(result),"a",1);
5058 emitcode("pop","acc");
5059 if (AOP_SIZE(result) >= 3) {
5060 lbl = newiTempLabel(NULL);
5061 emitcode("jnb","F0,!tlabel",lbl->key+100);
5062 emitcode("cpl","a");
5063 emitcode("addc","a,#0");
5064 emitcode("","!tlabeldef", lbl->key+100);
5065 aopPut(AOP(result),"a",2);
5067 emitcode("pop","acc");
5068 if (AOP_SIZE(result) >= 4) {
5069 lbl = newiTempLabel(NULL);
5070 emitcode("jnb","F0,!tlabel",lbl->key+100);
5071 emitcode("cpl","a");
5072 emitcode("addc","a,#0");
5073 emitcode("","!tlabeldef", lbl->key+100);
5074 aopPut(AOP(result),"a",3);
5076 if (AOP_TYPE(result) == AOP_ACC)
5078 /* We stashed the result away above. */
5079 emitcode("mov", "acc,%s", DP2_RESULT_REG);
5083 freeAsmop (result, NULL, ic, TRUE);
5085 /* restore EA bit in F1 */
5086 lbl = newiTempLabel(NULL);
5087 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5088 emitcode ("setb","EA");
5089 emitcode("","!tlabeldef",lbl->key+100);
5093 /*-----------------------------------------------------------------*/
5094 /* genMult - generates code for multiplication */
5095 /*-----------------------------------------------------------------*/
5097 genMult (iCode * ic)
5099 operand *left = IC_LEFT (ic);
5100 operand *right = IC_RIGHT (ic);
5101 operand *result = IC_RESULT (ic);
5103 D (emitcode (";", "genMult "););
5105 /* assign the amsops */
5108 /* special cases first */
5110 if (AOP_TYPE (left) == AOP_CRY &&
5111 AOP_TYPE (right) == AOP_CRY)
5113 genMultbits (left, right, result, ic);
5117 /* if both are of size == 1 */
5118 if (AOP_SIZE (left) == 1 &&
5119 AOP_SIZE (right) == 1)
5121 genMultOneByte (left, right, result, ic);
5125 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5126 /* use the ds390 ARITHMETIC accel UNIT */
5127 genMultTwoByte (left, right, result, ic);
5130 /* should have been converted to function call */
5134 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5135 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5136 freeAsmop (result, NULL, ic, TRUE);
5139 /*-----------------------------------------------------------------*/
5140 /* genDivbits :- division of bits */
5141 /*-----------------------------------------------------------------*/
5143 genDivbits (operand * left,
5151 /* the result must be bit */
5152 LOAD_AB_FOR_DIV (left, right, l);
5153 emitcode ("div", "ab");
5154 emitcode ("rrc", "a");
5155 aopOp(result, ic, TRUE, FALSE);
5157 aopPut (AOP (result), "c", 0);
5160 /*-----------------------------------------------------------------*/
5161 /* genDivOneByte : 8 bit division */
5162 /*-----------------------------------------------------------------*/
5164 genDivOneByte (operand * left,
5169 bool lUnsigned, rUnsigned;
5170 bool runtimeSign, compiletimeSign;
5176 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5177 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5179 /* signed or unsigned */
5180 if (lUnsigned && rUnsigned)
5182 /* unsigned is easy */
5183 LOAD_AB_FOR_DIV (left, right, l);
5184 emitcode ("div", "ab");
5187 aopOp (result, ic, TRUE, FALSE);
5188 aopPut (AOP (result), "a", 0);
5191 size = AOP_SIZE (result) - 1;
5194 aopPut (AOP (result), zero, offset++);
5198 /* signed is a little bit more difficult */
5200 /* now sign adjust for both left & right */
5202 /* let's see what's needed: */
5203 /* apply negative sign during runtime */
5204 runtimeSign = FALSE;
5205 /* negative sign from literals */
5206 compiletimeSign = FALSE;
5210 if (AOP_TYPE(left) == AOP_LIT)
5212 /* signed literal */
5213 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5215 compiletimeSign = TRUE;
5218 /* signed but not literal */
5224 if (AOP_TYPE(right) == AOP_LIT)
5226 /* signed literal */
5227 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5229 compiletimeSign ^= TRUE;
5232 /* signed but not literal */
5236 /* initialize F0, which stores the runtime sign */
5239 if (compiletimeSign)
5240 emitcode ("setb", "F0"); /* set sign flag */
5242 emitcode ("clr", "F0"); /* reset sign flag */
5245 /* save the signs of the operands */
5246 if (AOP_TYPE(right) == AOP_LIT)
5248 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5250 if (!rUnsigned && val < 0)
5251 emitcode ("mov", "b,#0x%02x", -val);
5253 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5255 else /* ! literal */
5258 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5261 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5262 lbl = newiTempLabel (NULL);
5263 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5264 emitcode ("cpl", "F0"); /* complement sign flag */
5265 emitcode ("cpl", "a"); /* 2's complement */
5266 emitcode ("inc", "a");
5267 emitcode ("", "!tlabeldef", lbl->key + 100);
5268 emitcode ("mov", "b,a");
5272 if (AOP_TYPE(left) == AOP_LIT)
5274 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5276 if (!lUnsigned && val < 0)
5277 emitcode ("mov", "a,#0x%02x", -val);
5279 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5281 else /* ! literal */
5284 emitcode ("mov", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5287 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5288 lbl = newiTempLabel (NULL);
5289 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5290 emitcode ("cpl", "F0"); /* complement sign flag */
5291 emitcode ("cpl", "a"); /* 2's complement */
5292 emitcode ("inc", "a");
5293 emitcode ("", "!tlabeldef", lbl->key + 100);
5297 /* now the division */
5298 emitcode ("nop", "; workaround for DS80C390 div bug.");
5299 emitcode ("div", "ab");
5301 if (runtimeSign || compiletimeSign)
5303 lbl = newiTempLabel (NULL);
5305 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5306 emitcode ("cpl", "a"); /* lsb 2's complement */
5307 emitcode ("inc", "a");
5308 emitcode ("", "!tlabeldef", lbl->key + 100);
5310 _G.accInUse++; _G.bInUse++;
5311 aopOp (result, ic, TRUE, FALSE);
5312 size = AOP_SIZE (result) - 1;
5316 /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
5317 then the result will be in b, a */
5318 emitcode ("mov", "b,a"); /* 1 */
5319 /* msb is 0x00 or 0xff depending on the sign */
5322 emitcode ("mov", "c,F0");
5323 emitcode ("subb", "a,acc");
5324 emitcode ("xch", "a,b"); /* 2 */
5326 aopPut (AOP (result), "b", offset++); /* write msb's */
5328 else /* compiletimeSign */
5330 aopPut (AOP (result), "#0xff", offset++); /* write msb's */
5332 aopPut (AOP (result), "a", 0); /* 3: write lsb */
5336 _G.accInUse++; _G.bInUse++;
5337 aopOp(result, ic, TRUE, FALSE);
5338 size = AOP_SIZE (result) - 1;
5340 aopPut (AOP (result), "a", 0);
5342 aopPut (AOP (result), zero, offset++);
5344 _G.accInUse--; _G.bInUse--;
5348 /*-----------------------------------------------------------------*/
5349 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
5350 /*-----------------------------------------------------------------*/
5351 static void genDivTwoByte (operand *left, operand *right,
5352 operand *result, iCode *ic)
5354 sym_link *retype = getSpec(operandType(right));
5355 sym_link *letype = getSpec(operandType(left));
5356 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5359 /* save EA bit in F1 */
5360 lbl = newiTempLabel(NULL);
5361 emitcode ("setb","F1");
5362 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5363 emitcode ("clr","F1");
5364 emitcode("","!tlabeldef",lbl->key+100);
5366 /* load up MA with left */
5368 emitcode("clr","F0");
5369 lbl = newiTempLabel(NULL);
5370 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5371 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5372 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5373 emitcode ("xch", "a,b");
5374 emitcode ("cpl","a");
5375 emitcode ("add", "a,#1");
5376 emitcode ("xch", "a,b");
5377 emitcode ("cpl", "a"); // msb
5378 emitcode ("addc","a,#0");
5379 emitcode ("setb","F0");
5380 emitcode ("","!tlabeldef",lbl->key+100);
5381 emitcode ("mov","ma,b");
5382 emitcode ("mov","ma,a");
5384 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5385 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5388 /* load up MB with right */
5390 if (AOP_TYPE(right) == AOP_LIT) {
5391 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5393 lbl = newiTempLabel(NULL);
5394 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5395 emitcode("setb","F0");
5396 emitcode ("","!tlabeldef",lbl->key+100);
5399 emitcode ("mov","mb,#!constbyte",val & 0xff);
5400 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5402 lbl = newiTempLabel(NULL);
5403 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5404 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5405 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5406 emitcode ("xch", "a,b");
5407 emitcode ("cpl","a");
5408 emitcode ("add", "a,#1");
5409 emitcode ("xch", "a,b");
5410 emitcode ("cpl", "a"); // msb
5411 emitcode ("addc", "a,#0");
5412 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5413 emitcode ("setb","F0");
5414 emitcode ("","!tlabeldef",lbl->key+100);
5415 emitcode ("mov","mb,b");
5416 emitcode ("mov","mb,a");
5419 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5420 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5423 /* wait for multiplication to finish */
5424 lbl = newiTempLabel(NULL);
5425 emitcode("","!tlabeldef", lbl->key+100);
5426 emitcode("mov","a,mcnt1");
5427 emitcode("anl","a,#!constbyte",0x80);
5428 emitcode("jnz","!tlabel",lbl->key+100);
5430 freeAsmop (left, NULL, ic, TRUE);
5431 freeAsmop (right, NULL, ic,TRUE);
5432 aopOp(result, ic, TRUE, FALSE);
5434 /* if unsigned then simple */
5436 aopPut(AOP(result),"ma",1);
5437 aopPut(AOP(result),"ma",0);
5439 emitcode("push","ma");
5441 /* negate result if needed */
5442 lbl = newiTempLabel(NULL);
5443 emitcode("jnb","F0,!tlabel",lbl->key+100);
5444 emitcode("cpl","a");
5445 emitcode("add","a,#1");
5446 emitcode("","!tlabeldef", lbl->key+100);
5447 aopPut(AOP(result),"a",0);
5448 emitcode("pop","acc");
5449 lbl = newiTempLabel(NULL);
5450 emitcode("jnb","F0,!tlabel",lbl->key+100);
5451 emitcode("cpl","a");
5452 emitcode("addc","a,#0");
5453 emitcode("","!tlabeldef", lbl->key+100);
5454 aopPut(AOP(result),"a",1);
5456 freeAsmop (result, NULL, ic, TRUE);
5457 /* restore EA bit in F1 */
5458 lbl = newiTempLabel(NULL);
5459 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5460 emitcode ("setb","EA");
5461 emitcode("","!tlabeldef",lbl->key+100);
5465 /*-----------------------------------------------------------------*/
5466 /* genDiv - generates code for division */
5467 /*-----------------------------------------------------------------*/
5471 operand *left = IC_LEFT (ic);
5472 operand *right = IC_RIGHT (ic);
5473 operand *result = IC_RESULT (ic);
5475 D (emitcode (";", "genDiv "););
5477 /* assign the amsops */
5480 /* special cases first */
5482 if (AOP_TYPE (left) == AOP_CRY &&
5483 AOP_TYPE (right) == AOP_CRY)
5485 genDivbits (left, right, result, ic);
5489 /* if both are of size == 1 */
5490 if (AOP_SIZE (left) == 1 &&
5491 AOP_SIZE (right) == 1)
5493 genDivOneByte (left, right, result, ic);
5497 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5498 /* use the ds390 ARITHMETIC accel UNIT */
5499 genDivTwoByte (left, right, result, ic);
5502 /* should have been converted to function call */
5505 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5506 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5507 freeAsmop (result, NULL, ic, TRUE);
5510 /*-----------------------------------------------------------------*/
5511 /* genModbits :- modulus of bits */
5512 /*-----------------------------------------------------------------*/
5514 genModbits (operand * left,
5522 /* the result must be bit */
5523 LOAD_AB_FOR_DIV (left, right, l);
5524 emitcode ("div", "ab");
5525 emitcode ("mov", "a,b");
5526 emitcode ("rrc", "a");
5527 aopOp(result, ic, TRUE, FALSE);
5528 aopPut (AOP (result), "c", 0);
5531 /*-----------------------------------------------------------------*/
5532 /* genModOneByte : 8 bit modulus */
5533 /*-----------------------------------------------------------------*/
5535 genModOneByte (operand * left,
5540 bool lUnsigned, rUnsigned;
5541 bool runtimeSign, compiletimeSign;
5547 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5548 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5550 /* signed or unsigned */
5551 if (lUnsigned && rUnsigned)
5553 /* unsigned is easy */
5554 LOAD_AB_FOR_DIV (left, right, l);
5555 emitcode ("div", "ab");
5556 aopOp (result, ic, TRUE, FALSE);
5557 aopPut (AOP (result), "b", 0);
5559 for (size = AOP_SIZE (result) - 1; size--;)
5560 aopPut (AOP (result), zero, offset++);
5564 /* signed is a little bit more difficult */
5566 /* now sign adjust for both left & right */
5568 /* modulus: sign of the right operand has no influence on the result! */
5569 if (AOP_TYPE(right) == AOP_LIT)
5571 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5573 if (!rUnsigned && val < 0)
5574 emitcode ("mov", "b,#0x%02x", -val);
5576 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5578 else /* ! literal */
5581 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5584 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5585 lbl = newiTempLabel (NULL);
5586 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5587 emitcode ("cpl", "a"); /* 2's complement */
5588 emitcode ("inc", "a");
5589 emitcode ("", "!tlabeldef", lbl->key + 100);
5590 emitcode ("mov", "b,a");
5594 /* let's see what's needed: */
5595 /* apply negative sign during runtime */
5596 runtimeSign = FALSE;
5597 /* negative sign from literals */
5598 compiletimeSign = FALSE;
5600 /* sign adjust left side */
5601 if (AOP_TYPE(left) == AOP_LIT)
5603 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5605 if (!lUnsigned && val < 0)
5607 compiletimeSign = TRUE; /* set sign flag */
5608 emitcode ("mov", "a,#0x%02x", -val);
5611 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5613 else /* ! literal */
5615 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5620 emitcode ("clr", "F0"); /* clear sign flag */
5622 lbl = newiTempLabel (NULL);
5623 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5624 emitcode ("setb", "F0"); /* set sign flag */
5625 emitcode ("cpl", "a"); /* 2's complement */
5626 emitcode ("inc", "a");
5627 emitcode ("", "!tlabeldef", lbl->key + 100);
5631 /* now the modulus */
5632 emitcode ("nop", "; workaround for DS80C390 div bug.");
5633 emitcode ("div", "ab");
5635 if (runtimeSign || compiletimeSign)
5637 emitcode ("mov", "a,b");
5638 lbl = newiTempLabel (NULL);
5640 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5641 emitcode ("cpl", "a"); /* lsb 2's complement */
5642 emitcode ("inc", "a");
5643 emitcode ("", "!tlabeldef", lbl->key + 100);
5645 _G.accInUse++; _G.bInUse++;
5646 aopOp (result, ic, TRUE, FALSE);
5647 size = AOP_SIZE (result) - 1;
5651 /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
5652 then the result will be in b, a */
5653 emitcode ("mov", "b,a"); /* 1 */
5654 /* msb is 0x00 or 0xff depending on the sign */
5657 emitcode ("mov", "c,F0");
5658 emitcode ("subb", "a,acc");
5659 emitcode ("xch", "a,b"); /* 2 */
5661 aopPut (AOP (result), "b", offset++); /* write msb's */
5663 else /* compiletimeSign */
5665 aopPut (AOP (result), "#0xff", offset++); /* write msb's */
5667 aopPut (AOP (result), "a", 0); /* 3: write lsb */
5671 _G.accInUse++; _G.bInUse++;
5672 aopOp(result, ic, TRUE, FALSE);
5673 size = AOP_SIZE (result) - 1;
5675 aopPut (AOP (result), "b", 0);
5677 aopPut (AOP (result), zero, offset++);
5679 _G.accInUse--; _G.bInUse--;
5683 /*-----------------------------------------------------------------*/
5684 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
5685 /*-----------------------------------------------------------------*/
5686 static void genModTwoByte (operand *left, operand *right,
5687 operand *result, iCode *ic)
5689 sym_link *retype = getSpec(operandType(right));
5690 sym_link *letype = getSpec(operandType(left));
5691 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5694 /* load up MA with left */
5695 /* save EA bit in F1 */
5696 lbl = newiTempLabel(NULL);
5697 emitcode ("setb","F1");
5698 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5699 emitcode ("clr","F1");
5700 emitcode("","!tlabeldef",lbl->key+100);
5703 lbl = newiTempLabel(NULL);
5704 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5705 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5706 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5707 emitcode ("xch", "a,b");
5708 emitcode ("cpl","a");
5709 emitcode ("add", "a,#1");
5710 emitcode ("xch", "a,b");
5711 emitcode ("cpl", "a"); // msb
5712 emitcode ("addc","a,#0");
5713 emitcode ("","!tlabeldef",lbl->key+100);
5714 emitcode ("mov","ma,b");
5715 emitcode ("mov","ma,a");
5717 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5718 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5721 /* load up MB with right */
5723 if (AOP_TYPE(right) == AOP_LIT) {
5724 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5728 emitcode ("mov","mb,#!constbyte",val & 0xff);
5729 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5731 lbl = newiTempLabel(NULL);
5732 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5733 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5734 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5735 emitcode ("xch", "a,b");
5736 emitcode ("cpl","a");
5737 emitcode ("add", "a,#1");
5738 emitcode ("xch", "a,b");
5739 emitcode ("cpl", "a"); // msb
5740 emitcode ("addc", "a,#0");
5741 emitcode ("","!tlabeldef",lbl->key+100);
5742 emitcode ("mov","mb,b");
5743 emitcode ("mov","mb,a");
5746 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5747 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5750 /* wait for multiplication to finish */
5751 lbl = newiTempLabel(NULL);
5752 emitcode("","!tlabeldef", lbl->key+100);
5753 emitcode("mov","a,mcnt1");
5754 emitcode("anl","a,#!constbyte",0x80);
5755 emitcode("jnz","!tlabel",lbl->key+100);
5757 freeAsmop (left, NULL, ic, TRUE);
5758 freeAsmop (right, NULL, ic,TRUE);
5759 aopOp(result, ic, TRUE, FALSE);
5761 aopPut(AOP(result),"mb",1);
5762 aopPut(AOP(result),"mb",0);
5763 freeAsmop (result, NULL, ic, TRUE);
5765 /* restore EA bit in F1 */
5766 lbl = newiTempLabel(NULL);
5767 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5768 emitcode ("setb","EA");
5769 emitcode("","!tlabeldef",lbl->key+100);
5773 /*-----------------------------------------------------------------*/
5774 /* genMod - generates code for division */
5775 /*-----------------------------------------------------------------*/
5779 operand *left = IC_LEFT (ic);
5780 operand *right = IC_RIGHT (ic);
5781 operand *result = IC_RESULT (ic);
5783 D (emitcode (";", "genMod "); );
5785 /* assign the amsops */
5788 /* special cases first */
5790 if (AOP_TYPE (left) == AOP_CRY &&
5791 AOP_TYPE (right) == AOP_CRY)
5793 genModbits (left, right, result, ic);
5797 /* if both are of size == 1 */
5798 if (AOP_SIZE (left) == 1 &&
5799 AOP_SIZE (right) == 1)
5801 genModOneByte (left, right, result, ic);
5805 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5806 /* use the ds390 ARITHMETIC accel UNIT */
5807 genModTwoByte (left, right, result, ic);
5811 /* should have been converted to function call */
5815 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5816 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5817 freeAsmop (result, NULL, ic, TRUE);
5820 /*-----------------------------------------------------------------*/
5821 /* genIfxJump :- will create a jump depending on the ifx */
5822 /*-----------------------------------------------------------------*/
5824 genIfxJump (iCode * ic, char *jval)
5827 symbol *tlbl = newiTempLabel (NULL);
5830 D (emitcode (";", "genIfxJump"););
5832 /* if true label then we jump if condition
5836 jlbl = IC_TRUE (ic);
5837 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5838 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5842 /* false label is present */
5843 jlbl = IC_FALSE (ic);
5844 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5845 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5847 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5848 emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5850 emitcode (inst, "!tlabel", tlbl->key + 100);
5851 emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5852 emitcode ("", "!tlabeldef", tlbl->key + 100);
5854 /* mark the icode as generated */
5858 /*-----------------------------------------------------------------*/
5859 /* genCmp :- greater or less than comparison */
5860 /*-----------------------------------------------------------------*/
5862 genCmp (operand * left, operand * right,
5863 iCode * ic, iCode * ifx, int sign)
5865 int size, offset = 0;
5866 unsigned long lit = 0L;
5869 D (emitcode (";", "genCmp"););
5871 result = IC_RESULT (ic);
5873 /* if left & right are bit variables */
5874 if (AOP_TYPE (left) == AOP_CRY &&
5875 AOP_TYPE (right) == AOP_CRY)
5877 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5878 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5882 /* subtract right from left if at the
5883 end the carry flag is set then we know that
5884 left is greater than right */
5885 size = max (AOP_SIZE (left), AOP_SIZE (right));
5887 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5888 if ((size == 1) && !sign
5889 && (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5891 symbol *lbl = newiTempLabel (NULL);
5892 emitcode ("cjne", "%s,%s,!tlabel",
5893 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
5894 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5896 emitcode ("", "!tlabeldef", lbl->key + 100);
5900 if (AOP_TYPE (right) == AOP_LIT)
5902 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5903 /* optimize if(x < 0) or if(x >= 0) */
5912 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
5914 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5915 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5917 aopOp (result, ic, FALSE, FALSE);
5919 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5921 freeAsmop (result, NULL, ic, TRUE);
5922 genIfxJump (ifx, "acc.7");
5927 emitcode ("rlc", "a");
5929 goto release_freedLR;
5937 // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5938 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5939 // emitcode (";", "genCmp #2");
5940 if (sign && (size == 0))
5942 // emitcode (";", "genCmp #3");
5943 emitcode ("xrl", "a,#!constbyte",0x80);
5944 if (AOP_TYPE (right) == AOP_LIT)
5946 unsigned long lit = (unsigned long)
5947 floatFromVal (AOP (right)->aopu.aop_lit);
5948 // emitcode (";", "genCmp #3.1");
5949 emitcode ("subb", "a,#!constbyte",
5950 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5954 // emitcode (";", "genCmp #3.2");
5956 MOVB(aopGet (AOP (right), offset++, FALSE, FALSE, "b"));
5957 saveAccWarn = DEFAULT_ACC_WARNING;
5958 emitcode ("xrl", "b,#!constbyte",0x80);
5959 emitcode ("subb", "a,b");
5966 // emitcode (";", "genCmp #4");
5968 s = aopGet (AOP (right), offset++, FALSE, FALSE, "b");
5969 saveAccWarn = DEFAULT_ACC_WARNING;
5971 emitcode ("subb", "a,%s", s);
5978 /* Don't need the left & right operands any more; do need the result. */
5979 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5980 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5982 aopOp (result, ic, FALSE, FALSE);
5986 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5992 /* if the result is used in the next
5993 ifx conditional branch then generate
5994 code a little differently */
5997 genIfxJump (ifx, "c");
6003 /* leave the result in acc */
6005 freeAsmop (result, NULL, ic, TRUE);
6008 /*-----------------------------------------------------------------*/
6009 /* genCmpGt :- greater than comparison */
6010 /*-----------------------------------------------------------------*/
6012 genCmpGt (iCode * ic, iCode * ifx)
6014 operand *left, *right;
6015 sym_link *letype, *retype;
6018 D (emitcode (";", "genCmpGt ");
6021 left = IC_LEFT (ic);
6022 right = IC_RIGHT (ic);
6024 letype = getSpec (operandType (left));
6025 retype = getSpec (operandType (right));
6026 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6028 /* assign the left & right amsops */
6031 genCmp (right, left, ic, ifx, sign);
6034 /*-----------------------------------------------------------------*/
6035 /* genCmpLt - less than comparisons */
6036 /*-----------------------------------------------------------------*/
6038 genCmpLt (iCode * ic, iCode * ifx)
6040 operand *left, *right;
6041 sym_link *letype, *retype;
6044 D (emitcode (";", "genCmpLt "););
6046 left = IC_LEFT (ic);
6047 right = IC_RIGHT (ic);
6049 letype = getSpec (operandType (left));
6050 retype = getSpec (operandType (right));
6051 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6053 /* assign the left & right amsops */
6056 genCmp (left, right, ic, ifx, sign);
6059 /*-----------------------------------------------------------------*/
6060 /* gencjneshort - compare and jump if not equal */
6061 /*-----------------------------------------------------------------*/
6063 gencjneshort (operand * left, operand * right, symbol * lbl)
6065 int size = max (AOP_SIZE (left), AOP_SIZE (right));
6067 unsigned long lit = 0L;
6069 D (emitcode (";", "gencjneshort");
6072 /* if the left side is a literal or
6073 if the right is in a pointer register and left
6075 if ((AOP_TYPE (left) == AOP_LIT) ||
6076 (AOP_TYPE (left) == AOP_IMMD) ||
6077 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6084 if (AOP_TYPE (right) == AOP_LIT)
6085 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6087 if (opIsGptr (left) || opIsGptr (right))
6089 /* We are comparing a generic pointer to something.
6090 * Exclude the generic type byte from the comparison.
6093 D (emitcode (";", "cjneshort: generic ptr special case."););
6097 /* if the right side is a literal then anything goes */
6098 if (AOP_TYPE (right) == AOP_LIT &&
6099 AOP_TYPE (left) != AOP_DIR)
6103 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6104 emitcode ("cjne", "a,%s,!tlabel",
6105 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
6111 /* if the right side is in a register or in direct space or
6112 if the left is a pointer register & right is not */
6113 else if (AOP_TYPE (right) == AOP_REG ||
6114 AOP_TYPE (right) == AOP_DIR ||
6115 AOP_TYPE (right) == AOP_LIT ||
6116 AOP_TYPE (right) == AOP_IMMD ||
6117 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6118 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6122 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6123 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6124 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6125 emitcode ("jnz", "!tlabel", lbl->key + 100);
6127 emitcode ("cjne", "a,%s,!tlabel",
6128 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
6135 /* right is a pointer reg need both a & b */
6138 MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6139 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6140 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
6146 /*-----------------------------------------------------------------*/
6147 /* gencjne - compare and jump if not equal */
6148 /*-----------------------------------------------------------------*/
6150 gencjne (operand * left, operand * right, symbol * lbl)
6152 symbol *tlbl = newiTempLabel (NULL);
6154 D (emitcode (";", "gencjne");
6157 gencjneshort (left, right, lbl);
6159 emitcode ("mov", "a,%s", one);
6160 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
6161 emitcode ("", "!tlabeldef", lbl->key + 100);
6162 emitcode ("clr", "a");
6163 emitcode ("", "!tlabeldef", tlbl->key + 100);
6166 /*-----------------------------------------------------------------*/
6167 /* genCmpEq - generates code for equal to */
6168 /*-----------------------------------------------------------------*/
6170 genCmpEq (iCode * ic, iCode * ifx)
6172 operand *left, *right, *result;
6174 D (emitcode (";", "genCmpEq ");
6178 AOP_SET_LOCALS (ic);
6180 /* if literal, literal on the right or
6181 if the right is in a pointer register and left
6183 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6184 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6186 operand *t = IC_RIGHT (ic);
6187 IC_RIGHT (ic) = IC_LEFT (ic);
6191 if (ifx && /* !AOP_SIZE(result) */
6192 OP_SYMBOL (result) &&
6193 OP_SYMBOL (result)->regType == REG_CND)
6196 /* if they are both bit variables */
6197 if (AOP_TYPE (left) == AOP_CRY &&
6198 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6200 if (AOP_TYPE (right) == AOP_LIT)
6202 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6205 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6206 emitcode ("cpl", "c");
6210 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6214 emitcode ("clr", "c");
6216 /* AOP_TYPE(right) == AOP_CRY */
6220 symbol *lbl = newiTempLabel (NULL);
6221 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6222 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6223 emitcode ("cpl", "c");
6224 emitcode ("", "!tlabeldef", (lbl->key + 100));
6226 /* if true label then we jump if condition
6228 tlbl = newiTempLabel (NULL);
6231 emitcode ("jnc", "!tlabel", tlbl->key + 100);
6232 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6236 emitcode ("jc", "!tlabel", tlbl->key + 100);
6237 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6239 emitcode ("", "!tlabeldef", tlbl->key + 100);
6243 tlbl = newiTempLabel (NULL);
6244 gencjneshort (left, right, tlbl);
6247 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6248 emitcode ("", "!tlabeldef", tlbl->key + 100);
6252 symbol *lbl = newiTempLabel (NULL);
6253 emitcode ("sjmp", "!tlabel", lbl->key + 100);
6254 emitcode ("", "!tlabeldef", tlbl->key + 100);
6255 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6256 emitcode ("", "!tlabeldef", lbl->key + 100);
6259 /* mark the icode as generated */
6262 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6263 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6267 /* if they are both bit variables */
6268 if (AOP_TYPE (left) == AOP_CRY &&
6269 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6271 if (AOP_TYPE (right) == AOP_LIT)
6273 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6276 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6277 emitcode ("cpl", "c");
6281 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6285 emitcode ("clr", "c");
6287 /* AOP_TYPE(right) == AOP_CRY */
6291 symbol *lbl = newiTempLabel (NULL);
6292 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6293 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6294 emitcode ("cpl", "c");
6295 emitcode ("", "!tlabeldef", (lbl->key + 100));
6298 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6299 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6301 aopOp (result, ic, TRUE, FALSE);
6304 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6311 genIfxJump (ifx, "c");
6314 /* if the result is used in an arithmetic operation
6315 then put the result in place */
6320 gencjne (left, right, newiTempLabel (NULL));
6322 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6323 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6325 aopOp (result, ic, TRUE, FALSE);
6327 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6329 aopPut (AOP (result), "a", 0);
6334 genIfxJump (ifx, "a");
6337 /* if the result is used in an arithmetic operation
6338 then put the result in place */
6339 if (AOP_TYPE (result) != AOP_CRY)
6341 /* leave the result in acc */
6345 freeAsmop (result, NULL, ic, TRUE);
6348 /*-----------------------------------------------------------------*/
6349 /* ifxForOp - returns the icode containing the ifx for operand */
6350 /*-----------------------------------------------------------------*/
6352 ifxForOp (operand * op, iCode * ic)
6354 /* if true symbol then needs to be assigned */
6355 if (IS_TRUE_SYMOP (op))
6358 /* if this has register type condition and
6359 the next instruction is ifx with the same operand
6360 and live to of the operand is upto the ifx only then */
6362 ic->next->op == IFX &&
6363 IC_COND (ic->next)->key == op->key &&
6364 OP_SYMBOL (op)->liveTo <= ic->next->seq)
6369 /*-----------------------------------------------------------------*/
6370 /* hasInc - operand is incremented before any other use */
6371 /*-----------------------------------------------------------------*/
6373 hasInc (operand *op, iCode *ic, int osize)
6375 sym_link *type = operandType(op);
6376 sym_link *retype = getSpec (type);
6377 iCode *lic = ic->next;
6380 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6381 if (!IS_SYMOP(op)) return NULL;
6383 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6384 if (IS_AGGREGATE(type->next)) return NULL;
6385 if (osize != (isize = getSize(type->next))) return NULL;
6388 /* if operand of the form op = op + <sizeof *op> */
6389 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6390 isOperandEqual(IC_RESULT(lic),op) &&
6391 isOperandLiteral(IC_RIGHT(lic)) &&
6392 operandLitValue(IC_RIGHT(lic)) == isize) {
6395 /* if the operand used or deffed */
6396 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
6399 /* if GOTO or IFX */
6400 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6406 /*-----------------------------------------------------------------*/
6407 /* genAndOp - for && operation */
6408 /*-----------------------------------------------------------------*/
6410 genAndOp (iCode * ic)
6412 operand *left, *right, *result;
6415 D (emitcode (";", "genAndOp "););
6417 /* note here that && operations that are in an
6418 if statement are taken away by backPatchLabels
6419 only those used in arthmetic operations remain */
6421 AOP_SET_LOCALS (ic);
6423 /* if both are bit variables */
6424 if (AOP_TYPE (left) == AOP_CRY &&
6425 AOP_TYPE (right) == AOP_CRY)
6427 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6428 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6429 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6430 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6432 aopOp (result,ic,FALSE, FALSE);
6437 tlbl = newiTempLabel (NULL);
6439 emitcode ("jz", "!tlabel", tlbl->key + 100);
6441 emitcode ("", "!tlabeldef", tlbl->key + 100);
6442 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6443 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6445 aopOp (result,ic,FALSE, FALSE);
6448 freeAsmop (result, NULL, ic, TRUE);
6452 /*-----------------------------------------------------------------*/
6453 /* genOrOp - for || operation */
6454 /*-----------------------------------------------------------------*/
6456 genOrOp (iCode * ic)
6458 operand *left, *right, *result;
6461 D (emitcode (";", "genOrOp "););
6463 /* note here that || operations that are in an
6464 if statement are taken away by backPatchLabels
6465 only those used in arthmetic operations remain */
6467 AOP_SET_LOCALS (ic);
6469 /* if both are bit variables */
6470 if (AOP_TYPE (left) == AOP_CRY &&
6471 AOP_TYPE (right) == AOP_CRY)
6473 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6474 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6475 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6476 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6478 aopOp (result,ic,FALSE, FALSE);
6484 tlbl = newiTempLabel (NULL);
6486 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6488 emitcode ("", "!tlabeldef", tlbl->key + 100);
6489 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6490 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6492 aopOp (result,ic,FALSE, FALSE);
6497 freeAsmop (result, NULL, ic, TRUE);
6500 /*-----------------------------------------------------------------*/
6501 /* isLiteralBit - test if lit == 2^n */
6502 /*-----------------------------------------------------------------*/
6504 isLiteralBit (unsigned long lit)
6506 unsigned long pw[32] =
6507 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6508 0x100L, 0x200L, 0x400L, 0x800L,
6509 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6510 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6511 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6512 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6513 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6516 for (idx = 0; idx < 32; idx++)
6522 /*-----------------------------------------------------------------*/
6523 /* continueIfTrue - */
6524 /*-----------------------------------------------------------------*/
6526 continueIfTrue (iCode * ic)
6529 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6533 /*-----------------------------------------------------------------*/
6535 /*-----------------------------------------------------------------*/
6537 jumpIfTrue (iCode * ic)
6540 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6544 /*-----------------------------------------------------------------*/
6545 /* jmpTrueOrFalse - */
6546 /*-----------------------------------------------------------------*/
6548 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6550 // ugly but optimized by peephole
6553 symbol *nlbl = newiTempLabel (NULL);
6554 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6555 emitcode ("", "!tlabeldef", tlbl->key + 100);
6556 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6557 emitcode ("", "!tlabeldef", nlbl->key + 100);
6561 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6562 emitcode ("", "!tlabeldef", tlbl->key + 100);
6567 // Generate code to perform a bit-wise logic operation
6568 // on two operands in far space (assumed to already have been
6569 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6570 // in far space. This requires pushing the result on the stack
6571 // then popping it into the result.
6573 genFarFarLogicOp(iCode *ic, char *logicOp)
6575 int size, resultSize, compSize;
6579 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6580 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
6581 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6583 _startLazyDPSEvaluation();
6584 for (size = compSize; (size--); offset++)
6586 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6587 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6588 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6590 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6591 emitcode ("push", "acc");
6593 _endLazyDPSEvaluation();
6595 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6596 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6597 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6599 resultSize = AOP_SIZE(IC_RESULT(ic));
6601 ADJUST_PUSHED_RESULT(compSize, resultSize);
6603 _startLazyDPSEvaluation();
6606 emitcode ("pop", "acc");
6607 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6609 _endLazyDPSEvaluation();
6610 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6614 /*-----------------------------------------------------------------*/
6615 /* genAnd - code for and */
6616 /*-----------------------------------------------------------------*/
6618 genAnd (iCode * ic, iCode * ifx)
6620 operand *left, *right, *result;
6621 int size, offset = 0;
6622 unsigned long lit = 0L;
6627 D (emitcode (";", "genAnd "););
6629 AOP_OP_3_NOFATAL (ic, pushResult);
6630 AOP_SET_LOCALS (ic);
6634 genFarFarLogicOp(ic, "anl");
6639 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6641 AOP_TYPE (left), AOP_TYPE (right));
6642 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6644 AOP_SIZE (left), AOP_SIZE (right));
6647 /* if left is a literal & right is not then exchange them */
6648 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6649 #ifdef LOGIC_OPS_BROKEN
6650 || AOP_NEEDSACC (left)
6654 operand *tmp = right;
6659 /* if result = right then exchange them */
6660 if (sameRegs (AOP (result), AOP (right)))
6662 operand *tmp = right;
6667 /* if right is bit then exchange them */
6668 if (AOP_TYPE (right) == AOP_CRY &&
6669 AOP_TYPE (left) != AOP_CRY)
6671 operand *tmp = right;
6675 if (AOP_TYPE (right) == AOP_LIT)
6676 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6678 size = AOP_SIZE (result);
6681 // result = bit & yy;
6682 if (AOP_TYPE (left) == AOP_CRY)
6684 // c = bit & literal;
6685 if (AOP_TYPE (right) == AOP_LIT)
6689 if (size && sameRegs (AOP (result), AOP (left)))
6692 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6697 if (size && (AOP_TYPE (result) == AOP_CRY))
6699 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6702 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6707 emitcode ("clr", "c");
6712 if (AOP_TYPE (right) == AOP_CRY)
6715 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6716 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6721 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6723 emitcode ("rrc", "a");
6724 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6732 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6733 genIfxJump (ifx, "c");
6737 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6738 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6739 if ((AOP_TYPE (right) == AOP_LIT) &&
6740 (AOP_TYPE (result) == AOP_CRY) &&
6741 (AOP_TYPE (left) != AOP_CRY))
6743 int posbit = isLiteralBit (lit);
6748 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6751 emitcode ("mov", "c,acc.%d", posbit & 0x07);
6757 SNPRINTF (buff, sizeof(buff),
6758 "acc.%d", posbit & 0x07);
6759 genIfxJump (ifx, buff);
6763 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6770 symbol *tlbl = newiTempLabel (NULL);
6771 int sizel = AOP_SIZE (left);
6773 emitcode ("setb", "c");
6776 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6778 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6780 if ((posbit = isLiteralBit (bytelit)) != 0)
6781 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6784 if (bytelit != 0x0FFL)
6785 emitcode ("anl", "a,%s",
6786 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6787 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6792 // bit = left & literal
6795 emitcode ("clr", "c");
6796 emitcode ("", "!tlabeldef", tlbl->key + 100);
6798 // if(left & literal)
6802 jmpTrueOrFalse (ifx, tlbl);
6804 emitcode ("", "!tlabeldef", tlbl->key + 100);
6812 /* if left is same as result */
6813 if (sameRegs (AOP (result), AOP (left)))
6815 for (; size--; offset++)
6817 if (AOP_TYPE (right) == AOP_LIT)
6819 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6821 else if (bytelit == 0)
6822 aopPut (AOP (result), zero, offset);
6823 else if (IS_AOP_PREG (result))
6825 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6826 emitcode ("anl", "a,%s",
6827 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6828 aopPut (AOP (result), "a", offset);
6831 emitcode ("anl", "%s,%s",
6832 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6833 aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6837 if (AOP_TYPE (left) == AOP_ACC)
6838 emitcode ("anl", "a,%s",
6839 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6842 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6843 if (IS_AOP_PREG (result))
6845 emitcode ("anl", "a,%s",
6846 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6847 aopPut (AOP (result), "a", offset);
6850 emitcode ("anl", "%s,a",
6851 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6858 // left & result in different registers
6859 if (AOP_TYPE (result) == AOP_CRY)
6862 // if(size), result in bit
6863 // if(!size && ifx), conditional oper: if(left & right)
6864 symbol *tlbl = newiTempLabel (NULL);
6865 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6867 emitcode ("setb", "c");
6870 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6871 emitcode ("anl", "a,%s",
6872 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6874 if (AOP_TYPE(left)==AOP_ACC) {
6875 emitcode("mov", "b,a");
6876 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6877 emitcode("anl", "a,b");
6879 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6880 emitcode ("anl", "a,%s",
6881 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6884 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6890 emitcode ("", "!tlabeldef", tlbl->key + 100);
6894 jmpTrueOrFalse (ifx, tlbl);
6896 emitcode ("", "!tlabeldef", tlbl->key + 100);
6900 for (; (size--); offset++)
6903 // result = left & right
6904 if (AOP_TYPE (right) == AOP_LIT)
6906 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6908 aopPut (AOP (result),
6909 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6913 else if (bytelit == 0)
6915 aopPut (AOP (result), zero, offset);
6918 D (emitcode (";", "better literal AND."););
6919 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6920 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6921 FALSE, FALSE, DP2_RESULT_REG));
6926 // faster than result <- left, anl result,right
6927 // and better if result is SFR
6928 if (AOP_TYPE (left) == AOP_ACC)
6930 emitcode ("anl", "a,%s",
6931 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6935 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6936 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6938 emitcode("mov", "b,a");
6942 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6943 emitcode ("anl", "a,%s", rOp);
6946 aopPut (AOP (result), "a", offset);
6952 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6953 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6954 freeAsmop (result, NULL, ic, TRUE);
6958 /*-----------------------------------------------------------------*/
6959 /* genOr - code for or */
6960 /*-----------------------------------------------------------------*/
6962 genOr (iCode * ic, iCode * ifx)
6964 operand *left, *right, *result;
6965 int size, offset = 0;
6966 unsigned long lit = 0L;
6969 D (emitcode (";", "genOr "););
6971 AOP_OP_3_NOFATAL (ic, pushResult);
6972 AOP_SET_LOCALS (ic);
6976 genFarFarLogicOp(ic, "orl");
6982 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6984 AOP_TYPE (left), AOP_TYPE (right));
6985 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6987 AOP_SIZE (left), AOP_SIZE (right));
6990 /* if left is a literal & right is not then exchange them */
6991 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6992 #ifdef LOGIC_OPS_BROKEN
6993 || AOP_NEEDSACC (left) // I think this is a net loss now.
6997 operand *tmp = right;
7002 /* if result = right then exchange them */
7003 if (sameRegs (AOP (result), AOP (right)))
7005 operand *tmp = right;
7010 /* if right is bit then exchange them */
7011 if (AOP_TYPE (right) == AOP_CRY &&
7012 AOP_TYPE (left) != AOP_CRY)
7014 operand *tmp = right;
7018 if (AOP_TYPE (right) == AOP_LIT)
7019 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7021 size = AOP_SIZE (result);
7025 if (AOP_TYPE (left) == AOP_CRY)
7027 if (AOP_TYPE (right) == AOP_LIT)
7029 // c = bit & literal;
7032 // lit != 0 => result = 1
7033 if (AOP_TYPE (result) == AOP_CRY)
7036 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7038 continueIfTrue (ifx);
7041 emitcode ("setb", "c");
7045 // lit == 0 => result = left
7046 if (size && sameRegs (AOP (result), AOP (left)))
7048 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7053 if (AOP_TYPE (right) == AOP_CRY)
7056 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7057 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7062 symbol *tlbl = newiTempLabel (NULL);
7063 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
7064 emitcode ("setb", "c");
7065 emitcode ("jb", "%s,!tlabel",
7066 AOP (left)->aopu.aop_dir, tlbl->key + 100);
7068 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7069 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7071 jmpTrueOrFalse (ifx, tlbl);
7077 emitcode ("", "!tlabeldef", tlbl->key + 100);
7086 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7087 genIfxJump (ifx, "c");
7091 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7092 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7093 if ((AOP_TYPE (right) == AOP_LIT) &&
7094 (AOP_TYPE (result) == AOP_CRY) &&
7095 (AOP_TYPE (left) != AOP_CRY))
7101 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7103 continueIfTrue (ifx);
7108 // lit = 0, result = boolean(left)
7110 emitcode ("setb", "c");
7114 symbol *tlbl = newiTempLabel (NULL);
7115 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7117 emitcode ("", "!tlabeldef", tlbl->key + 100);
7121 genIfxJump (ifx, "a");
7129 /* if left is same as result */
7130 if (sameRegs (AOP (result), AOP (left)))
7132 for (; size--; offset++)
7134 if (AOP_TYPE (right) == AOP_LIT)
7136 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7142 if (IS_AOP_PREG (left))
7144 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7145 emitcode ("orl", "a,%s",
7146 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7147 aopPut (AOP (result), "a", offset);
7151 emitcode ("orl", "%s,%s",
7152 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
7153 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7159 if (AOP_TYPE (left) == AOP_ACC)
7161 emitcode ("orl", "a,%s",
7162 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7166 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7167 if (IS_AOP_PREG (left))
7169 emitcode ("orl", "a,%s",
7170 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7171 aopPut (AOP (result), "a", offset);
7175 emitcode ("orl", "%s,a",
7176 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7184 // left & result in different registers
7185 if (AOP_TYPE (result) == AOP_CRY)
7188 // if(size), result in bit
7189 // if(!size && ifx), conditional oper: if(left | right)
7190 symbol *tlbl = newiTempLabel (NULL);
7191 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7193 emitcode ("setb", "c");
7196 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7197 emitcode ("orl", "a,%s",
7198 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7200 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7201 emitcode ("orl", "a,%s",
7202 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
7204 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7210 emitcode ("", "!tlabeldef", tlbl->key + 100);
7214 jmpTrueOrFalse (ifx, tlbl);
7216 emitcode ("", "!tlabeldef", tlbl->key + 100);
7220 _startLazyDPSEvaluation();
7221 for (; (size--); offset++)
7224 // result = left & right
7225 if (AOP_TYPE (right) == AOP_LIT)
7227 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7229 aopPut (AOP (result),
7230 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7234 D (emitcode (";", "better literal OR."););
7235 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7236 emitcode ("orl", "a, %s",
7237 aopGet (AOP (right), offset,
7238 FALSE, FALSE, DP2_RESULT_REG));
7243 // faster than result <- left, anl result,right
7244 // and better if result is SFR
7245 if (AOP_TYPE (left) == AOP_ACC)
7247 emitcode ("orl", "a,%s",
7248 aopGet (AOP (right), offset,
7249 FALSE, FALSE, DP2_RESULT_REG));
7253 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7255 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7257 emitcode("mov", "b,a");
7261 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7262 emitcode ("orl", "a,%s", rOp);
7265 aopPut (AOP (result), "a", offset);
7267 _endLazyDPSEvaluation();
7272 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7273 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7274 freeAsmop (result, NULL, ic, TRUE);
7277 /*-----------------------------------------------------------------*/
7278 /* genXor - code for xclusive or */
7279 /*-----------------------------------------------------------------*/
7281 genXor (iCode * ic, iCode * ifx)
7283 operand *left, *right, *result;
7284 int size, offset = 0;
7285 unsigned long lit = 0L;
7288 D (emitcode (";", "genXor "););
7290 AOP_OP_3_NOFATAL (ic, pushResult);
7291 AOP_SET_LOCALS (ic);
7295 genFarFarLogicOp(ic, "xrl");
7300 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7302 AOP_TYPE (left), AOP_TYPE (right));
7303 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7305 AOP_SIZE (left), AOP_SIZE (right));
7308 /* if left is a literal & right is not ||
7309 if left needs acc & right does not */
7310 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7311 #ifdef LOGIC_OPS_BROKEN
7312 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
7316 operand *tmp = right;
7321 /* if result = right then exchange them */
7322 if (sameRegs (AOP (result), AOP (right)))
7324 operand *tmp = right;
7329 /* if right is bit then exchange them */
7330 if (AOP_TYPE (right) == AOP_CRY &&
7331 AOP_TYPE (left) != AOP_CRY)
7333 operand *tmp = right;
7337 if (AOP_TYPE (right) == AOP_LIT)
7338 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7340 size = AOP_SIZE (result);
7344 if (AOP_TYPE (left) == AOP_CRY)
7346 if (AOP_TYPE (right) == AOP_LIT)
7348 // c = bit & literal;
7351 // lit>>1 != 0 => result = 1
7352 if (AOP_TYPE (result) == AOP_CRY)
7355 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7357 continueIfTrue (ifx);
7360 emitcode ("setb", "c");
7367 // lit == 0, result = left
7368 if (size && sameRegs (AOP (result), AOP (left)))
7370 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7374 // lit == 1, result = not(left)
7375 if (size && sameRegs (AOP (result), AOP (left)))
7377 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7382 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7383 emitcode ("cpl", "c");
7392 symbol *tlbl = newiTempLabel (NULL);
7393 if (AOP_TYPE (right) == AOP_CRY)
7396 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7400 int sizer = AOP_SIZE (right);
7402 // if val>>1 != 0, result = 1
7403 emitcode ("setb", "c");
7406 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
7408 // test the msb of the lsb
7409 emitcode ("anl", "a,#!constbyte",0xfe);
7410 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7414 emitcode ("rrc", "a");
7416 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7417 emitcode ("cpl", "c");
7418 emitcode ("", "!tlabeldef", (tlbl->key + 100));
7425 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7426 genIfxJump (ifx, "c");
7430 if (sameRegs (AOP (result), AOP (left)))
7432 /* if left is same as result */
7433 for (; size--; offset++)
7435 if (AOP_TYPE (right) == AOP_LIT)
7437 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7439 else if (IS_AOP_PREG (left))
7441 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7442 emitcode ("xrl", "a,%s",
7443 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7444 aopPut (AOP (result), "a", offset);
7447 emitcode ("xrl", "%s,%s",
7448 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
7449 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7453 if (AOP_TYPE (left) == AOP_ACC)
7454 emitcode ("xrl", "a,%s",
7455 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7458 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7459 if (IS_AOP_PREG (left))
7461 emitcode ("xrl", "a,%s",
7462 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7463 aopPut (AOP (result), "a", offset);
7466 emitcode ("xrl", "%s,a",
7467 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7474 // left & result in different registers
7475 if (AOP_TYPE (result) == AOP_CRY)
7478 // if(size), result in bit
7479 // if(!size && ifx), conditional oper: if(left ^ right)
7480 symbol *tlbl = newiTempLabel (NULL);
7481 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7484 emitcode ("setb", "c");
7487 if ((AOP_TYPE (right) == AOP_LIT) &&
7488 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7490 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7494 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7495 emitcode ("xrl", "a,%s",
7496 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7498 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7499 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7501 emitcode("mov", "b,a");
7505 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7506 emitcode ("xrl", "a,%s", rOp);
7509 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7515 emitcode ("", "!tlabeldef", tlbl->key + 100);
7519 jmpTrueOrFalse (ifx, tlbl);
7523 for (; (size--); offset++)
7526 // result = left & right
7527 if (AOP_TYPE (right) == AOP_LIT)
7529 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7531 aopPut (AOP (result),
7532 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7536 D (emitcode (";", "better literal XOR."););
7537 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7538 emitcode ("xrl", "a, %s",
7539 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7543 // faster than result <- left, anl result,right
7544 // and better if result is SFR
7545 if (AOP_TYPE (left) == AOP_ACC)
7547 emitcode ("xrl", "a,%s",
7548 aopGet (AOP (right), offset,
7549 FALSE, FALSE, DP2_RESULT_REG));
7553 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7554 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7556 emitcode("mov", "b,a");
7560 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7561 emitcode ("xrl", "a,%s", rOp);
7564 aopPut (AOP (result), "a", offset);
7571 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7572 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7573 freeAsmop (result, NULL, ic, TRUE);
7576 /*-----------------------------------------------------------------*/
7577 /* genInline - write the inline code out */
7578 /*-----------------------------------------------------------------*/
7580 genInline (iCode * ic)
7582 char *buffer, *bp, *bp1;
7584 D (emitcode (";", "genInline "); );
7586 _G.inLine += (!options.asmpeep);
7588 buffer = Safe_strdup(IC_INLINE(ic));
7592 /* emit each line as a code */
7617 /* emitcode("",buffer); */
7618 _G.inLine -= (!options.asmpeep);
7621 /*-----------------------------------------------------------------*/
7622 /* genRRC - rotate right with carry */
7623 /*-----------------------------------------------------------------*/
7627 operand *left, *result;
7630 D (emitcode (";", "genRRC "););
7632 /* rotate right with carry */
7633 left = IC_LEFT (ic);
7634 result = IC_RESULT (ic);
7635 aopOp (left, ic, FALSE, FALSE);
7636 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7638 /* move it to the result */
7639 size = AOP_SIZE (result);
7643 _startLazyDPSEvaluation ();
7646 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7647 emitcode ("rrc", "a");
7648 if (AOP_SIZE (result) > 1)
7649 aopPut (AOP (result), "a", offset--);
7651 _endLazyDPSEvaluation ();
7653 /* now we need to put the carry into the
7654 highest order byte of the result */
7655 if (AOP_SIZE (result) > 1)
7657 MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7659 emitcode ("mov", "acc.7,c");
7660 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7661 freeAsmop (left, NULL, ic, TRUE);
7662 freeAsmop (result, NULL, ic, TRUE);
7665 /*-----------------------------------------------------------------*/
7666 /* genRLC - generate code for rotate left with carry */
7667 /*-----------------------------------------------------------------*/
7671 operand *left, *result;
7675 D (emitcode (";", "genRLC "););
7677 /* rotate right with carry */
7678 left = IC_LEFT (ic);
7679 result = IC_RESULT (ic);
7680 aopOp (left, ic, FALSE, FALSE);
7681 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7683 /* move it to the result */
7684 size = AOP_SIZE (result);
7688 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7690 emitcode ("add", "a,acc");
7691 if (AOP_SIZE (result) > 1)
7693 aopPut (AOP (result), "a", offset++);
7696 _startLazyDPSEvaluation ();
7699 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7701 emitcode ("rlc", "a");
7702 if (AOP_SIZE (result) > 1)
7703 aopPut (AOP (result), "a", offset++);
7705 _endLazyDPSEvaluation ();
7707 /* now we need to put the carry into the
7708 highest order byte of the result */
7709 if (AOP_SIZE (result) > 1)
7711 l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7714 emitcode ("mov", "acc.0,c");
7715 aopPut (AOP (result), "a", 0);
7716 freeAsmop (left, NULL, ic, TRUE);
7717 freeAsmop (result, NULL, ic, TRUE);
7720 /*-----------------------------------------------------------------*/
7721 /* genGetHbit - generates code get highest order bit */
7722 /*-----------------------------------------------------------------*/
7724 genGetHbit (iCode * ic)
7726 operand *left, *result;
7727 left = IC_LEFT (ic);
7728 result = IC_RESULT (ic);
7729 aopOp (left, ic, FALSE, FALSE);
7730 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7732 D (emitcode (";", "genGetHbit "););
7734 /* get the highest order byte into a */
7735 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7736 if (AOP_TYPE (result) == AOP_CRY)
7738 emitcode ("rlc", "a");
7743 emitcode ("rl", "a");
7744 emitcode ("anl", "a,#1");
7749 freeAsmop (left, NULL, ic, TRUE);
7750 freeAsmop (result, NULL, ic, TRUE);
7753 /*-----------------------------------------------------------------*/
7754 /* genSwap - generates code to swap nibbles or bytes */
7755 /*-----------------------------------------------------------------*/
7757 genSwap (iCode * ic)
7759 operand *left, *result;
7761 D(emitcode ("; genSwap",""));
7763 left = IC_LEFT (ic);
7764 result = IC_RESULT (ic);
7765 aopOp (left, ic, FALSE, FALSE);
7766 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7768 _startLazyDPSEvaluation ();
7769 switch (AOP_SIZE (left))
7771 case 1: /* swap nibbles in byte */
7772 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7773 emitcode ("swap", "a");
7774 aopPut (AOP (result), "a", 0);
7776 case 2: /* swap bytes in word */
7777 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7779 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7780 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7781 aopPut (AOP (result), "a", 1);
7783 else if (operandsEqu (left, result))
7786 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7787 if (AOP_NEEDSACC (left) || AOP_NEEDSACC (result))
7789 emitcode ("mov", "b,a");
7793 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7794 aopPut (AOP (result), reg, 1);
7799 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7800 aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE, NULL), 1);
7804 wassertl(FALSE, "unsupported SWAP operand size");
7806 _endLazyDPSEvaluation ();
7808 freeAsmop (left, NULL, ic, TRUE);
7809 freeAsmop (result, NULL, ic, TRUE);
7812 /*-----------------------------------------------------------------*/
7813 /* AccRol - rotate left accumulator by known count */
7814 /*-----------------------------------------------------------------*/
7816 AccRol (int shCount)
7818 shCount &= 0x0007; // shCount : 0..7
7825 emitcode ("rl", "a");
7828 emitcode ("rl", "a");
7829 emitcode ("rl", "a");
7832 emitcode ("swap", "a");
7833 emitcode ("rr", "a");
7836 emitcode ("swap", "a");
7839 emitcode ("swap", "a");
7840 emitcode ("rl", "a");
7843 emitcode ("rr", "a");
7844 emitcode ("rr", "a");
7847 emitcode ("rr", "a");
7852 /*-----------------------------------------------------------------*/
7853 /* AccLsh - left shift accumulator by known count */
7854 /*-----------------------------------------------------------------*/
7856 AccLsh (int shCount)
7861 emitcode ("add", "a,acc");
7862 else if (shCount == 2)
7864 emitcode ("add", "a,acc");
7865 emitcode ("add", "a,acc");
7869 /* rotate left accumulator */
7871 /* and kill the lower order bits */
7872 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7877 /*-----------------------------------------------------------------*/
7878 /* AccRsh - right shift accumulator by known count */
7879 /*-----------------------------------------------------------------*/
7881 AccRsh (int shCount)
7888 emitcode ("rrc", "a");
7892 /* rotate right accumulator */
7893 AccRol (8 - shCount);
7894 /* and kill the higher order bits */
7895 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7900 #ifdef BETTER_LITERAL_SHIFT
7901 /*-----------------------------------------------------------------*/
7902 /* AccSRsh - signed right shift accumulator by known count */
7903 /*-----------------------------------------------------------------*/
7905 AccSRsh (int shCount)
7912 emitcode ("mov", "c,acc.7");
7913 emitcode ("rrc", "a");
7915 else if (shCount == 2)
7917 emitcode ("mov", "c,acc.7");
7918 emitcode ("rrc", "a");
7919 emitcode ("mov", "c,acc.7");
7920 emitcode ("rrc", "a");
7924 tlbl = newiTempLabel (NULL);
7925 /* rotate right accumulator */
7926 AccRol (8 - shCount);
7927 /* and kill the higher order bits */
7928 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7929 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7930 emitcode ("orl", "a,#!constbyte",
7931 (unsigned char) ~SRMask[shCount]);
7932 emitcode ("", "!tlabeldef", tlbl->key + 100);
7938 #ifdef BETTER_LITERAL_SHIFT
7939 /*-----------------------------------------------------------------*/
7940 /* shiftR1Left2Result - shift right one byte from left to result */
7941 /*-----------------------------------------------------------------*/
7943 shiftR1Left2Result (operand * left, int offl,
7944 operand * result, int offr,
7945 int shCount, int sign)
7947 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7948 /* shift right accumulator */
7953 aopPut (AOP (result), "a", offr);
7957 #ifdef BETTER_LITERAL_SHIFT
7958 /*-----------------------------------------------------------------*/
7959 /* shiftL1Left2Result - shift left one byte from left to result */
7960 /*-----------------------------------------------------------------*/
7962 shiftL1Left2Result (operand * left, int offl,
7963 operand * result, int offr, int shCount)
7965 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7966 /* shift left accumulator */
7968 aopPut (AOP (result), "a", offr);
7972 #ifdef BETTER_LITERAL_SHIFT
7973 /*-----------------------------------------------------------------*/
7974 /* movLeft2Result - move byte from left to result */
7975 /*-----------------------------------------------------------------*/
7977 movLeft2Result (operand * left, int offl,
7978 operand * result, int offr, int sign)
7981 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7983 l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
7985 if (*l == '@' && (IS_AOP_PREG (result)))
7987 emitcode ("mov", "a,%s", l);
7988 aopPut (AOP (result), "a", offr);
7994 aopPut (AOP (result), l, offr);
7998 /* MSB sign in acc.7 ! */
7999 if (getDataSize (left) == offl + 1)
8001 emitcode ("mov", "a,%s", l);
8002 aopPut (AOP (result), "a", offr);
8010 #ifdef BETTER_LITERAL_SHIFT
8011 /*-----------------------------------------------------------------*/
8012 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
8013 /*-----------------------------------------------------------------*/
8017 emitcode ("rrc", "a");
8018 emitcode ("xch", "a,%s", x);
8019 emitcode ("rrc", "a");
8020 emitcode ("xch", "a,%s", x);
8024 #ifdef BETTER_LITERAL_SHIFT
8026 /*-----------------------------------------------------------------*/
8027 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
8028 /*-----------------------------------------------------------------*/
8032 emitcode ("xch", "a,%s", x);
8033 emitcode ("rlc", "a");
8034 emitcode ("xch", "a,%s", x);
8035 emitcode ("rlc", "a");
8039 #ifdef BETTER_LITERAL_SHIFT
8040 /*-----------------------------------------------------------------*/
8041 /* AccAXLsh1 - left shift a:x<-0 by 1 */
8042 /*-----------------------------------------------------------------*/
8046 emitcode ("xch", "a,%s", x);
8047 emitcode ("add", "a,acc");
8048 emitcode ("xch", "a,%s", x);
8049 emitcode ("rlc", "a");
8053 #ifdef BETTER_LITERAL_SHIFT
8054 /*-----------------------------------------------------------------*/
8055 /* AccAXLsh - left shift a:x by known count (0..7) */
8056 /*-----------------------------------------------------------------*/
8058 AccAXLsh (char *x, int shCount)
8073 case 5: // AAAAABBB:CCCCCDDD
8075 AccRol (shCount); // BBBAAAAA:CCCCCDDD
8077 emitcode ("anl", "a,#!constbyte",
8078 SLMask[shCount]); // BBB00000:CCCCCDDD
8080 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
8082 AccRol (shCount); // DDDCCCCC:BBB00000
8084 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8086 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8088 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8090 emitcode ("anl", "a,#!constbyte",
8091 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8093 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8095 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8098 case 6: // AAAAAABB:CCCCCCDD
8099 emitcode ("anl", "a,#!constbyte",
8100 SRMask[shCount]); // 000000BB:CCCCCCDD
8101 emitcode ("mov", "c,acc.0"); // c = B
8102 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8104 AccAXRrl1 (x); // BCCCCCCD:D000000B
8105 AccAXRrl1 (x); // BBCCCCCC:DD000000
8107 emitcode("rrc","a");
8108 emitcode("xch","a,%s", x);
8109 emitcode("rrc","a");
8110 emitcode("mov","c,acc.0"); //<< get correct bit
8111 emitcode("xch","a,%s", x);
8113 emitcode("rrc","a");
8114 emitcode("xch","a,%s", x);
8115 emitcode("rrc","a");
8116 emitcode("xch","a,%s", x);
8119 case 7: // a:x <<= 7
8121 emitcode ("anl", "a,#!constbyte",
8122 SRMask[shCount]); // 0000000B:CCCCCCCD
8124 emitcode ("mov", "c,acc.0"); // c = B
8126 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
8128 AccAXRrl1 (x); // BCCCCCCC:D0000000
8137 #ifdef BETTER_LITERAL_SHIFT
8139 /*-----------------------------------------------------------------*/
8140 /* AccAXRsh - right shift a:x known count (0..7) */
8141 /*-----------------------------------------------------------------*/
8143 AccAXRsh (char *x, int shCount)
8151 AccAXRrl1 (x); // 0->a:x
8156 AccAXRrl1 (x); // 0->a:x
8159 AccAXRrl1 (x); // 0->a:x
8164 case 5: // AAAAABBB:CCCCCDDD = a:x
8166 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8168 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8170 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8172 emitcode ("anl", "a,#!constbyte",
8173 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8175 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8177 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8179 emitcode ("anl", "a,#!constbyte",
8180 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8182 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8184 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8186 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8189 case 6: // AABBBBBB:CCDDDDDD
8191 emitcode ("mov", "c,acc.7");
8192 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8194 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8196 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8198 emitcode ("anl", "a,#!constbyte",
8199 SRMask[shCount]); // 000000AA:BBBBBBCC
8202 case 7: // ABBBBBBB:CDDDDDDD
8204 emitcode ("mov", "c,acc.7"); // c = A
8206 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8208 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8210 emitcode ("anl", "a,#!constbyte",
8211 SRMask[shCount]); // 0000000A:BBBBBBBC
8220 #ifdef BETTER_LITERAL_SHIFT
8221 /*-----------------------------------------------------------------*/
8222 /* AccAXRshS - right shift signed a:x known count (0..7) */
8223 /*-----------------------------------------------------------------*/
8225 AccAXRshS (char *x, int shCount)
8233 emitcode ("mov", "c,acc.7");
8234 AccAXRrl1 (x); // s->a:x
8238 emitcode ("mov", "c,acc.7");
8239 AccAXRrl1 (x); // s->a:x
8241 emitcode ("mov", "c,acc.7");
8242 AccAXRrl1 (x); // s->a:x
8247 case 5: // AAAAABBB:CCCCCDDD = a:x
8249 tlbl = newiTempLabel (NULL);
8250 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8252 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8254 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8256 emitcode ("anl", "a,#!constbyte",
8257 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8259 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8261 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8263 emitcode ("anl", "a,#!constbyte",
8264 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8266 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8268 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8270 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
8272 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8273 emitcode ("orl", "a,#!constbyte",
8274 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
8276 emitcode ("", "!tlabeldef", tlbl->key + 100);
8277 break; // SSSSAAAA:BBBCCCCC
8279 case 6: // AABBBBBB:CCDDDDDD
8281 tlbl = newiTempLabel (NULL);
8282 emitcode ("mov", "c,acc.7");
8283 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8285 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8287 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8289 emitcode ("anl", "a,#!constbyte",
8290 SRMask[shCount]); // 000000AA:BBBBBBCC
8292 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8293 emitcode ("orl", "a,#!constbyte",
8294 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
8296 emitcode ("", "!tlabeldef", tlbl->key + 100);
8298 case 7: // ABBBBBBB:CDDDDDDD
8300 tlbl = newiTempLabel (NULL);
8301 emitcode ("mov", "c,acc.7"); // c = A
8303 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8305 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8307 emitcode ("anl", "a,#!constbyte",
8308 SRMask[shCount]); // 0000000A:BBBBBBBC
8310 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8311 emitcode ("orl", "a,#!constbyte",
8312 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
8314 emitcode ("", "!tlabeldef", tlbl->key + 100);
8322 #ifdef BETTER_LITERAL_SHIFT
8324 _loadLeftIntoAx(char **lsb,
8330 // Get the initial value from left into a pair of registers.
8331 // MSB must be in A, LSB can be any register.
8333 // If the result is held in registers, it is an optimization
8334 // if the LSB can be held in the register which will hold the,
8335 // result LSB since this saves us from having to copy it into
8336 // the result following AccAXLsh.
8338 // If the result is addressed indirectly, this is not a gain.
8339 if (AOP_NEEDSACC(result))
8343 _startLazyDPSEvaluation();
8344 if (AOP_TYPE(left) == AOP_DPTR2)
8347 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
8348 // get LSB in DP2_RESULT_REG.
8349 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
8350 assert(!strcmp(leftByte, DP2_RESULT_REG));
8354 // get LSB into DP2_RESULT_REG
8355 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
8356 if (strcmp(leftByte, DP2_RESULT_REG))
8359 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
8362 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
8363 assert(strcmp(leftByte, DP2_RESULT_REG));
8366 _endLazyDPSEvaluation();
8367 *lsb = DP2_RESULT_REG;
8371 if (sameRegs (AOP (result), AOP (left)) &&
8372 ((offl + MSB16) == offr))
8374 /* don't crash result[offr] */
8375 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
8376 emitcode ("xch", "a,%s",
8377 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
8381 movLeft2Result (left, offl, result, offr, 0);
8382 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
8384 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
8385 assert(strcmp(*lsb,"a"));
8390 _storeAxResults(char *lsb,
8394 _startLazyDPSEvaluation();
8395 if (AOP_NEEDSACC(result))
8397 /* We have to explicitly update the result LSB.
8399 emitcode("xch","a,%s", lsb);
8400 aopPut(AOP(result), "a", offr);
8401 emitcode("mov","a,%s", lsb);
8403 if (getDataSize (result) > 1)
8405 aopPut (AOP (result), "a", offr + MSB16);
8407 _endLazyDPSEvaluation();
8410 /*-----------------------------------------------------------------*/
8411 /* shiftL2Left2Result - shift left two bytes from left to result */
8412 /*-----------------------------------------------------------------*/
8414 shiftL2Left2Result (operand * left, int offl,
8415 operand * result, int offr, int shCount)
8419 _loadLeftIntoAx(&lsb, left, result, offl, offr);
8421 AccAXLsh (lsb, shCount);
8423 _storeAxResults(lsb, result, offr);
8427 #ifdef BETTER_LITERAL_SHIFT
8428 /*-----------------------------------------------------------------*/
8429 /* shiftR2Left2Result - shift right two bytes from left to result */
8430 /*-----------------------------------------------------------------*/
8432 shiftR2Left2Result (operand * left, int offl,
8433 operand * result, int offr,
8434 int shCount, int sign)
8438 _loadLeftIntoAx(&lsb, left, result, offl, offr);
8440 /* a:x >> shCount (x = lsb(result)) */
8443 AccAXRshS(lsb, shCount);
8447 AccAXRsh(lsb, shCount);
8450 _storeAxResults(lsb, result, offr);
8454 /*-----------------------------------------------------------------*/
8455 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8456 /*-----------------------------------------------------------------*/
8458 shiftLLeftOrResult (operand * left, int offl,
8459 operand * result, int offr, int shCount)
8461 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8462 /* shift left accumulator */
8464 /* or with result */
8465 emitcode ("orl", "a,%s",
8466 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8467 /* back to result */
8468 aopPut (AOP (result), "a", offr);
8473 /*-----------------------------------------------------------------*/
8474 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8475 /*-----------------------------------------------------------------*/
8477 shiftRLeftOrResult (operand * left, int offl,
8478 operand * result, int offr, int shCount)
8480 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8481 /* shift right accumulator */
8483 /* or with result */
8484 emitcode ("orl", "a,%s",
8485 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8486 /* back to result */
8487 aopPut (AOP (result), "a", offr);
8491 #ifdef BETTER_LITERAL_SHIFT
8492 /*-----------------------------------------------------------------*/
8493 /* genlshOne - left shift a one byte quantity by known count */
8494 /*-----------------------------------------------------------------*/
8496 genlshOne (operand * result, operand * left, int shCount)
8498 D (emitcode (";", "genlshOne "););
8499 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8503 #ifdef BETTER_LITERAL_SHIFT
8504 /*-----------------------------------------------------------------*/
8505 /* genlshTwo - left shift two bytes by known amount != 0 */
8506 /*-----------------------------------------------------------------*/
8508 genlshTwo (operand * result, operand * left, int shCount)
8512 D (emitcode (";", "genlshTwo "););
8514 size = getDataSize (result);
8516 /* if shCount >= 8 */
8521 _startLazyDPSEvaluation();
8527 _endLazyDPSEvaluation();
8528 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8529 aopPut (AOP (result), zero, LSB);
8533 movLeft2Result (left, LSB, result, MSB16, 0);
8534 aopPut (AOP (result), zero, LSB);
8535 _endLazyDPSEvaluation();
8540 aopPut (AOP (result), zero, LSB);
8541 _endLazyDPSEvaluation();
8545 /* 1 <= shCount <= 7 */
8550 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8554 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8562 /*-----------------------------------------------------------------*/
8563 /* shiftLLong - shift left one long from left to result */
8564 /* offl = LSB or MSB16 */
8565 /*-----------------------------------------------------------------*/
8567 shiftLLong (operand * left, operand * result, int offr)
8570 int size = AOP_SIZE (result);
8572 if (size >= LSB + offr)
8574 l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8576 emitcode ("add", "a,acc");
8577 if (sameRegs (AOP (left), AOP (result)) &&
8578 size >= MSB16 + offr && offr != LSB)
8579 emitcode ("xch", "a,%s",
8580 aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8582 aopPut (AOP (result), "a", LSB + offr);
8585 if (size >= MSB16 + offr)
8587 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8589 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8591 emitcode ("rlc", "a");
8592 if (sameRegs (AOP (left), AOP (result)) &&
8593 size >= MSB24 + offr && offr != LSB)
8594 emitcode ("xch", "a,%s",
8595 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8597 aopPut (AOP (result), "a", MSB16 + offr);
8600 if (size >= MSB24 + offr)
8602 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8604 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8606 emitcode ("rlc", "a");
8607 if (sameRegs (AOP (left), AOP (result)) &&
8608 size >= MSB32 + offr && offr != LSB)
8609 emitcode ("xch", "a,%s",
8610 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8612 aopPut (AOP (result), "a", MSB24 + offr);
8615 if (size > MSB32 + offr)
8617 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8619 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8621 emitcode ("rlc", "a");
8622 aopPut (AOP (result), "a", MSB32 + offr);
8625 aopPut (AOP (result), zero, LSB);
8631 /*-----------------------------------------------------------------*/
8632 /* genlshFour - shift four byte by a known amount != 0 */
8633 /*-----------------------------------------------------------------*/
8635 genlshFour (operand * result, operand * left, int shCount)
8639 D (emitcode (";", "genlshFour ");
8642 size = AOP_SIZE (result);
8644 /* if shifting more that 3 bytes */
8649 /* lowest order of left goes to the highest
8650 order of the destination */
8651 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8653 movLeft2Result (left, LSB, result, MSB32, 0);
8654 aopPut (AOP (result), zero, LSB);
8655 aopPut (AOP (result), zero, MSB16);
8656 aopPut (AOP (result), zero, MSB24);
8660 /* more than two bytes */
8661 else if (shCount >= 16)
8663 /* lower order two bytes goes to higher order two bytes */
8665 /* if some more remaining */
8667 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8670 movLeft2Result (left, MSB16, result, MSB32, 0);
8671 movLeft2Result (left, LSB, result, MSB24, 0);
8673 aopPut (AOP (result), zero, MSB16);
8674 aopPut (AOP (result), zero, LSB);
8678 /* if more than 1 byte */
8679 else if (shCount >= 8)
8681 /* lower order three bytes goes to higher order three bytes */
8686 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8688 movLeft2Result (left, LSB, result, MSB16, 0);
8694 movLeft2Result (left, MSB24, result, MSB32, 0);
8695 movLeft2Result (left, MSB16, result, MSB24, 0);
8696 movLeft2Result (left, LSB, result, MSB16, 0);
8697 aopPut (AOP (result), zero, LSB);
8699 else if (shCount == 1)
8700 shiftLLong (left, result, MSB16);
8703 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8704 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8705 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8706 aopPut (AOP (result), zero, LSB);
8711 /* 1 <= shCount <= 7 */
8712 else if (shCount <= 2)
8714 shiftLLong (left, result, LSB);
8716 shiftLLong (result, result, LSB);
8718 /* 3 <= shCount <= 7, optimize */
8721 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8722 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8723 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8728 #ifdef BETTER_LITERAL_SHIFT
8729 /*-----------------------------------------------------------------*/
8730 /* genLeftShiftLiteral - left shifting by known count */
8731 /*-----------------------------------------------------------------*/
8733 genLeftShiftLiteral (operand * left,
8738 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8741 size = getSize (operandType (result));
8743 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8745 /* We only handle certain easy cases so far. */
8747 && (shCount < (size * 8))
8751 D(emitcode (";", "genLeftShiftLiteral wimping out"););
8755 freeAsmop (right, NULL, ic, TRUE);
8757 aopOp(left, ic, FALSE, FALSE);
8758 aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8761 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8763 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8764 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8766 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8769 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8771 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8772 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8774 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8780 emitcode ("; shift left ", "result %d, left %d", size,
8784 /* I suppose that the left size >= result size */
8787 _startLazyDPSEvaluation();
8790 movLeft2Result (left, size, result, size, 0);
8792 _endLazyDPSEvaluation();
8794 else if (shCount >= (size * 8))
8796 _startLazyDPSEvaluation();
8799 aopPut (AOP (result), zero, size);
8801 _endLazyDPSEvaluation();
8808 genlshOne (result, left, shCount);
8812 genlshTwo (result, left, shCount);
8816 genlshFour (result, left, shCount);
8820 fprintf(stderr, "*** ack! mystery literal shift!\n");
8824 freeAsmop (left, NULL, ic, TRUE);
8825 freeAsmop (result, NULL, ic, TRUE);
8830 /*-----------------------------------------------------------------*/
8831 /* genLeftShift - generates code for left shifting */
8832 /*-----------------------------------------------------------------*/
8834 genLeftShift (iCode * ic)
8836 operand *left, *right, *result;
8839 symbol *tlbl, *tlbl1;
8841 D (emitcode (";", "genLeftShift "););
8843 right = IC_RIGHT (ic);
8844 left = IC_LEFT (ic);
8845 result = IC_RESULT (ic);
8847 aopOp (right, ic, FALSE, FALSE);
8850 #ifdef BETTER_LITERAL_SHIFT
8851 /* if the shift count is known then do it
8852 as efficiently as possible */
8853 if (AOP_TYPE (right) == AOP_LIT)
8855 if (genLeftShiftLiteral (left, right, result, ic))
8862 /* shift count is unknown then we have to form
8863 a loop get the loop count in B : Note: we take
8864 only the lower order byte since shifting
8865 more that 32 bits make no sense anyway, ( the
8866 largest size of an object can be only 32 bits ) */
8868 if (AOP_TYPE (right) == AOP_LIT)
8870 /* Really should be handled by genLeftShiftLiteral,
8871 * but since I'm too lazy to fix that today, at least we can make
8872 * some small improvement.
8874 emitcode("mov", "b,#!constbyte",
8875 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8879 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8880 emitcode ("inc", "b");
8882 freeAsmop (right, NULL, ic, TRUE);
8883 aopOp (left, ic, FALSE, FALSE);
8884 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8886 /* now move the left to the result if they are not the
8888 if (!sameRegs (AOP (left), AOP (result)) &&
8889 AOP_SIZE (result) > 1)
8892 size = AOP_SIZE (result);
8894 _startLazyDPSEvaluation ();
8897 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8898 if (*l == '@' && (IS_AOP_PREG (result)))
8901 emitcode ("mov", "a,%s", l);
8902 aopPut (AOP (result), "a", offset);
8905 aopPut (AOP (result), l, offset);
8908 _endLazyDPSEvaluation ();
8911 tlbl = newiTempLabel (NULL);
8912 size = AOP_SIZE (result);
8914 tlbl1 = newiTempLabel (NULL);
8916 /* if it is only one byte then */
8919 symbol *tlbl1 = newiTempLabel (NULL);
8921 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8922 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8923 emitcode ("", "!tlabeldef", tlbl->key + 100);
8924 emitcode ("add", "a,acc");
8925 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8926 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8927 aopPut (AOP (result), "a", 0);
8931 reAdjustPreg (AOP (result));
8933 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8934 emitcode ("", "!tlabeldef", tlbl->key + 100);
8935 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8936 emitcode ("add", "a,acc");
8937 aopPut (AOP (result), "a", offset++);
8938 _startLazyDPSEvaluation ();
8941 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8942 emitcode ("rlc", "a");
8943 aopPut (AOP (result), "a", offset++);
8945 _endLazyDPSEvaluation ();
8946 reAdjustPreg (AOP (result));
8948 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8949 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8951 freeAsmop (left, NULL, ic, TRUE);
8952 freeAsmop (result, NULL, ic, TRUE);
8955 #ifdef BETTER_LITERAL_SHIFT
8956 /*-----------------------------------------------------------------*/
8957 /* genrshOne - right shift a one byte quantity by known count */
8958 /*-----------------------------------------------------------------*/
8960 genrshOne (operand * result, operand * left,
8961 int shCount, int sign)
8963 D (emitcode (";", "genrshOne"););
8964 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8968 #ifdef BETTER_LITERAL_SHIFT
8969 /*-----------------------------------------------------------------*/
8970 /* genrshTwo - right shift two bytes by known amount != 0 */
8971 /*-----------------------------------------------------------------*/
8973 genrshTwo (operand * result, operand * left,
8974 int shCount, int sign)
8976 D (emitcode (";", "genrshTwo"););
8978 /* if shCount >= 8 */
8982 _startLazyDPSEvaluation();
8985 shiftR1Left2Result (left, MSB16, result, LSB,
8990 movLeft2Result (left, MSB16, result, LSB, sign);
8992 addSign (result, MSB16, sign);
8993 _endLazyDPSEvaluation();
8996 /* 1 <= shCount <= 7 */
8999 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9004 /*-----------------------------------------------------------------*/
9005 /* shiftRLong - shift right one long from left to result */
9006 /* offl = LSB or MSB16 */
9007 /*-----------------------------------------------------------------*/
9009 shiftRLong (operand * left, int offl,
9010 operand * result, int sign)
9012 int isSameRegs=sameRegs(AOP(left),AOP(result));
9014 if (isSameRegs && offl>1) {
9015 // we are in big trouble, but this shouldn't happen
9016 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9019 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
9024 emitcode ("rlc", "a");
9025 emitcode ("subb", "a,acc");
9026 emitcode ("xch", "a,%s",
9027 aopGet(AOP(left), MSB32, FALSE, FALSE, DP2_RESULT_REG));
9029 aopPut (AOP(result), zero, MSB32);
9034 emitcode ("clr", "c");
9036 emitcode ("mov", "c,acc.7");
9039 emitcode ("rrc", "a");
9041 if (isSameRegs && offl==MSB16) {
9043 "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE, DP2_RESULT_REG));
9045 aopPut (AOP (result), "a", MSB32);
9046 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
9049 emitcode ("rrc", "a");
9050 if (isSameRegs && offl==1) {
9051 emitcode ("xch", "a,%s",
9052 aopGet (AOP (left), MSB16, FALSE, FALSE, DP2_RESULT_REG));
9054 aopPut (AOP (result), "a", MSB24);
9055 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, NULL));
9057 emitcode ("rrc", "a");
9058 aopPut (AOP (result), "a", MSB16 - offl);
9062 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, NULL));
9063 emitcode ("rrc", "a");
9064 aopPut (AOP (result), "a", LSB);
9068 /*-----------------------------------------------------------------*/
9069 /* genrshFour - shift four byte by a known amount != 0 */
9070 /*-----------------------------------------------------------------*/
9072 genrshFour (operand * result, operand * left,
9073 int shCount, int sign)
9075 D (emitcode (";", "genrshFour"););
9077 /* if shifting more that 3 bytes */
9081 _startLazyDPSEvaluation();
9083 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9085 movLeft2Result (left, MSB32, result, LSB, sign);
9086 addSign (result, MSB16, sign);
9087 _endLazyDPSEvaluation();
9089 else if (shCount >= 16)
9092 _startLazyDPSEvaluation();
9094 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9097 movLeft2Result (left, MSB24, result, LSB, 0);
9098 movLeft2Result (left, MSB32, result, MSB16, sign);
9100 addSign (result, MSB24, sign);
9101 _endLazyDPSEvaluation();
9103 else if (shCount >= 8)
9106 _startLazyDPSEvaluation();
9109 shiftRLong (left, MSB16, result, sign);
9111 else if (shCount == 0)
9113 movLeft2Result (left, MSB16, result, LSB, 0);
9114 movLeft2Result (left, MSB24, result, MSB16, 0);
9115 movLeft2Result (left, MSB32, result, MSB24, sign);
9116 addSign (result, MSB32, sign);
9120 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9121 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9122 /* the last shift is signed */
9123 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9124 addSign (result, MSB32, sign);
9126 _endLazyDPSEvaluation();
9130 /* 1 <= shCount <= 7 */
9133 shiftRLong (left, LSB, result, sign);
9135 shiftRLong (result, LSB, result, sign);
9139 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9140 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9141 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9146 #ifdef BETTER_LITERAL_SHIFT
9147 /*-----------------------------------------------------------------*/
9148 /* genRightShiftLiteral - right shifting by known count */
9149 /*-----------------------------------------------------------------*/
9151 genRightShiftLiteral (operand * left,
9157 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9160 size = getSize (operandType (result));
9162 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
9164 /* We only handle certain easy cases so far. */
9166 && (shCount < (size * 8))
9171 D(emitcode (";", "genRightShiftLiteral wimping out"););
9175 freeAsmop (right, NULL, ic, TRUE);
9177 aopOp (left, ic, FALSE, FALSE);
9178 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9181 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9185 /* test the LEFT size !!! */
9187 /* I suppose that the left size >= result size */
9190 size = getDataSize (result);
9191 _startLazyDPSEvaluation();
9194 movLeft2Result (left, size, result, size, 0);
9196 _endLazyDPSEvaluation();
9198 else if (shCount >= (size * 8))
9202 /* get sign in acc.7 */
9203 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
9205 addSign (result, LSB, sign);
9212 genrshOne (result, left, shCount, sign);
9216 genrshTwo (result, left, shCount, sign);
9220 genrshFour (result, left, shCount, sign);
9227 freeAsmop (left, NULL, ic, TRUE);
9228 freeAsmop (result, NULL, ic, TRUE);
9234 /*-----------------------------------------------------------------*/
9235 /* genSignedRightShift - right shift of signed number */
9236 /*-----------------------------------------------------------------*/
9238 genSignedRightShift (iCode * ic)
9240 operand *right, *left, *result;
9243 symbol *tlbl, *tlbl1;
9245 D (emitcode (";", "genSignedRightShift "););
9247 /* we do it the hard way put the shift count in b
9248 and loop thru preserving the sign */
9250 right = IC_RIGHT (ic);
9251 left = IC_LEFT (ic);
9252 result = IC_RESULT (ic);
9254 aopOp (right, ic, FALSE, FALSE);
9256 #ifdef BETTER_LITERAL_SHIFT
9257 if (AOP_TYPE (right) == AOP_LIT)
9259 if (genRightShiftLiteral (left, right, result, ic, 1))
9265 /* shift count is unknown then we have to form
9266 a loop get the loop count in B : Note: we take
9267 only the lower order byte since shifting
9268 more that 32 bits make no sense anyway, ( the
9269 largest size of an object can be only 32 bits ) */
9271 if (AOP_TYPE (right) == AOP_LIT)
9273 /* Really should be handled by genRightShiftLiteral,
9274 * but since I'm too lazy to fix that today, at least we can make
9275 * some small improvement.
9277 emitcode("mov", "b,#!constbyte",
9278 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9282 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
9283 emitcode ("inc", "b");
9285 freeAsmop (right, NULL, ic, TRUE);
9286 aopOp (left, ic, FALSE, FALSE);
9287 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9289 /* now move the left to the result if they are not the
9291 if (!sameRegs (AOP (left), AOP (result)) &&
9292 AOP_SIZE (result) > 1)
9295 size = AOP_SIZE (result);
9297 _startLazyDPSEvaluation ();
9300 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
9301 if (*l == '@' && IS_AOP_PREG (result))
9304 emitcode ("mov", "a,%s", l);
9305 aopPut (AOP (result), "a", offset);
9308 aopPut (AOP (result), l, offset);
9311 _endLazyDPSEvaluation ();
9314 /* mov the highest order bit to OVR */
9315 tlbl = newiTempLabel (NULL);
9316 tlbl1 = newiTempLabel (NULL);
9318 size = AOP_SIZE (result);
9320 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
9321 emitcode ("rlc", "a");
9322 emitcode ("mov", "ov,c");
9323 /* if it is only one byte then */
9326 MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9327 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9328 emitcode ("", "!tlabeldef", tlbl->key + 100);
9329 emitcode ("mov", "c,ov");
9330 emitcode ("rrc", "a");
9331 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9332 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9333 aopPut (AOP (result), "a", 0);
9337 reAdjustPreg (AOP (result));
9338 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9339 emitcode ("", "!tlabeldef", tlbl->key + 100);
9340 emitcode ("mov", "c,ov");
9341 _startLazyDPSEvaluation ();
9344 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
9345 emitcode ("rrc", "a");
9346 aopPut (AOP (result), "a", offset--);
9348 _endLazyDPSEvaluation ();
9349 reAdjustPreg (AOP (result));
9350 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9351 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9354 freeAsmop (left, NULL, ic, TRUE);
9355 freeAsmop (result, NULL, ic, TRUE);
9358 /*-----------------------------------------------------------------*/
9359 /* genRightShift - generate code for right shifting */
9360 /*-----------------------------------------------------------------*/
9362 genRightShift (iCode * ic)
9364 operand *right, *left, *result;
9368 symbol *tlbl, *tlbl1;
9370 D (emitcode (";", "genRightShift "););
9372 /* if signed then we do it the hard way preserve the
9373 sign bit moving it inwards */
9374 letype = getSpec (operandType (IC_LEFT (ic)));
9376 if (!SPEC_USIGN (letype))
9378 genSignedRightShift (ic);
9382 /* signed & unsigned types are treated the same : i.e. the
9383 signed is NOT propagated inwards : quoting from the
9384 ANSI - standard : "for E1 >> E2, is equivalent to division
9385 by 2**E2 if unsigned or if it has a non-negative value,
9386 otherwise the result is implementation defined ", MY definition
9387 is that the sign does not get propagated */
9389 right = IC_RIGHT (ic);
9390 left = IC_LEFT (ic);
9391 result = IC_RESULT (ic);
9393 aopOp (right, ic, FALSE, FALSE);
9395 #ifdef BETTER_LITERAL_SHIFT
9396 /* if the shift count is known then do it
9397 as efficiently as possible */
9398 if (AOP_TYPE (right) == AOP_LIT)
9400 if (genRightShiftLiteral (left, right, result, ic, 0))
9407 /* shift count is unknown then we have to form
9408 a loop get the loop count in B : Note: we take
9409 only the lower order byte since shifting
9410 more that 32 bits make no sense anyway, ( the
9411 largest size of an object can be only 32 bits ) */
9413 if (AOP_TYPE (right) == AOP_LIT)
9415 /* Really should be handled by genRightShiftLiteral,
9416 * but since I'm too lazy to fix that today, at least we can make
9417 * some small improvement.
9419 emitcode("mov", "b,#!constbyte",
9420 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9424 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
9425 emitcode ("inc", "b");
9427 freeAsmop (right, NULL, ic, TRUE);
9428 aopOp (left, ic, FALSE, FALSE);
9429 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9431 /* now move the left to the result if they are not the
9433 if (!sameRegs (AOP (left), AOP (result)) &&
9434 AOP_SIZE (result) > 1)
9437 size = AOP_SIZE (result);
9439 _startLazyDPSEvaluation ();
9442 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
9443 if (*l == '@' && IS_AOP_PREG (result))
9446 emitcode ("mov", "a,%s", l);
9447 aopPut (AOP (result), "a", offset);
9450 aopPut (AOP (result), l, offset);
9453 _endLazyDPSEvaluation ();
9456 tlbl = newiTempLabel (NULL);
9457 tlbl1 = newiTempLabel (NULL);
9458 size = AOP_SIZE (result);
9461 /* if it is only one byte then */
9464 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9465 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9466 emitcode ("", "!tlabeldef", tlbl->key + 100);
9468 emitcode ("rrc", "a");
9469 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9470 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9471 aopPut (AOP (result), "a", 0);
9475 reAdjustPreg (AOP (result));
9476 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9477 emitcode ("", "!tlabeldef", tlbl->key + 100);
9479 _startLazyDPSEvaluation ();
9482 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
9483 emitcode ("rrc", "a");
9484 aopPut (AOP (result), "a", offset--);
9486 _endLazyDPSEvaluation ();
9487 reAdjustPreg (AOP (result));
9489 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9490 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9493 freeAsmop (left, NULL, ic, TRUE);
9494 freeAsmop (result, NULL, ic, TRUE);
9498 /*-----------------------------------------------------------------*/
9499 /* emitPtrByteGet - emits code to get a byte into A through a */
9500 /* pointer register (R0, R1, or DPTR). The */
9501 /* original value of A can be preserved in B. */
9502 /*-----------------------------------------------------------------*/
9504 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9511 emitcode ("mov", "b,a");
9512 emitcode ("mov", "a,@%s", rname);
9517 emitcode ("mov", "b,a");
9518 emitcode ("movx", "a,@%s", rname);
9523 emitcode ("mov", "b,a");
9524 emitcode ("movx", "a,@dptr");
9529 emitcode ("mov", "b,a");
9530 emitcode ("clr", "a");
9531 emitcode ("movc", "a,@a+dptr");
9537 emitcode ("push", "b");
9538 emitcode ("push", "acc");
9540 emitcode ("lcall", "__gptrget");
9542 emitcode ("pop", "b");
9547 /*-----------------------------------------------------------------*/
9548 /* emitPtrByteSet - emits code to set a byte from src through a */
9549 /* pointer register (R0, R1, or DPTR). */
9550 /*-----------------------------------------------------------------*/
9552 emitPtrByteSet (char *rname, int p_type, char *src)
9561 emitcode ("mov", "@%s,a", rname);
9564 emitcode ("mov", "@%s,%s", rname, src);
9569 emitcode ("movx", "@%s,a", rname);
9574 emitcode ("movx", "@dptr,a");
9579 emitcode ("lcall", "__gptrput");
9584 /*-----------------------------------------------------------------*/
9585 /* genUnpackBits - generates code for unpacking bits */
9586 /*-----------------------------------------------------------------*/
9588 genUnpackBits (operand * result, char *rname, int ptype)
9590 int offset = 0; /* result byte offset */
9591 int rsize; /* result size */
9592 int rlen = 0; /* remaining bitfield length */
9593 sym_link *etype; /* bitfield type information */
9594 int blen; /* bitfield length */
9595 int bstr; /* bitfield starting bit within byte */
9597 D(emitcode ("; genUnpackBits",""));
9599 etype = getSpec (operandType (result));
9600 rsize = getSize (operandType (result));
9601 blen = SPEC_BLEN (etype);
9602 bstr = SPEC_BSTR (etype);
9604 /* If the bitfield length is less than a byte */
9607 emitPtrByteGet (rname, ptype, FALSE);
9609 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
9610 aopPut (AOP (result), "a", offset++);
9614 /* Bit field did not fit in a byte. Copy all
9615 but the partial byte at the end. */
9616 for (rlen=blen;rlen>=8;rlen-=8)
9618 emitPtrByteGet (rname, ptype, FALSE);
9619 aopPut (AOP (result), "a", offset++);
9621 emitcode ("inc", "%s", rname);
9624 /* Handle the partial byte at the end */
9627 emitPtrByteGet (rname, ptype, FALSE);
9628 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
9629 aopPut (AOP (result), "a", offset++);
9637 aopPut (AOP (result), zero, offset++);
9642 /*-----------------------------------------------------------------*/
9643 /* genDataPointerGet - generates code when ptr offset is known */
9644 /*-----------------------------------------------------------------*/
9646 genDataPointerGet (operand * left,
9652 int size, offset = 0;
9653 aopOp (result, ic, TRUE, FALSE);
9655 /* get the string representation of the name */
9656 l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9657 size = AOP_SIZE (result);
9658 _startLazyDPSEvaluation ();
9663 SNPRINTF (buff, sizeof(buff),
9664 "(%s + %d)", l + 1, offset);
9668 SNPRINTF (buff, sizeof(buff),
9671 aopPut (AOP (result), buff, offset++);
9673 _endLazyDPSEvaluation ();
9675 freeAsmop (left, NULL, ic, TRUE);
9676 freeAsmop (result, NULL, ic, TRUE);
9679 /*-----------------------------------------------------------------*/
9680 /* genNearPointerGet - emitcode for near pointer fetch */
9681 /*-----------------------------------------------------------------*/
9683 genNearPointerGet (operand * left,
9691 sym_link *rtype, *retype, *letype;
9692 sym_link *ltype = operandType (left);
9695 rtype = operandType (result);
9696 retype = getSpec (rtype);
9697 letype = getSpec (ltype);
9699 aopOp (left, ic, FALSE, FALSE);
9701 /* if left is rematerialisable and
9702 result is not bitfield variable type and
9703 the left is pointer to data space i.e
9704 lower 128 bytes of space */
9705 if (AOP_TYPE (left) == AOP_IMMD &&
9706 !IS_BITFIELD (retype) &&
9707 !IS_BITFIELD (letype) &&
9708 DCL_TYPE (ltype) == POINTER)
9710 genDataPointerGet (left, result, ic);
9714 /* if the value is already in a pointer register
9715 then don't need anything more */
9716 if (!AOP_INPREG (AOP (left)))
9718 /* otherwise get a free pointer register */
9720 preg = getFreePtr (ic, &aop, FALSE);
9721 emitcode ("mov", "%s,%s",
9723 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9727 rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9729 freeAsmop (left, NULL, ic, TRUE);
9730 aopOp (result, ic, FALSE, FALSE);
9732 /* if bitfield then unpack the bits */
9733 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9734 genUnpackBits (result, rname, POINTER);
9737 /* we have can just get the values */
9738 int size = AOP_SIZE (result);
9743 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9746 emitcode ("mov", "a,@%s", rname);
9747 aopPut (AOP (result), "a", offset);
9751 SNPRINTF (buff, sizeof(buff), "@%s", rname);
9752 aopPut (AOP (result), buff, offset);
9757 emitcode ("inc", "%s", rname);
9762 /* now some housekeeping stuff */
9765 /* we had to allocate for this iCode */
9766 if (pi) { /* post increment present */
9767 aopPut(AOP ( left ),rname,0);
9769 freeAsmop (NULL, aop, ic, TRUE);
9773 /* we did not allocate which means left
9774 already in a pointer register, then
9775 if size > 0 && this could be used again
9776 we have to point it back to where it
9778 if (AOP_SIZE (result) > 1 &&
9779 !OP_SYMBOL (left)->remat &&
9780 (OP_SYMBOL (left)->liveTo > ic->seq ||
9784 int size = AOP_SIZE (result) - 1;
9786 emitcode ("dec", "%s", rname);
9791 freeAsmop (result, NULL, ic, TRUE);
9792 if (pi) pi->generated = 1;
9795 /*-----------------------------------------------------------------*/
9796 /* genPagedPointerGet - emitcode for paged pointer fetch */
9797 /*-----------------------------------------------------------------*/
9799 genPagedPointerGet (operand * left,
9807 sym_link *rtype, *retype, *letype;
9809 rtype = operandType (result);
9810 retype = getSpec (rtype);
9811 letype = getSpec (operandType (left));
9812 aopOp (left, ic, FALSE, FALSE);
9814 /* if the value is already in a pointer register
9815 then don't need anything more */
9816 if (!AOP_INPREG (AOP (left)))
9818 /* otherwise get a free pointer register */
9820 preg = getFreePtr (ic, &aop, FALSE);
9821 emitcode ("mov", "%s,%s",
9823 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9827 rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9829 freeAsmop (left, NULL, ic, TRUE);
9830 aopOp (result, ic, FALSE, FALSE);
9832 /* if bitfield then unpack the bits */
9833 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9834 genUnpackBits (result, rname, PPOINTER);
9837 /* we have can just get the values */
9838 int size = AOP_SIZE (result);
9844 emitcode ("movx", "a,@%s", rname);
9845 aopPut (AOP (result), "a", offset);
9850 emitcode ("inc", "%s", rname);
9854 /* now some housekeeping stuff */
9857 /* we had to allocate for this iCode */
9858 if (pi) aopPut ( AOP (left), rname, 0);
9859 freeAsmop (NULL, aop, ic, TRUE);
9863 /* we did not allocate which means left
9864 already in a pointer register, then
9865 if size > 0 && this could be used again
9866 we have to point it back to where it
9868 if (AOP_SIZE (result) > 1 &&
9869 !OP_SYMBOL (left)->remat &&
9870 (OP_SYMBOL (left)->liveTo > ic->seq ||
9874 int size = AOP_SIZE (result) - 1;
9876 emitcode ("dec", "%s", rname);
9881 freeAsmop (result, NULL, ic, TRUE);
9882 if (pi) pi->generated = 1;
9885 /*-----------------------------------------------------------------*/
9886 /* genFarPointerGet - gget value from far space */
9887 /*-----------------------------------------------------------------*/
9889 genFarPointerGet (operand * left,
9890 operand * result, iCode * ic, iCode *pi)
9892 int size, offset, dopi=1;
9893 sym_link *retype = getSpec (operandType (result));
9894 sym_link *letype = getSpec (operandType (left));
9895 D (emitcode (";", "genFarPointerGet"););
9897 aopOp (left, ic, FALSE, FALSE);
9899 /* if the operand is already in dptr
9900 then we do nothing else we move the value to dptr */
9901 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9903 /* if this is remateriazable */
9904 if (AOP_TYPE (left) == AOP_IMMD)
9906 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9910 /* we need to get it byte by byte */
9911 _startLazyDPSEvaluation ();
9912 if (AOP_TYPE (left) != AOP_DPTR)
9914 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9915 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9916 if (options.model == MODEL_FLAT24)
9917 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9921 /* We need to generate a load to DPTR indirect through DPTR. */
9922 D (emitcode (";", "genFarPointerGet -- indirection special case."););
9923 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9924 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9925 if (options.model == MODEL_FLAT24)
9926 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9927 emitcode ("pop", "dph");
9928 emitcode ("pop", "dpl");
9931 _endLazyDPSEvaluation ();
9934 /* so dptr know contains the address */
9935 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9937 /* if bit then unpack */
9938 if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
9939 if (AOP_INDPTRn(left)) {
9940 genSetDPTR(AOP(left)->aopu.dptr);
9942 genUnpackBits (result, "dptr", FPOINTER);
9943 if (AOP_INDPTRn(left)) {
9948 size = AOP_SIZE (result);
9951 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9953 genSetDPTR(AOP(left)->aopu.dptr);
9954 emitcode ("movx", "a,@dptr");
9955 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9956 emitcode ("inc", "dptr");
9958 aopPut (AOP (result), "a", offset++);
9961 _startLazyDPSEvaluation ();
9963 if (AOP_INDPTRn(left)) {
9964 genSetDPTR(AOP(left)->aopu.dptr);
9970 emitcode ("movx", "a,@dptr");
9971 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9972 emitcode ("inc", "dptr");
9974 aopPut (AOP (result), "a", offset++);
9976 _endLazyDPSEvaluation ();
9979 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9980 if (!AOP_INDPTRn(left)) {
9981 _startLazyDPSEvaluation ();
9982 aopPut ( AOP (left), "dpl", 0);
9983 aopPut ( AOP (left), "dph", 1);
9984 if (options.model == MODEL_FLAT24)
9985 aopPut ( AOP (left), "dpx", 2);
9986 _endLazyDPSEvaluation ();
9989 } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) &&
9990 AOP_SIZE(result) > 1 &&
9992 (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
9994 size = AOP_SIZE (result) - 1;
9995 if (AOP_INDPTRn(left)) {
9996 genSetDPTR(AOP(left)->aopu.dptr);
9998 while (size--) emitcode ("lcall","__decdptr");
9999 if (AOP_INDPTRn(left)) {
10004 freeAsmop (left, NULL, ic, TRUE);
10005 freeAsmop (result, NULL, ic, TRUE);
10008 /*-----------------------------------------------------------------*/
10009 /* genCodePointerGet - get value from code space */
10010 /*-----------------------------------------------------------------*/
10012 genCodePointerGet (operand * left,
10013 operand * result, iCode * ic, iCode *pi)
10015 int size, offset, dopi=1;
10016 sym_link *retype = getSpec (operandType (result));
10018 aopOp (left, ic, FALSE, FALSE);
10020 /* if the operand is already in dptr
10021 then we do nothing else we move the value to dptr */
10022 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
10024 /* if this is remateriazable */
10025 if (AOP_TYPE (left) == AOP_IMMD)
10027 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
10030 { /* we need to get it byte by byte */
10031 _startLazyDPSEvaluation ();
10032 if (AOP_TYPE (left) != AOP_DPTR)
10034 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10035 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10036 if (options.model == MODEL_FLAT24)
10037 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10041 /* We need to generate a load to DPTR indirect through DPTR. */
10042 D (emitcode (";", "gencodePointerGet -- indirection special case."););
10043 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
10044 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
10045 if (options.model == MODEL_FLAT24)
10046 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10047 emitcode ("pop", "dph");
10048 emitcode ("pop", "dpl");
10051 _endLazyDPSEvaluation ();
10054 /* so dptr know contains the address */
10055 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
10057 /* if bit then unpack */
10058 if (IS_BITFIELD (retype)) {
10059 if (AOP_INDPTRn(left)) {
10060 genSetDPTR(AOP(left)->aopu.dptr);
10062 genUnpackBits (result, "dptr", CPOINTER);
10063 if (AOP_INDPTRn(left)) {
10068 size = AOP_SIZE (result);
10070 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10072 genSetDPTR(AOP(left)->aopu.dptr);
10073 emitcode ("clr", "a");
10074 emitcode ("movc", "a,@a+dptr");
10075 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10076 emitcode ("inc", "dptr");
10078 aopPut (AOP (result), "a", offset++);
10081 _startLazyDPSEvaluation ();
10084 if (AOP_INDPTRn(left)) {
10085 genSetDPTR(AOP(left)->aopu.dptr);
10091 emitcode ("clr", "a");
10092 emitcode ("movc", "a,@a+dptr");
10093 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10094 emitcode ("inc", "dptr");
10095 aopPut (AOP (result), "a", offset++);
10097 _endLazyDPSEvaluation ();
10100 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10101 if (!AOP_INDPTRn(left)) {
10102 _startLazyDPSEvaluation ();
10104 aopPut ( AOP (left), "dpl", 0);
10105 aopPut ( AOP (left), "dph", 1);
10106 if (options.model == MODEL_FLAT24)
10107 aopPut ( AOP (left), "dpx", 2);
10109 _endLazyDPSEvaluation ();
10112 } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
10113 AOP_SIZE(result) > 1 &&
10114 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10116 size = AOP_SIZE (result) - 1;
10117 if (AOP_INDPTRn(left)) {
10118 genSetDPTR(AOP(left)->aopu.dptr);
10120 while (size--) emitcode ("lcall","__decdptr");
10121 if (AOP_INDPTRn(left)) {
10126 freeAsmop (left, NULL, ic, TRUE);
10127 freeAsmop (result, NULL, ic, TRUE);
10130 /*-----------------------------------------------------------------*/
10131 /* genGenPointerGet - gget value from generic pointer space */
10132 /*-----------------------------------------------------------------*/
10134 genGenPointerGet (operand * left,
10135 operand * result, iCode * ic, iCode * pi)
10138 sym_link *retype = getSpec (operandType (result));
10139 sym_link *letype = getSpec (operandType (left));
10141 D (emitcode (";", "genGenPointerGet "); );
10143 aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
10145 /* if the operand is already in dptr
10146 then we do nothing else we move the value to dptr */
10147 if (AOP_TYPE (left) != AOP_STR)
10149 /* if this is remateriazable */
10150 if (AOP_TYPE (left) == AOP_IMMD)
10152 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
10153 if (AOP(left)->aopu.aop_immd.from_cast_remat)
10155 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
10159 emitcode ("mov", "b,#%d", pointerCode (retype));
10163 { /* we need to get it byte by byte */
10164 _startLazyDPSEvaluation ();
10165 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
10166 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
10167 if (options.model == MODEL_FLAT24) {
10168 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
10169 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
10171 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
10173 _endLazyDPSEvaluation ();
10177 /* so dptr-b now contains the address */
10179 aopOp (result, ic, FALSE, TRUE);
10182 /* if bit then unpack */
10183 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10185 genUnpackBits (result, "dptr", GPOINTER);
10189 size = AOP_SIZE (result);
10196 // Get two bytes at a time, results in _AP & A.
10197 // dptr will be incremented ONCE by __gptrgetWord.
10199 // Note: any change here must be coordinated
10200 // with the implementation of __gptrgetWord
10201 // in device/lib/_gptrget.c
10202 emitcode ("lcall", "__gptrgetWord");
10203 aopPut (AOP (result), DP2_RESULT_REG, offset++);
10204 aopPut (AOP (result), "a", offset++);
10209 // Only one byte to get.
10210 emitcode ("lcall", "__gptrget");
10211 aopPut (AOP (result), "a", offset++);
10214 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
10216 emitcode ("inc", "dptr");
10221 if (pi && AOP_TYPE (left) != AOP_IMMD) {
10222 _startLazyDPSEvaluation ();
10224 aopPut ( AOP (left), "dpl", 0);
10225 aopPut ( AOP (left), "dph", 1);
10226 if (options.model == MODEL_FLAT24) {
10227 aopPut ( AOP (left), "dpx", 2);
10228 aopPut ( AOP (left), "b", 3);
10229 } else aopPut ( AOP (left), "b", 2);
10231 _endLazyDPSEvaluation ();
10234 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
10235 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10237 size = AOP_SIZE (result) - 1;
10238 while (size--) emitcode ("lcall","__decdptr");
10241 freeAsmop (left, NULL, ic, TRUE);
10242 freeAsmop (result, NULL, ic, TRUE);
10245 /*-----------------------------------------------------------------*/
10246 /* genPointerGet - generate code for pointer get */
10247 /*-----------------------------------------------------------------*/
10249 genPointerGet (iCode * ic, iCode *pi)
10251 operand *left, *result;
10252 sym_link *type, *etype;
10255 D (emitcode (";", "genPointerGet ");
10258 left = IC_LEFT (ic);
10259 result = IC_RESULT (ic);
10261 /* depending on the type of pointer we need to
10262 move it to the correct pointer register */
10263 type = operandType (left);
10264 etype = getSpec (type);
10265 /* if left is of type of pointer then it is simple */
10266 if (IS_PTR (type) && !IS_FUNC (type->next))
10267 p_type = DCL_TYPE (type);
10270 /* we have to go by the storage class */
10271 p_type = PTR_TYPE (SPEC_OCLS (etype));
10273 /* special case when cast remat */
10274 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10275 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
10276 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10277 type = operandType (left);
10278 p_type = DCL_TYPE (type);
10280 /* now that we have the pointer type we assign
10281 the pointer values */
10287 genNearPointerGet (left, result, ic, pi);
10291 genPagedPointerGet (left, result, ic, pi);
10295 genFarPointerGet (left, result, ic, pi);
10299 genCodePointerGet (left, result, ic, pi);
10303 genGenPointerGet (left, result, ic, pi);
10309 /*-----------------------------------------------------------------*/
10310 /* genPackBits - generates code for packed bit storage */
10311 /*-----------------------------------------------------------------*/
10313 genPackBits (sym_link * etype,
10315 char *rname, int p_type)
10317 int offset = 0; /* source byte offset */
10318 int rlen = 0; /* remaining bitfield length */
10319 int blen; /* bitfield length */
10320 int bstr; /* bitfield starting bit within byte */
10321 int litval; /* source literal value (if AOP_LIT) */
10322 unsigned char mask; /* bitmask within current byte */
10324 D(emitcode ("; genPackBits",""));
10326 blen = SPEC_BLEN (etype);
10327 bstr = SPEC_BSTR (etype);
10329 /* If the bitfield length is less than a byte */
10332 mask = ((unsigned char) (0xFF << (blen + bstr)) |
10333 (unsigned char) (0xFF >> (8 - bstr)));
10335 if (AOP_TYPE (right) == AOP_LIT)
10337 /* Case with a bitfield length <8 and literal source
10339 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10341 litval &= (~mask) & 0xff;
10342 emitPtrByteGet (rname, p_type, FALSE);
10343 if ((mask|litval)!=0xff)
10344 emitcode ("anl","a,#!constbyte", mask);
10346 emitcode ("orl","a,#!constbyte", litval);
10350 if ((blen==1) && (p_type!=GPOINTER))
10352 /* Case with a bitfield length == 1 and no generic pointer
10354 if (AOP_TYPE (right) == AOP_CRY)
10355 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10358 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
10359 emitcode ("rrc","a");
10361 emitPtrByteGet (rname, p_type, FALSE);
10362 emitcode ("mov","acc.%d,c",bstr);
10366 /* Case with a bitfield length < 8 and arbitrary source
10368 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
10369 /* shift and mask source value */
10371 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10373 /* transfer A to B and get next byte */
10374 emitPtrByteGet (rname, p_type, TRUE);
10376 emitcode ("anl", "a,#!constbyte", mask);
10377 emitcode ("orl", "a,b");
10378 if (p_type == GPOINTER)
10379 emitcode ("pop", "b");
10383 emitPtrByteSet (rname, p_type, "a");
10387 /* Bit length is greater than 7 bits. In this case, copy */
10388 /* all except the partial byte at the end */
10389 for (rlen=blen;rlen>=8;rlen-=8)
10391 emitPtrByteSet (rname, p_type,
10392 aopGet (AOP (right), offset++, FALSE, TRUE, NULL) );
10394 emitcode ("inc", "%s", rname);
10397 /* If there was a partial byte at the end */
10400 mask = (((unsigned char) -1 << rlen) & 0xff);
10402 if (AOP_TYPE (right) == AOP_LIT)
10404 /* Case with partial byte and literal source
10406 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10407 litval >>= (blen-rlen);
10408 litval &= (~mask) & 0xff;
10409 emitPtrByteGet (rname, p_type, FALSE);
10410 if ((mask|litval)!=0xff)
10411 emitcode ("anl","a,#!constbyte", mask);
10413 emitcode ("orl","a,#!constbyte", litval);
10417 /* Case with partial byte and arbitrary source
10419 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10420 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10422 /* transfer A to B and get next byte */
10423 emitPtrByteGet (rname, p_type, TRUE);
10425 emitcode ("anl", "a,#!constbyte", mask);
10426 emitcode ("orl", "a,b");
10427 if (p_type == GPOINTER)
10428 emitcode ("pop", "b");
10430 emitPtrByteSet (rname, p_type, "a");
10436 /*-----------------------------------------------------------------*/
10437 /* genDataPointerSet - remat pointer to data space */
10438 /*-----------------------------------------------------------------*/
10440 genDataPointerSet (operand * right,
10444 int size, offset = 0;
10445 char *l, buff[256];
10447 aopOp (right, ic, FALSE, FALSE);
10449 l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
10450 size = AOP_SIZE (right);
10455 SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
10459 SNPRINTF (buff, sizeof(buff), "%s", l + 1);
10462 emitcode ("mov", "%s,%s", buff,
10463 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10466 freeAsmop (right, NULL, ic, TRUE);
10467 freeAsmop (result, NULL, ic, TRUE);
10470 /*-----------------------------------------------------------------*/
10471 /* genNearPointerSet - emitcode for near pointer put */
10472 /*-----------------------------------------------------------------*/
10474 genNearPointerSet (operand * right,
10481 sym_link *retype, *letype;
10482 sym_link *ptype = operandType (result);
10484 retype = getSpec (operandType (right));
10485 letype = getSpec (ptype);
10487 aopOp (result, ic, FALSE, FALSE);
10489 /* if the result is rematerializable &
10490 in data space & not a bit variable */
10491 if (AOP_TYPE (result) == AOP_IMMD &&
10492 DCL_TYPE (ptype) == POINTER &&
10493 !IS_BITVAR (retype) &&
10494 !IS_BITVAR (letype))
10496 genDataPointerSet (right, result, ic);
10500 /* if the value is already in a pointer register
10501 then don't need anything more */
10502 if (!AOP_INPREG (AOP (result)))
10504 /* otherwise get a free pointer register */
10507 aop = newAsmop (0);
10508 preg = getFreePtr (ic, &aop, FALSE);
10509 emitcode ("mov", "%s,%s",
10511 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10512 rname = preg->name;
10515 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10517 aopOp (right, ic, FALSE, FALSE);
10519 /* if bitfield then unpack the bits */
10520 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10521 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10524 /* we have can just get the values */
10525 int size = AOP_SIZE (right);
10530 l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
10534 emitcode ("mov", "@%s,a", rname);
10537 emitcode ("mov", "@%s,%s", rname, l);
10539 emitcode ("inc", "%s", rname);
10544 /* now some housekeeping stuff */
10547 /* we had to allocate for this iCode */
10548 if (pi) aopPut (AOP (result),rname,0);
10549 freeAsmop (NULL, aop, ic, TRUE);
10553 /* we did not allocate which means left
10554 already in a pointer register, then
10555 if size > 0 && this could be used again
10556 we have to point it back to where it
10558 if (AOP_SIZE (right) > 1 &&
10559 !OP_SYMBOL (result)->remat &&
10560 (OP_SYMBOL (result)->liveTo > ic->seq ||
10564 int size = AOP_SIZE (right) - 1;
10566 emitcode ("dec", "%s", rname);
10571 if (pi) pi->generated = 1;
10572 freeAsmop (result, NULL, ic, TRUE);
10573 freeAsmop (right, NULL, ic, TRUE);
10578 /*-----------------------------------------------------------------*/
10579 /* genPagedPointerSet - emitcode for Paged pointer put */
10580 /*-----------------------------------------------------------------*/
10582 genPagedPointerSet (operand * right,
10589 sym_link *retype, *letype;
10591 retype = getSpec (operandType (right));
10592 letype = getSpec (operandType (result));
10594 aopOp (result, ic, FALSE, FALSE);
10596 /* if the value is already in a pointer register
10597 then don't need anything more */
10598 if (!AOP_INPREG (AOP (result)))
10600 /* otherwise get a free pointer register */
10603 aop = newAsmop (0);
10604 preg = getFreePtr (ic, &aop, FALSE);
10605 emitcode ("mov", "%s,%s",
10607 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10608 rname = preg->name;
10611 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10613 aopOp (right, ic, FALSE, FALSE);
10615 /* if bitfield then unpack the bits */
10616 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10617 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10620 /* we have can just get the values */
10621 int size = AOP_SIZE (right);
10626 MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10628 emitcode ("movx", "@%s,a", rname);
10631 emitcode ("inc", "%s", rname);
10637 /* now some housekeeping stuff */
10640 if (pi) aopPut (AOP (result),rname,0);
10641 /* we had to allocate for this iCode */
10642 freeAsmop (NULL, aop, ic, TRUE);
10646 /* we did not allocate which means left
10647 already in a pointer register, then
10648 if size > 0 && this could be used again
10649 we have to point it back to where it
10651 if (AOP_SIZE (right) > 1 &&
10652 !OP_SYMBOL (result)->remat &&
10653 (OP_SYMBOL (result)->liveTo > ic->seq ||
10657 int size = AOP_SIZE (right) - 1;
10659 emitcode ("dec", "%s", rname);
10664 if (pi) pi->generated = 1;
10665 freeAsmop (result, NULL, ic, TRUE);
10666 freeAsmop (right, NULL, ic, TRUE);
10671 /*-----------------------------------------------------------------*/
10672 /* genFarPointerSet - set value from far space */
10673 /*-----------------------------------------------------------------*/
10675 genFarPointerSet (operand * right,
10676 operand * result, iCode * ic, iCode *pi)
10678 int size, offset, dopi=1;
10679 sym_link *retype = getSpec (operandType (right));
10680 sym_link *letype = getSpec (operandType (result));
10682 aopOp (result, ic, FALSE, FALSE);
10684 /* if the operand is already in dptr
10685 then we do nothing else we move the value to dptr */
10686 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10688 /* if this is remateriazable */
10689 if (AOP_TYPE (result) == AOP_IMMD)
10690 emitcode ("mov", "dptr,%s",
10691 aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10694 /* we need to get it byte by byte */
10695 _startLazyDPSEvaluation ();
10696 if (AOP_TYPE (result) != AOP_DPTR)
10698 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10699 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10700 if (options.model == MODEL_FLAT24)
10701 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10705 /* We need to generate a load to DPTR indirect through DPTR. */
10706 D (emitcode (";", "genFarPointerSet -- indirection special case."););
10708 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10709 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10710 if (options.model == MODEL_FLAT24)
10711 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10712 emitcode ("pop", "dph");
10713 emitcode ("pop", "dpl");
10716 _endLazyDPSEvaluation ();
10719 /* so dptr know contains the address */
10720 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10722 /* if bit then unpack */
10723 if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
10724 if (AOP_INDPTRn(result)) {
10725 genSetDPTR(AOP(result)->aopu.dptr);
10727 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10728 if (AOP_INDPTRn(result)) {
10732 size = AOP_SIZE (right);
10734 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10736 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10738 genSetDPTR(AOP(result)->aopu.dptr);
10739 emitcode ("movx", "@dptr,a");
10740 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10741 emitcode ("inc", "dptr");
10745 _startLazyDPSEvaluation ();
10747 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10749 if (AOP_INDPTRn(result)) {
10750 genSetDPTR(AOP(result)->aopu.dptr);
10756 emitcode ("movx", "@dptr,a");
10757 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10758 emitcode ("inc", "dptr");
10760 _endLazyDPSEvaluation ();
10764 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10765 if (!AOP_INDPTRn(result)) {
10766 _startLazyDPSEvaluation ();
10768 aopPut (AOP(result),"dpl",0);
10769 aopPut (AOP(result),"dph",1);
10770 if (options.model == MODEL_FLAT24)
10771 aopPut (AOP(result),"dpx",2);
10773 _endLazyDPSEvaluation ();
10776 } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
10777 AOP_SIZE(right) > 1 &&
10778 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10780 size = AOP_SIZE (right) - 1;
10781 if (AOP_INDPTRn(result)) {
10782 genSetDPTR(AOP(result)->aopu.dptr);
10784 while (size--) emitcode ("lcall","__decdptr");
10785 if (AOP_INDPTRn(result)) {
10789 freeAsmop (result, NULL, ic, TRUE);
10790 freeAsmop (right, NULL, ic, TRUE);
10793 /*-----------------------------------------------------------------*/
10794 /* genGenPointerSet - set value from generic pointer space */
10795 /*-----------------------------------------------------------------*/
10797 genGenPointerSet (operand * right,
10798 operand * result, iCode * ic, iCode *pi)
10801 sym_link *retype = getSpec (operandType (right));
10802 sym_link *letype = getSpec (operandType (result));
10804 aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10806 /* if the operand is already in dptr
10807 then we do nothing else we move the value to dptr */
10808 if (AOP_TYPE (result) != AOP_STR)
10810 _startLazyDPSEvaluation ();
10811 /* if this is remateriazable */
10812 if (AOP_TYPE (result) == AOP_IMMD)
10814 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10815 if (AOP(result)->aopu.aop_immd.from_cast_remat)
10817 MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10822 "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10826 { /* we need to get it byte by byte */
10827 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10828 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10829 if (options.model == MODEL_FLAT24) {
10830 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10831 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10833 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10836 _endLazyDPSEvaluation ();
10838 /* so dptr + b now contains the address */
10840 aopOp (right, ic, FALSE, TRUE);
10844 /* if bit then unpack */
10845 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10847 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10851 size = AOP_SIZE (right);
10854 _startLazyDPSEvaluation ();
10859 // Set two bytes at a time, passed in _AP & A.
10860 // dptr will be incremented ONCE by __gptrputWord.
10862 // Note: any change here must be coordinated
10863 // with the implementation of __gptrputWord
10864 // in device/lib/_gptrput.c
10865 emitcode("mov", "_ap, %s",
10866 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10867 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10871 emitcode ("lcall", "__gptrputWord");
10876 // Only one byte to put.
10877 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10881 emitcode ("lcall", "__gptrput");
10884 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10886 emitcode ("inc", "dptr");
10889 _endLazyDPSEvaluation ();
10892 if (pi && AOP_TYPE (result) != AOP_IMMD) {
10893 _startLazyDPSEvaluation ();
10895 aopPut (AOP(result),"dpl",0);
10896 aopPut (AOP(result),"dph",1);
10897 if (options.model == MODEL_FLAT24) {
10898 aopPut (AOP(result),"dpx",2);
10899 aopPut (AOP(result),"b",3);
10901 aopPut (AOP(result),"b",2);
10903 _endLazyDPSEvaluation ();
10906 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10907 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10909 size = AOP_SIZE (right) - 1;
10910 while (size--) emitcode ("lcall","__decdptr");
10912 freeAsmop (result, NULL, ic, TRUE);
10913 freeAsmop (right, NULL, ic, TRUE);
10916 /*-----------------------------------------------------------------*/
10917 /* genPointerSet - stores the value into a pointer location */
10918 /*-----------------------------------------------------------------*/
10920 genPointerSet (iCode * ic, iCode *pi)
10922 operand *right, *result;
10923 sym_link *type, *etype;
10926 D (emitcode (";", "genPointerSet "););
10928 right = IC_RIGHT (ic);
10929 result = IC_RESULT (ic);
10931 /* depending on the type of pointer we need to
10932 move it to the correct pointer register */
10933 type = operandType (result);
10934 etype = getSpec (type);
10935 /* if left is of type of pointer then it is simple */
10936 if (IS_PTR (type) && !IS_FUNC (type->next))
10938 p_type = DCL_TYPE (type);
10942 /* we have to go by the storage class */
10943 p_type = PTR_TYPE (SPEC_OCLS (etype));
10945 /* special case when cast remat */
10946 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10947 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10948 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10949 type = operandType (result);
10950 p_type = DCL_TYPE (type);
10953 /* now that we have the pointer type we assign
10954 the pointer values */
10960 genNearPointerSet (right, result, ic, pi);
10964 genPagedPointerSet (right, result, ic, pi);
10968 genFarPointerSet (right, result, ic, pi);
10972 genGenPointerSet (right, result, ic, pi);
10976 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10977 "genPointerSet: illegal pointer type");
10982 /*-----------------------------------------------------------------*/
10983 /* genIfx - generate code for Ifx statement */
10984 /*-----------------------------------------------------------------*/
10986 genIfx (iCode * ic, iCode * popIc)
10988 operand *cond = IC_COND (ic);
10991 D (emitcode (";", "genIfx "););
10993 aopOp (cond, ic, FALSE, FALSE);
10995 /* get the value into acc */
10996 if (AOP_TYPE (cond) != AOP_CRY)
11005 /* the result is now in the accumulator */
11006 freeAsmop (cond, NULL, ic, TRUE);
11008 /* if there was something to be popped then do it */
11012 /* if the condition is a bit variable */
11013 if (isbit && IS_ITEMP (cond) &&
11016 genIfxJump (ic, SPIL_LOC (cond)->rname);
11018 else if (isbit && !IS_ITEMP (cond))
11020 genIfxJump (ic, OP_SYMBOL (cond)->rname);
11024 genIfxJump (ic, "a");
11030 /*-----------------------------------------------------------------*/
11031 /* genAddrOf - generates code for address of */
11032 /*-----------------------------------------------------------------*/
11034 genAddrOf (iCode * ic)
11036 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
11039 D (emitcode (";", "genAddrOf ");
11042 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11044 /* if the operand is on the stack then we
11045 need to get the stack offset of this
11047 if (sym->onStack) {
11049 /* if 10 bit stack */
11050 if (options.stack10bit) {
11054 tsprintf(buff, sizeof(buff),
11055 "#!constbyte",(options.stack_loc >> 16) & 0xff);
11056 /* if it has an offset then we need to compute it */
11057 /* emitcode ("subb", "a,#!constbyte", */
11058 /* -((sym->stack < 0) ? */
11059 /* ((short) (sym->stack - _G.nRegsSaved)) : */
11060 /* ((short) sym->stack)) & 0xff); */
11061 /* emitcode ("mov","b,a"); */
11062 /* emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
11063 /* ((short) (sym->stack - _G.nRegsSaved)) : */
11064 /* ((short) sym->stack)) >> 8) & 0xff); */
11066 emitcode ("mov", "a,_bpx");
11067 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
11068 ((char) (sym->stack - _G.nRegsSaved)) :
11069 ((char) sym->stack )) & 0xff);
11070 emitcode ("mov", "b,a");
11071 emitcode ("mov", "a,_bpx+1");
11073 offset = (((sym->stack < 0) ?
11074 ((short) (sym->stack - _G.nRegsSaved)) :
11075 ((short) sym->stack )) >> 8) & 0xff;
11077 emitcode ("addc","a,#!constbyte", offset);
11079 aopPut (AOP (IC_RESULT (ic)), "b", 0);
11080 aopPut (AOP (IC_RESULT (ic)), "a", 1);
11081 aopPut (AOP (IC_RESULT (ic)), buff, 2);
11083 /* we can just move _bp */
11084 aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
11085 aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
11086 aopPut (AOP (IC_RESULT (ic)), buff, 2);
11089 /* if it has an offset then we need to compute it */
11091 emitcode ("mov", "a,_bp");
11092 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
11093 aopPut (AOP (IC_RESULT (ic)), "a", 0);
11095 /* we can just move _bp */
11096 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
11098 /* fill the result with zero */
11099 size = AOP_SIZE (IC_RESULT (ic)) - 1;
11102 if (options.stack10bit && size < (FPTRSIZE - 1)) {
11104 "*** warning: pointer to stack var truncated.\n");
11109 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
11115 /* object not on stack then we need the name */
11116 size = AOP_SIZE (IC_RESULT (ic));
11121 char s[SDCC_NAME_MAX];
11125 tsprintf(s, sizeof(s), "#!his",sym->rname);
11128 tsprintf(s, sizeof(s), "#!hihis",sym->rname);
11131 tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
11133 default: /* should not need this (just in case) */
11134 SNPRINTF (s, sizeof(s), "#(%s >> %d)",
11141 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11144 aopPut (AOP (IC_RESULT (ic)), s, offset++);
11148 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11152 #if 0 // obsolete, and buggy for != xdata
11153 /*-----------------------------------------------------------------*/
11154 /* genArrayInit - generates code for address of */
11155 /*-----------------------------------------------------------------*/
11157 genArrayInit (iCode * ic)
11159 literalList *iLoop;
11161 int elementSize = 0, eIndex;
11162 unsigned val, lastVal;
11164 operand *left=IC_LEFT(ic);
11166 D (emitcode (";", "genArrayInit "););
11168 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
11170 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
11172 // Load immediate value into DPTR.
11173 emitcode("mov", "dptr, %s",
11174 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
11176 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
11179 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11180 "Unexpected operand to genArrayInit.\n");
11183 // a regression because of SDCCcse.c:1.52
11184 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
11185 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
11186 if (options.model == MODEL_FLAT24)
11187 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
11191 type = operandType(IC_LEFT(ic));
11193 if (type && type->next)
11195 elementSize = getSize(type->next);
11199 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11200 "can't determine element size in genArrayInit.\n");
11204 iLoop = IC_ARRAYILIST(ic);
11209 bool firstpass = TRUE;
11211 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
11212 iLoop->count, (int)iLoop->literalValue, elementSize);
11218 symbol *tlbl = NULL;
11220 count = ix > 256 ? 256 : ix;
11224 tlbl = newiTempLabel (NULL);
11225 if (firstpass || (count & 0xff))
11227 emitcode("mov", "b, #!constbyte", count & 0xff);
11230 emitcode ("", "!tlabeldef", tlbl->key + 100);
11235 for (eIndex = 0; eIndex < elementSize; eIndex++)
11237 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
11238 if (val != lastVal)
11240 emitcode("mov", "a, #!constbyte", val);
11244 emitcode("movx", "@dptr, a");
11245 emitcode("inc", "dptr");
11250 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
11256 iLoop = iLoop->next;
11259 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
11263 /*-----------------------------------------------------------------*/
11264 /* genFarFarAssign - assignment when both are in far space */
11265 /*-----------------------------------------------------------------*/
11267 genFarFarAssign (operand * result, operand * right, iCode * ic)
11269 int size = AOP_SIZE (right);
11271 symbol *rSym = NULL;
11275 /* quick & easy case. */
11276 D(emitcode(";","genFarFarAssign (1 byte case)"););
11277 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
11278 freeAsmop (right, NULL, ic, FALSE);
11279 /* now assign DPTR to result */
11281 aopOp(result, ic, FALSE, FALSE);
11283 aopPut(AOP(result), "a", 0);
11284 freeAsmop(result, NULL, ic, FALSE);
11288 /* See if we've got an underlying symbol to abuse. */
11289 if (IS_SYMOP(result) && OP_SYMBOL(result))
11291 if (IS_TRUE_SYMOP(result))
11293 rSym = OP_SYMBOL(result);
11295 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
11297 rSym = OP_SYMBOL(result)->usl.spillLoc;
11301 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
11303 /* We can use the '390 auto-toggle feature to good effect here. */
11305 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
11306 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11307 emitcode ("mov", "dptr,#%s", rSym->rname);
11308 /* DP2 = result, DP1 = right, DP1 is current. */
11311 emitcode("movx", "a,@dptr");
11312 emitcode("movx", "@dptr,a");
11315 emitcode("inc", "dptr");
11316 emitcode("inc", "dptr");
11319 emitcode("mov", "dps,#0");
11320 freeAsmop (right, NULL, ic, FALSE);
11322 some alternative code for processors without auto-toggle
11323 no time to test now, so later well put in...kpb
11324 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
11325 emitcode("mov", "dps,#1"); /* Select DPTR2. */
11326 emitcode ("mov", "dptr,#%s", rSym->rname);
11327 /* DP2 = result, DP1 = right, DP1 is current. */
11331 emitcode("movx", "a,@dptr");
11333 emitcode("inc", "dptr");
11334 emitcode("inc", "dps");
11335 emitcode("movx", "@dptr,a");
11337 emitcode("inc", "dptr");
11338 emitcode("inc", "dps");
11340 emitcode("mov", "dps,#0");
11341 freeAsmop (right, NULL, ic, FALSE);
11346 D (emitcode (";", "genFarFarAssign"););
11347 aopOp (result, ic, TRUE, TRUE);
11349 _startLazyDPSEvaluation ();
11353 aopPut (AOP (result),
11354 aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
11357 _endLazyDPSEvaluation ();
11358 freeAsmop (result, NULL, ic, FALSE);
11359 freeAsmop (right, NULL, ic, FALSE);
11363 /*-----------------------------------------------------------------*/
11364 /* genAssign - generate code for assignment */
11365 /*-----------------------------------------------------------------*/
11367 genAssign (iCode * ic)
11369 operand *result, *right;
11371 unsigned long lit = 0L;
11373 D (emitcode (";", "genAssign ");
11376 result = IC_RESULT (ic);
11377 right = IC_RIGHT (ic);
11379 /* if they are the same */
11380 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11383 aopOp (right, ic, FALSE, FALSE);
11385 emitcode (";", "genAssign: resultIsFar = %s",
11386 isOperandInFarSpace (result) ?
11389 /* special case both in far space */
11390 if ((AOP_TYPE (right) == AOP_DPTR ||
11391 AOP_TYPE (right) == AOP_DPTR2) &&
11392 /* IS_TRUE_SYMOP(result) && */
11393 isOperandInFarSpace (result))
11395 genFarFarAssign (result, right, ic);
11399 aopOp (result, ic, TRUE, FALSE);
11401 /* if they are the same registers */
11402 if (sameRegs (AOP (right), AOP (result)))
11405 /* if the result is a bit */
11406 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
11408 /* if the right size is a literal then
11409 we know what the value is */
11410 if (AOP_TYPE (right) == AOP_LIT)
11412 if (((int) operandLitValue (right)))
11413 aopPut (AOP (result), one, 0);
11415 aopPut (AOP (result), zero, 0);
11419 /* the right is also a bit variable */
11420 if (AOP_TYPE (right) == AOP_CRY)
11422 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11423 aopPut (AOP (result), "c", 0);
11427 /* we need to or */
11429 aopPut (AOP (result), "a", 0);
11433 /* bit variables done */
11435 size = AOP_SIZE (result);
11437 if (AOP_TYPE (right) == AOP_LIT)
11438 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11441 (AOP_TYPE (result) != AOP_REG) &&
11442 (AOP_TYPE (right) == AOP_LIT) &&
11443 !IS_FLOAT (operandType (right)))
11445 _startLazyDPSEvaluation ();
11446 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
11448 aopPut (AOP (result),
11449 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11454 /* And now fill the rest with zeros. */
11457 emitcode ("clr", "a");
11461 aopPut (AOP (result), "a", offset++);
11463 _endLazyDPSEvaluation ();
11467 _startLazyDPSEvaluation ();
11470 aopPut (AOP (result),
11471 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11475 _endLazyDPSEvaluation ();
11479 freeAsmop (right, NULL, ic, FALSE);
11480 freeAsmop (result, NULL, ic, TRUE);
11483 /*-----------------------------------------------------------------*/
11484 /* genJumpTab - generates code for jump table */
11485 /*-----------------------------------------------------------------*/
11487 genJumpTab (iCode * ic)
11492 D (emitcode (";", "genJumpTab ");
11495 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
11496 /* get the condition into accumulator */
11497 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
11499 /* multiply by four! */
11500 emitcode ("add", "a,acc");
11501 emitcode ("add", "a,acc");
11502 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11504 jtab = newiTempLabel (NULL);
11505 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
11506 emitcode ("jmp", "@a+dptr");
11507 emitcode ("", "!tlabeldef", jtab->key + 100);
11508 /* now generate the jump labels */
11509 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11510 jtab = setNextItem (IC_JTLABELS (ic)))
11511 emitcode ("ljmp", "!tlabel", jtab->key + 100);
11515 /*-----------------------------------------------------------------*/
11516 /* genCast - gen code for casting */
11517 /*-----------------------------------------------------------------*/
11519 genCast (iCode * ic)
11521 operand *result = IC_RESULT (ic);
11522 sym_link *ctype = operandType (IC_LEFT (ic));
11523 sym_link *rtype = operandType (IC_RIGHT (ic));
11524 operand *right = IC_RIGHT (ic);
11527 D (emitcode (";", "genCast "););
11529 /* if they are equivalent then do nothing */
11530 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11533 aopOp (right, ic, FALSE, AOP_IS_STR (result));
11534 aopOp (result, ic, FALSE, (AOP_TYPE(right) == AOP_DPTR));
11536 /* if the result is a bit */
11537 if (IS_BITVAR (OP_SYMBOL (result)->type)
11538 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
11540 /* if the right size is a literal then
11541 we know what the value is */
11542 if (AOP_TYPE (right) == AOP_LIT)
11544 if (((int) operandLitValue (right)))
11545 aopPut (AOP (result), one, 0);
11547 aopPut (AOP (result), zero, 0);
11552 /* the right is also a bit variable */
11553 if (AOP_TYPE (right) == AOP_CRY)
11555 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11556 aopPut (AOP (result), "c", 0);
11560 /* we need to or */
11562 aopPut (AOP (result), "a", 0);
11566 /* if they are the same size : or less */
11567 if (AOP_SIZE (result) <= AOP_SIZE (right))
11570 /* if they are in the same place */
11571 if (sameRegs (AOP (right), AOP (result)))
11574 /* if they in different places then copy */
11575 size = AOP_SIZE (result);
11577 _startLazyDPSEvaluation ();
11580 aopPut (AOP (result),
11581 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11585 _endLazyDPSEvaluation ();
11590 /* if the result is of type pointer */
11591 if (IS_PTR (ctype))
11595 sym_link *type = operandType (right);
11597 /* pointer to generic pointer */
11598 if (IS_GENPTR (ctype))
11602 p_type = DCL_TYPE (type);
11606 #if OLD_CAST_BEHAVIOR
11607 /* KV: we are converting a non-pointer type to
11608 * a generic pointer. This (ifdef'd out) code
11609 * says that the resulting generic pointer
11610 * should have the same class as the storage
11611 * location of the non-pointer variable.
11613 * For example, converting an int (which happens
11614 * to be stored in DATA space) to a pointer results
11615 * in a DATA generic pointer; if the original int
11616 * in XDATA space, so will be the resulting pointer.
11618 * I don't like that behavior, and thus this change:
11619 * all such conversions will be forced to XDATA and
11620 * throw a warning. If you want some non-XDATA
11621 * type, or you want to suppress the warning, you
11622 * must go through an intermediate cast, like so:
11624 * char _generic *gp = (char _xdata *)(intVar);
11626 sym_link *etype = getSpec (type);
11628 /* we have to go by the storage class */
11629 if (SPEC_OCLS (etype) != generic)
11631 p_type = PTR_TYPE (SPEC_OCLS (etype));
11636 /* Converting unknown class (i.e. register variable)
11637 * to generic pointer. This is not good, but
11638 * we'll make a guess (and throw a warning).
11641 werror (W_INT_TO_GEN_PTR_CAST);
11645 /* the first two bytes are known */
11646 size = GPTRSIZE - 1;
11648 _startLazyDPSEvaluation ();
11651 aopPut (AOP (result),
11652 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11656 _endLazyDPSEvaluation ();
11658 /* the last byte depending on type */
11660 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11665 // pointerTypeToGPByte will have bitched.
11669 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11670 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11675 /* just copy the pointers */
11676 size = AOP_SIZE (result);
11678 _startLazyDPSEvaluation ();
11681 aopPut (AOP (result),
11682 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11686 _endLazyDPSEvaluation ();
11690 /* so we now know that the size of destination is greater
11691 than the size of the source */
11692 /* we move to result for the size of source */
11693 size = AOP_SIZE (right);
11695 _startLazyDPSEvaluation ();
11698 aopPut (AOP (result),
11699 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11703 _endLazyDPSEvaluation ();
11705 /* now depending on the sign of the source && destination */
11706 size = AOP_SIZE (result) - AOP_SIZE (right);
11707 /* if unsigned or not an integral type */
11708 /* also, if the source is a bit, we don't need to sign extend, because
11709 * it can't possibly have set the sign bit.
11711 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
11715 aopPut (AOP (result), zero, offset++);
11720 /* we need to extend the sign :{ */
11721 MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11722 FALSE, FALSE, NULL));
11723 emitcode ("rlc", "a");
11724 emitcode ("subb", "a,acc");
11726 aopPut (AOP (result), "a", offset++);
11729 /* we are done hurray !!!! */
11732 freeAsmop (right, NULL, ic, TRUE);
11733 freeAsmop (result, NULL, ic, TRUE);
11737 /*-----------------------------------------------------------------*/
11738 /* genDjnz - generate decrement & jump if not zero instrucion */
11739 /*-----------------------------------------------------------------*/
11741 genDjnz (iCode * ic, iCode * ifx)
11743 symbol *lbl, *lbl1;
11747 /* if the if condition has a false label
11748 then we cannot save */
11749 if (IC_FALSE (ifx))
11752 /* if the minus is not of the form
11754 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11755 !IS_OP_LITERAL (IC_RIGHT (ic)))
11758 if (operandLitValue (IC_RIGHT (ic)) != 1)
11761 /* if the size of this greater than one then no
11763 if (getSize (operandType (IC_RESULT (ic))) > 1)
11766 /* otherwise we can save BIG */
11767 D(emitcode(";", "genDjnz"););
11769 lbl = newiTempLabel (NULL);
11770 lbl1 = newiTempLabel (NULL);
11772 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11774 if (AOP_NEEDSACC(IC_RESULT(ic)))
11776 /* If the result is accessed indirectly via
11777 * the accumulator, we must explicitly write
11778 * it back after the decrement.
11780 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11782 if (strcmp(rByte, "a"))
11784 /* Something is hopelessly wrong */
11785 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11786 __FILE__, __LINE__);
11787 /* We can just give up; the generated code will be inefficient,
11788 * but what the hey.
11790 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11793 emitcode ("dec", "%s", rByte);
11794 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11795 emitcode ("jnz", "!tlabel", lbl->key + 100);
11797 else if (IS_AOP_PREG (IC_RESULT (ic)))
11799 emitcode ("dec", "%s",
11800 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11801 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11802 emitcode ("jnz", "!tlabel", lbl->key + 100);
11806 emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11809 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11810 emitcode ("", "!tlabeldef", lbl->key + 100);
11811 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11812 emitcode ("", "!tlabeldef", lbl1->key + 100);
11814 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11815 ifx->generated = 1;
11819 /*-----------------------------------------------------------------*/
11820 /* genReceive - generate code for a receive iCode */
11821 /*-----------------------------------------------------------------*/
11823 genReceive (iCode * ic)
11825 int size = getSize (operandType (IC_RESULT (ic)));
11829 D (emitcode (";", "genReceive "););
11831 if (ic->argreg == 1)
11833 /* first parameter */
11834 if (AOP_IS_STR(IC_RESULT(ic)))
11836 /* Nothing to do: it's already in the proper place. */
11843 useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11844 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11845 IS_TRUE_SYMOP (IC_RESULT (ic)));
11848 aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11851 /* Sanity checking... */
11852 if (AOP_USESDPTR(IC_RESULT(ic)))
11854 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11855 "genReceive got unexpected DPTR.");
11857 assignResultValue (IC_RESULT (ic));
11862 /* second receive onwards */
11863 /* this gets a little tricky since unused recevies will be
11864 eliminated, we have saved the reg in the type field . and
11865 we use that to figure out which register to use */
11866 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11867 rb1off = ic->argreg;
11870 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11873 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11876 /*-----------------------------------------------------------------*/
11877 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
11878 /*-----------------------------------------------------------------*/
11879 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11881 operand *from , *to , *count;
11886 /* we know it has to be 3 parameters */
11887 assert (nparms == 3);
11889 rsave = newBitVect(16);
11890 /* save DPTR if it needs to be saved */
11891 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11892 if (bitVectBitValue(ic->rMask,i))
11893 rsave = bitVectSetBit(rsave,i);
11895 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11896 ds390_rUmaskForOp (IC_RESULT(ic))));
11903 aopOp (from, ic->next, FALSE, FALSE);
11905 /* get from into DPTR1 */
11906 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11907 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11908 if (options.model == MODEL_FLAT24) {
11909 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11912 freeAsmop (from, NULL, ic, FALSE);
11913 aopOp (to, ic, FALSE, FALSE);
11914 /* get "to" into DPTR */
11915 /* if the operand is already in dptr
11916 then we do nothing else we move the value to dptr */
11917 if (AOP_TYPE (to) != AOP_STR) {
11918 /* if already in DPTR then we need to push */
11919 if (AOP_TYPE(to) == AOP_DPTR) {
11920 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11921 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11922 if (options.model == MODEL_FLAT24)
11923 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11924 emitcode ("pop", "dph");
11925 emitcode ("pop", "dpl");
11927 _startLazyDPSEvaluation ();
11928 /* if this is remateriazable */
11929 if (AOP_TYPE (to) == AOP_IMMD) {
11930 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11931 } else { /* we need to get it byte by byte */
11932 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11933 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11934 if (options.model == MODEL_FLAT24) {
11935 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11938 _endLazyDPSEvaluation ();
11941 freeAsmop (to, NULL, ic, FALSE);
11942 _G.dptrInUse = _G.dptr1InUse = 1;
11943 aopOp (count, ic->next->next, FALSE,FALSE);
11944 lbl =newiTempLabel(NULL);
11946 /* now for the actual copy */
11947 if (AOP_TYPE(count) == AOP_LIT &&
11948 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11949 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11951 emitcode ("lcall","__bi_memcpyc2x_s");
11953 emitcode ("lcall","__bi_memcpyx2x_s");
11955 freeAsmop (count, NULL, ic, FALSE);
11957 symbol *lbl1 = newiTempLabel(NULL);
11959 emitcode (";"," Auto increment but no djnz");
11960 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11961 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11962 freeAsmop (count, NULL, ic, FALSE);
11963 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11964 emitcode ("","!tlabeldef",lbl->key+100);
11966 emitcode ("clr","a");
11967 emitcode ("movc", "a,@a+dptr");
11969 emitcode ("movx", "a,@dptr");
11970 emitcode ("movx", "@dptr,a");
11971 emitcode ("inc", "dptr");
11972 emitcode ("inc", "dptr");
11973 emitcode ("mov","a,b");
11974 emitcode ("orl","a,_ap");
11975 emitcode ("jz","!tlabel",lbl1->key+100);
11976 emitcode ("mov","a,_ap");
11977 emitcode ("add","a,#!constbyte",0xFF);
11978 emitcode ("mov","_ap,a");
11979 emitcode ("mov","a,b");
11980 emitcode ("addc","a,#!constbyte",0xFF);
11981 emitcode ("mov","b,a");
11982 emitcode ("sjmp","!tlabel",lbl->key+100);
11983 emitcode ("","!tlabeldef",lbl1->key+100);
11985 emitcode ("mov", "dps,#0");
11986 _G.dptrInUse = _G.dptr1InUse = 0;
11987 unsavermask(rsave);
11991 /*-----------------------------------------------------------------*/
11992 /* genMemcmpX2X - gen code for memcmp xdata to xdata */
11993 /*-----------------------------------------------------------------*/
11994 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11996 operand *from , *to , *count;
12001 /* we know it has to be 3 parameters */
12002 assert (nparms == 3);
12004 rsave = newBitVect(16);
12005 /* save DPTR if it needs to be saved */
12006 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12007 if (bitVectBitValue(ic->rMask,i))
12008 rsave = bitVectSetBit(rsave,i);
12010 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12011 ds390_rUmaskForOp (IC_RESULT(ic))));
12018 aopOp (from, ic->next, FALSE, FALSE);
12020 /* get from into DPTR1 */
12021 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12022 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12023 if (options.model == MODEL_FLAT24) {
12024 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12027 freeAsmop (from, NULL, ic, FALSE);
12028 aopOp (to, ic, FALSE, FALSE);
12029 /* get "to" into DPTR */
12030 /* if the operand is already in dptr
12031 then we do nothing else we move the value to dptr */
12032 if (AOP_TYPE (to) != AOP_STR) {
12033 /* if already in DPTR then we need to push */
12034 if (AOP_TYPE(to) == AOP_DPTR) {
12035 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12036 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12037 if (options.model == MODEL_FLAT24)
12038 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12039 emitcode ("pop", "dph");
12040 emitcode ("pop", "dpl");
12042 _startLazyDPSEvaluation ();
12043 /* if this is remateriazable */
12044 if (AOP_TYPE (to) == AOP_IMMD) {
12045 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12046 } else { /* we need to get it byte by byte */
12047 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12048 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12049 if (options.model == MODEL_FLAT24) {
12050 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12053 _endLazyDPSEvaluation ();
12056 freeAsmop (to, NULL, ic, FALSE);
12057 _G.dptrInUse = _G.dptr1InUse = 1;
12058 aopOp (count, ic->next->next, FALSE,FALSE);
12059 lbl =newiTempLabel(NULL);
12060 lbl2 =newiTempLabel(NULL);
12062 /* now for the actual compare */
12063 if (AOP_TYPE(count) == AOP_LIT &&
12064 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12065 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12067 emitcode("lcall","__bi_memcmpc2x_s");
12069 emitcode("lcall","__bi_memcmpx2x_s");
12070 freeAsmop (count, NULL, ic, FALSE);
12071 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12072 aopPut(AOP(IC_RESULT(ic)),"a",0);
12073 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12075 symbol *lbl1 = newiTempLabel(NULL);
12077 emitcode("push","ar0");
12078 emitcode (";"," Auto increment but no djnz");
12079 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12080 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12081 freeAsmop (count, NULL, ic, FALSE);
12082 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12083 emitcode ("","!tlabeldef",lbl->key+100);
12085 emitcode ("clr","a");
12086 emitcode ("movc", "a,@a+dptr");
12088 emitcode ("movx", "a,@dptr");
12089 emitcode ("mov","r0,a");
12090 emitcode ("movx", "a,@dptr");
12091 emitcode ("clr","c");
12092 emitcode ("subb","a,r0");
12093 emitcode ("jnz","!tlabel",lbl2->key+100);
12094 emitcode ("inc", "dptr");
12095 emitcode ("inc", "dptr");
12096 emitcode ("mov","a,b");
12097 emitcode ("orl","a,_ap");
12098 emitcode ("jz","!tlabel",lbl1->key+100);
12099 emitcode ("mov","a,_ap");
12100 emitcode ("add","a,#!constbyte",0xFF);
12101 emitcode ("mov","_ap,a");
12102 emitcode ("mov","a,b");
12103 emitcode ("addc","a,#!constbyte",0xFF);
12104 emitcode ("mov","b,a");
12105 emitcode ("sjmp","!tlabel",lbl->key+100);
12106 emitcode ("","!tlabeldef",lbl1->key+100);
12107 emitcode ("clr","a");
12108 emitcode ("","!tlabeldef",lbl2->key+100);
12109 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12110 aopPut(AOP(IC_RESULT(ic)),"a",0);
12111 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12112 emitcode("pop","ar0");
12113 emitcode ("mov", "dps,#0");
12115 _G.dptrInUse = _G.dptr1InUse = 0;
12116 unsavermask(rsave);
12120 /*-----------------------------------------------------------------*/
12121 /* genInp - gen code for __builtin_inp read data from a mem mapped */
12122 /* port, first parameter output area second parameter pointer to */
12123 /* port third parameter count */
12124 /*-----------------------------------------------------------------*/
12125 static void genInp( iCode *ic, int nparms, operand **parms)
12127 operand *from , *to , *count;
12132 /* we know it has to be 3 parameters */
12133 assert (nparms == 3);
12135 rsave = newBitVect(16);
12136 /* save DPTR if it needs to be saved */
12137 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12138 if (bitVectBitValue(ic->rMask,i))
12139 rsave = bitVectSetBit(rsave,i);
12141 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12142 ds390_rUmaskForOp (IC_RESULT(ic))));
12149 aopOp (from, ic->next, FALSE, FALSE);
12151 /* get from into DPTR1 */
12152 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12153 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12154 if (options.model == MODEL_FLAT24) {
12155 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12158 freeAsmop (from, NULL, ic, FALSE);
12159 aopOp (to, ic, FALSE, FALSE);
12160 /* get "to" into DPTR */
12161 /* if the operand is already in dptr
12162 then we do nothing else we move the value to dptr */
12163 if (AOP_TYPE (to) != AOP_STR) {
12164 /* if already in DPTR then we need to push */
12165 if (AOP_TYPE(to) == AOP_DPTR) {
12166 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12167 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12168 if (options.model == MODEL_FLAT24)
12169 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12170 emitcode ("pop", "dph");
12171 emitcode ("pop", "dpl");
12173 _startLazyDPSEvaluation ();
12174 /* if this is remateriazable */
12175 if (AOP_TYPE (to) == AOP_IMMD) {
12176 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12177 } else { /* we need to get it byte by byte */
12178 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12179 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12180 if (options.model == MODEL_FLAT24) {
12181 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12184 _endLazyDPSEvaluation ();
12187 freeAsmop (to, NULL, ic, FALSE);
12189 _G.dptrInUse = _G.dptr1InUse = 1;
12190 aopOp (count, ic->next->next, FALSE,FALSE);
12191 lbl =newiTempLabel(NULL);
12193 /* now for the actual copy */
12194 if (AOP_TYPE(count) == AOP_LIT &&
12195 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12196 emitcode (";","OH JOY auto increment with djnz (very fast)");
12197 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
12198 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12199 freeAsmop (count, NULL, ic, FALSE);
12200 emitcode ("","!tlabeldef",lbl->key+100);
12201 emitcode ("movx", "a,@dptr"); /* read data from port */
12202 emitcode ("dec","dps"); /* switch to DPTR */
12203 emitcode ("movx", "@dptr,a"); /* save into location */
12204 emitcode ("inc", "dptr"); /* point to next area */
12205 emitcode ("inc","dps"); /* switch to DPTR2 */
12206 emitcode ("djnz","b,!tlabel",lbl->key+100);
12208 symbol *lbl1 = newiTempLabel(NULL);
12210 emitcode (";"," Auto increment but no djnz");
12211 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12212 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12213 freeAsmop (count, NULL, ic, FALSE);
12214 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
12215 emitcode ("","!tlabeldef",lbl->key+100);
12216 emitcode ("movx", "a,@dptr");
12217 emitcode ("dec","dps"); /* switch to DPTR */
12218 emitcode ("movx", "@dptr,a");
12219 emitcode ("inc", "dptr");
12220 emitcode ("inc","dps"); /* switch to DPTR2 */
12221 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
12222 /* emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
12223 emitcode ("mov","a,b");
12224 emitcode ("orl","a,_ap");
12225 emitcode ("jz","!tlabel",lbl1->key+100);
12226 emitcode ("mov","a,_ap");
12227 emitcode ("add","a,#!constbyte",0xFF);
12228 emitcode ("mov","_ap,a");
12229 emitcode ("mov","a,b");
12230 emitcode ("addc","a,#!constbyte",0xFF);
12231 emitcode ("mov","b,a");
12232 emitcode ("sjmp","!tlabel",lbl->key+100);
12233 emitcode ("","!tlabeldef",lbl1->key+100);
12235 emitcode ("mov", "dps,#0");
12236 _G.dptrInUse = _G.dptr1InUse = 0;
12237 unsavermask(rsave);
12241 /*-----------------------------------------------------------------*/
12242 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
12243 /* port, first parameter output area second parameter pointer to */
12244 /* port third parameter count */
12245 /*-----------------------------------------------------------------*/
12246 static void genOutp( iCode *ic, int nparms, operand **parms)
12248 operand *from , *to , *count;
12253 /* we know it has to be 3 parameters */
12254 assert (nparms == 3);
12256 rsave = newBitVect(16);
12257 /* save DPTR if it needs to be saved */
12258 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12259 if (bitVectBitValue(ic->rMask,i))
12260 rsave = bitVectSetBit(rsave,i);
12262 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12263 ds390_rUmaskForOp (IC_RESULT(ic))));
12270 aopOp (from, ic->next, FALSE, FALSE);
12272 /* get from into DPTR1 */
12273 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12274 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12275 if (options.model == MODEL_FLAT24) {
12276 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12279 freeAsmop (from, NULL, ic, FALSE);
12280 aopOp (to, ic, FALSE, FALSE);
12281 /* get "to" into DPTR */
12282 /* if the operand is already in dptr
12283 then we do nothing else we move the value to dptr */
12284 if (AOP_TYPE (to) != AOP_STR) {
12285 /* if already in DPTR then we need to push */
12286 if (AOP_TYPE(to) == AOP_DPTR) {
12287 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12288 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12289 if (options.model == MODEL_FLAT24)
12290 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12291 emitcode ("pop", "dph");
12292 emitcode ("pop", "dpl");
12294 _startLazyDPSEvaluation ();
12295 /* if this is remateriazable */
12296 if (AOP_TYPE (to) == AOP_IMMD) {
12297 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12298 } else { /* we need to get it byte by byte */
12299 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12300 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12301 if (options.model == MODEL_FLAT24) {
12302 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12305 _endLazyDPSEvaluation ();
12308 freeAsmop (to, NULL, ic, FALSE);
12310 _G.dptrInUse = _G.dptr1InUse = 1;
12311 aopOp (count, ic->next->next, FALSE,FALSE);
12312 lbl =newiTempLabel(NULL);
12314 /* now for the actual copy */
12315 if (AOP_TYPE(count) == AOP_LIT &&
12316 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12317 emitcode (";","OH JOY auto increment with djnz (very fast)");
12318 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
12319 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12320 emitcode ("","!tlabeldef",lbl->key+100);
12321 emitcode ("movx", "a,@dptr"); /* read data from port */
12322 emitcode ("inc","dps"); /* switch to DPTR2 */
12323 emitcode ("movx", "@dptr,a"); /* save into location */
12324 emitcode ("inc", "dptr"); /* point to next area */
12325 emitcode ("dec","dps"); /* switch to DPTR */
12326 emitcode ("djnz","b,!tlabel",lbl->key+100);
12327 freeAsmop (count, NULL, ic, FALSE);
12329 symbol *lbl1 = newiTempLabel(NULL);
12331 emitcode (";"," Auto increment but no djnz");
12332 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12333 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12334 freeAsmop (count, NULL, ic, FALSE);
12335 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
12336 emitcode ("","!tlabeldef",lbl->key+100);
12337 emitcode ("movx", "a,@dptr");
12338 emitcode ("inc", "dptr");
12339 emitcode ("inc","dps"); /* switch to DPTR2 */
12340 emitcode ("movx", "@dptr,a");
12341 emitcode ("dec","dps"); /* switch to DPTR */
12342 emitcode ("mov","a,b");
12343 emitcode ("orl","a,_ap");
12344 emitcode ("jz","!tlabel",lbl1->key+100);
12345 emitcode ("mov","a,_ap");
12346 emitcode ("add","a,#!constbyte",0xFF);
12347 emitcode ("mov","_ap,a");
12348 emitcode ("mov","a,b");
12349 emitcode ("addc","a,#!constbyte",0xFF);
12350 emitcode ("mov","b,a");
12351 emitcode ("sjmp","!tlabel",lbl->key+100);
12352 emitcode ("","!tlabeldef",lbl1->key+100);
12354 emitcode ("mov", "dps,#0");
12355 _G.dptrInUse = _G.dptr1InUse = 0;
12356 unsavermask(rsave);
12360 /*-----------------------------------------------------------------*/
12361 /* genSwapW - swap lower & high order bytes */
12362 /*-----------------------------------------------------------------*/
12363 static void genSwapW(iCode *ic, int nparms, operand **parms)
12367 assert (nparms==1);
12370 dest=IC_RESULT(ic);
12372 assert(getSize(operandType(src))==2);
12374 aopOp (src, ic, FALSE, FALSE);
12375 emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
12377 MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
12379 freeAsmop (src, NULL, ic, FALSE);
12381 aopOp (dest,ic, FALSE, FALSE);
12382 aopPut(AOP(dest),"b",0);
12383 aopPut(AOP(dest),"a",1);
12384 freeAsmop (dest, NULL, ic, FALSE);
12387 /*-----------------------------------------------------------------*/
12388 /* genMemsetX - gencode for memSetX data */
12389 /*-----------------------------------------------------------------*/
12390 static void genMemsetX(iCode *ic, int nparms, operand **parms)
12392 operand *to , *val , *count;
12398 /* we know it has to be 3 parameters */
12399 assert (nparms == 3);
12405 /* save DPTR if it needs to be saved */
12406 rsave = newBitVect(16);
12407 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12408 if (bitVectBitValue(ic->rMask,i))
12409 rsave = bitVectSetBit(rsave,i);
12411 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12412 ds390_rUmaskForOp (IC_RESULT(ic))));
12415 aopOp (to, ic, FALSE, FALSE);
12416 /* get "to" into DPTR */
12417 /* if the operand is already in dptr
12418 then we do nothing else we move the value to dptr */
12419 if (AOP_TYPE (to) != AOP_STR) {
12420 /* if already in DPTR then we need to push */
12421 if (AOP_TYPE(to) == AOP_DPTR) {
12422 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12423 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12424 if (options.model == MODEL_FLAT24)
12425 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12426 emitcode ("pop", "dph");
12427 emitcode ("pop", "dpl");
12429 _startLazyDPSEvaluation ();
12430 /* if this is remateriazable */
12431 if (AOP_TYPE (to) == AOP_IMMD) {
12432 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12433 } else { /* we need to get it byte by byte */
12434 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12435 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12436 if (options.model == MODEL_FLAT24) {
12437 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12440 _endLazyDPSEvaluation ();
12443 freeAsmop (to, NULL, ic, FALSE);
12445 aopOp (val, ic->next->next, FALSE,FALSE);
12446 aopOp (count, ic->next->next, FALSE,FALSE);
12447 lbl =newiTempLabel(NULL);
12448 /* now for the actual copy */
12449 if (AOP_TYPE(count) == AOP_LIT &&
12450 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12451 l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
12452 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12454 emitcode ("","!tlabeldef",lbl->key+100);
12455 emitcode ("movx", "@dptr,a");
12456 emitcode ("inc", "dptr");
12457 emitcode ("djnz","b,!tlabel",lbl->key+100);
12459 symbol *lbl1 = newiTempLabel(NULL);
12461 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12462 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12463 emitcode ("","!tlabeldef",lbl->key+100);
12464 MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
12465 emitcode ("movx", "@dptr,a");
12466 emitcode ("inc", "dptr");
12467 emitcode ("mov","a,b");
12468 emitcode ("orl","a,_ap");
12469 emitcode ("jz","!tlabel",lbl1->key+100);
12470 emitcode ("mov","a,_ap");
12471 emitcode ("add","a,#!constbyte",0xFF);
12472 emitcode ("mov","_ap,a");
12473 emitcode ("mov","a,b");
12474 emitcode ("addc","a,#!constbyte",0xFF);
12475 emitcode ("mov","b,a");
12476 emitcode ("sjmp","!tlabel",lbl->key+100);
12477 emitcode ("","!tlabeldef",lbl1->key+100);
12479 freeAsmop (count, NULL, ic, FALSE);
12480 unsavermask(rsave);
12483 /*-----------------------------------------------------------------*/
12484 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
12485 /*-----------------------------------------------------------------*/
12486 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
12489 operand *pnum, *result;
12492 assert (nparms==1);
12493 /* save registers that need to be saved */
12494 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12495 ds390_rUmaskForOp (IC_RESULT(ic))));
12498 aopOp (pnum, ic, FALSE, FALSE);
12499 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12500 freeAsmop (pnum, NULL, ic, FALSE);
12501 emitcode ("lcall","NatLib_LoadPrimitive");
12502 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12503 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
12504 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
12505 for (i = (size-1) ; i >= 0 ; i-- ) {
12506 emitcode ("push","a%s",javaRet[i]);
12508 for (i=0; i < size ; i++ ) {
12509 emitcode ("pop","a%s",
12510 aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
12513 for (i = 0 ; i < size ; i++ ) {
12514 aopPut(AOP(result),javaRet[i],i);
12517 freeAsmop (result, NULL, ic, FALSE);
12518 unsavermask(rsave);
12521 /*-----------------------------------------------------------------*/
12522 /* genNatLibLoadPointer - calls TINI api function to load pointer */
12523 /*-----------------------------------------------------------------*/
12524 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
12527 operand *pnum, *result;
12531 assert (nparms==1);
12532 /* save registers that need to be saved */
12533 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12534 ds390_rUmaskForOp (IC_RESULT(ic))));
12537 aopOp (pnum, ic, FALSE, FALSE);
12538 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12539 freeAsmop (pnum, NULL, ic, FALSE);
12540 emitcode ("lcall","NatLib_LoadPointer");
12541 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12542 if (AOP_TYPE(result)!=AOP_STR) {
12543 for (i = 0 ; i < size ; i++ ) {
12544 aopPut(AOP(result),fReturn[i],i);
12547 freeAsmop (result, NULL, ic, FALSE);
12548 unsavermask(rsave);
12551 /*-----------------------------------------------------------------*/
12552 /* genNatLibInstallStateBlock - */
12553 /*-----------------------------------------------------------------*/
12554 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
12555 operand **parms, const char *name)
12558 operand *psb, *handle;
12559 assert (nparms==2);
12561 /* save registers that need to be saved */
12562 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12563 ds390_rUmaskForOp (IC_RESULT(ic))));
12567 /* put pointer to state block into DPTR1 */
12568 aopOp (psb, ic, FALSE, FALSE);
12569 if (AOP_TYPE (psb) == AOP_IMMD) {
12570 emitcode ("mov","dps,#1");
12571 emitcode ("mov", "dptr,%s",
12572 aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12573 emitcode ("mov","dps,#0");
12575 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12576 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12577 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12579 freeAsmop (psb, NULL, ic, FALSE);
12581 /* put libraryID into DPTR */
12582 emitcode ("mov","dptr,#LibraryID");
12584 /* put handle into r3:r2 */
12585 aopOp (handle, ic, FALSE, FALSE);
12586 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12587 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12588 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12589 emitcode ("pop","ar3");
12590 emitcode ("pop","ar2");
12592 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12593 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12595 freeAsmop (psb, NULL, ic, FALSE);
12597 /* make the call */
12598 emitcode ("lcall","NatLib_Install%sStateBlock",name);
12600 /* put return value into place*/
12602 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12604 aopPut(AOP(IC_RESULT(ic)),"a",0);
12605 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12606 unsavermask(rsave);
12609 /*-----------------------------------------------------------------*/
12610 /* genNatLibRemoveStateBlock - */
12611 /*-----------------------------------------------------------------*/
12612 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12618 /* save registers that need to be saved */
12619 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12620 ds390_rUmaskForOp (IC_RESULT(ic))));
12622 /* put libraryID into DPTR */
12623 emitcode ("mov","dptr,#LibraryID");
12624 /* make the call */
12625 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12626 unsavermask(rsave);
12629 /*-----------------------------------------------------------------*/
12630 /* genNatLibGetStateBlock - */
12631 /*-----------------------------------------------------------------*/
12632 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12633 operand **parms,const char *name)
12636 symbol *lbl = newiTempLabel(NULL);
12639 /* save registers that need to be saved */
12640 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12641 ds390_rUmaskForOp (IC_RESULT(ic))));
12643 /* put libraryID into DPTR */
12644 emitcode ("mov","dptr,#LibraryID");
12645 /* make the call */
12646 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12647 emitcode ("jnz","!tlabel",lbl->key+100);
12649 /* put return value into place */
12650 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12651 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12652 emitcode ("push","ar3");
12653 emitcode ("push","ar2");
12654 emitcode ("pop","%s",
12655 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12656 emitcode ("pop","%s",
12657 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12659 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12660 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12662 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12663 emitcode ("","!tlabeldef",lbl->key+100);
12664 unsavermask(rsave);
12667 /*-----------------------------------------------------------------*/
12668 /* genMMMalloc - */
12669 /*-----------------------------------------------------------------*/
12670 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12671 int size, const char *name)
12676 symbol *lbl = newiTempLabel(NULL);
12678 assert (nparms == 1);
12679 /* save registers that need to be saved */
12680 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12681 ds390_rUmaskForOp (IC_RESULT(ic))));
12684 aopOp (bsize,ic,FALSE,FALSE);
12686 /* put the size in R4-R2 */
12687 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12688 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12689 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12691 emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12692 emitcode("pop","ar4");
12694 emitcode("pop","ar3");
12695 emitcode("pop","ar2");
12697 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12698 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12700 emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12703 freeAsmop (bsize, NULL, ic, FALSE);
12705 /* make the call */
12706 emitcode ("lcall","MM_%s",name);
12707 emitcode ("jz","!tlabel",lbl->key+100);
12708 emitcode ("mov","r2,#!constbyte",0xff);
12709 emitcode ("mov","r3,#!constbyte",0xff);
12710 emitcode ("","!tlabeldef",lbl->key+100);
12711 /* we don't care about the pointer : we just save the handle */
12712 rsym = OP_SYMBOL(IC_RESULT(ic));
12713 if (rsym->liveFrom != rsym->liveTo) {
12714 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12715 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12716 emitcode ("push","ar3");
12717 emitcode ("push","ar2");
12718 emitcode ("pop","%s",
12719 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12720 emitcode ("pop","%s",
12721 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12723 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12724 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12726 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12728 unsavermask(rsave);
12731 /*-----------------------------------------------------------------*/
12733 /*-----------------------------------------------------------------*/
12734 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12739 assert (nparms == 1);
12740 /* save registers that need to be saved */
12741 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12742 ds390_rUmaskForOp (IC_RESULT(ic))));
12745 aopOp (handle,ic,FALSE,FALSE);
12747 /* put the size in R4-R2 */
12748 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12749 emitcode("push","%s",
12750 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12751 emitcode("push","%s",
12752 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12753 emitcode("pop","ar3");
12754 emitcode("pop","ar2");
12756 emitcode ("mov","r2,%s",
12757 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12758 emitcode ("mov","r3,%s",
12759 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12761 freeAsmop (handle, NULL, ic, FALSE);
12763 /* make the call */
12764 emitcode ("lcall","MM_Deref");
12767 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12768 if (rsym->liveFrom != rsym->liveTo) {
12769 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12770 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12771 _startLazyDPSEvaluation ();
12773 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12774 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12775 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12777 _endLazyDPSEvaluation ();
12782 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12783 unsavermask(rsave);
12786 /*-----------------------------------------------------------------*/
12787 /* genMMUnrestrictedPersist - */
12788 /*-----------------------------------------------------------------*/
12789 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12794 assert (nparms == 1);
12795 /* save registers that need to be saved */
12796 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12797 ds390_rUmaskForOp (IC_RESULT(ic))));
12800 aopOp (handle,ic,FALSE,FALSE);
12802 /* put the size in R3-R2 */
12803 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12804 emitcode("push","%s",
12805 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12806 emitcode("push","%s",
12807 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12808 emitcode("pop","ar3");
12809 emitcode("pop","ar2");
12811 emitcode ("mov","r2,%s",
12812 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12813 emitcode ("mov","r3,%s",
12814 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12816 freeAsmop (handle, NULL, ic, FALSE);
12818 /* make the call */
12819 emitcode ("lcall","MM_UnrestrictedPersist");
12822 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12823 if (rsym->liveFrom != rsym->liveTo) {
12824 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12825 aopPut(AOP(IC_RESULT(ic)),"a",0);
12826 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12829 unsavermask(rsave);
12832 /*-----------------------------------------------------------------*/
12833 /* genSystemExecJavaProcess - */
12834 /*-----------------------------------------------------------------*/
12835 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12838 operand *handle, *pp;
12840 assert (nparms==2);
12841 /* save registers that need to be saved */
12842 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12843 ds390_rUmaskForOp (IC_RESULT(ic))));
12848 /* put the handle in R3-R2 */
12849 aopOp (handle,ic,FALSE,FALSE);
12850 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12851 emitcode("push","%s",
12852 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12853 emitcode("push","%s",
12854 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12855 emitcode("pop","ar3");
12856 emitcode("pop","ar2");
12858 emitcode ("mov","r2,%s",
12859 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12860 emitcode ("mov","r3,%s",
12861 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12863 freeAsmop (handle, NULL, ic, FALSE);
12865 /* put pointer in DPTR */
12866 aopOp (pp,ic,FALSE,FALSE);
12867 if (AOP_TYPE(pp) == AOP_IMMD) {
12868 emitcode ("mov", "dptr,%s",
12869 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12870 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12871 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12872 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12873 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12875 freeAsmop (handle, NULL, ic, FALSE);
12877 /* make the call */
12878 emitcode ("lcall","System_ExecJavaProcess");
12880 /* put result in place */
12882 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12883 if (rsym->liveFrom != rsym->liveTo) {
12884 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12885 aopPut(AOP(IC_RESULT(ic)),"a",0);
12886 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12890 unsavermask(rsave);
12893 /*-----------------------------------------------------------------*/
12894 /* genSystemRTCRegisters - */
12895 /*-----------------------------------------------------------------*/
12896 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12902 assert (nparms==1);
12903 /* save registers that need to be saved */
12904 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12905 ds390_rUmaskForOp (IC_RESULT(ic))));
12908 /* put pointer in DPTR */
12909 aopOp (pp,ic,FALSE,FALSE);
12910 if (AOP_TYPE (pp) == AOP_IMMD) {
12911 emitcode ("mov","dps,#1");
12912 emitcode ("mov", "dptr,%s",
12913 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12914 emitcode ("mov","dps,#0");
12916 emitcode ("mov","dpl1,%s",
12917 aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12918 emitcode ("mov","dph1,%s",
12919 aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12920 emitcode ("mov","dpx1,%s",
12921 aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12923 freeAsmop (pp, NULL, ic, FALSE);
12925 /* make the call */
12926 emitcode ("lcall","System_%sRTCRegisters",name);
12928 unsavermask(rsave);
12931 /*-----------------------------------------------------------------*/
12932 /* genSystemThreadSleep - */
12933 /*-----------------------------------------------------------------*/
12934 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12939 assert (nparms==1);
12940 /* save registers that need to be saved */
12941 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12942 ds390_rUmaskForOp (IC_RESULT(ic))));
12945 aopOp(to,ic,FALSE,FALSE);
12946 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12947 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12948 emitcode ("push","%s",
12949 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12950 emitcode ("push","%s",
12951 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12952 emitcode ("push","%s",
12953 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12954 emitcode ("push","%s",
12955 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12956 emitcode ("pop","ar3");
12957 emitcode ("pop","ar2");
12958 emitcode ("pop","ar1");
12959 emitcode ("pop","ar0");
12961 emitcode ("mov","r0,%s",
12962 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12963 emitcode ("mov","r1,%s",
12964 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12965 emitcode ("mov","r2,%s",
12966 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12967 emitcode ("mov","r3,%s",
12968 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12970 freeAsmop (to, NULL, ic, FALSE);
12972 /* suspend in acc */
12974 aopOp(s,ic,FALSE,FALSE);
12975 emitcode ("mov","a,%s",
12976 aopGet(AOP(s),0,FALSE,TRUE,NULL));
12977 freeAsmop (s, NULL, ic, FALSE);
12979 /* make the call */
12980 emitcode ("lcall","System_%s",name);
12982 unsavermask(rsave);
12985 /*-----------------------------------------------------------------*/
12986 /* genSystemThreadResume - */
12987 /*-----------------------------------------------------------------*/
12988 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12993 assert (nparms==2);
12994 /* save registers that need to be saved */
12995 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12996 ds390_rUmaskForOp (IC_RESULT(ic))));
13002 aopOp(pid,ic,FALSE,FALSE);
13003 emitcode ("mov","r0,%s",
13004 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
13005 freeAsmop (pid, NULL, ic, FALSE);
13008 aopOp(tid,ic,FALSE,FALSE);
13009 emitcode ("mov","a,%s",
13010 aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
13011 freeAsmop (tid, NULL, ic, FALSE);
13013 emitcode ("lcall","System_ThreadResume");
13015 /* put result into place */
13017 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13018 if (rsym->liveFrom != rsym->liveTo) {
13019 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13020 aopPut(AOP(IC_RESULT(ic)),"a",0);
13021 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13024 unsavermask(rsave);
13027 /*-----------------------------------------------------------------*/
13028 /* genSystemProcessResume - */
13029 /*-----------------------------------------------------------------*/
13030 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
13035 assert (nparms==1);
13036 /* save registers that need to be saved */
13037 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13038 ds390_rUmaskForOp (IC_RESULT(ic))));
13043 aopOp(pid,ic,FALSE,FALSE);
13044 emitcode ("mov","a,%s",
13045 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
13046 freeAsmop (pid, NULL, ic, FALSE);
13048 emitcode ("lcall","System_ProcessResume");
13050 unsavermask(rsave);
13053 /*-----------------------------------------------------------------*/
13055 /*-----------------------------------------------------------------*/
13056 static void genSystem (iCode *ic,int nparms,char *name)
13058 assert(nparms == 0);
13060 emitcode ("lcall","System_%s",name);
13063 /*-----------------------------------------------------------------*/
13064 /* genSystemPoll - */
13065 /*-----------------------------------------------------------------*/
13066 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
13071 assert (nparms==1);
13072 /* save registers that need to be saved */
13073 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13074 ds390_rUmaskForOp (IC_RESULT(ic))));
13077 aopOp (fp,ic,FALSE,FALSE);
13078 if (AOP_TYPE (fp) == AOP_IMMD) {
13079 emitcode ("mov", "dptr,%s",
13080 aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
13081 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
13082 emitcode ("mov","dpl,%s",
13083 aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
13084 emitcode ("mov","dph,%s",
13085 aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
13086 emitcode ("mov","dpx,%s",
13087 aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
13089 freeAsmop (fp, NULL, ic, FALSE);
13091 emitcode ("lcall","System_%sPoll",name);
13093 /* put result into place */
13095 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13096 if (rsym->liveFrom != rsym->liveTo) {
13097 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13098 aopPut(AOP(IC_RESULT(ic)),"a",0);
13099 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13102 unsavermask(rsave);
13105 /*-----------------------------------------------------------------*/
13106 /* genSystemGetCurrentID - */
13107 /*-----------------------------------------------------------------*/
13108 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
13110 assert (nparms==0);
13112 emitcode ("lcall","System_GetCurrent%sId",name);
13113 /* put result into place */
13115 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13116 if (rsym->liveFrom != rsym->liveTo) {
13117 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13118 aopPut(AOP(IC_RESULT(ic)),"a",0);
13119 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13124 /*-----------------------------------------------------------------*/
13125 /* genDummyRead - generate code for dummy read of volatiles */
13126 /*-----------------------------------------------------------------*/
13128 genDummyRead (iCode * ic)
13133 D(emitcode("; genDummyRead",""));
13135 op = IC_RIGHT (ic);
13136 if (op && IS_SYMOP (op))
13138 aopOp (op, ic, FALSE, FALSE);
13140 /* if the result is a bit */
13141 if (AOP_TYPE (op) == AOP_CRY)
13142 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13145 /* bit variables done */
13147 size = AOP_SIZE (op);
13151 MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
13156 freeAsmop (op, NULL, ic, TRUE);
13160 if (op && IS_SYMOP (op))
13162 aopOp (op, ic, FALSE, FALSE);
13164 /* if the result is a bit */
13165 if (AOP_TYPE (op) == AOP_CRY)
13166 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13169 /* bit variables done */
13171 size = AOP_SIZE (op);
13175 MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
13180 freeAsmop (op, NULL, ic, TRUE);
13185 /*-----------------------------------------------------------------*/
13186 /* genCritical - generate code for start of a critical sequence */
13187 /*-----------------------------------------------------------------*/
13189 genCritical (iCode *ic)
13191 symbol *tlbl = newiTempLabel (NULL);
13193 D(emitcode("; genCritical",""));
13195 if (IC_RESULT (ic))
13196 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
13198 emitcode ("setb", "c");
13199 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
13200 emitcode ("clr", "c");
13201 emitcode ("", "%05d$:", (tlbl->key + 100));
13203 if (IC_RESULT (ic))
13204 outBitC (IC_RESULT (ic)); /* save old ea in an operand */
13206 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
13208 if (IC_RESULT (ic))
13209 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13212 /*-----------------------------------------------------------------*/
13213 /* genEndCritical - generate code for end of a critical sequence */
13214 /*-----------------------------------------------------------------*/
13216 genEndCritical (iCode *ic)
13218 D(emitcode("; genEndCritical",""));
13222 aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
13223 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
13225 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
13226 emitcode ("mov", "ea,c");
13230 MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE, FALSE));
13231 emitcode ("rrc", "a");
13232 emitcode ("mov", "ea,c");
13234 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
13238 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
13239 emitcode ("mov", "ea,c");
13245 /*-----------------------------------------------------------------*/
13246 /* genBuiltIn - calls the appropriate function to generating code */
13247 /* for a built in function */
13248 /*-----------------------------------------------------------------*/
13249 static void genBuiltIn (iCode *ic)
13251 operand *bi_parms[MAX_BUILTIN_ARGS];
13256 /* get all the arguments for a built in function */
13257 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
13259 /* which function is it */
13260 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
13261 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
13262 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
13263 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
13264 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
13265 } else if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
13266 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
13267 } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
13268 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
13269 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
13270 genMemsetX(bi_iCode,nbi_parms,bi_parms);
13271 } else if (strcmp(bif->name,"__builtin_inp")==0) {
13272 genInp(bi_iCode,nbi_parms,bi_parms);
13273 } else if (strcmp(bif->name,"__builtin_outp")==0) {
13274 genOutp(bi_iCode,nbi_parms,bi_parms);
13275 } else if (strcmp(bif->name,"__builtin_swapw")==0) {
13276 genSwapW(bi_iCode,nbi_parms,bi_parms);
13277 /* JavaNative builtIns */
13278 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
13279 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
13280 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
13281 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
13282 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
13283 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
13284 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
13285 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
13286 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
13287 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
13288 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
13289 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
13290 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
13291 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
13292 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
13293 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
13294 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
13295 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
13296 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
13297 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
13298 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
13299 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
13300 } else if (strcmp(bif->name,"MM_Malloc")==0) {
13301 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
13302 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
13303 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
13304 } else if (strcmp(bif->name,"MM_Free")==0) {
13305 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
13306 } else if (strcmp(bif->name,"MM_Deref")==0) {
13307 genMMDeref(bi_iCode,nbi_parms,bi_parms);
13308 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
13309 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
13310 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
13311 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
13312 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
13313 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
13314 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
13315 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
13316 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
13317 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
13318 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
13319 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
13320 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
13321 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
13322 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
13323 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
13324 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
13325 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13326 } else if (strcmp(bif->name,"System_SaveThread")==0) {
13327 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13328 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
13329 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13330 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
13331 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
13332 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
13333 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
13334 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
13335 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
13336 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
13337 genSystem(bi_iCode,nbi_parms,"ProcessYield");
13338 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
13339 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
13340 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
13341 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
13342 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
13343 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
13344 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
13345 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
13346 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
13347 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
13349 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
13355 /*-----------------------------------------------------------------*/
13356 /* gen390Code - generate code for Dallas 390 based controllers */
13357 /*-----------------------------------------------------------------*/
13359 gen390Code (iCode * lic)
13364 lineHead = lineCurr = NULL;
13365 dptrn[1][0] = "dpl1";
13366 dptrn[1][1] = "dph1";
13367 dptrn[1][2] = "dpx1";
13369 if (options.model == MODEL_FLAT24) {
13370 fReturnSizeDS390 = 5;
13371 fReturn = fReturn24;
13373 fReturnSizeDS390 = 4;
13374 fReturn = fReturn16;
13375 options.stack10bit=0;
13378 /* print the allocation information */
13379 if (allocInfo && currFunc)
13380 printAllocInfo (currFunc, codeOutFile);
13382 /* if debug information required */
13383 if (options.debug && currFunc)
13385 debugFile->writeFunction (currFunc, lic);
13387 /* stack pointer name */
13388 if (options.useXstack)
13394 for (ic = lic; ic; ic = ic->next)
13397 _G.current_iCode = ic;
13399 if (ic->lineno && cln != ic->lineno)
13403 debugFile->writeCLine (ic);
13405 if (!options.noCcodeInAsm) {
13406 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
13407 printCLine(ic->filename, ic->lineno));
13411 if (options.iCodeInAsm) {
13412 emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
13414 /* if the result is marked as
13415 spilt and rematerializable or code for
13416 this has already been generated then
13418 if (resultRemat (ic) || ic->generated)
13421 /* depending on the operation */
13441 /* IPOP happens only when trying to restore a
13442 spilt live range, if there is an ifx statement
13443 following this pop then the if statement might
13444 be using some of the registers being popped which
13445 would destory the contents of the register so
13446 we need to check for this condition and handle it */
13448 ic->next->op == IFX &&
13449 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
13450 genIfx (ic->next, ic);
13468 genEndFunction (ic);
13488 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
13505 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
13509 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
13516 /* note these two are xlated by algebraic equivalence
13517 during parsing SDCC.y */
13518 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
13519 "got '>=' or '<=' shouldn't have come here");
13523 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
13535 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
13539 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
13543 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
13567 genRightShift (ic);
13570 case GET_VALUE_AT_ADDRESS:
13571 genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
13575 if (POINTER_SET (ic))
13576 genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
13602 if (ic->builtinSEND) genBuiltIn(ic);
13603 else addSet (&_G.sendSet, ic);
13606 case DUMMY_READ_VOLATILE:
13615 genEndCritical (ic);
13622 #if 0 // obsolete, and buggy for != xdata
13634 /* now we are ready to call the
13635 peep hole optimizer */
13636 if (!options.nopeep)
13637 peepHole (&lineHead);
13639 /* now do the actual printing */
13640 printLine (lineHead, codeOutFile);