1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for DS80C390
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7 DS390 adaptation by Kevin Vigor <kevin@vigor.nu>
9 This program is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 2, or (at your option) any
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 In other words, you are welcome to use, share and improve this program.
24 You are forbidden to forbid anyone else to use, share and improve
25 what you give them. Help stamp out software-hoarding!
26 -------------------------------------------------------------------------*/
36 #include "SDCCglobl.h"
39 #ifdef HAVE_SYS_ISA_DEFS_H
40 #include <sys/isa_defs.h>
42 #ifdef HAVE_MACHINE_ENDIAN_H
43 #include <machine/endian.h>
48 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
49 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
50 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
56 #define BETTER_LITERAL_SHIFT
58 char *aopLiteral (value * val, int offset);
61 /* this is the down and dirty file with all kinds of
62 kludgy & hacky stuff. This is what it is all about
63 CODE GENERATION for a specific MCU . some of the
64 routines may be reusable, will have to see */
66 static char *zero = "#0";
67 static char *one = "#1";
72 #define TR_DPTR(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_DPTR1 %s ", s); }
73 #define TR_AP(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_AP %s ", s); }
75 unsigned fReturnSizeDS390 = 5; /* shared with ralloc.c */
76 static char *fReturn24[] =
77 {"dpl", "dph", "dpx", "b", "a"};
78 static char *fReturn16[] =
79 {"dpl", "dph", "b", "a"};
80 static char **fReturn = fReturn24;
81 static char *accUse[] =
83 static char *dptrn[2][3];
84 static char *javaRet[] = { "r0","r1","r2","r3"};
85 static short rbank = -1;
102 static char *rb1regs[] = {
103 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
106 static void saveRBank (int, iCode *, bool);
108 #define RESULTONSTACK(x) \
109 (IC_RESULT(x) && IC_RESULT(x)->aop && \
110 IC_RESULT(x)->aop->type == AOP_STK )
112 /* #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x); */
114 char *_mova_tmp = strdup(x); \
115 if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \
117 emitcode("mov","a,%s",_mova_tmp); \
121 #define MOVB(x) { char *_movb_tmp = strdup(x); \
122 if (strcmp(_movb_tmp,"b")) \
124 emitcode("mov","b,%s",_movb_tmp); \
128 #define CLRC emitcode("clr","c")
129 #define SETC emitcode("setb","c")
131 // A scratch register which will be used to hold
132 // result bytes from operands in far space via DPTR2.
133 #define DP2_RESULT_REG "_ap"
135 static lineNode *lineHead = NULL;
136 static lineNode *lineCurr = NULL;
138 static unsigned char SLMask[] =
139 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
140 0xE0, 0xC0, 0x80, 0x00};
141 static unsigned char SRMask[] =
142 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
143 0x07, 0x03, 0x01, 0x00};
149 #define PROTECT_SP {if (options.protect_sp_update) { \
150 symbol *lbl = newiTempLabel(NULL); \
151 emitcode ("setb","F1"); \
152 emitcode ("jbc","EA,!tlabel",lbl->key+100); \
153 emitcode ("clr","F1"); \
154 emitcode ("","!tlabeldef",lbl->key+100); \
156 #define UNPROTECT_SP { if (options.protect_sp_update) { \
157 symbol *lbl = newiTempLabel(NULL); \
158 emitcode ("jnb","F1,!tlabel",lbl->key+100); \
159 emitcode ("setb","EA"); \
160 emitcode ("","!tlabeldef",lbl->key+100); \
164 /*-----------------------------------------------------------------*/
165 /* emitcode - writes the code into a file : for now it is simple */
166 /*-----------------------------------------------------------------*/
168 emitcode (char *inst, char *fmt,...)
171 char lb[INITIAL_INLINEASM];
180 SNPRINTF (lb, sizeof(lb), "%s\t", inst);
184 SNPRINTF (lb, sizeof(lb), "%s", inst);
187 tvsprintf (lb + strlen(lb), sizeof(lb) - strlen(lb),
192 tvsprintf (lb, sizeof(lb), fmt, ap);
196 while (isspace (*lbp))
203 lineCurr = (lineCurr ?
204 connectLine (lineCurr, newLineNode (lb)) :
205 (lineHead = newLineNode (lb)));
208 lineCurr->isInline = _G.inLine;
209 lineCurr->isDebug = _G.debugLine;
213 /*-----------------------------------------------------------------*/
214 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
215 /*-----------------------------------------------------------------*/
217 getFreePtr (iCode * ic, asmop ** aopp, bool result)
222 /* the logic: if r0 & r1 used in the instruction
223 then we are in trouble otherwise */
225 /* first check if r0 & r1 are used by this
226 instruction, in which case we are in trouble */
227 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
228 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
233 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
234 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
236 /* if no usage of r0 then return it */
239 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
240 (*aopp)->type = AOP_R0;
242 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
245 /* if no usage of r1 then return it */
248 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
249 (*aopp)->type = AOP_R1;
251 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
254 /* now we know they both have usage */
255 /* if r0 not used in this instruction */
258 /* push it if not already pushed */
261 emitcode ("push", "%s",
262 ds390_regWithIdx (R0_IDX)->dname);
266 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
267 (*aopp)->type = AOP_R0;
269 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
272 /* if r1 not used then */
276 /* push it if not already pushed */
279 emitcode ("push", "%s",
280 ds390_regWithIdx (R1_IDX)->dname);
284 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
285 (*aopp)->type = AOP_R1;
286 return ds390_regWithIdx (R1_IDX);
290 /* I said end of world but not quite end of world yet */
291 /* if this is a result then we can push it on the stack */
294 (*aopp)->type = AOP_STK;
298 /* other wise this is true end of the world */
299 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
300 "getFreePtr should never reach here");
303 return NULL; // notreached, but makes compiler happy.
306 /*-----------------------------------------------------------------*/
307 /* newAsmop - creates a new asmOp */
308 /*-----------------------------------------------------------------*/
310 newAsmop (short type)
314 aop = Safe_calloc (1, sizeof (asmop));
319 static int _currentDPS; /* Current processor DPS. */
320 static int _desiredDPS; /* DPS value compiler thinks we should be using. */
321 static int _lazyDPS = 0; /* if non-zero, we are doing lazy evaluation of DPS changes. */
323 /*-----------------------------------------------------------------*/
324 /* genSetDPTR: generate code to select which DPTR is in use (zero */
325 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390 */
326 /* alternate DPTR (DPL1/DPH1/DPX1). */
327 /*-----------------------------------------------------------------*/
332 /* If we are doing lazy evaluation, simply note the desired
333 * change, but don't emit any code yet.
343 emitcode ("mov", "dps,#0");
348 emitcode ("mov", "dps,#1");
352 /*-----------------------------------------------------------------*/
353 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
355 /* Any code that operates on DPTR (NB: not on the individual */
356 /* components, like DPH) *must* call _flushLazyDPS() before using */
357 /* DPTR within a lazy DPS evaluation block. */
359 /* Note that aopPut and aopGet already contain the proper calls to */
360 /* _flushLazyDPS, so it is safe to use these calls within a lazy */
361 /* DPS evaluation block. */
363 /* Also, _flushLazyDPS must be called before any flow control */
364 /* operations that could potentially branch out of the block. */
366 /* Lazy DPS evaluation is simply an optimization (though an */
367 /* important one), so if in doubt, leave it out. */
368 /*-----------------------------------------------------------------*/
370 _startLazyDPSEvaluation (void)
374 #ifdef BETTER_LITERAL_SHIFT
381 /*-----------------------------------------------------------------*/
382 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
383 /* desired one. Call before using DPTR within a lazy DPS evaluation */
385 /*-----------------------------------------------------------------*/
395 if (_desiredDPS != _currentDPS)
399 emitcode ("inc", "dps");
403 emitcode ("dec", "dps");
405 _currentDPS = _desiredDPS;
409 /*-----------------------------------------------------------------*/
410 /* _endLazyDPSEvaluation: end lazy DPS evaluation block. */
412 /* Forces us back to the safe state (standard DPTR selected). */
413 /*-----------------------------------------------------------------*/
415 _endLazyDPSEvaluation (void)
417 #ifdef BETTER_LITERAL_SHIFT
436 /*-----------------------------------------------------------------*/
437 /* pointerCode - returns the code for a pointer type */
438 /*-----------------------------------------------------------------*/
440 pointerCode (sym_link * etype)
443 return PTR_TYPE (SPEC_OCLS (etype));
447 /*-----------------------------------------------------------------*/
448 /* aopForSym - for a true symbol */
449 /*-----------------------------------------------------------------*/
451 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
454 memmap *space = SPEC_OCLS (sym->etype);
456 /* if already has one */
460 /* assign depending on the storage class */
461 /* if it is on the stack or indirectly addressable */
462 /* space we need to assign either r0 or r1 to it */
463 if ((sym->onStack && !options.stack10bit) || sym->iaccess)
465 sym->aop = aop = newAsmop (0);
466 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
467 aop->size = getSize (sym->type);
469 /* now assign the address of the variable to
470 the pointer register */
471 if (aop->type != AOP_STK)
477 emitcode ("push", "acc");
480 emitcode ("push", "b");
482 emitcode ("mov", "a,_bp");
483 emitcode ("add", "a,#!constbyte",
485 ((char) (sym->stack - _G.nRegsSaved)) :
486 ((char) sym->stack)) & 0xff);
487 emitcode ("mov", "%s,a",
488 aop->aopu.aop_ptr->name);
491 emitcode ("pop", "b");
494 emitcode ("pop", "acc");
497 emitcode ("mov", "%s,#%s",
498 aop->aopu.aop_ptr->name,
500 aop->paged = space->paged;
503 aop->aopu.aop_stk = sym->stack;
507 if (sym->onStack && options.stack10bit)
509 short stack_val = -((sym->stack < 0) ?
510 ((short) (sym->stack - _G.nRegsSaved)) :
511 ((short) sym->stack)) ;
512 if (useDP2 && _G.dptr1InUse) {
513 emitcode ("push","dpl1");
514 emitcode ("push","dph1");
515 emitcode ("push","dpx1");
516 } else if (_G.dptrInUse ) {
517 emitcode ("push","dpl");
518 emitcode ("push","dph");
519 emitcode ("push","dpx");
521 /* It's on the 10 bit stack, which is located in
524 if (stack_val < 0 && stack_val > -5) { /* between -5 & -1 */
526 if (options.model == MODEL_FLAT24)
527 emitcode ("mov", "dpx1,#!constbyte", (options.stack_loc >> 16) & 0xff);
529 emitcode ("mov", "dph1,_bpx+1");
530 emitcode ("mov", "dpl1,_bpx");
531 emitcode ("mov","dps,#1");
533 if (options.model == MODEL_FLAT24)
534 emitcode ("mov", "dpx,#!constbyte", (options.stack_loc >> 16) & 0xff);
535 emitcode ("mov", "dph,_bpx+1");
536 emitcode ("mov", "dpl,_bpx");
538 stack_val = -stack_val;
539 while (stack_val--) {
540 emitcode ("inc","dptr");
543 emitcode("mov","dps,#0");
547 emitcode ("push", "acc");
550 emitcode ("push", "b");
552 emitcode ("mov", "a,_bpx");
553 emitcode ("clr","c");
554 emitcode ("subb", "a,#!constbyte", stack_val & 0xff);
555 emitcode ("mov","b,a");
556 emitcode ("mov","a,_bpx+1");
557 emitcode ("subb","a,#!constbyte",(stack_val >> 8) & 0xff);
559 if (options.model == MODEL_FLAT24)
560 emitcode ("mov", "dpx1,#!constbyte", (options.stack_loc >> 16) & 0xff);
562 emitcode ("mov", "dph1,a");
563 emitcode ("mov", "dpl1,b");
565 if (options.model == MODEL_FLAT24)
566 emitcode ("mov", "dpx,#!constbyte", (options.stack_loc >> 16) & 0xff);
567 emitcode ("mov", "dph,a");
568 emitcode ("mov", "dpl,b");
572 emitcode ("pop", "b");
575 emitcode ("pop", "acc");
577 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
578 aop->size = getSize (sym->type);
582 /* if in bit space */
583 if (IN_BITSPACE (space))
585 sym->aop = aop = newAsmop (AOP_CRY);
586 aop->aopu.aop_dir = sym->rname;
587 aop->size = getSize (sym->type);
590 /* if it is in direct space */
591 if (IN_DIRSPACE (space))
593 sym->aop = aop = newAsmop (AOP_DIR);
594 aop->aopu.aop_dir = sym->rname;
595 aop->size = getSize (sym->type);
599 /* special case for a function */
600 if (IS_FUNC (sym->type))
602 sym->aop = aop = newAsmop (AOP_IMMD);
603 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
604 aop->size = FPTRSIZE;
608 /* only remaining is far space */
609 /* in which case DPTR gets the address */
610 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
615 emitcode ("mov", "dptr,#%s", sym->rname);
620 emitcode ("mov", "dptr,#%s", sym->rname);
622 aop->size = getSize (sym->type);
624 /* if it is in code space */
625 if (IN_CODESPACE (space))
631 /*-----------------------------------------------------------------*/
632 /* aopForRemat - rematerialzes an object */
633 /*-----------------------------------------------------------------*/
635 aopForRemat (symbol * sym)
637 iCode *ic = sym->rematiCode;
638 asmop *aop = newAsmop (AOP_IMMD);
645 val += (int) operandLitValue (IC_RIGHT (ic));
646 else if (ic->op == '-')
647 val -= (int) operandLitValue (IC_RIGHT (ic));
648 else if (IS_CAST_ICODE(ic)) {
649 sym_link *from_type = operandType(IC_RIGHT(ic));
650 aop->aopu.aop_immd.from_cast_remat = 1;
651 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
652 ptr_type = DCL_TYPE(from_type);
653 if (ptr_type == IPOINTER) {
660 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
665 SNPRINTF (buffer, sizeof(buffer),
667 OP_SYMBOL (IC_LEFT (ic))->rname,
668 val >= 0 ? '+' : '-',
673 if (IS_ASSIGN_ICODE(ic) && isOperandLiteral(IC_RIGHT(ic)))
675 SNPRINTF(buffer, sizeof(buffer),
676 "0x%x",(int) operandLitValue (IC_RIGHT (ic)));
680 strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
684 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);
685 /* set immd2 field if required */
686 if (aop->aopu.aop_immd.from_cast_remat)
688 tsprintf(buffer, sizeof(buffer), "#!constbyte",ptr_type);
689 aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
695 /*-----------------------------------------------------------------*/
696 /* aopHasRegs - returns true if aop has regs between from-to */
697 /*-----------------------------------------------------------------*/
698 static int aopHasRegs(asmop *aop, int from, int to)
702 if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
704 for (; size < aop->size ; size++) {
706 for (reg = from ; reg <= to ; reg++)
707 if (aop->aopu.aop_reg[size] == ds390_regWithIdx(reg)) return 1;
712 /*-----------------------------------------------------------------*/
713 /* regsInCommon - two operands have some registers in common */
714 /*-----------------------------------------------------------------*/
716 regsInCommon (operand * op1, operand * op2)
721 /* if they have registers in common */
722 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
725 sym1 = OP_SYMBOL (op1);
726 sym2 = OP_SYMBOL (op2);
728 if (sym1->nRegs == 0 || sym2->nRegs == 0)
731 for (i = 0; i < sym1->nRegs; i++)
737 for (j = 0; j < sym2->nRegs; j++)
742 if (sym2->regs[j] == sym1->regs[i])
750 /*-----------------------------------------------------------------*/
751 /* operandsEqu - equivalent */
752 /*-----------------------------------------------------------------*/
754 operandsEqu (operand * op1, operand * op2)
758 /* if they not symbols */
759 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
762 sym1 = OP_SYMBOL (op1);
763 sym2 = OP_SYMBOL (op2);
765 /* if both are itemps & one is spilt
766 and the other is not then false */
767 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
768 sym1->isspilt != sym2->isspilt)
771 /* if they are the same */
775 if (strcmp (sym1->rname, sym2->rname) == 0)
779 /* if left is a tmp & right is not */
780 if (IS_ITEMP (op1) &&
783 (sym1->usl.spillLoc == sym2))
786 if (IS_ITEMP (op2) &&
790 (sym2->usl.spillLoc == sym1))
796 /*-----------------------------------------------------------------*/
797 /* sameRegs - two asmops have the same registers */
798 /*-----------------------------------------------------------------*/
800 sameRegs (asmop * aop1, asmop * aop2)
806 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
813 if (aop1->type != AOP_REG ||
814 aop2->type != AOP_REG)
817 if (aop1->size != aop2->size)
820 for (i = 0; i < aop1->size; i++)
821 if (aop1->aopu.aop_reg[i] !=
822 aop2->aopu.aop_reg[i])
828 /*-----------------------------------------------------------------*/
829 /* aopOp - allocates an asmop for an operand : */
830 /*-----------------------------------------------------------------*/
832 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
841 /* if this a literal */
842 if (IS_OP_LITERAL (op))
844 op->aop = aop = newAsmop (AOP_LIT);
845 aop->aopu.aop_lit = op->operand.valOperand;
846 aop->size = getSize (operandType (op));
850 /* if already has a asmop then continue */
854 /* if the underlying symbol has a aop */
855 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
857 op->aop = OP_SYMBOL (op)->aop;
861 /* if this is a true symbol */
862 if (IS_TRUE_SYMOP (op))
864 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
868 /* this is a temporary : this has
874 e) can be a return use only */
876 sym = OP_SYMBOL (op);
879 /* if the type is a conditional */
880 if (sym->regType == REG_CND)
882 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
887 /* if it is spilt then two situations
889 b) has a spill location */
890 if (sym->isspilt || sym->nRegs == 0)
893 /* rematerialize it NOW */
896 sym->aop = op->aop = aop =
898 aop->size = getSize (sym->type);
905 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
906 aop->size = getSize (sym->type);
907 for (i = 0; i < 2; i++)
908 aop->aopu.aop_str[i] = accUse[i];
918 /* a AOP_STR uses DPTR, but DPTR is already in use;
921 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"AOP_STR with DPTR in use!");
924 aop = op->aop = sym->aop = newAsmop (AOP_STR);
925 aop->size = getSize (sym->type);
926 for (i = 0; i < (int) fReturnSizeDS390; i++)
927 aop->aopu.aop_str[i] = fReturn[i];
931 if (sym->dptr) { /* has been allocated to a DPTRn */
932 aop = op->aop = sym->aop = newAsmop (AOP_DPTRn);
933 aop->size = getSize (sym->type);
934 aop->aopu.dptr = sym->dptr;
937 /* else spill location */
938 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
939 /* force a new aop if sizes differ */
940 sym->usl.spillLoc->aop = NULL;
942 sym->aop = op->aop = aop =
943 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
944 aop->size = getSize (sym->type);
948 /* must be in a register */
949 sym->aop = op->aop = aop = newAsmop (AOP_REG);
950 aop->size = sym->nRegs;
951 for (i = 0; i < sym->nRegs; i++)
952 aop->aopu.aop_reg[i] = sym->regs[i];
955 /*-----------------------------------------------------------------*/
956 /* freeAsmop - free up the asmop given to an operand */
957 /*----------------------------------------------------------------*/
959 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
976 /* depending on the asmop type only three cases need work AOP_RO
977 , AOP_R1 && AOP_STK */
985 emitcode ("pop", "ar0");
989 bitVectUnSetBit (ic->rUsed, R0_IDX);
997 emitcode ("pop", "ar1");
1001 bitVectUnSetBit (ic->rUsed, R1_IDX);
1007 int stk = aop->aopu.aop_stk + aop->size;
1008 bitVectUnSetBit (ic->rUsed, R0_IDX);
1009 bitVectUnSetBit (ic->rUsed, R1_IDX);
1011 getFreePtr (ic, &aop, FALSE);
1013 if (options.stack10bit)
1015 /* I'm not sure what to do here yet... */
1018 "*** Warning: probably generating bad code for "
1019 "10 bit stack mode.\n");
1024 emitcode ("mov", "a,_bp");
1025 emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
1026 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1030 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1035 emitcode ("pop", "acc");
1036 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1039 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1042 freeAsmop (op, NULL, ic, TRUE);
1045 emitcode ("pop", "ar0");
1051 emitcode ("pop", "ar1");
1056 if (_G.dptr1InUse) {
1057 emitcode ("pop","dpx1");
1058 emitcode ("pop","dph1");
1059 emitcode ("pop","dpl1");
1064 emitcode ("pop","dpx");
1065 emitcode ("pop","dph");
1066 emitcode ("pop","dpl");
1071 /* all other cases just dealloc */
1077 OP_SYMBOL (op)->aop = NULL;
1078 /* if the symbol has a spill */
1080 SPIL_LOC (op)->aop = NULL;
1085 #define DEFAULT_ACC_WARNING 0
1086 static int saveAccWarn = DEFAULT_ACC_WARNING;
1088 /*-------------------------------------------------------------------*/
1089 /* aopGet - for fetching value of the aop */
1091 /* Set saveAcc to NULL if you are sure it is OK to clobber the value */
1092 /* in the accumulator. Set it to the name of a free register */
1093 /* if acc must be preserved; the register will be used to preserve */
1094 /* acc temporarily and to return the result byte. */
1095 /*-------------------------------------------------------------------*/
1104 /* offset is greater than
1106 if (offset > (aop->size - 1) &&
1107 aop->type != AOP_LIT)
1110 /* depending on type */
1116 /* if we need to increment it */
1117 while (offset > aop->coff)
1119 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1123 while (offset < aop->coff)
1125 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1132 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1133 return (dname ? "acc" : "a");
1135 SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1136 return Safe_strdup(buffer);
1139 assert(offset <= 3);
1140 return dptrn[aop->aopu.dptr][offset];
1145 if (aop->type == AOP_DPTR2)
1153 if (aop->type != AOP_DPTR2)
1155 if (saveAccWarn) { fprintf(stderr, "saveAcc for DPTR...\n"); }
1156 emitcode(";", "spanky: saveAcc for DPTR");
1159 emitcode ("xch", "a, %s", saveAcc);
1164 while (offset > aop->coff)
1166 emitcode ("inc", "dptr");
1170 while (offset < aop->coff)
1172 emitcode ("lcall", "__decdptr");
1179 emitcode ("clr", "a");
1180 emitcode ("movc", "a,@a+dptr");
1184 emitcode ("movx", "a,@dptr");
1187 if (aop->type == AOP_DPTR2)
1195 emitcode ("xch", "a, %s", saveAcc);
1196 if (strcmp(saveAcc, "_ap"))
1198 emitcode(";", "spiffy: non _ap return from aopGet.");
1203 return (dname ? "acc" : "a");
1206 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1208 SNPRINTF(buffer, sizeof(buffer),
1209 "%s",aop->aopu.aop_immd.aop_immd2);
1213 SNPRINTF(buffer, sizeof(buffer),
1214 "#%s", aop->aopu.aop_immd.aop_immd1);
1220 tsprintf(buffer, sizeof(buffer),
1221 "#!his",aop->aopu.aop_immd.aop_immd1);
1224 tsprintf(buffer, sizeof(buffer),
1225 "#!hihis",aop->aopu.aop_immd.aop_immd1);
1228 tsprintf(buffer, sizeof(buffer),
1229 "#!hihihis",aop->aopu.aop_immd.aop_immd1);
1231 default: /* should not need this (just in case) */
1232 SNPRINTF (buffer, sizeof(buffer),
1234 aop->aopu.aop_immd.aop_immd1,
1240 SNPRINTF (buffer, sizeof(buffer),
1241 "#%s", aop->aopu.aop_immd.aop_immd1);
1243 return Safe_strdup(buffer);
1248 SNPRINTF (buffer, sizeof(buffer),
1255 SNPRINTF(buffer, sizeof(buffer),
1256 "%s", aop->aopu.aop_dir);
1259 return Safe_strdup(buffer);
1263 return aop->aopu.aop_reg[offset]->dname;
1265 return aop->aopu.aop_reg[offset]->name;
1268 emitcode ("clr", "a");
1269 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1270 emitcode ("rlc", "a");
1271 return (dname ? "acc" : "a");
1274 if (!offset && dname)
1276 return aop->aopu.aop_str[offset];
1279 return aopLiteral (aop->aopu.aop_lit, offset);
1283 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1287 return aop->aopu.aop_str[offset];
1291 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1292 "aopget got unsupported aop->type");
1295 return NULL; // not reached, but makes compiler happy.
1297 /*-----------------------------------------------------------------*/
1298 /* aopPut - puts a string for a aop */
1299 /*-----------------------------------------------------------------*/
1301 aopPut (asmop * aop, char *s, int offset)
1303 if (aop->size && offset > (aop->size - 1))
1305 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1306 "aopPut got offset > aop->size");
1310 /* will assign value to value */
1311 /* depending on where it is ofcourse */
1317 SNPRINTF (buffer, sizeof(buffer),
1319 aop->aopu.aop_dir, offset);
1323 SNPRINTF (buffer, sizeof(buffer),
1324 "%s", aop->aopu.aop_dir);
1328 if (strcmp (buffer, s))
1330 emitcode ("mov", "%s,%s", buffer, s);
1335 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1336 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1339 strcmp (s, "r0") == 0 ||
1340 strcmp (s, "r1") == 0 ||
1341 strcmp (s, "r2") == 0 ||
1342 strcmp (s, "r3") == 0 ||
1343 strcmp (s, "r4") == 0 ||
1344 strcmp (s, "r5") == 0 ||
1345 strcmp (s, "r6") == 0 ||
1346 strcmp (s, "r7") == 0)
1348 emitcode ("mov", "%s,%s",
1349 aop->aopu.aop_reg[offset]->dname, s);
1353 emitcode ("mov", "%s,%s",
1354 aop->aopu.aop_reg[offset]->name, s);
1360 emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1366 if (aop->type == AOP_DPTR2)
1374 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1375 "aopPut writting to code space");
1379 while (offset > aop->coff)
1382 emitcode ("inc", "dptr");
1385 while (offset < aop->coff)
1388 emitcode ("lcall", "__decdptr");
1393 /* if not in accumulater */
1396 emitcode ("movx", "@dptr,a");
1398 if (aop->type == AOP_DPTR2)
1406 while (offset > aop->coff)
1409 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1411 while (offset < aop->coff)
1414 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1421 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1427 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1429 else if (strcmp (s, "r0") == 0 ||
1430 strcmp (s, "r1") == 0 ||
1431 strcmp (s, "r2") == 0 ||
1432 strcmp (s, "r3") == 0 ||
1433 strcmp (s, "r4") == 0 ||
1434 strcmp (s, "r5") == 0 ||
1435 strcmp (s, "r6") == 0 ||
1436 strcmp (s, "r7") == 0)
1439 SNPRINTF(buff, sizeof(buff),
1441 emitcode ("mov", "@%s,%s",
1442 aop->aopu.aop_ptr->name, buff);
1446 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1451 if (strcmp (s, "a") == 0)
1452 emitcode ("push", "acc");
1456 emitcode ("push", "acc");
1458 emitcode ("push", s);
1464 /* if bit variable */
1465 if (!aop->aopu.aop_dir)
1467 emitcode ("clr", "a");
1468 emitcode ("rlc", "a");
1473 emitcode ("clr", "%s", aop->aopu.aop_dir);
1475 emitcode ("setb", "%s", aop->aopu.aop_dir);
1476 else if (!strcmp (s, "c"))
1477 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1480 if (strcmp (s, "a"))
1485 /* set C, if a >= 1 */
1486 emitcode ("add", "a,#!constbyte",0xff);
1487 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1495 if (strcmp (aop->aopu.aop_str[offset], s))
1496 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1501 if (!offset && (strcmp (s, "acc") == 0))
1504 if (strcmp (aop->aopu.aop_str[offset], s))
1505 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1509 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1510 "aopPut got unsupported aop->type");
1517 /*--------------------------------------------------------------------*/
1518 /* reAdjustPreg - points a register back to where it should (coff==0) */
1519 /*--------------------------------------------------------------------*/
1521 reAdjustPreg (asmop * aop)
1523 if ((aop->coff==0) || (aop->size <= 1)) {
1532 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1536 if (aop->type == AOP_DPTR2)
1543 emitcode ("lcall", "__decdptr");
1546 if (aop->type == AOP_DPTR2)
1556 #define AOP(op) op->aop
1557 #define AOP_TYPE(op) AOP(op)->type
1558 #define AOP_SIZE(op) AOP(op)->size
1559 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1560 AOP_TYPE(x) == AOP_R0))
1562 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1563 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1566 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1567 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1568 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1569 #define AOP_INDPTRn(x) (AOP_TYPE(x) == AOP_DPTRn)
1570 #define AOP_USESDPTR(x) ((AOP_TYPE(x) == AOP_DPTR) || (AOP_TYPE(x) == AOP_STR))
1571 #define AOP_USESDPTR2(x) ((AOP_TYPE(x) == AOP_DPTR2) || (AOP_TYPE(x) == AOP_DPTRn))
1573 // The following two macros can be used even if the aop has not yet been aopOp'd.
1574 #define AOP_IS_STR(x) (IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
1575 #define AOP_IS_DPTRn(x) (IS_SYMOP(x) && OP_SYMBOL(x)->dptr)
1577 /* Workaround for DS80C390 bug: div ab may return bogus results
1578 * if A is accessed in instruction immediately before the div.
1580 * Will be fixed in B4 rev of processor, Dallas claims.
1583 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1584 if (!AOP_NEEDSACC(RIGHT)) \
1586 /* We can load A first, then B, since \
1587 * B (the RIGHT operand) won't clobber A, \
1588 * thus avoiding touching A right before the div. \
1590 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1591 L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL); \
1593 L = aopGet(AOP(RIGHT),0,FALSE,FALSE,"b"); \
1598 /* Just stuff in a nop after loading A. */ \
1599 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,NULL));\
1600 L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL); \
1602 emitcode("nop", "; workaround for DS80C390 div bug."); \
1605 /*-----------------------------------------------------------------*/
1606 /* genNotFloat - generates not for float operations */
1607 /*-----------------------------------------------------------------*/
1609 genNotFloat (operand * op, operand * res)
1615 D (emitcode (";", "genNotFloat "););
1617 /* we will put 127 in the first byte of
1619 aopPut (AOP (res), "#127", 0);
1620 size = AOP_SIZE (op) - 1;
1623 _startLazyDPSEvaluation ();
1624 l = aopGet (op->aop, offset++, FALSE, FALSE, NULL);
1629 emitcode ("orl", "a,%s",
1631 offset++, FALSE, FALSE,
1634 _endLazyDPSEvaluation ();
1636 tlbl = newiTempLabel (NULL);
1637 aopPut (res->aop, one, 1);
1638 emitcode ("jz", "!tlabel", (tlbl->key + 100));
1639 aopPut (res->aop, zero, 1);
1640 emitcode ("", "!tlabeldef", (tlbl->key + 100));
1642 size = res->aop->size - 2;
1644 /* put zeros in the rest */
1646 aopPut (res->aop, zero, offset++);
1649 /*-----------------------------------------------------------------*/
1650 /* opIsGptr: returns non-zero if the passed operand is */
1651 /* a generic pointer type. */
1652 /*-----------------------------------------------------------------*/
1654 opIsGptr (operand * op)
1656 sym_link *type = operandType (op);
1658 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1665 /*-----------------------------------------------------------------*/
1666 /* getDataSize - get the operand data size */
1667 /*-----------------------------------------------------------------*/
1669 getDataSize (operand * op)
1672 size = AOP_SIZE (op);
1673 if (size == GPTRSIZE)
1675 sym_link *type = operandType (op);
1676 if (IS_GENPTR (type))
1678 /* generic pointer; arithmetic operations
1679 * should ignore the high byte (pointer type).
1687 /*-----------------------------------------------------------------*/
1688 /* outAcc - output Acc */
1689 /*-----------------------------------------------------------------*/
1691 outAcc (operand * result)
1694 size = getDataSize (result);
1697 aopPut (AOP (result), "a", 0);
1700 /* unsigned or positive */
1703 aopPut (AOP (result), zero, offset++);
1708 /*-----------------------------------------------------------------*/
1709 /* outBitC - output a bit C */
1710 /*-----------------------------------------------------------------*/
1712 outBitC (operand * result)
1714 /* if the result is bit */
1715 if (AOP_TYPE (result) == AOP_CRY)
1717 aopPut (AOP (result), "c", 0);
1721 emitcode ("clr", "a");
1722 emitcode ("rlc", "a");
1727 /*-----------------------------------------------------------------*/
1728 /* toBoolean - emit code for orl a,operator(sizeop) */
1729 /*-----------------------------------------------------------------*/
1731 toBoolean (operand * oper)
1733 int size = AOP_SIZE (oper) - 1;
1737 /* The generic part of a generic pointer should
1738 * not participate in it's truth value.
1740 * i.e. 0x10000000 is zero.
1742 if (opIsGptr (oper))
1744 D (emitcode (";", "toBoolean: generic ptr special case."););
1748 _startLazyDPSEvaluation ();
1749 if (AOP_NEEDSACC (oper) && size)
1754 emitcode ("push", "b");
1756 MOVB (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1760 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1767 emitcode ("orl", "b,%s",
1768 aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1772 emitcode ("orl", "a,%s",
1773 aopGet (AOP (oper), offset++, FALSE, FALSE, DP2_RESULT_REG));
1776 _endLazyDPSEvaluation ();
1780 emitcode ("mov", "a,b");
1783 emitcode ("pop", "b");
1790 /*-----------------------------------------------------------------*/
1791 /* genNot - generate code for ! operation */
1792 /*-----------------------------------------------------------------*/
1797 sym_link *optype = operandType (IC_LEFT (ic));
1799 D (emitcode (";", "genNot "););
1801 /* assign asmOps to operand & result */
1802 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1803 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1805 /* if in bit space then a special case */
1806 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1808 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1809 emitcode ("cpl", "c");
1810 outBitC (IC_RESULT (ic));
1814 /* if type float then do float */
1815 if (IS_FLOAT (optype))
1817 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1821 toBoolean (IC_LEFT (ic));
1823 tlbl = newiTempLabel (NULL);
1824 emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1825 emitcode ("", "!tlabeldef", tlbl->key + 100);
1826 outBitC (IC_RESULT (ic));
1829 /* release the aops */
1830 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1831 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1835 /*-----------------------------------------------------------------*/
1836 /* genCpl - generate code for complement */
1837 /*-----------------------------------------------------------------*/
1845 D (emitcode (";", "genCpl "););
1848 /* assign asmOps to operand & result */
1849 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1850 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1852 /* special case if in bit space */
1853 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1854 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1855 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1856 emitcode ("cpl", "c");
1857 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1860 tlbl=newiTempLabel(NULL);
1861 emitcode ("cjne", "%s,#0x01,%05d$",
1862 aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE,NULL), tlbl->key+100);
1863 emitcode ("", "%05d$:", tlbl->key+100);
1864 outBitC (IC_RESULT(ic));
1868 size = AOP_SIZE (IC_RESULT (ic));
1869 _startLazyDPSEvaluation ();
1872 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
1873 emitcode ("cpl", "a");
1874 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1876 _endLazyDPSEvaluation ();
1880 /* release the aops */
1881 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1882 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1885 /*-----------------------------------------------------------------*/
1886 /* genUminusFloat - unary minus for floating points */
1887 /*-----------------------------------------------------------------*/
1889 genUminusFloat (operand * op, operand * result)
1891 int size, offset = 0;
1893 D(emitcode (";", "genUminusFloat"););
1895 /* for this we just copy and then flip the bit */
1897 _startLazyDPSEvaluation ();
1898 size = AOP_SIZE (op) - 1;
1902 aopPut (AOP (result),
1903 aopGet (AOP (op), offset, FALSE, FALSE, NULL),
1908 MOVA(aopGet (AOP (op), offset, FALSE, FALSE, NULL));
1910 emitcode ("cpl", "acc.7");
1911 aopPut (AOP (result), "a", offset);
1912 _endLazyDPSEvaluation ();
1915 /*-----------------------------------------------------------------*/
1916 /* genUminus - unary minus code generation */
1917 /*-----------------------------------------------------------------*/
1919 genUminus (iCode * ic)
1924 D (emitcode (";", "genUminus "););
1927 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1928 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1930 /* if both in bit space then special
1932 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1933 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1936 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1937 emitcode ("cpl", "c");
1938 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1942 optype = operandType (IC_LEFT (ic));
1944 /* if float then do float stuff */
1945 if (IS_FLOAT (optype))
1947 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1951 /* otherwise subtract from zero */
1952 size = AOP_SIZE (IC_LEFT (ic));
1954 _startLazyDPSEvaluation ();
1957 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL);
1958 if (!strcmp (l, "a"))
1962 emitcode ("cpl", "a");
1963 emitcode ("addc", "a,#0");
1969 emitcode ("clr", "a");
1970 emitcode ("subb", "a,%s", l);
1972 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1974 _endLazyDPSEvaluation ();
1976 /* if any remaining bytes in the result */
1977 /* we just need to propagate the sign */
1978 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic)))) != 0)
1980 emitcode ("rlc", "a");
1981 emitcode ("subb", "a,acc");
1983 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1987 /* release the aops */
1988 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1989 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1992 /*-----------------------------------------------------------------*/
1993 /* savermask - saves registers in the mask */
1994 /*-----------------------------------------------------------------*/
1995 static void savermask(bitVect *rs_mask)
1998 if (options.useXstack) {
1999 if (bitVectBitValue (rs_mask, R0_IDX))
2000 emitcode ("mov", "b,r0");
2001 emitcode ("mov", "r0,%s", spname);
2002 for (i = 0; i < ds390_nRegs; i++) {
2003 if (bitVectBitValue (rs_mask, i)) {
2005 emitcode ("mov", "a,b");
2007 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
2008 emitcode ("movx", "@r0,a");
2009 emitcode ("inc", "r0");
2012 emitcode ("mov", "%s,r0", spname);
2013 if (bitVectBitValue (rs_mask, R0_IDX))
2014 emitcode ("mov", "r0,b");
2016 for (i = 0; i < ds390_nRegs; i++) {
2017 if (bitVectBitValue (rs_mask, i))
2018 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2023 /*-----------------------------------------------------------------*/
2024 /* saveRegisters - will look for a call and save the registers */
2025 /*-----------------------------------------------------------------*/
2027 saveRegisters (iCode * lic)
2033 for (ic = lic; ic; ic = ic->next)
2034 if (ic->op == CALL || ic->op == PCALL)
2039 fprintf (stderr, "found parameter push with no function call\n");
2043 /* if the registers have been saved already then
2045 if (ic->regsSaved || IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic)))) return ;
2047 /* special case if DPTR alive across a function call then must save it
2048 even though callee saves */
2049 if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2051 rsave = newBitVect(ic->rMask->size);
2052 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2053 if (bitVectBitValue(ic->rMask,i))
2054 rsave = bitVectSetBit(rsave,i);
2056 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2058 /* safe the registers in use at this time but skip the
2059 ones for the result */
2060 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2061 ds390_rUmaskForOp (IC_RESULT(ic)));
2067 /*-----------------------------------------------------------------*/
2068 /* usavermask - restore registers with mask */
2069 /*-----------------------------------------------------------------*/
2070 static void unsavermask(bitVect *rs_mask)
2073 if (options.useXstack) {
2074 emitcode ("mov", "r0,%s", spname);
2075 for (i = ds390_nRegs; i >= 0; i--) {
2076 if (bitVectBitValue (rs_mask, i)) {
2077 emitcode ("dec", "r0");
2078 emitcode ("movx", "a,@r0");
2080 emitcode ("mov", "b,a");
2082 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
2085 emitcode ("mov", "%s,r0", spname);
2086 if (bitVectBitValue (rs_mask, R0_IDX))
2087 emitcode ("mov", "r0,b");
2089 for (i = ds390_nRegs; i >= 0; i--) {
2090 if (bitVectBitValue (rs_mask, i))
2091 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2096 /*-----------------------------------------------------------------*/
2097 /* unsaveRegisters - pop the pushed registers */
2098 /*-----------------------------------------------------------------*/
2100 unsaveRegisters (iCode * ic)
2104 if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2106 rsave = newBitVect(ic->rMask->size);
2107 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2108 if (bitVectBitValue(ic->rMask,i))
2109 rsave = bitVectSetBit(rsave,i);
2111 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2113 /* restore the registers in use at this time but skip the
2114 ones for the result */
2115 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2116 ds390_rUmaskForOp (IC_RESULT(ic)));
2122 /*-----------------------------------------------------------------*/
2124 /*-----------------------------------------------------------------*/
2126 pushSide (operand * oper, int size)
2129 _startLazyDPSEvaluation ();
2132 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, NULL);
2133 if (AOP_TYPE (oper) != AOP_REG &&
2134 AOP_TYPE (oper) != AOP_DIR &&
2137 emitcode ("mov", "a,%s", l);
2138 emitcode ("push", "acc");
2141 emitcode ("push", "%s", l);
2143 _endLazyDPSEvaluation ();
2146 /*-----------------------------------------------------------------*/
2147 /* assignResultValue - */
2148 /*-----------------------------------------------------------------*/
2150 assignResultValue (operand * oper)
2153 int size = AOP_SIZE (oper);
2155 _startLazyDPSEvaluation ();
2158 aopPut (AOP (oper), fReturn[offset], offset);
2161 _endLazyDPSEvaluation ();
2165 /*-----------------------------------------------------------------*/
2166 /* genXpush - pushes onto the external stack */
2167 /*-----------------------------------------------------------------*/
2169 genXpush (iCode * ic)
2171 asmop *aop = newAsmop (0);
2173 int size, offset = 0;
2175 D (emitcode (";", "genXpush ");
2178 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2179 r = getFreePtr (ic, &aop, FALSE);
2182 emitcode ("mov", "%s,_spx", r->name);
2184 size = AOP_SIZE (IC_LEFT (ic));
2185 _startLazyDPSEvaluation ();
2189 MOVA (aopGet (AOP (IC_LEFT (ic)),
2190 offset++, FALSE, FALSE, NULL));
2191 emitcode ("movx", "@%s,a", r->name);
2192 emitcode ("inc", "%s", r->name);
2195 _endLazyDPSEvaluation ();
2198 emitcode ("mov", "_spx,%s", r->name);
2200 freeAsmop (NULL, aop, ic, TRUE);
2201 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2204 /*-----------------------------------------------------------------*/
2205 /* genIpush - generate code for pushing this gets a little complex */
2206 /*-----------------------------------------------------------------*/
2208 genIpush (iCode * ic)
2210 int size, offset = 0;
2213 D (emitcode (";", "genIpush ");
2216 /* if this is not a parm push : ie. it is spill push
2217 and spill push is always done on the local stack */
2221 /* and the item is spilt then do nothing */
2222 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2225 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2226 size = AOP_SIZE (IC_LEFT (ic));
2227 /* push it on the stack */
2228 _startLazyDPSEvaluation ();
2231 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2237 emitcode ("push", "%s", l);
2239 _endLazyDPSEvaluation ();
2243 /* this is a paramter push: in this case we call
2244 the routine to find the call and save those
2245 registers that need to be saved */
2248 /* if use external stack then call the external
2249 stack pushing routine */
2250 if (options.useXstack)
2256 /* then do the push */
2257 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2259 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2260 size = AOP_SIZE (IC_LEFT (ic));
2262 _startLazyDPSEvaluation ();
2265 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2266 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2267 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2270 emitcode ("mov", "a,%s", l);
2271 emitcode ("push", "acc");
2275 emitcode ("push", "%s", l);
2278 _endLazyDPSEvaluation ();
2280 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2283 /*-----------------------------------------------------------------*/
2284 /* genIpop - recover the registers: can happen only for spilling */
2285 /*-----------------------------------------------------------------*/
2287 genIpop (iCode * ic)
2291 D (emitcode (";", "genIpop ");
2295 /* if the temp was not pushed then */
2296 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2299 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2300 size = AOP_SIZE (IC_LEFT (ic));
2301 offset = (size - 1);
2302 _startLazyDPSEvaluation ();
2305 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2306 FALSE, TRUE, NULL));
2308 _endLazyDPSEvaluation ();
2310 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2313 /*-----------------------------------------------------------------*/
2314 /* unsaveRBank - restores the resgister bank from stack */
2315 /*-----------------------------------------------------------------*/
2317 unsaveRBank (int bank, iCode * ic, bool popPsw)
2323 if (options.useXstack)
2327 /* Assume r0 is available for use. */
2328 r = ds390_regWithIdx (R0_IDX);;
2333 r = getFreePtr (ic, &aop, FALSE);
2335 emitcode ("mov", "%s,_spx", r->name);
2340 if (options.useXstack)
2342 emitcode ("movx", "a,@%s", r->name);
2343 emitcode ("mov", "psw,a");
2344 emitcode ("dec", "%s", r->name);
2348 emitcode ("pop", "psw");
2352 for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2354 if (options.useXstack)
2356 emitcode ("movx", "a,@%s", r->name);
2357 emitcode ("mov", "(%s+%d),a",
2358 regs390[i].base, 8 * bank + regs390[i].offset);
2359 emitcode ("dec", "%s", r->name);
2363 emitcode ("pop", "(%s+%d)",
2364 regs390[i].base, 8 * bank + regs390[i].offset);
2367 if (options.useXstack)
2369 emitcode ("mov", "_spx,%s", r->name);
2374 freeAsmop (NULL, aop, ic, TRUE);
2378 /*-----------------------------------------------------------------*/
2379 /* saveRBank - saves an entire register bank on the stack */
2380 /*-----------------------------------------------------------------*/
2382 saveRBank (int bank, iCode * ic, bool pushPsw)
2388 if (options.useXstack)
2392 /* Assume r0 is available for use. */
2393 r = ds390_regWithIdx (R0_IDX);;
2398 r = getFreePtr (ic, &aop, FALSE);
2400 emitcode ("mov", "%s,_spx", r->name);
2403 for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2405 if (options.useXstack)
2407 emitcode ("inc", "%s", r->name);
2408 emitcode ("mov", "a,(%s+%d)",
2409 regs390[i].base, 8 * bank + regs390[i].offset);
2410 emitcode ("movx", "@%s,a", r->name);
2413 emitcode ("push", "(%s+%d)",
2414 regs390[i].base, 8 * bank + regs390[i].offset);
2419 if (options.useXstack)
2421 emitcode ("mov", "a,psw");
2422 emitcode ("movx", "@%s,a", r->name);
2423 emitcode ("inc", "%s", r->name);
2424 emitcode ("mov", "_spx,%s", r->name);
2428 emitcode ("push", "psw");
2431 emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2436 freeAsmop (NULL, aop, ic, TRUE);
2445 /*-----------------------------------------------------------------*/
2446 /* genSend - gen code for SEND */
2447 /*-----------------------------------------------------------------*/
2448 static void genSend(set *sendSet)
2452 static int rb1_count = 0;
2454 for (sic = setFirstItem (sendSet); sic;
2455 sic = setNextItem (sendSet)) {
2456 int size, offset = 0;
2458 size=getSize(operandType(IC_LEFT(sic)));
2459 D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2460 if (sendCount == 0) { /* first parameter */
2461 // we know that dpl(hxb) is the result, so
2463 _startLazyDPSEvaluation ();
2465 aopOp (IC_LEFT (sic), sic, FALSE,
2466 (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2468 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2471 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2472 FALSE, FALSE, NULL);
2473 if (strcmp (l, fReturn[offset])) {
2474 emitcode ("mov", "%s,%s",
2480 _endLazyDPSEvaluation ();
2481 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2483 } else { /* if more parameter in registers */
2484 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2486 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
2487 FALSE, FALSE, NULL));
2489 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2495 /*-----------------------------------------------------------------*/
2496 /* genCall - generates a call statement */
2497 /*-----------------------------------------------------------------*/
2499 genCall (iCode * ic)
2502 bool restoreBank = FALSE;
2503 bool swapBanks = FALSE;
2505 D (emitcode (";", "genCall "););
2507 /* if we are calling a not _naked function that is not using
2508 the same register bank then we need to save the
2509 destination registers on the stack */
2510 dtype = operandType (IC_LEFT (ic));
2511 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2512 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2513 IFFUNC_ISISR (currFunc->type))
2517 /* This is unexpected; the bank should have been saved in
2520 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2526 /* if caller saves & we have not saved then */
2530 /* if send set is not empty the assign */
2531 /* We've saved all the registers we care about;
2532 * therefore, we may clobber any register not used
2533 * in the calling convention (i.e. anything not in
2538 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2539 genSend(reverseSet(_G.sendSet));
2541 genSend(_G.sendSet);
2548 emitcode ("mov", "psw,#!constbyte",
2549 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2553 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2554 OP_SYMBOL (IC_LEFT (ic))->rname :
2555 OP_SYMBOL (IC_LEFT (ic))->name));
2559 emitcode ("mov", "psw,#!constbyte",
2560 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2563 /* if we need assign a result value */
2564 if ((IS_ITEMP (IC_RESULT (ic)) &&
2565 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2566 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2567 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2568 IS_TRUE_SYMOP (IC_RESULT (ic)))
2570 if (isOperandInFarSpace (IC_RESULT (ic))
2571 && getSize (operandType (IC_RESULT (ic))) <= 2)
2573 int size = getSize (operandType (IC_RESULT (ic)));
2575 /* Special case for 1 or 2 byte return in far space. */
2579 emitcode ("mov", "b,%s", fReturn[1]);
2582 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2583 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2587 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2589 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2594 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2597 assignResultValue (IC_RESULT (ic));
2599 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2603 /* adjust the stack for parameters if
2605 if (ic->parmBytes) {
2607 if (options.stack10bit) {
2608 if (ic->parmBytes <= 10) {
2609 emitcode(";","stack adjustment for parms");
2610 for (i=0; i < ic->parmBytes ; i++) {
2611 emitcode("pop","acc");
2615 emitcode ("clr","c");
2616 emitcode ("mov","a,sp");
2617 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2618 emitcode ("mov","sp,a");
2619 emitcode ("mov","a,esp");
2620 emitcode ("anl","a,#3");
2621 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2622 emitcode ("mov","esp,a");
2626 if (ic->parmBytes > 3) {
2627 emitcode ("mov", "a,%s", spname);
2628 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2629 emitcode ("mov", "%s,a", spname);
2631 for (i = 0; i < ic->parmBytes; i++)
2632 emitcode ("dec", "%s", spname);
2636 /* if we hade saved some registers then unsave them */
2638 unsaveRegisters (ic);
2640 /* if register bank was saved then pop them */
2642 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2645 /*-----------------------------------------------------------------*/
2646 /* genPcall - generates a call by pointer statement */
2647 /*-----------------------------------------------------------------*/
2649 genPcall (iCode * ic)
2652 symbol *rlbl = newiTempLabel (NULL);
2653 bool restoreBank=FALSE;
2655 D (emitcode (";", "genPcall ");
2659 /* if caller saves & we have not saved then */
2663 /* if we are calling a function that is not using
2664 the same register bank then we need to save the
2665 destination registers on the stack */
2666 dtype = operandType (IC_LEFT (ic));
2667 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2668 IFFUNC_ISISR (currFunc->type) &&
2669 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2670 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2674 /* push the return address on to the stack */
2675 emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2676 emitcode ("push", "acc");
2677 emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2678 emitcode ("push", "acc");
2680 if (options.model == MODEL_FLAT24)
2682 emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2683 emitcode ("push", "acc");
2686 /* now push the calling address */
2687 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2689 pushSide (IC_LEFT (ic), FPTRSIZE);
2691 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2693 /* if send set is not empty the assign */
2696 genSend(reverseSet(_G.sendSet));
2700 emitcode ("ret", "");
2701 emitcode ("", "!tlabeldef", (rlbl->key + 100));
2704 /* if we need assign a result value */
2705 if ((IS_ITEMP (IC_RESULT (ic)) &&
2706 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2707 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2708 IS_TRUE_SYMOP (IC_RESULT (ic)))
2712 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2715 assignResultValue (IC_RESULT (ic));
2717 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2720 /* adjust the stack for parameters if
2725 if (options.stack10bit) {
2726 if (ic->parmBytes <= 10) {
2727 emitcode(";","stack adjustment for parms");
2728 for (i=0; i < ic->parmBytes ; i++) {
2729 emitcode("pop","acc");
2733 emitcode ("clr","c");
2734 emitcode ("mov","a,sp");
2735 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2736 emitcode ("mov","sp,a");
2737 emitcode ("mov","a,esp");
2738 emitcode ("anl","a,#3");
2739 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2740 emitcode ("mov","esp,a");
2744 if (ic->parmBytes > 3) {
2745 emitcode ("mov", "a,%s", spname);
2746 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2747 emitcode ("mov", "%s,a", spname);
2750 for (i = 0; i < ic->parmBytes; i++)
2751 emitcode ("dec", "%s", spname);
2755 /* if register bank was saved then unsave them */
2757 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2759 /* if we hade saved some registers then
2762 unsaveRegisters (ic);
2766 /*-----------------------------------------------------------------*/
2767 /* resultRemat - result is rematerializable */
2768 /*-----------------------------------------------------------------*/
2770 resultRemat (iCode * ic)
2772 if (SKIP_IC (ic) || ic->op == IFX)
2775 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2777 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2778 if (sym->remat && !POINTER_SET (ic))
2785 #if defined(__BORLANDC__) || defined(_MSC_VER)
2786 #define STRCASECMP stricmp
2788 #define STRCASECMP strcasecmp
2791 /*-----------------------------------------------------------------*/
2792 /* inExcludeList - return 1 if the string is in exclude Reg list */
2793 /*-----------------------------------------------------------------*/
2795 inExcludeList (char *s)
2799 if (options.excludeRegs[i] &&
2800 STRCASECMP (options.excludeRegs[i], "none") == 0)
2803 for (i = 0; options.excludeRegs[i]; i++)
2805 if (options.excludeRegs[i] &&
2806 STRCASECMP (s, options.excludeRegs[i]) == 0)
2812 /*-----------------------------------------------------------------*/
2813 /* genFunction - generated code for function entry */
2814 /*-----------------------------------------------------------------*/
2816 genFunction (iCode * ic)
2820 bool switchedPSW = FALSE;
2822 D (emitcode (";", "genFunction "););
2825 /* create the function header */
2826 emitcode (";", "-----------------------------------------");
2827 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2828 emitcode (";", "-----------------------------------------");
2830 emitcode ("", "%s:", sym->rname);
2831 ftype = operandType (IC_LEFT (ic));
2833 if (IFFUNC_ISNAKED(ftype))
2835 emitcode(";", "naked function: no prologue.");
2839 if (options.stack_probe)
2840 emitcode ("lcall","__stack_probe");
2841 /* if critical function then turn interrupts off */
2842 if (IFFUNC_ISCRITICAL (ftype))
2843 emitcode ("clr", "ea");
2845 /* here we need to generate the equates for the
2846 register bank if required */
2847 if (FUNC_REGBANK (ftype) != rbank)
2851 rbank = FUNC_REGBANK (ftype);
2852 for (i = 0; i < ds390_nRegs; i++)
2854 if (regs390[i].print) {
2855 if (strcmp (regs390[i].base, "0") == 0)
2856 emitcode ("", "%s !equ !constbyte",
2858 8 * rbank + regs390[i].offset);
2860 emitcode ("", "%s !equ %s + !constbyte",
2863 8 * rbank + regs390[i].offset);
2868 /* if this is an interrupt service routine then
2869 save acc, b, dpl, dph */
2870 if (IFFUNC_ISISR (sym->type))
2872 if (!inExcludeList ("acc"))
2873 emitcode ("push", "acc");
2874 if (!inExcludeList ("b"))
2875 emitcode ("push", "b");
2876 if (!inExcludeList ("dpl"))
2877 emitcode ("push", "dpl");
2878 if (!inExcludeList ("dph"))
2879 emitcode ("push", "dph");
2880 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2882 emitcode ("push", "dpx");
2883 /* Make sure we're using standard DPTR */
2884 emitcode ("push", "dps");
2885 emitcode ("mov", "dps,#0");
2886 if (options.stack10bit)
2888 /* This ISR could conceivably use DPTR2. Better save it. */
2889 emitcode ("push", "dpl1");
2890 emitcode ("push", "dph1");
2891 emitcode ("push", "dpx1");
2892 emitcode ("push", DP2_RESULT_REG);
2895 /* if this isr has no bank i.e. is going to
2896 run with bank 0 , then we need to save more
2898 if (!FUNC_REGBANK (sym->type))
2902 /* if this function does not call any other
2903 function then we can be economical and
2904 save only those registers that are used */
2905 if (!IFFUNC_HASFCALL(sym->type))
2908 /* if any registers used */
2911 /* save the registers used */
2912 for (i = 0; i < sym->regsUsed->size; i++)
2914 if (bitVectBitValue (sym->regsUsed, i) ||
2915 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2916 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2923 /* this function has a function call cannot
2924 determines register usage so we will have to push the
2926 saveRBank (0, ic, FALSE);
2927 if (options.parms_in_bank1) {
2928 for (i=0; i < 8 ; i++ ) {
2929 emitcode ("push","%s",rb1regs[i]);
2936 /* This ISR uses a non-zero bank.
2938 * We assume that the bank is available for our
2941 * However, if this ISR calls a function which uses some
2942 * other bank, we must save that bank entirely.
2944 unsigned long banksToSave = 0;
2946 if (IFFUNC_HASFCALL(sym->type))
2949 #define MAX_REGISTER_BANKS 4
2954 for (i = ic; i; i = i->next)
2956 if (i->op == ENDFUNCTION)
2958 /* we got to the end OK. */
2966 dtype = operandType (IC_LEFT(i));
2968 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2970 /* Mark this bank for saving. */
2971 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2973 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2977 banksToSave |= (1 << FUNC_REGBANK(dtype));
2980 /* And note that we don't need to do it in
2988 /* This is a mess; we have no idea what
2989 * register bank the called function might
2992 * The only thing I can think of to do is
2993 * throw a warning and hope.
2995 werror(W_FUNCPTR_IN_USING_ISR);
2999 if (banksToSave && options.useXstack)
3001 /* Since we aren't passing it an ic,
3002 * saveRBank will assume r0 is available to abuse.
3004 * So switch to our (trashable) bank now, so
3005 * the caller's R0 isn't trashed.
3007 emitcode ("push", "psw");
3008 emitcode ("mov", "psw,#!constbyte",
3009 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3013 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3015 if (banksToSave & (1 << ix))
3017 saveRBank(ix, NULL, FALSE);
3021 // jwk: this needs a closer look
3022 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3027 /* if callee-save to be used for this function
3028 then save the registers being used in this function */
3029 if (IFFUNC_CALLEESAVES(sym->type))
3033 /* if any registers used */
3036 /* save the registers used */
3037 for (i = 0; i < sym->regsUsed->size; i++)
3039 if (bitVectBitValue (sym->regsUsed, i) ||
3040 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3042 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3050 /* set the register bank to the desired value */
3051 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3054 emitcode ("push", "psw");
3055 emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3058 if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3059 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3060 if (options.stack10bit) {
3061 emitcode ("push","_bpx");
3062 emitcode ("push","_bpx+1");
3063 emitcode ("mov","_bpx,%s",spname);
3064 emitcode ("mov","_bpx+1,esp");
3065 emitcode ("anl","_bpx+1,#3");
3067 if (options.useXstack) {
3068 emitcode ("mov", "r0,%s", spname);
3069 emitcode ("mov", "a,_bp");
3070 emitcode ("movx", "@r0,a");
3071 emitcode ("inc", "%s", spname);
3073 /* set up the stack */
3074 emitcode ("push", "_bp"); /* save the callers stack */
3076 emitcode ("mov", "_bp,%s", spname);
3080 /* adjust the stack for the function */
3083 if (options.stack10bit) {
3084 if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
3085 assert (sym->recvSize <= 4);
3086 if (sym->stack <= 8) {
3087 while (i--) emitcode ("push","acc");
3090 emitcode ("mov","a,sp");
3091 emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3092 emitcode ("mov","sp,a");
3093 emitcode ("mov","a,esp");
3094 emitcode ("anl","a,#3");
3095 emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3096 emitcode ("mov","esp,a");
3101 werror (W_STACK_OVERFLOW, sym->name);
3103 if (i > 3 && sym->recvSize < 4) {
3105 emitcode ("mov", "a,sp");
3106 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3107 emitcode ("mov", "sp,a");
3111 emitcode ("inc", "sp");
3118 emitcode ("mov", "a,_spx");
3119 emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3120 emitcode ("mov", "_spx,a");
3125 /*-----------------------------------------------------------------*/
3126 /* genEndFunction - generates epilogue for functions */
3127 /*-----------------------------------------------------------------*/
3129 genEndFunction (iCode * ic)
3131 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3133 D (emitcode (";", "genEndFunction "););
3135 if (IFFUNC_ISNAKED(sym->type))
3137 emitcode(";", "naked function: no epilogue.");
3141 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3142 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3144 if (options.stack10bit) {
3146 emitcode ("mov", "sp,_bpx", spname);
3147 emitcode ("mov", "esp,_bpx+1", spname);
3150 emitcode ("mov", "%s,_bp", spname);
3154 /* if use external stack but some variables were
3155 added to the local stack then decrement the
3157 if (options.useXstack && sym->stack) {
3158 emitcode ("mov", "a,sp");
3159 emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3160 emitcode ("mov", "sp,a");
3164 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3165 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3167 if (options.useXstack) {
3168 emitcode ("mov", "r0,%s", spname);
3169 emitcode ("movx", "a,@r0");
3170 emitcode ("mov", "_bp,a");
3171 emitcode ("dec", "%s", spname);
3173 if (options.stack10bit) {
3174 emitcode ("pop", "_bpx+1");
3175 emitcode ("pop", "_bpx");
3177 emitcode ("pop", "_bp");
3182 /* restore the register bank */
3183 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3185 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3186 || !options.useXstack)
3188 /* Special case of ISR using non-zero bank with useXstack
3191 emitcode ("pop", "psw");
3195 if (IFFUNC_ISISR (sym->type))
3198 /* now we need to restore the registers */
3199 /* if this isr has no bank i.e. is going to
3200 run with bank 0 , then we need to save more
3202 if (!FUNC_REGBANK (sym->type))
3205 /* if this function does not call any other
3206 function then we can be economical and
3207 save only those registers that are used */
3208 if (!IFFUNC_HASFCALL(sym->type))
3211 /* if any registers used */
3214 /* save the registers used */
3215 for (i = sym->regsUsed->size; i >= 0; i--)
3217 if (bitVectBitValue (sym->regsUsed, i) ||
3218 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3219 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3226 /* this function has a function call cannot
3227 determines register usage so we will have to pop the
3229 if (options.parms_in_bank1) {
3230 for (i = 7 ; i >= 0 ; i-- ) {
3231 emitcode ("pop","%s",rb1regs[i]);
3234 unsaveRBank (0, ic, FALSE);
3239 /* This ISR uses a non-zero bank.
3241 * Restore any register banks saved by genFunction
3244 // jwk: this needs a closer look
3245 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3248 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3250 if (savedBanks & (1 << ix))
3252 unsaveRBank(ix, NULL, FALSE);
3256 if (options.useXstack)
3258 /* Restore bank AFTER calling unsaveRBank,
3259 * since it can trash r0.
3261 emitcode ("pop", "psw");
3265 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3267 if (options.stack10bit)
3269 emitcode ("pop", DP2_RESULT_REG);
3270 emitcode ("pop", "dpx1");
3271 emitcode ("pop", "dph1");
3272 emitcode ("pop", "dpl1");
3274 emitcode ("pop", "dps");
3275 emitcode ("pop", "dpx");
3277 if (!inExcludeList ("dph"))
3278 emitcode ("pop", "dph");
3279 if (!inExcludeList ("dpl"))
3280 emitcode ("pop", "dpl");
3281 if (!inExcludeList ("b"))
3282 emitcode ("pop", "b");
3283 if (!inExcludeList ("acc"))
3284 emitcode ("pop", "acc");
3286 if (IFFUNC_ISCRITICAL (sym->type))
3287 emitcode ("setb", "ea");
3289 /* if debug then send end of function */
3290 if (options.debug && currFunc) {
3292 emitcode ("", "C$%s$%d$%d$%d ==.",
3293 FileBaseName (ic->filename), currFunc->lastLine,
3294 ic->level, ic->block);
3295 if (IS_STATIC (currFunc->etype))
3296 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3298 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3302 emitcode ("reti", "");
3306 if (IFFUNC_ISCRITICAL (sym->type))
3307 emitcode ("setb", "ea");
3309 if (IFFUNC_CALLEESAVES(sym->type))
3313 /* if any registers used */
3316 /* save the registers used */
3317 for (i = sym->regsUsed->size; i >= 0; i--)
3319 if (bitVectBitValue (sym->regsUsed, i) ||
3320 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3321 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3327 /* if debug then send end of function */
3328 if (options.debug && currFunc)
3331 emitcode ("", "C$%s$%d$%d$%d ==.",
3332 FileBaseName (ic->filename), currFunc->lastLine,
3333 ic->level, ic->block);
3334 if (IS_STATIC (currFunc->etype))
3335 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3337 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3341 emitcode ("ret", "");
3346 /*-----------------------------------------------------------------*/
3347 /* genJavaNativeRet - generate code for return JavaNative */
3348 /*-----------------------------------------------------------------*/
3349 static void genJavaNativeRet(iCode *ic)
3353 aopOp (IC_LEFT (ic), ic, FALSE,
3354 AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
3355 size = AOP_SIZE (IC_LEFT (ic));
3359 /* it is assigned to GPR0-R3 then push them */
3360 if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3361 aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3362 for (i = 0 ; i < size ; i++ ) {
3363 emitcode ("push","%s",
3364 aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3366 for (i = (size-1) ; i >= 0 ; i--) {
3367 emitcode ("pop","a%s",javaRet[i]);
3370 for (i = 0 ; i < size ; i++)
3371 emitcode ("mov","%s,%s",javaRet[i],
3372 aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3374 for (i = size ; i < 4 ; i++ )
3375 emitcode ("mov","%s,#0",javaRet[i]);
3379 /*-----------------------------------------------------------------*/
3380 /* genRet - generate code for return statement */
3381 /*-----------------------------------------------------------------*/
3385 int size, offset = 0, pushed = 0;
3387 D (emitcode (";", "genRet "););
3389 /* if we have no return value then
3390 just generate the "ret" */
3394 /* if this is a JavaNative function then return
3395 value in different register */
3396 if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3397 genJavaNativeRet(ic);
3400 /* we have something to return then
3401 move the return value into place */
3402 aopOp (IC_LEFT (ic), ic, FALSE,
3403 (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
3404 size = AOP_SIZE (IC_LEFT (ic));
3406 _startLazyDPSEvaluation ();
3410 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3412 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3414 emitcode ("push", "%s", l);
3419 /* Since A is the last element of fReturn,
3420 * is is OK to clobber it in the aopGet.
3422 l = aopGet (AOP (IC_LEFT (ic)), offset,
3423 FALSE, FALSE, NULL);
3424 if (strcmp (fReturn[offset], l))
3425 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3428 _endLazyDPSEvaluation ();
3435 if (strcmp (fReturn[pushed], "a"))
3436 emitcode ("pop", fReturn[pushed]);
3438 emitcode ("pop", "acc");
3441 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3444 /* generate a jump to the return label
3445 if the next is not the return statement */
3446 if (!(ic->next && ic->next->op == LABEL &&
3447 IC_LABEL (ic->next) == returnLabel))
3449 emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3453 /*-----------------------------------------------------------------*/
3454 /* genLabel - generates a label */
3455 /*-----------------------------------------------------------------*/
3457 genLabel (iCode * ic)
3459 /* special case never generate */
3460 if (IC_LABEL (ic) == entryLabel)
3463 D (emitcode (";", "genLabel ");
3466 emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3469 /*-----------------------------------------------------------------*/
3470 /* genGoto - generates a ljmp */
3471 /*-----------------------------------------------------------------*/
3473 genGoto (iCode * ic)
3475 D (emitcode (";", "genGoto ");
3477 emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3480 /*-----------------------------------------------------------------*/
3481 /* findLabelBackwards: walks back through the iCode chain looking */
3482 /* for the given label. Returns number of iCode instructions */
3483 /* between that label and given ic. */
3484 /* Returns zero if label not found. */
3485 /*-----------------------------------------------------------------*/
3487 findLabelBackwards (iCode * ic, int key)
3496 /* If we have any pushes or pops, we cannot predict the distance.
3497 I don't like this at all, this should be dealt with in the
3499 if (ic->op == IPUSH || ic->op == IPOP) {
3503 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3505 /* printf("findLabelBackwards = %d\n", count); */
3513 /*-----------------------------------------------------------------*/
3514 /* genPlusIncr :- does addition with increment if possible */
3515 /*-----------------------------------------------------------------*/
3517 genPlusIncr (iCode * ic)
3519 unsigned int icount;
3520 unsigned int size = getDataSize (IC_RESULT (ic));
3522 /* will try to generate an increment */
3523 /* if the right side is not a literal
3525 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3528 /* if the literal value of the right hand side
3529 is greater than 4 then it is not worth it */
3530 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3533 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3534 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3536 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
3540 /* if increment 16 bits in register */
3542 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3543 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3544 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3553 /* If the next instruction is a goto and the goto target
3554 * is <= 5 instructions previous to this, we can generate
3555 * jumps straight to that target.
3557 if (ic->next && ic->next->op == GOTO
3558 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3561 D(emitcode (";", "tail increment optimized (range %d)", labelRange););
3562 tlbl = IC_LABEL (ic->next);
3567 tlbl = newiTempLabel (NULL);
3571 l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
3572 emitcode ("inc", "%s", l);
3574 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3575 IS_AOP_PREG (IC_RESULT (ic)))
3577 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3581 emitcode ("clr", "a");
3582 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3585 l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
3586 emitcode ("inc", "%s", l);
3589 if (!strcmp(l, "acc"))
3591 emitcode("jnz", "!tlabel", tlbl->key + 100);
3593 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3594 IS_AOP_PREG (IC_RESULT (ic)))
3596 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3600 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3603 l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
3604 emitcode ("inc", "%s", l);
3608 if (!strcmp(l, "acc"))
3610 emitcode("jnz", "!tlabel", tlbl->key + 100);
3612 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3613 IS_AOP_PREG (IC_RESULT (ic)))
3615 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3619 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3622 l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
3623 emitcode ("inc", "%s", l); }
3627 emitcode ("", "!tlabeldef", tlbl->key + 100);
3632 if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3633 !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 &&
3634 options.model == MODEL_FLAT24 ) {
3638 emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, NULL));
3640 emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, NULL));
3642 emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3645 while (icount--) emitcode ("inc","dptr");
3649 if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3650 AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3652 emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3653 while (icount--) emitcode ("inc","dptr");
3654 emitcode ("mov","dps,#0");
3658 /* if the sizes are greater than 1 then we cannot */
3659 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3660 AOP_SIZE (IC_LEFT (ic)) > 1)
3663 /* we can if the aops of the left & result match or
3664 if they are in registers and the registers are the
3667 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3668 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3669 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3674 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3675 emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3676 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3681 _startLazyDPSEvaluation ();
3684 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3686 _endLazyDPSEvaluation ();
3695 /*-----------------------------------------------------------------*/
3696 /* outBitAcc - output a bit in acc */
3697 /*-----------------------------------------------------------------*/
3699 outBitAcc (operand * result)
3701 symbol *tlbl = newiTempLabel (NULL);
3702 /* if the result is a bit */
3703 if (AOP_TYPE (result) == AOP_CRY)
3705 aopPut (AOP (result), "a", 0);
3709 emitcode ("jz", "!tlabel", tlbl->key + 100);
3710 emitcode ("mov", "a,%s", one);
3711 emitcode ("", "!tlabeldef", tlbl->key + 100);
3716 /*-----------------------------------------------------------------*/
3717 /* genPlusBits - generates code for addition of two bits */
3718 /*-----------------------------------------------------------------*/
3720 genPlusBits (iCode * ic)
3722 D (emitcode (";", "genPlusBits "););
3724 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3726 symbol *lbl = newiTempLabel (NULL);
3727 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3728 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3729 emitcode ("cpl", "c");
3730 emitcode ("", "!tlabeldef", (lbl->key + 100));
3731 outBitC (IC_RESULT (ic));
3735 emitcode ("clr", "a");
3736 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3737 emitcode ("rlc", "a");
3738 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3739 emitcode ("addc", "a,#0");
3740 outAcc (IC_RESULT (ic));
3745 adjustArithmeticResult (iCode * ic)
3747 if (opIsGptr (IC_RESULT (ic)) &&
3748 opIsGptr (IC_LEFT (ic)) &&
3749 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3751 aopPut (AOP (IC_RESULT (ic)),
3752 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3756 if (opIsGptr (IC_RESULT (ic)) &&
3757 opIsGptr (IC_RIGHT (ic)) &&
3758 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3760 aopPut (AOP (IC_RESULT (ic)),
3761 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3765 if (opIsGptr (IC_RESULT (ic)) &&
3766 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3767 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3768 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3769 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3772 SNPRINTF (buff, sizeof(buff),
3773 "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3774 aopPut (AOP (IC_RESULT (ic)), buff, GPTRSIZE - 1);
3778 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
3779 // generates the result if possible. If result is generated, returns TRUE; otherwise
3780 // returns false and caller must deal with fact that result isn't aopOp'd.
3781 bool aopOp3(iCode * ic)
3783 bool dp1InUse, dp2InUse;
3786 // First, generate the right opcode. DPTR may be used if neither left nor result are
3789 // D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
3790 // AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
3791 // AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
3792 // AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
3794 // D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
3795 // AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
3796 // AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
3797 // AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
3801 // Right uses DPTR unless left or result is an AOP_STR.
3802 aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)));
3804 // if the right used DPTR, left MUST use DPTR2.
3805 // if the right used DPTR2, left MUST use DPTR.
3806 // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
3807 // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
3808 // enabling us to assign DPTR to result.
3810 if (AOP_USESDPTR(IC_RIGHT(ic)))
3814 else if (AOP_USESDPTR2(IC_RIGHT(ic)))
3820 if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
3830 aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
3832 // We've op'd the left & right. So, if left or right are the same operand as result,
3833 // we know aopOp will succeed, and we can just do it & bail.
3834 if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)) ||
3835 isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
3837 // D(emitcode(";", "aopOp3: (left | right) & result equal"););
3838 aopOp(IC_RESULT(ic),ic,TRUE, FALSE);
3842 // Note which dptrs are currently in use.
3843 dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
3844 dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
3846 // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot
3848 if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
3853 // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
3854 if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
3859 // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck
3860 if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
3865 aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
3867 // Some sanity checking...
3868 if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
3871 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
3872 __FILE__, __LINE__, ic->filename, ic->lineno);
3873 emitcode(";", ">>> unexpected DPTR here.");
3876 if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
3879 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
3880 __FILE__, __LINE__, ic->filename, ic->lineno);
3881 emitcode(";", ">>> unexpected DPTR2 here.");
3887 // Macro to aopOp all three operands of an ic. If this cannot be done,
3888 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3889 // will be set TRUE. The caller must then handle the case specially, noting
3890 // that the IC_RESULT operand is not aopOp'd.
3892 #define AOP_OP_3_NOFATAL(ic, rc) \
3893 do { rc = !aopOp3(ic); } while (0)
3895 // aopOp the left & right operands of an ic.
3896 #define AOP_OP_2(ic) \
3897 aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
3898 aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
3900 // convienience macro.
3901 #define AOP_SET_LOCALS(ic) \
3902 left = IC_LEFT(ic); \
3903 right = IC_RIGHT(ic); \
3904 result = IC_RESULT(ic);
3907 // Given an integer value of pushedSize bytes on the stack,
3908 // adjust it to be resultSize bytes, either by discarding
3909 // the most significant bytes or by zero-padding.
3911 // On exit from this macro, pushedSize will have been adjusted to
3912 // equal resultSize, and ACC may be trashed.
3913 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3914 /* If the pushed data is bigger than the result, \
3915 * simply discard unused bytes. Icky, but works. \
3917 while (pushedSize > resultSize) \
3919 D (emitcode (";", "discarding unused result byte."););\
3920 emitcode ("pop", "acc"); \
3923 if (pushedSize < resultSize) \
3925 emitcode ("clr", "a"); \
3926 /* Conversly, we haven't pushed enough here. \
3927 * just zero-pad, and all is well. \
3929 while (pushedSize < resultSize) \
3931 emitcode("push", "acc"); \
3935 assert(pushedSize == resultSize);
3937 /*-----------------------------------------------------------------*/
3938 /* genPlus - generates code for addition */
3939 /*-----------------------------------------------------------------*/
3941 genPlus (iCode * ic)
3943 int size, offset = 0;
3947 D (emitcode (";", "genPlus "););
3949 /* special cases :- */
3950 if ( AOP_IS_STR(IC_LEFT(ic)) &&
3951 isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
3952 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
3953 size = floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
3955 while (size--) emitcode ("inc","dptr");
3957 emitcode ("mov","a,dpl");
3958 emitcode ("add","a,#!constbyte",size & 0xff);
3959 emitcode ("mov","dpl,a");
3960 emitcode ("mov","a,dph");
3961 emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
3962 emitcode ("mov","dph,a");
3963 emitcode ("mov","a,dpx");
3964 emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
3965 emitcode ("mov","dpx,a");
3967 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
3970 if ( IS_SYMOP(IC_LEFT(ic)) &&
3971 OP_SYMBOL(IC_LEFT(ic))->remat &&
3972 isOperandInFarSpace(IC_RIGHT(ic))) {
3973 operand *op = IC_RIGHT(ic);
3974 IC_RIGHT(ic) = IC_LEFT(ic);
3978 AOP_OP_3_NOFATAL (ic, pushResult);
3982 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3987 /* if literal, literal on the right or
3988 if left requires ACC or right is already
3990 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3991 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3992 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3994 operand *t = IC_RIGHT (ic);
3995 IC_RIGHT (ic) = IC_LEFT (ic);
3997 emitcode (";", "Swapped plus args.");
4000 /* if both left & right are in bit
4002 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4003 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4009 /* if left in bit space & right literal */
4010 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4011 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4013 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4014 /* if result in bit space */
4015 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4017 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4018 emitcode ("cpl", "c");
4019 outBitC (IC_RESULT (ic));
4023 size = getDataSize (IC_RESULT (ic));
4024 _startLazyDPSEvaluation ();
4027 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4028 emitcode ("addc", "a,#0");
4029 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4031 _endLazyDPSEvaluation ();
4036 /* if I can do an increment instead
4037 of add then GOOD for ME */
4038 if (genPlusIncr (ic) == TRUE)
4040 emitcode (";", "did genPlusIncr");
4045 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4047 _startLazyDPSEvaluation ();
4050 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4052 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4054 emitcode ("add", "a,%s",
4055 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, DP2_RESULT_REG));
4057 emitcode ("addc", "a,%s",
4058 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, DP2_RESULT_REG));
4062 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4064 /* right is going to use ACC or we would have taken the
4067 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4069 D(emitcode(";", "+ AOP_ACC special case."););
4070 emitcode("xch", "a, %s", DP2_RESULT_REG);
4072 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4075 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4078 emitcode("add", "a, %s", DP2_RESULT_REG);
4082 emitcode ("add", "a,%s",
4083 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE,
4089 emitcode ("addc", "a,%s",
4090 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE,
4096 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4100 emitcode ("push", "acc");
4104 _endLazyDPSEvaluation ();
4108 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4110 size = getDataSize (IC_LEFT (ic));
4111 rSize = getDataSize (IC_RESULT (ic));
4113 ADJUST_PUSHED_RESULT(size, rSize);
4115 _startLazyDPSEvaluation ();
4118 emitcode ("pop", "acc");
4119 aopPut (AOP (IC_RESULT (ic)), "a", size);
4121 _endLazyDPSEvaluation ();
4124 adjustArithmeticResult (ic);
4127 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4128 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4129 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4132 /*-----------------------------------------------------------------*/
4133 /* genMinusDec :- does subtraction with deccrement if possible */
4134 /*-----------------------------------------------------------------*/
4136 genMinusDec (iCode * ic)
4138 unsigned int icount;
4139 unsigned int size = getDataSize (IC_RESULT (ic));
4141 /* will try to generate an increment */
4142 /* if the right side is not a literal
4144 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4147 /* if the literal value of the right hand side
4148 is greater than 4 then it is not worth it */
4149 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4152 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4153 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4155 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
4159 /* if decrement 16 bits in register */
4160 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4161 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4162 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4171 /* If the next instruction is a goto and the goto target
4172 * is <= 5 instructions previous to this, we can generate
4173 * jumps straight to that target.
4175 if (ic->next && ic->next->op == GOTO
4176 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4179 emitcode (";", "tail decrement optimized (range %d)", labelRange);
4180 tlbl = IC_LABEL (ic->next);
4185 tlbl = newiTempLabel (NULL);
4189 l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
4190 emitcode ("dec", "%s", l);
4192 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4193 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4194 IS_AOP_PREG (IC_RESULT (ic)))
4196 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4200 emitcode ("mov", "a,#!constbyte",0xff);
4201 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4203 l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, NULL, NULL);
4204 emitcode ("dec", "%s", l);
4207 if (!strcmp(l, "acc"))
4209 emitcode("jnz", "!tlabel", tlbl->key + 100);
4211 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4212 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4213 IS_AOP_PREG (IC_RESULT (ic)))
4215 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4219 emitcode ("mov", "a,#!constbyte",0xff);
4220 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4222 l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, NULL, NULL);
4223 emitcode ("dec", "%s", l);
4227 if (!strcmp(l, "acc"))
4229 emitcode("jnz", "!tlabel", tlbl->key + 100);
4231 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4232 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4233 IS_AOP_PREG (IC_RESULT (ic)))
4235 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4239 emitcode ("mov", "a,#!constbyte",0xff);
4240 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4242 l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, NULL, NULL);
4243 emitcode ("dec", "%s", l);
4247 emitcode ("", "!tlabeldef", tlbl->key + 100);
4252 /* if the sizes are greater than 1 then we cannot */
4253 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4254 AOP_SIZE (IC_LEFT (ic)) > 1)
4257 /* we can if the aops of the left & result match or
4258 if they are in registers and the registers are the
4261 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4262 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4263 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4266 _startLazyDPSEvaluation ();
4269 emitcode ("dec", "%s",
4270 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
4272 _endLazyDPSEvaluation ();
4280 /*-----------------------------------------------------------------*/
4281 /* addSign - complete with sign */
4282 /*-----------------------------------------------------------------*/
4284 addSign (operand * result, int offset, int sign)
4286 int size = (getDataSize (result) - offset);
4289 _startLazyDPSEvaluation();
4292 emitcode ("rlc", "a");
4293 emitcode ("subb", "a,acc");
4296 aopPut (AOP (result), "a", offset++);
4303 aopPut (AOP (result), zero, offset++);
4306 _endLazyDPSEvaluation();
4310 /*-----------------------------------------------------------------*/
4311 /* genMinusBits - generates code for subtraction of two bits */
4312 /*-----------------------------------------------------------------*/
4314 genMinusBits (iCode * ic)
4316 symbol *lbl = newiTempLabel (NULL);
4318 D (emitcode (";", "genMinusBits "););
4320 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4322 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4323 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4324 emitcode ("cpl", "c");
4325 emitcode ("", "!tlabeldef", (lbl->key + 100));
4326 outBitC (IC_RESULT (ic));
4330 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4331 emitcode ("subb", "a,acc");
4332 emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4333 emitcode ("inc", "a");
4334 emitcode ("", "!tlabeldef", (lbl->key + 100));
4335 aopPut (AOP (IC_RESULT (ic)), "a", 0);
4336 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4340 /*-----------------------------------------------------------------*/
4341 /* genMinus - generates code for subtraction */
4342 /*-----------------------------------------------------------------*/
4344 genMinus (iCode * ic)
4346 int size, offset = 0;
4351 D (emitcode (";", "genMinus "););
4353 AOP_OP_3_NOFATAL(ic, pushResult);
4357 /* special cases :- */
4358 /* if both left & right are in bit space */
4359 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4360 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4366 /* if I can do an decrement instead
4367 of subtract then GOOD for ME */
4368 if (genMinusDec (ic) == TRUE)
4373 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4375 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4381 lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4386 /* if literal, add a,#-lit, else normal subb */
4387 _startLazyDPSEvaluation ();
4389 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4390 if (AOP_USESDPTR(IC_RIGHT(ic))) {
4391 emitcode ("mov","b,%s",
4392 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4393 MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4394 emitcode ("subb","a,b");
4396 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4397 emitcode ("subb", "a,%s",
4398 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE,
4402 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4403 /* first add without previous c */
4405 if (!size && lit==-1) {
4406 emitcode ("dec", "a");
4408 emitcode ("add", "a,#!constbyte",
4409 (unsigned int) (lit & 0x0FFL));
4412 emitcode ("addc", "a,#!constbyte",
4413 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4418 emitcode ("push", "acc");
4420 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4424 _endLazyDPSEvaluation ();
4428 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4430 size = getDataSize (IC_LEFT (ic));
4431 rSize = getDataSize (IC_RESULT (ic));
4433 ADJUST_PUSHED_RESULT(size, rSize);
4435 _startLazyDPSEvaluation ();
4438 emitcode ("pop", "acc");
4439 aopPut (AOP (IC_RESULT (ic)), "a", size);
4441 _endLazyDPSEvaluation ();
4444 adjustArithmeticResult (ic);
4447 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4448 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4449 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4453 /*-----------------------------------------------------------------*/
4454 /* genMultbits :- multiplication of bits */
4455 /*-----------------------------------------------------------------*/
4457 genMultbits (operand * left,
4462 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4463 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4464 aopOp(result, ic, TRUE, FALSE);
4469 /*-----------------------------------------------------------------*/
4470 /* genMultOneByte : 8*8=8/16 bit multiplication */
4471 /*-----------------------------------------------------------------*/
4473 genMultOneByte (operand * left,
4478 sym_link *opetype = operandType (result);
4482 /* (if two literals: the value is computed before) */
4483 /* if one literal, literal on the right */
4484 if (AOP_TYPE (left) == AOP_LIT)
4489 emitcode (";", "swapped left and right");
4492 if (SPEC_USIGN(opetype)
4493 // ignore the sign of left and right, what else can we do?
4494 || (SPEC_USIGN(operandType(left)) &&
4495 SPEC_USIGN(operandType(right)))) {
4496 // just an unsigned 8*8=8/16 multiply
4497 //emitcode (";","unsigned");
4498 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4499 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4500 emitcode ("mul", "ab");
4502 _G.accInUse++; _G.bInUse++;
4503 aopOp(result, ic, TRUE, FALSE);
4505 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4507 // this should never happen
4508 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4509 AOP_SIZE(result), __FILE__, lineno);
4513 aopPut (AOP (result), "a", 0);
4514 _G.accInUse--; _G.bInUse--;
4515 if (AOP_SIZE(result)==2)
4517 aopPut (AOP (result), "b", 1);
4522 // we have to do a signed multiply
4524 emitcode (";", "signed");
4525 emitcode ("clr", "F0"); // reset sign flag
4526 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4528 lbl=newiTempLabel(NULL);
4529 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4530 // left side is negative, 8-bit two's complement, this fails for -128
4531 emitcode ("setb", "F0"); // set sign flag
4532 emitcode ("cpl", "a");
4533 emitcode ("inc", "a");
4535 emitcode ("", "!tlabeldef", lbl->key+100);
4538 if (AOP_TYPE(right)==AOP_LIT) {
4539 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4540 /* AND literal negative */
4541 if ((int) val < 0) {
4542 emitcode ("cpl", "F0"); // complement sign flag
4543 emitcode ("mov", "b,#!constbyte", -val);
4545 emitcode ("mov", "b,#!constbyte", val);
4548 lbl=newiTempLabel(NULL);
4549 emitcode ("mov", "b,a");
4550 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4551 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4552 // right side is negative, 8-bit two's complement
4553 emitcode ("cpl", "F0"); // complement sign flag
4554 emitcode ("cpl", "a");
4555 emitcode ("inc", "a");
4556 emitcode ("", "!tlabeldef", lbl->key+100);
4558 emitcode ("mul", "ab");
4560 _G.accInUse++;_G.bInUse++;
4561 aopOp(result, ic, TRUE, FALSE);
4563 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4565 // this should never happen
4566 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4567 AOP_SIZE(result), __FILE__, lineno);
4571 lbl=newiTempLabel(NULL);
4572 emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4573 // only ONE op was negative, we have to do a 8/16-bit two's complement
4574 emitcode ("cpl", "a"); // lsb
4575 if (AOP_SIZE(result)==1) {
4576 emitcode ("inc", "a");
4578 emitcode ("add", "a,#1");
4579 emitcode ("xch", "a,b");
4580 emitcode ("cpl", "a"); // msb
4581 emitcode ("addc", "a,#0");
4582 emitcode ("xch", "a,b");
4585 emitcode ("", "!tlabeldef", lbl->key+100);
4586 aopPut (AOP (result), "a", 0);
4587 _G.accInUse--;_G.bInUse--;
4588 if (AOP_SIZE(result)==2) {
4589 aopPut (AOP (result), "b", 1);
4593 /*-----------------------------------------------------------------*/
4594 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
4595 /*-----------------------------------------------------------------*/
4596 static void genMultTwoByte (operand *left, operand *right,
4597 operand *result, iCode *ic)
4599 sym_link *retype = getSpec(operandType(right));
4600 sym_link *letype = getSpec(operandType(left));
4601 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4604 if (AOP_TYPE (left) == AOP_LIT) {
4609 /* save EA bit in F1 */
4610 lbl = newiTempLabel(NULL);
4611 emitcode ("setb","F1");
4612 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4613 emitcode ("clr","F1");
4614 emitcode("","!tlabeldef",lbl->key+100);
4616 /* load up MB with right */
4618 emitcode("clr","F0");
4619 if (AOP_TYPE(right) == AOP_LIT) {
4620 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4622 emitcode("setb","F0");
4625 emitcode ("mov","mb,#!constbyte",val & 0xff);
4626 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4628 lbl = newiTempLabel(NULL);
4629 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4630 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4631 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4632 emitcode ("xch", "a,b");
4633 emitcode ("cpl","a");
4634 emitcode ("add", "a,#1");
4635 emitcode ("xch", "a,b");
4636 emitcode ("cpl", "a"); // msb
4637 emitcode ("addc", "a,#0");
4638 emitcode ("setb","F0");
4639 emitcode ("","!tlabeldef",lbl->key+100);
4640 emitcode ("mov","mb,b");
4641 emitcode ("mov","mb,a");
4644 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4645 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4647 /* load up MA with left */
4649 lbl = newiTempLabel(NULL);
4650 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4651 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4652 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4653 emitcode ("xch", "a,b");
4654 emitcode ("cpl","a");
4655 emitcode ("add", "a,#1");
4656 emitcode ("xch", "a,b");
4657 emitcode ("cpl", "a"); // msb
4658 emitcode ("addc","a,#0");
4659 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4660 emitcode ("setb","F0");
4661 emitcode ("","!tlabeldef",lbl->key+100);
4662 emitcode ("mov","ma,b");
4663 emitcode ("mov","ma,a");
4665 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4666 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4668 /* wait for multiplication to finish */
4669 lbl = newiTempLabel(NULL);
4670 emitcode("","!tlabeldef", lbl->key+100);
4671 emitcode("mov","a,mcnt1");
4672 emitcode("anl","a,#!constbyte",0x80);
4673 emitcode("jnz","!tlabel",lbl->key+100);
4675 freeAsmop (left, NULL, ic, TRUE);
4676 freeAsmop (right, NULL, ic,TRUE);
4677 aopOp(result, ic, TRUE, FALSE);
4679 /* if unsigned then simple */
4681 emitcode ("mov","a,ma");
4682 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4683 emitcode ("mov","a,ma");
4684 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4685 aopPut(AOP(result),"ma",1);
4686 aopPut(AOP(result),"ma",0);
4688 emitcode("push","ma");
4689 emitcode("push","ma");
4690 emitcode("push","ma");
4692 /* negate result if needed */
4693 lbl = newiTempLabel(NULL);
4694 emitcode("jnb","F0,!tlabel",lbl->key+100);
4695 emitcode("cpl","a");
4696 emitcode("add","a,#1");
4697 emitcode("","!tlabeldef", lbl->key+100);
4698 if (AOP_TYPE(result) == AOP_ACC)
4700 D(emitcode(";", "ACC special case."););
4701 /* We know result is the only live aop, and
4702 * it's obviously not a DPTR2, so AP is available.
4704 emitcode("mov", "%s,acc", DP2_RESULT_REG);
4708 aopPut(AOP(result),"a",0);
4711 emitcode("pop","acc");
4712 lbl = newiTempLabel(NULL);
4713 emitcode("jnb","F0,!tlabel",lbl->key+100);
4714 emitcode("cpl","a");
4715 emitcode("addc","a,#0");
4716 emitcode("","!tlabeldef", lbl->key+100);
4717 aopPut(AOP(result),"a",1);
4718 emitcode("pop","acc");
4719 if (AOP_SIZE(result) >= 3) {
4720 lbl = newiTempLabel(NULL);
4721 emitcode("jnb","F0,!tlabel",lbl->key+100);
4722 emitcode("cpl","a");
4723 emitcode("addc","a,#0");
4724 emitcode("","!tlabeldef", lbl->key+100);
4725 aopPut(AOP(result),"a",2);
4727 emitcode("pop","acc");
4728 if (AOP_SIZE(result) >= 4) {
4729 lbl = newiTempLabel(NULL);
4730 emitcode("jnb","F0,!tlabel",lbl->key+100);
4731 emitcode("cpl","a");
4732 emitcode("addc","a,#0");
4733 emitcode("","!tlabeldef", lbl->key+100);
4734 aopPut(AOP(result),"a",3);
4736 if (AOP_TYPE(result) == AOP_ACC)
4738 /* We stashed the result away above. */
4739 emitcode("mov", "acc,%s", DP2_RESULT_REG);
4743 freeAsmop (result, NULL, ic, TRUE);
4745 /* restore EA bit in F1 */
4746 lbl = newiTempLabel(NULL);
4747 emitcode ("jnb","F1,!tlabel",lbl->key+100);
4748 emitcode ("setb","EA");
4749 emitcode("","!tlabeldef",lbl->key+100);
4753 /*-----------------------------------------------------------------*/
4754 /* genMult - generates code for multiplication */
4755 /*-----------------------------------------------------------------*/
4757 genMult (iCode * ic)
4759 operand *left = IC_LEFT (ic);
4760 operand *right = IC_RIGHT (ic);
4761 operand *result = IC_RESULT (ic);
4763 D (emitcode (";", "genMult "););
4765 /* assign the amsops */
4768 /* special cases first */
4770 if (AOP_TYPE (left) == AOP_CRY &&
4771 AOP_TYPE (right) == AOP_CRY)
4773 genMultbits (left, right, result, ic);
4777 /* if both are of size == 1 */
4778 if (AOP_SIZE (left) == 1 &&
4779 AOP_SIZE (right) == 1)
4781 genMultOneByte (left, right, result, ic);
4785 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4786 /* use the ds390 ARITHMETIC accel UNIT */
4787 genMultTwoByte (left, right, result, ic);
4790 /* should have been converted to function call */
4794 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4795 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4796 freeAsmop (result, NULL, ic, TRUE);
4799 /*-----------------------------------------------------------------*/
4800 /* genDivbits :- division of bits */
4801 /*-----------------------------------------------------------------*/
4803 genDivbits (operand * left,
4811 /* the result must be bit */
4812 LOAD_AB_FOR_DIV (left, right, l);
4813 emitcode ("div", "ab");
4814 emitcode ("rrc", "a");
4815 aopOp(result, ic, TRUE, FALSE);
4817 aopPut (AOP (result), "c", 0);
4820 /*-----------------------------------------------------------------*/
4821 /* genDivOneByte : 8 bit division */
4822 /*-----------------------------------------------------------------*/
4824 genDivOneByte (operand * left,
4829 sym_link *opetype = operandType (result);
4835 /* signed or unsigned */
4836 if (SPEC_USIGN (opetype))
4838 /* unsigned is easy */
4839 LOAD_AB_FOR_DIV (left, right, l);
4840 emitcode ("div", "ab");
4843 aopOp(result, ic, TRUE, FALSE);
4844 aopPut (AOP (result), "a", 0);
4847 size = AOP_SIZE (result) - 1;
4851 aopPut (AOP (result), zero, offset++);
4856 /* signed is a little bit more difficult */
4858 /* save the signs of the operands */
4859 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4860 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4861 emitcode ("push", "acc"); /* save it on the stack */
4863 /* now sign adjust for both left & right */
4864 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4865 lbl = newiTempLabel (NULL);
4866 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4867 emitcode ("cpl", "a");
4868 emitcode ("inc", "a");
4869 emitcode ("", "!tlabeldef", (lbl->key + 100));
4870 emitcode ("mov", "b,a");
4872 /* sign adjust left side */
4873 MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4875 lbl = newiTempLabel (NULL);
4876 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4877 emitcode ("cpl", "a");
4878 emitcode ("inc", "a");
4879 emitcode ("", "!tlabeldef", (lbl->key + 100));
4881 /* now the division */
4882 emitcode ("nop", "; workaround for DS80C390 div bug.");
4883 emitcode ("div", "ab");
4884 /* we are interested in the lower order
4886 emitcode ("mov", "b,a");
4887 lbl = newiTempLabel (NULL);
4888 emitcode ("pop", "acc");
4889 /* if there was an over flow we don't
4890 adjust the sign of the result */
4891 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4892 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4894 emitcode ("clr", "a");
4895 emitcode ("subb", "a,b");
4896 emitcode ("mov", "b,a");
4897 emitcode ("", "!tlabeldef", (lbl->key + 100));
4899 /* now we are done */
4900 _G.accInUse++; _G.bInUse++;
4901 aopOp(result, ic, TRUE, FALSE);
4903 aopPut (AOP (result), "b", 0);
4905 size = AOP_SIZE (result) - 1;
4909 emitcode ("mov", "c,b.7");
4910 emitcode ("subb", "a,acc");
4914 aopPut (AOP (result), "a", offset++);
4916 _G.accInUse--; _G.bInUse--;
4920 /*-----------------------------------------------------------------*/
4921 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
4922 /*-----------------------------------------------------------------*/
4923 static void genDivTwoByte (operand *left, operand *right,
4924 operand *result, iCode *ic)
4926 sym_link *retype = getSpec(operandType(right));
4927 sym_link *letype = getSpec(operandType(left));
4928 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4931 /* save EA bit in F1 */
4932 lbl = newiTempLabel(NULL);
4933 emitcode ("setb","F1");
4934 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4935 emitcode ("clr","F1");
4936 emitcode("","!tlabeldef",lbl->key+100);
4938 /* load up MA with left */
4940 emitcode("clr","F0");
4941 lbl = newiTempLabel(NULL);
4942 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4943 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4944 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4945 emitcode ("xch", "a,b");
4946 emitcode ("cpl","a");
4947 emitcode ("add", "a,#1");
4948 emitcode ("xch", "a,b");
4949 emitcode ("cpl", "a"); // msb
4950 emitcode ("addc","a,#0");
4951 emitcode ("setb","F0");
4952 emitcode ("","!tlabeldef",lbl->key+100);
4953 emitcode ("mov","ma,b");
4954 emitcode ("mov","ma,a");
4956 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4957 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4960 /* load up MB with right */
4962 if (AOP_TYPE(right) == AOP_LIT) {
4963 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4965 lbl = newiTempLabel(NULL);
4966 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4967 emitcode("setb","F0");
4968 emitcode ("","!tlabeldef",lbl->key+100);
4971 emitcode ("mov","mb,#!constbyte",val & 0xff);
4972 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4974 lbl = newiTempLabel(NULL);
4975 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4976 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4977 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4978 emitcode ("xch", "a,b");
4979 emitcode ("cpl","a");
4980 emitcode ("add", "a,#1");
4981 emitcode ("xch", "a,b");
4982 emitcode ("cpl", "a"); // msb
4983 emitcode ("addc", "a,#0");
4984 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4985 emitcode ("setb","F0");
4986 emitcode ("","!tlabeldef",lbl->key+100);
4987 emitcode ("mov","mb,b");
4988 emitcode ("mov","mb,a");
4991 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4992 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4995 /* wait for multiplication to finish */
4996 lbl = newiTempLabel(NULL);
4997 emitcode("","!tlabeldef", lbl->key+100);
4998 emitcode("mov","a,mcnt1");
4999 emitcode("anl","a,#!constbyte",0x80);
5000 emitcode("jnz","!tlabel",lbl->key+100);
5002 freeAsmop (left, NULL, ic, TRUE);
5003 freeAsmop (right, NULL, ic,TRUE);
5004 aopOp(result, ic, TRUE, FALSE);
5006 /* if unsigned then simple */
5008 aopPut(AOP(result),"ma",1);
5009 aopPut(AOP(result),"ma",0);
5011 emitcode("push","ma");
5013 /* negate result if needed */
5014 lbl = newiTempLabel(NULL);
5015 emitcode("jnb","F0,!tlabel",lbl->key+100);
5016 emitcode("cpl","a");
5017 emitcode("add","a,#1");
5018 emitcode("","!tlabeldef", lbl->key+100);
5019 aopPut(AOP(result),"a",0);
5020 emitcode("pop","acc");
5021 lbl = newiTempLabel(NULL);
5022 emitcode("jnb","F0,!tlabel",lbl->key+100);
5023 emitcode("cpl","a");
5024 emitcode("addc","a,#0");
5025 emitcode("","!tlabeldef", lbl->key+100);
5026 aopPut(AOP(result),"a",1);
5028 freeAsmop (result, NULL, ic, TRUE);
5029 /* restore EA bit in F1 */
5030 lbl = newiTempLabel(NULL);
5031 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5032 emitcode ("setb","EA");
5033 emitcode("","!tlabeldef",lbl->key+100);
5037 /*-----------------------------------------------------------------*/
5038 /* genDiv - generates code for division */
5039 /*-----------------------------------------------------------------*/
5043 operand *left = IC_LEFT (ic);
5044 operand *right = IC_RIGHT (ic);
5045 operand *result = IC_RESULT (ic);
5047 D (emitcode (";", "genDiv "););
5049 /* assign the amsops */
5052 /* special cases first */
5054 if (AOP_TYPE (left) == AOP_CRY &&
5055 AOP_TYPE (right) == AOP_CRY)
5057 genDivbits (left, right, result, ic);
5061 /* if both are of size == 1 */
5062 if (AOP_SIZE (left) == 1 &&
5063 AOP_SIZE (right) == 1)
5065 genDivOneByte (left, right, result, ic);
5069 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5070 /* use the ds390 ARITHMETIC accel UNIT */
5071 genDivTwoByte (left, right, result, ic);
5074 /* should have been converted to function call */
5077 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5078 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5079 freeAsmop (result, NULL, ic, TRUE);
5082 /*-----------------------------------------------------------------*/
5083 /* genModbits :- modulus of bits */
5084 /*-----------------------------------------------------------------*/
5086 genModbits (operand * left,
5094 /* the result must be bit */
5095 LOAD_AB_FOR_DIV (left, right, l);
5096 emitcode ("div", "ab");
5097 emitcode ("mov", "a,b");
5098 emitcode ("rrc", "a");
5099 aopOp(result, ic, TRUE, FALSE);
5100 aopPut (AOP (result), "c", 0);
5103 /*-----------------------------------------------------------------*/
5104 /* genModOneByte : 8 bit modulus */
5105 /*-----------------------------------------------------------------*/
5107 genModOneByte (operand * left,
5112 sym_link *opetype = operandType (result);
5116 /* signed or unsigned */
5117 if (SPEC_USIGN (opetype))
5119 /* unsigned is easy */
5120 LOAD_AB_FOR_DIV (left, right, l);
5121 emitcode ("div", "ab");
5122 aopOp(result, ic, TRUE, FALSE);
5123 aopPut (AOP (result), "b", 0);
5127 /* signed is a little bit more difficult */
5129 /* save the signs of the operands */
5130 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5132 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
5133 emitcode ("push", "acc"); /* save it on the stack */
5135 /* now sign adjust for both left & right */
5136 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5138 lbl = newiTempLabel (NULL);
5139 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5140 emitcode ("cpl", "a");
5141 emitcode ("inc", "a");
5142 emitcode ("", "!tlabeldef", (lbl->key + 100));
5143 emitcode ("mov", "b,a");
5145 /* sign adjust left side */
5146 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5148 lbl = newiTempLabel (NULL);
5149 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5150 emitcode ("cpl", "a");
5151 emitcode ("inc", "a");
5152 emitcode ("", "!tlabeldef", (lbl->key + 100));
5154 /* now the multiplication */
5155 emitcode ("nop", "; workaround for DS80C390 div bug.");
5156 emitcode ("div", "ab");
5157 /* we are interested in the lower order
5159 lbl = newiTempLabel (NULL);
5160 emitcode ("pop", "acc");
5161 /* if there was an over flow we don't
5162 adjust the sign of the result */
5163 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
5164 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5166 emitcode ("clr", "a");
5167 emitcode ("subb", "a,b");
5168 emitcode ("mov", "b,a");
5169 emitcode ("", "!tlabeldef", (lbl->key + 100));
5172 /* now we are done */
5173 aopOp(result, ic, TRUE, FALSE);
5174 aopPut (AOP (result), "b", 0);
5179 /*-----------------------------------------------------------------*/
5180 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
5181 /*-----------------------------------------------------------------*/
5182 static void genModTwoByte (operand *left, operand *right,
5183 operand *result, iCode *ic)
5185 sym_link *retype = getSpec(operandType(right));
5186 sym_link *letype = getSpec(operandType(left));
5187 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5190 /* load up MA with left */
5191 /* save EA bit in F1 */
5192 lbl = newiTempLabel(NULL);
5193 emitcode ("setb","F1");
5194 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5195 emitcode ("clr","F1");
5196 emitcode("","!tlabeldef",lbl->key+100);
5199 lbl = newiTempLabel(NULL);
5200 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5201 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5202 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5203 emitcode ("xch", "a,b");
5204 emitcode ("cpl","a");
5205 emitcode ("add", "a,#1");
5206 emitcode ("xch", "a,b");
5207 emitcode ("cpl", "a"); // msb
5208 emitcode ("addc","a,#0");
5209 emitcode ("","!tlabeldef",lbl->key+100);
5210 emitcode ("mov","ma,b");
5211 emitcode ("mov","ma,a");
5213 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5214 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5217 /* load up MB with right */
5219 if (AOP_TYPE(right) == AOP_LIT) {
5220 int val=floatFromVal (AOP (right)->aopu.aop_lit);
5224 emitcode ("mov","mb,#!constbyte",val & 0xff);
5225 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5227 lbl = newiTempLabel(NULL);
5228 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5229 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5230 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5231 emitcode ("xch", "a,b");
5232 emitcode ("cpl","a");
5233 emitcode ("add", "a,#1");
5234 emitcode ("xch", "a,b");
5235 emitcode ("cpl", "a"); // msb
5236 emitcode ("addc", "a,#0");
5237 emitcode ("","!tlabeldef",lbl->key+100);
5238 emitcode ("mov","mb,b");
5239 emitcode ("mov","mb,a");
5242 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5243 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5246 /* wait for multiplication to finish */
5247 lbl = newiTempLabel(NULL);
5248 emitcode("","!tlabeldef", lbl->key+100);
5249 emitcode("mov","a,mcnt1");
5250 emitcode("anl","a,#!constbyte",0x80);
5251 emitcode("jnz","!tlabel",lbl->key+100);
5253 freeAsmop (left, NULL, ic, TRUE);
5254 freeAsmop (right, NULL, ic,TRUE);
5255 aopOp(result, ic, TRUE, FALSE);
5257 aopPut(AOP(result),"mb",1);
5258 aopPut(AOP(result),"mb",0);
5259 freeAsmop (result, NULL, ic, TRUE);
5261 /* restore EA bit in F1 */
5262 lbl = newiTempLabel(NULL);
5263 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5264 emitcode ("setb","EA");
5265 emitcode("","!tlabeldef",lbl->key+100);
5269 /*-----------------------------------------------------------------*/
5270 /* genMod - generates code for division */
5271 /*-----------------------------------------------------------------*/
5275 operand *left = IC_LEFT (ic);
5276 operand *right = IC_RIGHT (ic);
5277 operand *result = IC_RESULT (ic);
5279 D (emitcode (";", "genMod "); );
5281 /* assign the amsops */
5284 /* special cases first */
5286 if (AOP_TYPE (left) == AOP_CRY &&
5287 AOP_TYPE (right) == AOP_CRY)
5289 genModbits (left, right, result, ic);
5293 /* if both are of size == 1 */
5294 if (AOP_SIZE (left) == 1 &&
5295 AOP_SIZE (right) == 1)
5297 genModOneByte (left, right, result, ic);
5301 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5302 /* use the ds390 ARITHMETIC accel UNIT */
5303 genModTwoByte (left, right, result, ic);
5307 /* should have been converted to function call */
5311 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5312 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5313 freeAsmop (result, NULL, ic, TRUE);
5316 /*-----------------------------------------------------------------*/
5317 /* genIfxJump :- will create a jump depending on the ifx */
5318 /*-----------------------------------------------------------------*/
5320 genIfxJump (iCode * ic, char *jval)
5323 symbol *tlbl = newiTempLabel (NULL);
5326 D (emitcode (";", "genIfxJump"););
5328 /* if true label then we jump if condition
5332 jlbl = IC_TRUE (ic);
5333 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5334 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5338 /* false label is present */
5339 jlbl = IC_FALSE (ic);
5340 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5341 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5343 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5344 emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5346 emitcode (inst, "!tlabel", tlbl->key + 100);
5347 emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5348 emitcode ("", "!tlabeldef", tlbl->key + 100);
5350 /* mark the icode as generated */
5354 /*-----------------------------------------------------------------*/
5355 /* genCmp :- greater or less than comparison */
5356 /*-----------------------------------------------------------------*/
5358 genCmp (operand * left, operand * right,
5359 iCode * ic, iCode * ifx, int sign)
5361 int size, offset = 0;
5362 unsigned long lit = 0L;
5365 D (emitcode (";", "genCmp"););
5367 result = IC_RESULT (ic);
5369 /* if left & right are bit variables */
5370 if (AOP_TYPE (left) == AOP_CRY &&
5371 AOP_TYPE (right) == AOP_CRY)
5373 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5374 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
5378 /* subtract right from left if at the
5379 end the carry flag is set then we know that
5380 left is greater than right */
5381 size = max (AOP_SIZE (left), AOP_SIZE (right));
5383 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5384 if ((size == 1) && !sign
5385 && (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5387 symbol *lbl = newiTempLabel (NULL);
5388 emitcode ("cjne", "%s,%s,!tlabel",
5389 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
5390 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5392 emitcode ("", "!tlabeldef", lbl->key + 100);
5396 if (AOP_TYPE (right) == AOP_LIT)
5398 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5399 /* optimize if(x < 0) or if(x >= 0) */
5408 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
5410 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5411 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5413 aopOp (result, ic, FALSE, FALSE);
5415 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5417 freeAsmop (result, NULL, ic, TRUE);
5418 genIfxJump (ifx, "acc.7");
5423 emitcode ("rlc", "a");
5425 goto release_freedLR;
5433 // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5434 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5435 // emitcode (";", "genCmp #2");
5436 if (sign && (size == 0))
5438 // emitcode (";", "genCmp #3");
5439 emitcode ("xrl", "a,#!constbyte",0x80);
5440 if (AOP_TYPE (right) == AOP_LIT)
5442 unsigned long lit = (unsigned long)
5443 floatFromVal (AOP (right)->aopu.aop_lit);
5444 // emitcode (";", "genCmp #3.1");
5445 emitcode ("subb", "a,#!constbyte",
5446 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5450 // emitcode (";", "genCmp #3.2");
5452 MOVB(aopGet (AOP (right), offset++, FALSE, FALSE, "b"));
5453 saveAccWarn = DEFAULT_ACC_WARNING;
5454 emitcode ("xrl", "b,#!constbyte",0x80);
5455 emitcode ("subb", "a,b");
5462 // emitcode (";", "genCmp #4");
5464 s = aopGet (AOP (right), offset++, FALSE, FALSE, "b");
5465 saveAccWarn = DEFAULT_ACC_WARNING;
5467 emitcode ("subb", "a,%s", s);
5474 /* Don't need the left & right operands any more; do need the result. */
5475 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5476 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5478 aopOp (result, ic, FALSE, FALSE);
5482 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5488 /* if the result is used in the next
5489 ifx conditional branch then generate
5490 code a little differently */
5493 genIfxJump (ifx, "c");
5499 /* leave the result in acc */
5501 freeAsmop (result, NULL, ic, TRUE);
5504 /*-----------------------------------------------------------------*/
5505 /* genCmpGt :- greater than comparison */
5506 /*-----------------------------------------------------------------*/
5508 genCmpGt (iCode * ic, iCode * ifx)
5510 operand *left, *right;
5511 sym_link *letype, *retype;
5514 D (emitcode (";", "genCmpGt ");
5517 left = IC_LEFT (ic);
5518 right = IC_RIGHT (ic);
5520 letype = getSpec (operandType (left));
5521 retype = getSpec (operandType (right));
5522 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5524 /* assign the left & right amsops */
5527 genCmp (right, left, ic, ifx, sign);
5530 /*-----------------------------------------------------------------*/
5531 /* genCmpLt - less than comparisons */
5532 /*-----------------------------------------------------------------*/
5534 genCmpLt (iCode * ic, iCode * ifx)
5536 operand *left, *right;
5537 sym_link *letype, *retype;
5540 D (emitcode (";", "genCmpLt "););
5542 left = IC_LEFT (ic);
5543 right = IC_RIGHT (ic);
5545 letype = getSpec (operandType (left));
5546 retype = getSpec (operandType (right));
5547 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5549 /* assign the left & right amsops */
5552 genCmp (left, right, ic, ifx, sign);
5555 /*-----------------------------------------------------------------*/
5556 /* gencjneshort - compare and jump if not equal */
5557 /*-----------------------------------------------------------------*/
5559 gencjneshort (operand * left, operand * right, symbol * lbl)
5561 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5563 unsigned long lit = 0L;
5565 D (emitcode (";", "gencjneshort");
5568 /* if the left side is a literal or
5569 if the right is in a pointer register and left
5571 if ((AOP_TYPE (left) == AOP_LIT) ||
5572 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5579 if (AOP_TYPE (right) == AOP_LIT)
5580 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5582 if (opIsGptr (left) || opIsGptr (right))
5584 /* We are comparing a generic pointer to something.
5585 * Exclude the generic type byte from the comparison.
5588 D (emitcode (";", "cjneshort: generic ptr special case."););
5592 /* if the right side is a literal then anything goes */
5593 if (AOP_TYPE (right) == AOP_LIT &&
5594 AOP_TYPE (left) != AOP_DIR)
5598 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5599 emitcode ("cjne", "a,%s,!tlabel",
5600 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG),
5606 /* if the right side is in a register or in direct space or
5607 if the left is a pointer register & right is not */
5608 else if (AOP_TYPE (right) == AOP_REG ||
5609 AOP_TYPE (right) == AOP_DIR ||
5610 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5611 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5615 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5616 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5617 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5618 emitcode ("jnz", "!tlabel", lbl->key + 100);
5620 emitcode ("cjne", "a,%s,!tlabel",
5621 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
5628 /* right is a pointer reg need both a & b */
5631 MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5632 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
5633 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5639 /*-----------------------------------------------------------------*/
5640 /* gencjne - compare and jump if not equal */
5641 /*-----------------------------------------------------------------*/
5643 gencjne (operand * left, operand * right, symbol * lbl)
5645 symbol *tlbl = newiTempLabel (NULL);
5647 D (emitcode (";", "gencjne");
5650 gencjneshort (left, right, lbl);
5652 emitcode ("mov", "a,%s", one);
5653 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5654 emitcode ("", "!tlabeldef", lbl->key + 100);
5655 emitcode ("clr", "a");
5656 emitcode ("", "!tlabeldef", tlbl->key + 100);
5659 /*-----------------------------------------------------------------*/
5660 /* genCmpEq - generates code for equal to */
5661 /*-----------------------------------------------------------------*/
5663 genCmpEq (iCode * ic, iCode * ifx)
5665 operand *left, *right, *result;
5667 D (emitcode (";", "genCmpEq ");
5671 AOP_SET_LOCALS (ic);
5673 /* if literal, literal on the right or
5674 if the right is in a pointer register and left
5676 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5677 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5679 operand *t = IC_RIGHT (ic);
5680 IC_RIGHT (ic) = IC_LEFT (ic);
5684 if (ifx && /* !AOP_SIZE(result) */
5685 OP_SYMBOL (result) &&
5686 OP_SYMBOL (result)->regType == REG_CND)
5689 /* if they are both bit variables */
5690 if (AOP_TYPE (left) == AOP_CRY &&
5691 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5693 if (AOP_TYPE (right) == AOP_LIT)
5695 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5698 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5699 emitcode ("cpl", "c");
5703 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5707 emitcode ("clr", "c");
5709 /* AOP_TYPE(right) == AOP_CRY */
5713 symbol *lbl = newiTempLabel (NULL);
5714 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5715 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5716 emitcode ("cpl", "c");
5717 emitcode ("", "!tlabeldef", (lbl->key + 100));
5719 /* if true label then we jump if condition
5721 tlbl = newiTempLabel (NULL);
5724 emitcode ("jnc", "!tlabel", tlbl->key + 100);
5725 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5729 emitcode ("jc", "!tlabel", tlbl->key + 100);
5730 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5732 emitcode ("", "!tlabeldef", tlbl->key + 100);
5736 tlbl = newiTempLabel (NULL);
5737 gencjneshort (left, right, tlbl);
5740 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5741 emitcode ("", "!tlabeldef", tlbl->key + 100);
5745 symbol *lbl = newiTempLabel (NULL);
5746 emitcode ("sjmp", "!tlabel", lbl->key + 100);
5747 emitcode ("", "!tlabeldef", tlbl->key + 100);
5748 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5749 emitcode ("", "!tlabeldef", lbl->key + 100);
5752 /* mark the icode as generated */
5755 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5756 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5760 /* if they are both bit variables */
5761 if (AOP_TYPE (left) == AOP_CRY &&
5762 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5764 if (AOP_TYPE (right) == AOP_LIT)
5766 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5769 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5770 emitcode ("cpl", "c");
5774 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5778 emitcode ("clr", "c");
5780 /* AOP_TYPE(right) == AOP_CRY */
5784 symbol *lbl = newiTempLabel (NULL);
5785 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5786 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5787 emitcode ("cpl", "c");
5788 emitcode ("", "!tlabeldef", (lbl->key + 100));
5791 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5792 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5794 aopOp (result, ic, TRUE, FALSE);
5797 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5804 genIfxJump (ifx, "c");
5807 /* if the result is used in an arithmetic operation
5808 then put the result in place */
5813 gencjne (left, right, newiTempLabel (NULL));
5815 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5816 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5818 aopOp (result, ic, TRUE, FALSE);
5820 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5822 aopPut (AOP (result), "a", 0);
5827 genIfxJump (ifx, "a");
5830 /* if the result is used in an arithmetic operation
5831 then put the result in place */
5832 if (AOP_TYPE (result) != AOP_CRY)
5834 /* leave the result in acc */
5838 freeAsmop (result, NULL, ic, TRUE);
5841 /*-----------------------------------------------------------------*/
5842 /* ifxForOp - returns the icode containing the ifx for operand */
5843 /*-----------------------------------------------------------------*/
5845 ifxForOp (operand * op, iCode * ic)
5847 /* if true symbol then needs to be assigned */
5848 if (IS_TRUE_SYMOP (op))
5851 /* if this has register type condition and
5852 the next instruction is ifx with the same operand
5853 and live to of the operand is upto the ifx only then */
5855 ic->next->op == IFX &&
5856 IC_COND (ic->next)->key == op->key &&
5857 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5862 /*-----------------------------------------------------------------*/
5863 /* hasInc - operand is incremented before any other use */
5864 /*-----------------------------------------------------------------*/
5866 hasInc (operand *op, iCode *ic, int osize)
5868 sym_link *type = operandType(op);
5869 sym_link *retype = getSpec (type);
5870 iCode *lic = ic->next;
5873 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5874 if (!IS_SYMOP(op)) return NULL;
5876 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5877 if (IS_AGGREGATE(type->next)) return NULL;
5878 if (osize != (isize = getSize(type->next))) return NULL;
5881 /* if operand of the form op = op + <sizeof *op> */
5882 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5883 isOperandEqual(IC_RESULT(lic),op) &&
5884 isOperandLiteral(IC_RIGHT(lic)) &&
5885 operandLitValue(IC_RIGHT(lic)) == isize) {
5888 /* if the operand used or deffed */
5889 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5892 /* if GOTO or IFX */
5893 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5899 /*-----------------------------------------------------------------*/
5900 /* genAndOp - for && operation */
5901 /*-----------------------------------------------------------------*/
5903 genAndOp (iCode * ic)
5905 operand *left, *right, *result;
5908 D (emitcode (";", "genAndOp "););
5910 /* note here that && operations that are in an
5911 if statement are taken away by backPatchLabels
5912 only those used in arthmetic operations remain */
5914 AOP_SET_LOCALS (ic);
5916 /* if both are bit variables */
5917 if (AOP_TYPE (left) == AOP_CRY &&
5918 AOP_TYPE (right) == AOP_CRY)
5920 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5921 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5922 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5923 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5925 aopOp (result,ic,FALSE, FALSE);
5930 tlbl = newiTempLabel (NULL);
5932 emitcode ("jz", "!tlabel", tlbl->key + 100);
5934 emitcode ("", "!tlabeldef", tlbl->key + 100);
5935 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5936 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5938 aopOp (result,ic,FALSE, FALSE);
5941 freeAsmop (result, NULL, ic, TRUE);
5945 /*-----------------------------------------------------------------*/
5946 /* genOrOp - for || operation */
5947 /*-----------------------------------------------------------------*/
5949 genOrOp (iCode * ic)
5951 operand *left, *right, *result;
5954 D (emitcode (";", "genOrOp "););
5956 /* note here that || operations that are in an
5957 if statement are taken away by backPatchLabels
5958 only those used in arthmetic operations remain */
5960 AOP_SET_LOCALS (ic);
5962 /* if both are bit variables */
5963 if (AOP_TYPE (left) == AOP_CRY &&
5964 AOP_TYPE (right) == AOP_CRY)
5966 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5967 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5968 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5969 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5971 aopOp (result,ic,FALSE, FALSE);
5977 tlbl = newiTempLabel (NULL);
5979 emitcode ("jnz", "!tlabel", tlbl->key + 100);
5981 emitcode ("", "!tlabeldef", tlbl->key + 100);
5982 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5983 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5985 aopOp (result,ic,FALSE, FALSE);
5990 freeAsmop (result, NULL, ic, TRUE);
5993 /*-----------------------------------------------------------------*/
5994 /* isLiteralBit - test if lit == 2^n */
5995 /*-----------------------------------------------------------------*/
5997 isLiteralBit (unsigned long lit)
5999 unsigned long pw[32] =
6000 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6001 0x100L, 0x200L, 0x400L, 0x800L,
6002 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6003 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6004 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6005 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6006 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6009 for (idx = 0; idx < 32; idx++)
6015 /*-----------------------------------------------------------------*/
6016 /* continueIfTrue - */
6017 /*-----------------------------------------------------------------*/
6019 continueIfTrue (iCode * ic)
6022 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6026 /*-----------------------------------------------------------------*/
6028 /*-----------------------------------------------------------------*/
6030 jumpIfTrue (iCode * ic)
6033 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6037 /*-----------------------------------------------------------------*/
6038 /* jmpTrueOrFalse - */
6039 /*-----------------------------------------------------------------*/
6041 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6043 // ugly but optimized by peephole
6046 symbol *nlbl = newiTempLabel (NULL);
6047 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6048 emitcode ("", "!tlabeldef", tlbl->key + 100);
6049 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6050 emitcode ("", "!tlabeldef", nlbl->key + 100);
6054 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6055 emitcode ("", "!tlabeldef", tlbl->key + 100);
6060 // Generate code to perform a bit-wise logic operation
6061 // on two operands in far space (assumed to already have been
6062 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6063 // in far space. This requires pushing the result on the stack
6064 // then popping it into the result.
6066 genFarFarLogicOp(iCode *ic, char *logicOp)
6068 int size, resultSize, compSize;
6072 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6073 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
6074 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6076 _startLazyDPSEvaluation();
6077 for (size = compSize; (size--); offset++)
6079 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6080 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6081 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6083 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6084 emitcode ("push", "acc");
6086 _endLazyDPSEvaluation();
6088 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6089 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6090 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6092 resultSize = AOP_SIZE(IC_RESULT(ic));
6094 ADJUST_PUSHED_RESULT(compSize, resultSize);
6096 _startLazyDPSEvaluation();
6099 emitcode ("pop", "acc");
6100 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6102 _endLazyDPSEvaluation();
6103 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6107 /*-----------------------------------------------------------------*/
6108 /* genAnd - code for and */
6109 /*-----------------------------------------------------------------*/
6111 genAnd (iCode * ic, iCode * ifx)
6113 operand *left, *right, *result;
6114 int size, offset = 0;
6115 unsigned long lit = 0L;
6120 D (emitcode (";", "genAnd "););
6122 AOP_OP_3_NOFATAL (ic, pushResult);
6123 AOP_SET_LOCALS (ic);
6127 genFarFarLogicOp(ic, "anl");
6132 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6134 AOP_TYPE (left), AOP_TYPE (right));
6135 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6137 AOP_SIZE (left), AOP_SIZE (right));
6140 /* if left is a literal & right is not then exchange them */
6141 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6142 #ifdef LOGIC_OPS_BROKEN
6143 || AOP_NEEDSACC (left)
6147 operand *tmp = right;
6152 /* if result = right then exchange them */
6153 if (sameRegs (AOP (result), AOP (right)))
6155 operand *tmp = right;
6160 /* if right is bit then exchange them */
6161 if (AOP_TYPE (right) == AOP_CRY &&
6162 AOP_TYPE (left) != AOP_CRY)
6164 operand *tmp = right;
6168 if (AOP_TYPE (right) == AOP_LIT)
6169 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6171 size = AOP_SIZE (result);
6174 // result = bit & yy;
6175 if (AOP_TYPE (left) == AOP_CRY)
6177 // c = bit & literal;
6178 if (AOP_TYPE (right) == AOP_LIT)
6182 if (size && sameRegs (AOP (result), AOP (left)))
6185 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6190 if (size && (AOP_TYPE (result) == AOP_CRY))
6192 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6195 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6200 emitcode ("clr", "c");
6205 if (AOP_TYPE (right) == AOP_CRY)
6208 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6209 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6214 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6216 emitcode ("rrc", "a");
6217 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6225 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6226 genIfxJump (ifx, "c");
6230 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6231 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6232 if ((AOP_TYPE (right) == AOP_LIT) &&
6233 (AOP_TYPE (result) == AOP_CRY) &&
6234 (AOP_TYPE (left) != AOP_CRY))
6236 int posbit = isLiteralBit (lit);
6241 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6244 emitcode ("mov", "c,acc.%d", posbit & 0x07);
6250 SNPRINTF (buff, sizeof(buff),
6251 "acc.%d", posbit & 0x07);
6252 genIfxJump (ifx, buff);
6256 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6263 symbol *tlbl = newiTempLabel (NULL);
6264 int sizel = AOP_SIZE (left);
6266 emitcode ("setb", "c");
6269 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6271 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6273 if ((posbit = isLiteralBit (bytelit)) != 0)
6274 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6277 if (bytelit != 0x0FFL)
6278 emitcode ("anl", "a,%s",
6279 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6280 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6285 // bit = left & literal
6288 emitcode ("clr", "c");
6289 emitcode ("", "!tlabeldef", tlbl->key + 100);
6291 // if(left & literal)
6295 jmpTrueOrFalse (ifx, tlbl);
6303 /* if left is same as result */
6304 if (sameRegs (AOP (result), AOP (left)))
6306 for (; size--; offset++)
6308 if (AOP_TYPE (right) == AOP_LIT)
6310 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6312 else if (bytelit == 0)
6313 aopPut (AOP (result), zero, offset);
6314 else if (IS_AOP_PREG (result))
6316 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6317 emitcode ("anl", "a,%s",
6318 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6319 aopPut (AOP (result), "a", offset);
6322 emitcode ("anl", "%s,%s",
6323 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6324 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6328 if (AOP_TYPE (left) == AOP_ACC)
6329 emitcode ("anl", "a,%s",
6330 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6333 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6334 if (IS_AOP_PREG (result))
6336 emitcode ("anl", "a,%s",
6337 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6338 aopPut (AOP (result), "a", offset);
6341 emitcode ("anl", "%s,a",
6342 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6349 // left & result in different registers
6350 if (AOP_TYPE (result) == AOP_CRY)
6353 // if(size), result in bit
6354 // if(!size && ifx), conditional oper: if(left & right)
6355 symbol *tlbl = newiTempLabel (NULL);
6356 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6358 emitcode ("setb", "c");
6361 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6362 emitcode ("anl", "a,%s",
6363 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6365 if (AOP_TYPE(left)==AOP_ACC) {
6366 emitcode("mov", "b,a");
6367 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6368 emitcode("anl", "a,b");
6370 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6371 emitcode ("anl", "a,%s",
6372 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6375 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6381 emitcode ("", "!tlabeldef", tlbl->key + 100);
6385 jmpTrueOrFalse (ifx, tlbl);
6389 for (; (size--); offset++)
6392 // result = left & right
6393 if (AOP_TYPE (right) == AOP_LIT)
6395 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6397 aopPut (AOP (result),
6398 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6402 else if (bytelit == 0)
6404 aopPut (AOP (result), zero, offset);
6407 D (emitcode (";", "better literal AND."););
6408 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6409 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6410 FALSE, FALSE, DP2_RESULT_REG));
6415 // faster than result <- left, anl result,right
6416 // and better if result is SFR
6417 if (AOP_TYPE (left) == AOP_ACC)
6419 emitcode ("anl", "a,%s",
6420 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6424 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6425 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6427 emitcode("mov", "b,a");
6431 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6432 emitcode ("anl", "a,%s", rOp);
6435 aopPut (AOP (result), "a", offset);
6441 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6442 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6443 freeAsmop (result, NULL, ic, TRUE);
6447 /*-----------------------------------------------------------------*/
6448 /* genOr - code for or */
6449 /*-----------------------------------------------------------------*/
6451 genOr (iCode * ic, iCode * ifx)
6453 operand *left, *right, *result;
6454 int size, offset = 0;
6455 unsigned long lit = 0L;
6458 D (emitcode (";", "genOr "););
6460 AOP_OP_3_NOFATAL (ic, pushResult);
6461 AOP_SET_LOCALS (ic);
6465 genFarFarLogicOp(ic, "orl");
6471 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6473 AOP_TYPE (left), AOP_TYPE (right));
6474 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6476 AOP_SIZE (left), AOP_SIZE (right));
6479 /* if left is a literal & right is not then exchange them */
6480 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6481 #ifdef LOGIC_OPS_BROKEN
6482 || AOP_NEEDSACC (left) // I think this is a net loss now.
6486 operand *tmp = right;
6491 /* if result = right then exchange them */
6492 if (sameRegs (AOP (result), AOP (right)))
6494 operand *tmp = right;
6499 /* if right is bit then exchange them */
6500 if (AOP_TYPE (right) == AOP_CRY &&
6501 AOP_TYPE (left) != AOP_CRY)
6503 operand *tmp = right;
6507 if (AOP_TYPE (right) == AOP_LIT)
6508 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6510 size = AOP_SIZE (result);
6514 if (AOP_TYPE (left) == AOP_CRY)
6516 if (AOP_TYPE (right) == AOP_LIT)
6518 // c = bit & literal;
6521 // lit != 0 => result = 1
6522 if (AOP_TYPE (result) == AOP_CRY)
6525 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6527 continueIfTrue (ifx);
6530 emitcode ("setb", "c");
6534 // lit == 0 => result = left
6535 if (size && sameRegs (AOP (result), AOP (left)))
6537 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6542 if (AOP_TYPE (right) == AOP_CRY)
6545 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6546 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6551 symbol *tlbl = newiTempLabel (NULL);
6552 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6553 emitcode ("setb", "c");
6554 emitcode ("jb", "%s,!tlabel",
6555 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6557 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6558 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6560 jmpTrueOrFalse (ifx, tlbl);
6566 emitcode ("", "!tlabeldef", tlbl->key + 100);
6575 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6576 genIfxJump (ifx, "c");
6580 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6581 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6582 if ((AOP_TYPE (right) == AOP_LIT) &&
6583 (AOP_TYPE (result) == AOP_CRY) &&
6584 (AOP_TYPE (left) != AOP_CRY))
6590 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6592 continueIfTrue (ifx);
6597 // lit = 0, result = boolean(left)
6599 emitcode ("setb", "c");
6603 symbol *tlbl = newiTempLabel (NULL);
6604 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6606 emitcode ("", "!tlabeldef", tlbl->key + 100);
6610 genIfxJump (ifx, "a");
6618 /* if left is same as result */
6619 if (sameRegs (AOP (result), AOP (left)))
6621 for (; size--; offset++)
6623 if (AOP_TYPE (right) == AOP_LIT)
6625 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6631 if (IS_AOP_PREG (left))
6633 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6634 emitcode ("orl", "a,%s",
6635 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6636 aopPut (AOP (result), "a", offset);
6640 emitcode ("orl", "%s,%s",
6641 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6642 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6648 if (AOP_TYPE (left) == AOP_ACC)
6650 emitcode ("orl", "a,%s",
6651 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6655 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6656 if (IS_AOP_PREG (left))
6658 emitcode ("orl", "a,%s",
6659 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6660 aopPut (AOP (result), "a", offset);
6664 emitcode ("orl", "%s,a",
6665 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6673 // left & result in different registers
6674 if (AOP_TYPE (result) == AOP_CRY)
6677 // if(size), result in bit
6678 // if(!size && ifx), conditional oper: if(left | right)
6679 symbol *tlbl = newiTempLabel (NULL);
6680 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6682 emitcode ("setb", "c");
6685 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6686 emitcode ("orl", "a,%s",
6687 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6689 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6690 emitcode ("orl", "a,%s",
6691 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6693 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6699 emitcode ("", "!tlabeldef", tlbl->key + 100);
6703 jmpTrueOrFalse (ifx, tlbl);
6707 _startLazyDPSEvaluation();
6708 for (; (size--); offset++)
6711 // result = left & right
6712 if (AOP_TYPE (right) == AOP_LIT)
6714 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6716 aopPut (AOP (result),
6717 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6721 D (emitcode (";", "better literal OR."););
6722 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6723 emitcode ("orl", "a, %s",
6724 aopGet (AOP (right), offset,
6725 FALSE, FALSE, DP2_RESULT_REG));
6730 // faster than result <- left, anl result,right
6731 // and better if result is SFR
6732 if (AOP_TYPE (left) == AOP_ACC)
6734 emitcode ("orl", "a,%s",
6735 aopGet (AOP (right), offset,
6736 FALSE, FALSE, DP2_RESULT_REG));
6740 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6742 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6744 emitcode("mov", "b,a");
6748 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6749 emitcode ("orl", "a,%s", rOp);
6752 aopPut (AOP (result), "a", offset);
6754 _endLazyDPSEvaluation();
6759 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6760 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6761 freeAsmop (result, NULL, ic, TRUE);
6764 /*-----------------------------------------------------------------*/
6765 /* genXor - code for xclusive or */
6766 /*-----------------------------------------------------------------*/
6768 genXor (iCode * ic, iCode * ifx)
6770 operand *left, *right, *result;
6771 int size, offset = 0;
6772 unsigned long lit = 0L;
6775 D (emitcode (";", "genXor "););
6777 AOP_OP_3_NOFATAL (ic, pushResult);
6778 AOP_SET_LOCALS (ic);
6782 genFarFarLogicOp(ic, "xrl");
6787 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6789 AOP_TYPE (left), AOP_TYPE (right));
6790 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6792 AOP_SIZE (left), AOP_SIZE (right));
6795 /* if left is a literal & right is not ||
6796 if left needs acc & right does not */
6797 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6798 #ifdef LOGIC_OPS_BROKEN
6799 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6803 operand *tmp = right;
6808 /* if result = right then exchange them */
6809 if (sameRegs (AOP (result), AOP (right)))
6811 operand *tmp = right;
6816 /* if right is bit then exchange them */
6817 if (AOP_TYPE (right) == AOP_CRY &&
6818 AOP_TYPE (left) != AOP_CRY)
6820 operand *tmp = right;
6824 if (AOP_TYPE (right) == AOP_LIT)
6825 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6827 size = AOP_SIZE (result);
6831 if (AOP_TYPE (left) == AOP_CRY)
6833 if (AOP_TYPE (right) == AOP_LIT)
6835 // c = bit & literal;
6838 // lit>>1 != 0 => result = 1
6839 if (AOP_TYPE (result) == AOP_CRY)
6842 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6844 continueIfTrue (ifx);
6847 emitcode ("setb", "c");
6854 // lit == 0, result = left
6855 if (size && sameRegs (AOP (result), AOP (left)))
6857 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6861 // lit == 1, result = not(left)
6862 if (size && sameRegs (AOP (result), AOP (left)))
6864 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6869 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6870 emitcode ("cpl", "c");
6879 symbol *tlbl = newiTempLabel (NULL);
6880 if (AOP_TYPE (right) == AOP_CRY)
6883 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6887 int sizer = AOP_SIZE (right);
6889 // if val>>1 != 0, result = 1
6890 emitcode ("setb", "c");
6893 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
6895 // test the msb of the lsb
6896 emitcode ("anl", "a,#!constbyte",0xfe);
6897 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6901 emitcode ("rrc", "a");
6903 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6904 emitcode ("cpl", "c");
6905 emitcode ("", "!tlabeldef", (tlbl->key + 100));
6912 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6913 genIfxJump (ifx, "c");
6917 if (sameRegs (AOP (result), AOP (left)))
6919 /* if left is same as result */
6920 for (; size--; offset++)
6922 if (AOP_TYPE (right) == AOP_LIT)
6924 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6926 else if (IS_AOP_PREG (left))
6928 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6929 emitcode ("xrl", "a,%s",
6930 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6931 aopPut (AOP (result), "a", offset);
6934 emitcode ("xrl", "%s,%s",
6935 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6936 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6940 if (AOP_TYPE (left) == AOP_ACC)
6941 emitcode ("xrl", "a,%s",
6942 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6945 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6946 if (IS_AOP_PREG (left))
6948 emitcode ("xrl", "a,%s",
6949 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6950 aopPut (AOP (result), "a", offset);
6953 emitcode ("xrl", "%s,a",
6954 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6961 // left & result in different registers
6962 if (AOP_TYPE (result) == AOP_CRY)
6965 // if(size), result in bit
6966 // if(!size && ifx), conditional oper: if(left ^ right)
6967 symbol *tlbl = newiTempLabel (NULL);
6968 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6971 emitcode ("setb", "c");
6974 if ((AOP_TYPE (right) == AOP_LIT) &&
6975 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6977 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6981 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6982 emitcode ("xrl", "a,%s",
6983 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6985 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6986 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6988 emitcode("mov", "b,a");
6992 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6993 emitcode ("xrl", "a,%s", rOp);
6996 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7002 emitcode ("", "!tlabeldef", tlbl->key + 100);
7006 jmpTrueOrFalse (ifx, tlbl);
7010 for (; (size--); offset++)
7013 // result = left & right
7014 if (AOP_TYPE (right) == AOP_LIT)
7016 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7018 aopPut (AOP (result),
7019 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7023 D (emitcode (";", "better literal XOR."););
7024 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7025 emitcode ("xrl", "a, %s",
7026 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7030 // faster than result <- left, anl result,right
7031 // and better if result is SFR
7032 if (AOP_TYPE (left) == AOP_ACC)
7034 emitcode ("xrl", "a,%s",
7035 aopGet (AOP (right), offset,
7036 FALSE, FALSE, DP2_RESULT_REG));
7040 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7041 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7043 emitcode("mov", "b,a");
7047 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7048 emitcode ("xrl", "a,%s", rOp);
7051 aopPut (AOP (result), "a", offset);
7058 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7059 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7060 freeAsmop (result, NULL, ic, TRUE);
7063 /*-----------------------------------------------------------------*/
7064 /* genInline - write the inline code out */
7065 /*-----------------------------------------------------------------*/
7067 genInline (iCode * ic)
7069 char *buffer, *bp, *bp1;
7071 D (emitcode (";", "genInline "); );
7073 _G.inLine += (!options.asmpeep);
7075 buffer = Safe_strdup(IC_INLINE(ic));
7079 /* emit each line as a code */
7104 /* emitcode("",buffer); */
7105 _G.inLine -= (!options.asmpeep);
7108 /*-----------------------------------------------------------------*/
7109 /* genRRC - rotate right with carry */
7110 /*-----------------------------------------------------------------*/
7114 operand *left, *result;
7117 D (emitcode (";", "genRRC "););
7119 /* rotate right with carry */
7120 left = IC_LEFT (ic);
7121 result = IC_RESULT (ic);
7122 aopOp (left, ic, FALSE, FALSE);
7123 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7125 /* move it to the result */
7126 size = AOP_SIZE (result);
7130 _startLazyDPSEvaluation ();
7133 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7134 emitcode ("rrc", "a");
7135 if (AOP_SIZE (result) > 1)
7136 aopPut (AOP (result), "a", offset--);
7138 _endLazyDPSEvaluation ();
7140 /* now we need to put the carry into the
7141 highest order byte of the result */
7142 if (AOP_SIZE (result) > 1)
7144 MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7146 emitcode ("mov", "acc.7,c");
7147 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7148 freeAsmop (left, NULL, ic, TRUE);
7149 freeAsmop (result, NULL, ic, TRUE);
7152 /*-----------------------------------------------------------------*/
7153 /* genRLC - generate code for rotate left with carry */
7154 /*-----------------------------------------------------------------*/
7158 operand *left, *result;
7162 D (emitcode (";", "genRLC "););
7164 /* rotate right with carry */
7165 left = IC_LEFT (ic);
7166 result = IC_RESULT (ic);
7167 aopOp (left, ic, FALSE, FALSE);
7168 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7170 /* move it to the result */
7171 size = AOP_SIZE (result);
7175 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7177 emitcode ("add", "a,acc");
7178 if (AOP_SIZE (result) > 1)
7180 aopPut (AOP (result), "a", offset++);
7183 _startLazyDPSEvaluation ();
7186 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7188 emitcode ("rlc", "a");
7189 if (AOP_SIZE (result) > 1)
7190 aopPut (AOP (result), "a", offset++);
7192 _endLazyDPSEvaluation ();
7194 /* now we need to put the carry into the
7195 highest order byte of the result */
7196 if (AOP_SIZE (result) > 1)
7198 l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7201 emitcode ("mov", "acc.0,c");
7202 aopPut (AOP (result), "a", 0);
7203 freeAsmop (left, NULL, ic, TRUE);
7204 freeAsmop (result, NULL, ic, TRUE);
7207 /*-----------------------------------------------------------------*/
7208 /* genGetHbit - generates code get highest order bit */
7209 /*-----------------------------------------------------------------*/
7211 genGetHbit (iCode * ic)
7213 operand *left, *result;
7214 left = IC_LEFT (ic);
7215 result = IC_RESULT (ic);
7216 aopOp (left, ic, FALSE, FALSE);
7217 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7219 D (emitcode (";", "genGetHbit "););
7221 /* get the highest order byte into a */
7222 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7223 if (AOP_TYPE (result) == AOP_CRY)
7225 emitcode ("rlc", "a");
7230 emitcode ("rl", "a");
7231 emitcode ("anl", "a,#1");
7236 freeAsmop (left, NULL, ic, TRUE);
7237 freeAsmop (result, NULL, ic, TRUE);
7240 /*-----------------------------------------------------------------*/
7241 /* AccRol - rotate left accumulator by known count */
7242 /*-----------------------------------------------------------------*/
7244 AccRol (int shCount)
7246 shCount &= 0x0007; // shCount : 0..7
7253 emitcode ("rl", "a");
7256 emitcode ("rl", "a");
7257 emitcode ("rl", "a");
7260 emitcode ("swap", "a");
7261 emitcode ("rr", "a");
7264 emitcode ("swap", "a");
7267 emitcode ("swap", "a");
7268 emitcode ("rl", "a");
7271 emitcode ("rr", "a");
7272 emitcode ("rr", "a");
7275 emitcode ("rr", "a");
7280 /*-----------------------------------------------------------------*/
7281 /* AccLsh - left shift accumulator by known count */
7282 /*-----------------------------------------------------------------*/
7284 AccLsh (int shCount)
7289 emitcode ("add", "a,acc");
7290 else if (shCount == 2)
7292 emitcode ("add", "a,acc");
7293 emitcode ("add", "a,acc");
7297 /* rotate left accumulator */
7299 /* and kill the lower order bits */
7300 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7305 /*-----------------------------------------------------------------*/
7306 /* AccRsh - right shift accumulator by known count */
7307 /*-----------------------------------------------------------------*/
7309 AccRsh (int shCount)
7316 emitcode ("rrc", "a");
7320 /* rotate right accumulator */
7321 AccRol (8 - shCount);
7322 /* and kill the higher order bits */
7323 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7328 #ifdef BETTER_LITERAL_SHIFT
7329 /*-----------------------------------------------------------------*/
7330 /* AccSRsh - signed right shift accumulator by known count */
7331 /*-----------------------------------------------------------------*/
7333 AccSRsh (int shCount)
7340 emitcode ("mov", "c,acc.7");
7341 emitcode ("rrc", "a");
7343 else if (shCount == 2)
7345 emitcode ("mov", "c,acc.7");
7346 emitcode ("rrc", "a");
7347 emitcode ("mov", "c,acc.7");
7348 emitcode ("rrc", "a");
7352 tlbl = newiTempLabel (NULL);
7353 /* rotate right accumulator */
7354 AccRol (8 - shCount);
7355 /* and kill the higher order bits */
7356 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7357 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7358 emitcode ("orl", "a,#!constbyte",
7359 (unsigned char) ~SRMask[shCount]);
7360 emitcode ("", "!tlabeldef", tlbl->key + 100);
7366 #ifdef BETTER_LITERAL_SHIFT
7367 /*-----------------------------------------------------------------*/
7368 /* shiftR1Left2Result - shift right one byte from left to result */
7369 /*-----------------------------------------------------------------*/
7371 shiftR1Left2Result (operand * left, int offl,
7372 operand * result, int offr,
7373 int shCount, int sign)
7375 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7376 /* shift right accumulator */
7381 aopPut (AOP (result), "a", offr);
7385 #ifdef BETTER_LITERAL_SHIFT
7386 /*-----------------------------------------------------------------*/
7387 /* shiftL1Left2Result - shift left one byte from left to result */
7388 /*-----------------------------------------------------------------*/
7390 shiftL1Left2Result (operand * left, int offl,
7391 operand * result, int offr, int shCount)
7393 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7394 /* shift left accumulator */
7396 aopPut (AOP (result), "a", offr);
7400 #ifdef BETTER_LITERAL_SHIFT
7401 /*-----------------------------------------------------------------*/
7402 /* movLeft2Result - move byte from left to result */
7403 /*-----------------------------------------------------------------*/
7405 movLeft2Result (operand * left, int offl,
7406 operand * result, int offr, int sign)
7409 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7411 l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
7413 if (*l == '@' && (IS_AOP_PREG (result)))
7415 emitcode ("mov", "a,%s", l);
7416 aopPut (AOP (result), "a", offr);
7422 aopPut (AOP (result), l, offr);
7426 /* MSB sign in acc.7 ! */
7427 if (getDataSize (left) == offl + 1)
7429 emitcode ("mov", "a,%s", l);
7430 aopPut (AOP (result), "a", offr);
7438 #ifdef BETTER_LITERAL_SHIFT
7439 /*-----------------------------------------------------------------*/
7440 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7441 /*-----------------------------------------------------------------*/
7445 emitcode ("rrc", "a");
7446 emitcode ("xch", "a,%s", x);
7447 emitcode ("rrc", "a");
7448 emitcode ("xch", "a,%s", x);
7452 #ifdef BETTER_LITERAL_SHIFT
7454 /*-----------------------------------------------------------------*/
7455 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7456 /*-----------------------------------------------------------------*/
7460 emitcode ("xch", "a,%s", x);
7461 emitcode ("rlc", "a");
7462 emitcode ("xch", "a,%s", x);
7463 emitcode ("rlc", "a");
7467 #ifdef BETTER_LITERAL_SHIFT
7468 /*-----------------------------------------------------------------*/
7469 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7470 /*-----------------------------------------------------------------*/
7474 emitcode ("xch", "a,%s", x);
7475 emitcode ("add", "a,acc");
7476 emitcode ("xch", "a,%s", x);
7477 emitcode ("rlc", "a");
7481 #ifdef BETTER_LITERAL_SHIFT
7482 /*-----------------------------------------------------------------*/
7483 /* AccAXLsh - left shift a:x by known count (0..7) */
7484 /*-----------------------------------------------------------------*/
7486 AccAXLsh (char *x, int shCount)
7501 case 5: // AAAAABBB:CCCCCDDD
7503 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7505 emitcode ("anl", "a,#!constbyte",
7506 SLMask[shCount]); // BBB00000:CCCCCDDD
7508 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7510 AccRol (shCount); // DDDCCCCC:BBB00000
7512 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7514 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7516 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7518 emitcode ("anl", "a,#!constbyte",
7519 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7521 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7523 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7526 case 6: // AAAAAABB:CCCCCCDD
7527 emitcode ("anl", "a,#!constbyte",
7528 SRMask[shCount]); // 000000BB:CCCCCCDD
7529 emitcode ("mov", "c,acc.0"); // c = B
7530 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7532 AccAXRrl1 (x); // BCCCCCCD:D000000B
7533 AccAXRrl1 (x); // BBCCCCCC:DD000000
7535 emitcode("rrc","a");
7536 emitcode("xch","a,%s", x);
7537 emitcode("rrc","a");
7538 emitcode("mov","c,acc.0"); //<< get correct bit
7539 emitcode("xch","a,%s", x);
7541 emitcode("rrc","a");
7542 emitcode("xch","a,%s", x);
7543 emitcode("rrc","a");
7544 emitcode("xch","a,%s", x);
7547 case 7: // a:x <<= 7
7549 emitcode ("anl", "a,#!constbyte",
7550 SRMask[shCount]); // 0000000B:CCCCCCCD
7552 emitcode ("mov", "c,acc.0"); // c = B
7554 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7556 AccAXRrl1 (x); // BCCCCCCC:D0000000
7565 #ifdef BETTER_LITERAL_SHIFT
7567 /*-----------------------------------------------------------------*/
7568 /* AccAXRsh - right shift a:x known count (0..7) */
7569 /*-----------------------------------------------------------------*/
7571 AccAXRsh (char *x, int shCount)
7579 AccAXRrl1 (x); // 0->a:x
7584 AccAXRrl1 (x); // 0->a:x
7587 AccAXRrl1 (x); // 0->a:x
7592 case 5: // AAAAABBB:CCCCCDDD = a:x
7594 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7596 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7598 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7600 emitcode ("anl", "a,#!constbyte",
7601 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7603 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7605 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7607 emitcode ("anl", "a,#!constbyte",
7608 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7610 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7612 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7614 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7617 case 6: // AABBBBBB:CCDDDDDD
7619 emitcode ("mov", "c,acc.7");
7620 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7622 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7624 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7626 emitcode ("anl", "a,#!constbyte",
7627 SRMask[shCount]); // 000000AA:BBBBBBCC
7630 case 7: // ABBBBBBB:CDDDDDDD
7632 emitcode ("mov", "c,acc.7"); // c = A
7634 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7636 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7638 emitcode ("anl", "a,#!constbyte",
7639 SRMask[shCount]); // 0000000A:BBBBBBBC
7648 #ifdef BETTER_LITERAL_SHIFT
7649 /*-----------------------------------------------------------------*/
7650 /* AccAXRshS - right shift signed a:x known count (0..7) */
7651 /*-----------------------------------------------------------------*/
7653 AccAXRshS (char *x, int shCount)
7661 emitcode ("mov", "c,acc.7");
7662 AccAXRrl1 (x); // s->a:x
7666 emitcode ("mov", "c,acc.7");
7667 AccAXRrl1 (x); // s->a:x
7669 emitcode ("mov", "c,acc.7");
7670 AccAXRrl1 (x); // s->a:x
7675 case 5: // AAAAABBB:CCCCCDDD = a:x
7677 tlbl = newiTempLabel (NULL);
7678 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7680 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7682 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7684 emitcode ("anl", "a,#!constbyte",
7685 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7687 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7689 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7691 emitcode ("anl", "a,#!constbyte",
7692 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7694 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7696 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7698 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7700 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7701 emitcode ("orl", "a,#!constbyte",
7702 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7704 emitcode ("", "!tlabeldef", tlbl->key + 100);
7705 break; // SSSSAAAA:BBBCCCCC
7707 case 6: // AABBBBBB:CCDDDDDD
7709 tlbl = newiTempLabel (NULL);
7710 emitcode ("mov", "c,acc.7");
7711 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7713 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7715 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7717 emitcode ("anl", "a,#!constbyte",
7718 SRMask[shCount]); // 000000AA:BBBBBBCC
7720 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7721 emitcode ("orl", "a,#!constbyte",
7722 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7724 emitcode ("", "!tlabeldef", tlbl->key + 100);
7726 case 7: // ABBBBBBB:CDDDDDDD
7728 tlbl = newiTempLabel (NULL);
7729 emitcode ("mov", "c,acc.7"); // c = A
7731 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7733 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7735 emitcode ("anl", "a,#!constbyte",
7736 SRMask[shCount]); // 0000000A:BBBBBBBC
7738 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7739 emitcode ("orl", "a,#!constbyte",
7740 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7742 emitcode ("", "!tlabeldef", tlbl->key + 100);
7750 #ifdef BETTER_LITERAL_SHIFT
7752 _loadLeftIntoAx(char **lsb,
7758 // Get the initial value from left into a pair of registers.
7759 // MSB must be in A, LSB can be any register.
7761 // If the result is held in registers, it is an optimization
7762 // if the LSB can be held in the register which will hold the,
7763 // result LSB since this saves us from having to copy it into
7764 // the result following AccAXLsh.
7766 // If the result is addressed indirectly, this is not a gain.
7767 if (AOP_NEEDSACC(result))
7771 _startLazyDPSEvaluation();
7772 if (AOP_TYPE(left) == AOP_DPTR2)
7775 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
7776 // get LSB in DP2_RESULT_REG.
7777 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
7778 assert(!strcmp(leftByte, DP2_RESULT_REG));
7782 // get LSB into DP2_RESULT_REG
7783 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
7784 if (strcmp(leftByte, DP2_RESULT_REG))
7787 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7790 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
7791 assert(strcmp(leftByte, DP2_RESULT_REG));
7794 _endLazyDPSEvaluation();
7795 *lsb = DP2_RESULT_REG;
7799 if (sameRegs (AOP (result), AOP (left)) &&
7800 ((offl + MSB16) == offr))
7802 /* don't crash result[offr] */
7803 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
7804 emitcode ("xch", "a,%s",
7805 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
7809 movLeft2Result (left, offl, result, offr, 0);
7810 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
7812 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
7813 assert(strcmp(*lsb,"a"));
7818 _storeAxResults(char *lsb,
7822 _startLazyDPSEvaluation();
7823 if (AOP_NEEDSACC(result))
7825 /* We have to explicitly update the result LSB.
7827 emitcode("xch","a,%s", lsb);
7828 aopPut(AOP(result), "a", offr);
7829 emitcode("mov","a,%s", lsb);
7831 if (getDataSize (result) > 1)
7833 aopPut (AOP (result), "a", offr + MSB16);
7835 _endLazyDPSEvaluation();
7838 /*-----------------------------------------------------------------*/
7839 /* shiftL2Left2Result - shift left two bytes from left to result */
7840 /*-----------------------------------------------------------------*/
7842 shiftL2Left2Result (operand * left, int offl,
7843 operand * result, int offr, int shCount)
7847 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7849 AccAXLsh (lsb, shCount);
7851 _storeAxResults(lsb, result, offr);
7855 #ifdef BETTER_LITERAL_SHIFT
7856 /*-----------------------------------------------------------------*/
7857 /* shiftR2Left2Result - shift right two bytes from left to result */
7858 /*-----------------------------------------------------------------*/
7860 shiftR2Left2Result (operand * left, int offl,
7861 operand * result, int offr,
7862 int shCount, int sign)
7866 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7868 /* a:x >> shCount (x = lsb(result)) */
7871 AccAXRshS(lsb, shCount);
7875 AccAXRsh(lsb, shCount);
7878 _storeAxResults(lsb, result, offr);
7884 /*-----------------------------------------------------------------*/
7885 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7886 /*-----------------------------------------------------------------*/
7888 shiftLLeftOrResult (operand * left, int offl,
7889 operand * result, int offr, int shCount)
7891 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7892 /* shift left accumulator */
7894 /* or with result */
7895 emitcode ("orl", "a,%s",
7896 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7897 /* back to result */
7898 aopPut (AOP (result), "a", offr);
7904 /*-----------------------------------------------------------------*/
7905 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7906 /*-----------------------------------------------------------------*/
7908 shiftRLeftOrResult (operand * left, int offl,
7909 operand * result, int offr, int shCount)
7911 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7912 /* shift right accumulator */
7914 /* or with result */
7915 emitcode ("orl", "a,%s",
7916 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7917 /* back to result */
7918 aopPut (AOP (result), "a", offr);
7922 #ifdef BETTER_LITERAL_SHIFT
7923 /*-----------------------------------------------------------------*/
7924 /* genlshOne - left shift a one byte quantity by known count */
7925 /*-----------------------------------------------------------------*/
7927 genlshOne (operand * result, operand * left, int shCount)
7929 D (emitcode (";", "genlshOne "););
7930 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7934 #ifdef BETTER_LITERAL_SHIFT
7935 /*-----------------------------------------------------------------*/
7936 /* genlshTwo - left shift two bytes by known amount != 0 */
7937 /*-----------------------------------------------------------------*/
7939 genlshTwo (operand * result, operand * left, int shCount)
7943 D (emitcode (";", "genlshTwo "););
7945 size = getDataSize (result);
7947 /* if shCount >= 8 */
7952 _startLazyDPSEvaluation();
7958 _endLazyDPSEvaluation();
7959 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7960 aopPut (AOP (result), zero, LSB);
7964 movLeft2Result (left, LSB, result, MSB16, 0);
7965 aopPut (AOP (result), zero, LSB);
7966 _endLazyDPSEvaluation();
7971 aopPut (AOP (result), zero, LSB);
7972 _endLazyDPSEvaluation();
7976 /* 1 <= shCount <= 7 */
7981 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7985 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7993 /*-----------------------------------------------------------------*/
7994 /* shiftLLong - shift left one long from left to result */
7995 /* offl = LSB or MSB16 */
7996 /*-----------------------------------------------------------------*/
7998 shiftLLong (operand * left, operand * result, int offr)
8001 int size = AOP_SIZE (result);
8003 if (size >= LSB + offr)
8005 l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8007 emitcode ("add", "a,acc");
8008 if (sameRegs (AOP (left), AOP (result)) &&
8009 size >= MSB16 + offr && offr != LSB)
8010 emitcode ("xch", "a,%s",
8011 aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8013 aopPut (AOP (result), "a", LSB + offr);
8016 if (size >= MSB16 + offr)
8018 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8020 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8022 emitcode ("rlc", "a");
8023 if (sameRegs (AOP (left), AOP (result)) &&
8024 size >= MSB24 + offr && offr != LSB)
8025 emitcode ("xch", "a,%s",
8026 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8028 aopPut (AOP (result), "a", MSB16 + offr);
8031 if (size >= MSB24 + offr)
8033 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8035 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8037 emitcode ("rlc", "a");
8038 if (sameRegs (AOP (left), AOP (result)) &&
8039 size >= MSB32 + offr && offr != LSB)
8040 emitcode ("xch", "a,%s",
8041 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8043 aopPut (AOP (result), "a", MSB24 + offr);
8046 if (size > MSB32 + offr)
8048 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8050 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8052 emitcode ("rlc", "a");
8053 aopPut (AOP (result), "a", MSB32 + offr);
8056 aopPut (AOP (result), zero, LSB);
8062 /*-----------------------------------------------------------------*/
8063 /* genlshFour - shift four byte by a known amount != 0 */
8064 /*-----------------------------------------------------------------*/
8066 genlshFour (operand * result, operand * left, int shCount)
8070 D (emitcode (";", "genlshFour ");
8073 size = AOP_SIZE (result);
8075 /* if shifting more that 3 bytes */
8080 /* lowest order of left goes to the highest
8081 order of the destination */
8082 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8084 movLeft2Result (left, LSB, result, MSB32, 0);
8085 aopPut (AOP (result), zero, LSB);
8086 aopPut (AOP (result), zero, MSB16);
8087 aopPut (AOP (result), zero, MSB24);
8091 /* more than two bytes */
8092 else if (shCount >= 16)
8094 /* lower order two bytes goes to higher order two bytes */
8096 /* if some more remaining */
8098 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8101 movLeft2Result (left, MSB16, result, MSB32, 0);
8102 movLeft2Result (left, LSB, result, MSB24, 0);
8104 aopPut (AOP (result), zero, MSB16);
8105 aopPut (AOP (result), zero, LSB);
8109 /* if more than 1 byte */
8110 else if (shCount >= 8)
8112 /* lower order three bytes goes to higher order three bytes */
8117 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8119 movLeft2Result (left, LSB, result, MSB16, 0);
8125 movLeft2Result (left, MSB24, result, MSB32, 0);
8126 movLeft2Result (left, MSB16, result, MSB24, 0);
8127 movLeft2Result (left, LSB, result, MSB16, 0);
8128 aopPut (AOP (result), zero, LSB);
8130 else if (shCount == 1)
8131 shiftLLong (left, result, MSB16);
8134 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8135 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8136 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8137 aopPut (AOP (result), zero, LSB);
8142 /* 1 <= shCount <= 7 */
8143 else if (shCount <= 2)
8145 shiftLLong (left, result, LSB);
8147 shiftLLong (result, result, LSB);
8149 /* 3 <= shCount <= 7, optimize */
8152 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8153 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8154 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8159 #ifdef BETTER_LITERAL_SHIFT
8160 /*-----------------------------------------------------------------*/
8161 /* genLeftShiftLiteral - left shifting by known count */
8162 /*-----------------------------------------------------------------*/
8164 genLeftShiftLiteral (operand * left,
8169 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8172 size = getSize (operandType (result));
8174 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8176 /* We only handle certain easy cases so far. */
8178 && (shCount < (size * 8))
8182 D(emitcode (";", "genLeftShiftLiteral wimping out"););
8186 freeAsmop (right, NULL, ic, TRUE);
8188 aopOp(left, ic, FALSE, FALSE);
8189 aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8192 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8194 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8195 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8197 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8200 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8202 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8203 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8205 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8211 emitcode ("; shift left ", "result %d, left %d", size,
8215 /* I suppose that the left size >= result size */
8218 _startLazyDPSEvaluation();
8221 movLeft2Result (left, size, result, size, 0);
8223 _endLazyDPSEvaluation();
8225 else if (shCount >= (size * 8))
8227 _startLazyDPSEvaluation();
8230 aopPut (AOP (result), zero, size);
8232 _endLazyDPSEvaluation();
8239 genlshOne (result, left, shCount);
8243 genlshTwo (result, left, shCount);
8247 genlshFour (result, left, shCount);
8251 fprintf(stderr, "*** ack! mystery literal shift!\n");
8255 freeAsmop (left, NULL, ic, TRUE);
8256 freeAsmop (result, NULL, ic, TRUE);
8261 /*-----------------------------------------------------------------*/
8262 /* genLeftShift - generates code for left shifting */
8263 /*-----------------------------------------------------------------*/
8265 genLeftShift (iCode * ic)
8267 operand *left, *right, *result;
8270 symbol *tlbl, *tlbl1;
8272 D (emitcode (";", "genLeftShift "););
8274 right = IC_RIGHT (ic);
8275 left = IC_LEFT (ic);
8276 result = IC_RESULT (ic);
8278 aopOp (right, ic, FALSE, FALSE);
8281 #ifdef BETTER_LITERAL_SHIFT
8282 /* if the shift count is known then do it
8283 as efficiently as possible */
8284 if (AOP_TYPE (right) == AOP_LIT)
8286 if (genLeftShiftLiteral (left, right, result, ic))
8293 /* shift count is unknown then we have to form
8294 a loop get the loop count in B : Note: we take
8295 only the lower order byte since shifting
8296 more that 32 bits make no sense anyway, ( the
8297 largest size of an object can be only 32 bits ) */
8299 if (AOP_TYPE (right) == AOP_LIT)
8301 /* Really should be handled by genLeftShiftLiteral,
8302 * but since I'm too lazy to fix that today, at least we can make
8303 * some small improvement.
8305 emitcode("mov", "b,#!constbyte",
8306 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8310 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8311 emitcode ("inc", "b");
8313 freeAsmop (right, NULL, ic, TRUE);
8314 aopOp (left, ic, FALSE, FALSE);
8315 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8317 /* now move the left to the result if they are not the
8319 if (!sameRegs (AOP (left), AOP (result)) &&
8320 AOP_SIZE (result) > 1)
8323 size = AOP_SIZE (result);
8325 _startLazyDPSEvaluation ();
8328 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8329 if (*l == '@' && (IS_AOP_PREG (result)))
8332 emitcode ("mov", "a,%s", l);
8333 aopPut (AOP (result), "a", offset);
8336 aopPut (AOP (result), l, offset);
8339 _endLazyDPSEvaluation ();
8342 tlbl = newiTempLabel (NULL);
8343 size = AOP_SIZE (result);
8345 tlbl1 = newiTempLabel (NULL);
8347 /* if it is only one byte then */
8350 symbol *tlbl1 = newiTempLabel (NULL);
8352 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8353 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8354 emitcode ("", "!tlabeldef", tlbl->key + 100);
8355 emitcode ("add", "a,acc");
8356 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8357 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8358 aopPut (AOP (result), "a", 0);
8362 reAdjustPreg (AOP (result));
8364 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8365 emitcode ("", "!tlabeldef", tlbl->key + 100);
8366 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8367 emitcode ("add", "a,acc");
8368 aopPut (AOP (result), "a", offset++);
8369 _startLazyDPSEvaluation ();
8372 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8373 emitcode ("rlc", "a");
8374 aopPut (AOP (result), "a", offset++);
8376 _endLazyDPSEvaluation ();
8377 reAdjustPreg (AOP (result));
8379 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8380 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8382 freeAsmop (left, NULL, ic, TRUE);
8383 freeAsmop (result, NULL, ic, TRUE);
8386 #ifdef BETTER_LITERAL_SHIFT
8387 /*-----------------------------------------------------------------*/
8388 /* genrshOne - right shift a one byte quantity by known count */
8389 /*-----------------------------------------------------------------*/
8391 genrshOne (operand * result, operand * left,
8392 int shCount, int sign)
8394 D (emitcode (";", "genrshOne"););
8395 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8399 #ifdef BETTER_LITERAL_SHIFT
8400 /*-----------------------------------------------------------------*/
8401 /* genrshTwo - right shift two bytes by known amount != 0 */
8402 /*-----------------------------------------------------------------*/
8404 genrshTwo (operand * result, operand * left,
8405 int shCount, int sign)
8407 D (emitcode (";", "genrshTwo"););
8409 /* if shCount >= 8 */
8413 _startLazyDPSEvaluation();
8416 shiftR1Left2Result (left, MSB16, result, LSB,
8421 movLeft2Result (left, MSB16, result, LSB, sign);
8423 addSign (result, MSB16, sign);
8424 _endLazyDPSEvaluation();
8427 /* 1 <= shCount <= 7 */
8430 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8437 /*-----------------------------------------------------------------*/
8438 /* shiftRLong - shift right one long from left to result */
8439 /* offl = LSB or MSB16 */
8440 /*-----------------------------------------------------------------*/
8442 shiftRLong (operand * left, int offl,
8443 operand * result, int sign)
8445 int isSameRegs=sameRegs(AOP(left),AOP(result));
8447 if (isSameRegs && offl>1) {
8448 // we are in big trouble, but this shouldn't happen
8449 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8452 MOVA (aopGet (AOP (left), MSB32, FALSE, NULL));
8457 emitcode ("rlc", "a");
8458 emitcode ("subb", "a,acc");
8459 emitcode ("xch", "a,%s",
8460 aopGet(AOP(left), MSB32, FALSE, DP2_RESULT_REG));
8462 aopPut (AOP(result), zero, MSB32);
8467 emitcode ("clr", "c");
8469 emitcode ("mov", "c,acc.7");
8472 emitcode ("rrc", "a");
8474 if (isSameRegs && offl==MSB16) {
8476 "a,%s",aopGet (AOP (left), MSB24, FALSE, DP2_RESULT_REG));
8478 aopPut (AOP (result), "a", MSB32);
8479 MOVA (aopGet (AOP (left), MSB24, FALSE, NULL));
8482 emitcode ("rrc", "a");
8483 if (isSameRegs && offl==1) {
8484 emitcode ("xch", "a,%s",
8485 aopGet (AOP (left), MSB16, FALSE, DP2_RESULT_REG));
8487 aopPut (AOP (result), "a", MSB24);
8488 MOVA (aopGet (AOP (left), MSB16, FALSE, NULL));
8490 emitcode ("rrc", "a");
8491 aopPut (AOP (result), "a", MSB16 - offl);
8495 MOVA (aopGet (AOP (left), LSB, FALSE, NULL));
8496 emitcode ("rrc", "a");
8497 aopPut (AOP (result), "a", LSB);
8504 /*-----------------------------------------------------------------*/
8505 /* genrshFour - shift four byte by a known amount != 0 */
8506 /*-----------------------------------------------------------------*/
8508 genrshFour (operand * result, operand * left,
8509 int shCount, int sign)
8511 D (emitcode (";", "genrshFour");
8514 /* if shifting more that 3 bytes */
8519 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8521 movLeft2Result (left, MSB32, result, LSB, sign);
8522 addSign (result, MSB16, sign);
8524 else if (shCount >= 16)
8528 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8531 movLeft2Result (left, MSB24, result, LSB, 0);
8532 movLeft2Result (left, MSB32, result, MSB16, sign);
8534 addSign (result, MSB24, sign);
8536 else if (shCount >= 8)
8540 shiftRLong (left, MSB16, result, sign);
8541 else if (shCount == 0)
8543 movLeft2Result (left, MSB16, result, LSB, 0);
8544 movLeft2Result (left, MSB24, result, MSB16, 0);
8545 movLeft2Result (left, MSB32, result, MSB24, sign);
8546 addSign (result, MSB32, sign);
8550 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8551 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8552 /* the last shift is signed */
8553 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8554 addSign (result, MSB32, sign);
8558 { /* 1 <= shCount <= 7 */
8561 shiftRLong (left, LSB, result, sign);
8563 shiftRLong (result, LSB, result, sign);
8567 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8568 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8569 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8575 #ifdef BETTER_LITERAL_SHIFT
8576 /*-----------------------------------------------------------------*/
8577 /* genRightShiftLiteral - right shifting by known count */
8578 /*-----------------------------------------------------------------*/
8580 genRightShiftLiteral (operand * left,
8586 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8589 size = getSize (operandType (result));
8591 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8593 /* We only handle certain easy cases so far. */
8595 && (shCount < (size * 8))
8599 D(emitcode (";", "genRightShiftLiteral wimping out"););
8603 freeAsmop (right, NULL, ic, TRUE);
8605 aopOp (left, ic, FALSE, FALSE);
8606 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8609 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8613 /* test the LEFT size !!! */
8615 /* I suppose that the left size >= result size */
8618 size = getDataSize (result);
8619 _startLazyDPSEvaluation();
8622 movLeft2Result (left, size, result, size, 0);
8624 _endLazyDPSEvaluation();
8626 else if (shCount >= (size * 8))
8630 /* get sign in acc.7 */
8631 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
8633 addSign (result, LSB, sign);
8640 genrshOne (result, left, shCount, sign);
8644 genrshTwo (result, left, shCount, sign);
8648 genrshFour (result, left, shCount, sign);
8655 freeAsmop (left, NULL, ic, TRUE);
8656 freeAsmop (result, NULL, ic, TRUE);
8662 /*-----------------------------------------------------------------*/
8663 /* genSignedRightShift - right shift of signed number */
8664 /*-----------------------------------------------------------------*/
8666 genSignedRightShift (iCode * ic)
8668 operand *right, *left, *result;
8671 symbol *tlbl, *tlbl1;
8673 D (emitcode (";", "genSignedRightShift "););
8675 /* we do it the hard way put the shift count in b
8676 and loop thru preserving the sign */
8678 right = IC_RIGHT (ic);
8679 left = IC_LEFT (ic);
8680 result = IC_RESULT (ic);
8682 aopOp (right, ic, FALSE, FALSE);
8684 #ifdef BETTER_LITERAL_SHIFT
8685 if (AOP_TYPE (right) == AOP_LIT)
8687 if (genRightShiftLiteral (left, right, result, ic, 1))
8693 /* shift count is unknown then we have to form
8694 a loop get the loop count in B : Note: we take
8695 only the lower order byte since shifting
8696 more that 32 bits make no sense anyway, ( the
8697 largest size of an object can be only 32 bits ) */
8699 if (AOP_TYPE (right) == AOP_LIT)
8701 /* Really should be handled by genRightShiftLiteral,
8702 * but since I'm too lazy to fix that today, at least we can make
8703 * some small improvement.
8705 emitcode("mov", "b,#!constbyte",
8706 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8710 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8711 emitcode ("inc", "b");
8713 freeAsmop (right, NULL, ic, TRUE);
8714 aopOp (left, ic, FALSE, FALSE);
8715 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8717 /* now move the left to the result if they are not the
8719 if (!sameRegs (AOP (left), AOP (result)) &&
8720 AOP_SIZE (result) > 1)
8723 size = AOP_SIZE (result);
8725 _startLazyDPSEvaluation ();
8728 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8729 if (*l == '@' && IS_AOP_PREG (result))
8732 emitcode ("mov", "a,%s", l);
8733 aopPut (AOP (result), "a", offset);
8736 aopPut (AOP (result), l, offset);
8739 _endLazyDPSEvaluation ();
8742 /* mov the highest order bit to OVR */
8743 tlbl = newiTempLabel (NULL);
8744 tlbl1 = newiTempLabel (NULL);
8746 size = AOP_SIZE (result);
8748 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
8749 emitcode ("rlc", "a");
8750 emitcode ("mov", "ov,c");
8751 /* if it is only one byte then */
8754 MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8755 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8756 emitcode ("", "!tlabeldef", tlbl->key + 100);
8757 emitcode ("mov", "c,ov");
8758 emitcode ("rrc", "a");
8759 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8760 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8761 aopPut (AOP (result), "a", 0);
8765 reAdjustPreg (AOP (result));
8766 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8767 emitcode ("", "!tlabeldef", tlbl->key + 100);
8768 emitcode ("mov", "c,ov");
8769 _startLazyDPSEvaluation ();
8772 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8773 emitcode ("rrc", "a");
8774 aopPut (AOP (result), "a", offset--);
8776 _endLazyDPSEvaluation ();
8777 reAdjustPreg (AOP (result));
8778 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8779 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8782 freeAsmop (left, NULL, ic, TRUE);
8783 freeAsmop (result, NULL, ic, TRUE);
8786 /*-----------------------------------------------------------------*/
8787 /* genRightShift - generate code for right shifting */
8788 /*-----------------------------------------------------------------*/
8790 genRightShift (iCode * ic)
8792 operand *right, *left, *result;
8796 symbol *tlbl, *tlbl1;
8798 D (emitcode (";", "genRightShift "););
8800 /* if signed then we do it the hard way preserve the
8801 sign bit moving it inwards */
8802 retype = getSpec (operandType (IC_RESULT (ic)));
8804 if (!SPEC_USIGN (retype))
8806 genSignedRightShift (ic);
8810 /* signed & unsigned types are treated the same : i.e. the
8811 signed is NOT propagated inwards : quoting from the
8812 ANSI - standard : "for E1 >> E2, is equivalent to division
8813 by 2**E2 if unsigned or if it has a non-negative value,
8814 otherwise the result is implementation defined ", MY definition
8815 is that the sign does not get propagated */
8817 right = IC_RIGHT (ic);
8818 left = IC_LEFT (ic);
8819 result = IC_RESULT (ic);
8821 aopOp (right, ic, FALSE, FALSE);
8823 #ifdef BETTER_LITERAL_SHIFT
8824 /* if the shift count is known then do it
8825 as efficiently as possible */
8826 if (AOP_TYPE (right) == AOP_LIT)
8828 if (genRightShiftLiteral (left, right, result, ic, 0))
8835 /* shift count is unknown then we have to form
8836 a loop get the loop count in B : Note: we take
8837 only the lower order byte since shifting
8838 more that 32 bits make no sense anyway, ( the
8839 largest size of an object can be only 32 bits ) */
8841 if (AOP_TYPE (right) == AOP_LIT)
8843 /* Really should be handled by genRightShiftLiteral,
8844 * but since I'm too lazy to fix that today, at least we can make
8845 * some small improvement.
8847 emitcode("mov", "b,#!constbyte",
8848 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8852 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8853 emitcode ("inc", "b");
8855 freeAsmop (right, NULL, ic, TRUE);
8856 aopOp (left, ic, FALSE, FALSE);
8857 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8859 /* now move the left to the result if they are not the
8861 if (!sameRegs (AOP (left), AOP (result)) &&
8862 AOP_SIZE (result) > 1)
8865 size = AOP_SIZE (result);
8867 _startLazyDPSEvaluation ();
8870 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8871 if (*l == '@' && IS_AOP_PREG (result))
8874 emitcode ("mov", "a,%s", l);
8875 aopPut (AOP (result), "a", offset);
8878 aopPut (AOP (result), l, offset);
8881 _endLazyDPSEvaluation ();
8884 tlbl = newiTempLabel (NULL);
8885 tlbl1 = newiTempLabel (NULL);
8886 size = AOP_SIZE (result);
8889 /* if it is only one byte then */
8892 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8893 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8894 emitcode ("", "!tlabeldef", tlbl->key + 100);
8896 emitcode ("rrc", "a");
8897 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8898 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8899 aopPut (AOP (result), "a", 0);
8903 reAdjustPreg (AOP (result));
8904 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8905 emitcode ("", "!tlabeldef", tlbl->key + 100);
8907 _startLazyDPSEvaluation ();
8910 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8911 emitcode ("rrc", "a");
8912 aopPut (AOP (result), "a", offset--);
8914 _endLazyDPSEvaluation ();
8915 reAdjustPreg (AOP (result));
8917 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8918 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8921 freeAsmop (left, NULL, ic, TRUE);
8922 freeAsmop (result, NULL, ic, TRUE);
8925 /*-----------------------------------------------------------------*/
8926 /* genUnpackBits - generates code for unpacking bits */
8927 /*-----------------------------------------------------------------*/
8929 genUnpackBits (operand * result, char *rname, int ptype)
8936 D (emitcode (";", "genUnpackBits "););
8938 etype = getSpec (operandType (result));
8940 /* read the first byte */
8946 emitcode ("mov", "a,@%s", rname);
8950 emitcode ("movx", "a,@%s", rname);
8954 emitcode ("movx", "a,@dptr");
8958 emitcode ("clr", "a");
8959 emitcode ("movc", "a,@a+dptr");
8963 emitcode ("lcall", "__gptrget");
8967 /* if we have bitdisplacement then it fits */
8968 /* into this byte completely or if length is */
8969 /* less than a byte */
8970 if (((shCnt = SPEC_BSTR (etype)) != 0) || (SPEC_BLEN (etype) <= 8))
8973 /* shift right acc */
8976 emitcode ("anl", "a,#!constbyte",
8977 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8978 aopPut (AOP (result), "a", offset);
8982 /* bit field did not fit in a byte */
8983 rlen = SPEC_BLEN (etype) - 8;
8984 aopPut (AOP (result), "a", offset++);
8993 emitcode ("inc", "%s", rname);
8994 emitcode ("mov", "a,@%s", rname);
8998 emitcode ("inc", "%s", rname);
8999 emitcode ("movx", "a,@%s", rname);
9003 emitcode ("inc", "dptr");
9004 emitcode ("movx", "a,@dptr");
9008 emitcode ("clr", "a");
9009 emitcode ("inc", "dptr");
9010 emitcode ("movc", "a,@a+dptr");
9014 emitcode ("inc", "dptr");
9015 emitcode ("lcall", "__gptrget");
9020 /* if we are done */
9024 aopPut (AOP (result), "a", offset++);
9030 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (rlen));
9031 aopPut (AOP (result), "a", offset);
9038 /*-----------------------------------------------------------------*/
9039 /* genDataPointerGet - generates code when ptr offset is known */
9040 /*-----------------------------------------------------------------*/
9042 genDataPointerGet (operand * left,
9048 int size, offset = 0;
9049 aopOp (result, ic, TRUE, FALSE);
9051 /* get the string representation of the name */
9052 l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9053 size = AOP_SIZE (result);
9054 _startLazyDPSEvaluation ();
9059 SNPRINTF (buff, sizeof(buff),
9060 "(%s + %d)", l + 1, offset);
9064 SNPRINTF (buff, sizeof(buff),
9067 aopPut (AOP (result), buff, offset++);
9069 _endLazyDPSEvaluation ();
9071 freeAsmop (left, NULL, ic, TRUE);
9072 freeAsmop (result, NULL, ic, TRUE);
9075 /*-----------------------------------------------------------------*/
9076 /* genNearPointerGet - emitcode for near pointer fetch */
9077 /*-----------------------------------------------------------------*/
9079 genNearPointerGet (operand * left,
9087 sym_link *rtype, *retype, *letype;
9088 sym_link *ltype = operandType (left);
9091 rtype = operandType (result);
9092 retype = getSpec (rtype);
9093 letype = getSpec (ltype);
9095 aopOp (left, ic, FALSE, FALSE);
9097 /* if left is rematerialisable and
9098 result is not bit variable type and
9099 the left is pointer to data space i.e
9100 lower 128 bytes of space */
9101 if (AOP_TYPE (left) == AOP_IMMD &&
9102 !IS_BITVAR (retype) &&
9103 !IS_BITVAR (letype) &&
9104 DCL_TYPE (ltype) == POINTER)
9106 genDataPointerGet (left, result, ic);
9110 /* if the value is already in a pointer register
9111 then don't need anything more */
9112 if (!AOP_INPREG (AOP (left)))
9114 /* otherwise get a free pointer register */
9116 preg = getFreePtr (ic, &aop, FALSE);
9117 emitcode ("mov", "%s,%s",
9119 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9123 rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9125 freeAsmop (left, NULL, ic, TRUE);
9126 aopOp (result, ic, FALSE, FALSE);
9128 /* if bitfield then unpack the bits */
9129 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9130 genUnpackBits (result, rname, POINTER);
9133 /* we have can just get the values */
9134 int size = AOP_SIZE (result);
9139 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9142 emitcode ("mov", "a,@%s", rname);
9143 aopPut (AOP (result), "a", offset);
9147 SNPRINTF (buff, sizeof(buff), "@%s", rname);
9148 aopPut (AOP (result), buff, offset);
9153 emitcode ("inc", "%s", rname);
9158 /* now some housekeeping stuff */
9161 /* we had to allocate for this iCode */
9162 if (pi) { /* post increment present */
9163 aopPut(AOP ( left ),rname,0);
9165 freeAsmop (NULL, aop, ic, TRUE);
9169 /* we did not allocate which means left
9170 already in a pointer register, then
9171 if size > 0 && this could be used again
9172 we have to point it back to where it
9174 if (AOP_SIZE (result) > 1 &&
9175 !OP_SYMBOL (left)->remat &&
9176 (OP_SYMBOL (left)->liveTo > ic->seq ||
9180 int size = AOP_SIZE (result) - 1;
9182 emitcode ("dec", "%s", rname);
9187 freeAsmop (result, NULL, ic, TRUE);
9188 if (pi) pi->generated = 1;
9191 /*-----------------------------------------------------------------*/
9192 /* genPagedPointerGet - emitcode for paged pointer fetch */
9193 /*-----------------------------------------------------------------*/
9195 genPagedPointerGet (operand * left,
9203 sym_link *rtype, *retype, *letype;
9205 rtype = operandType (result);
9206 retype = getSpec (rtype);
9207 letype = getSpec (operandType (left));
9208 aopOp (left, ic, FALSE, FALSE);
9210 /* if the value is already in a pointer register
9211 then don't need anything more */
9212 if (!AOP_INPREG (AOP (left)))
9214 /* otherwise get a free pointer register */
9216 preg = getFreePtr (ic, &aop, FALSE);
9217 emitcode ("mov", "%s,%s",
9219 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9223 rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9225 freeAsmop (left, NULL, ic, TRUE);
9226 aopOp (result, ic, FALSE, FALSE);
9228 /* if bitfield then unpack the bits */
9229 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9230 genUnpackBits (result, rname, PPOINTER);
9233 /* we have can just get the values */
9234 int size = AOP_SIZE (result);
9240 emitcode ("movx", "a,@%s", rname);
9241 aopPut (AOP (result), "a", offset);
9246 emitcode ("inc", "%s", rname);
9250 /* now some housekeeping stuff */
9253 /* we had to allocate for this iCode */
9254 if (pi) aopPut ( AOP (left), rname, 0);
9255 freeAsmop (NULL, aop, ic, TRUE);
9259 /* we did not allocate which means left
9260 already in a pointer register, then
9261 if size > 0 && this could be used again
9262 we have to point it back to where it
9264 if (AOP_SIZE (result) > 1 &&
9265 !OP_SYMBOL (left)->remat &&
9266 (OP_SYMBOL (left)->liveTo > ic->seq ||
9270 int size = AOP_SIZE (result) - 1;
9272 emitcode ("dec", "%s", rname);
9277 freeAsmop (result, NULL, ic, TRUE);
9278 if (pi) pi->generated = 1;
9281 /*-----------------------------------------------------------------*/
9282 /* genFarPointerGet - gget value from far space */
9283 /*-----------------------------------------------------------------*/
9285 genFarPointerGet (operand * left,
9286 operand * result, iCode * ic, iCode *pi)
9288 int size, offset, dopi=1;
9289 sym_link *retype = getSpec (operandType (result));
9290 sym_link *letype = getSpec (operandType (left));
9291 D (emitcode (";", "genFarPointerGet"););
9293 aopOp (left, ic, FALSE, FALSE);
9295 /* if the operand is already in dptr
9296 then we do nothing else we move the value to dptr */
9297 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9299 /* if this is remateriazable */
9300 if (AOP_TYPE (left) == AOP_IMMD)
9302 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9306 /* we need to get it byte by byte */
9307 _startLazyDPSEvaluation ();
9308 if (AOP_TYPE (left) != AOP_DPTR)
9310 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9311 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9312 if (options.model == MODEL_FLAT24)
9313 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9317 /* We need to generate a load to DPTR indirect through DPTR. */
9318 D (emitcode (";", "genFarPointerGet -- indirection special case.");
9320 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9321 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9322 if (options.model == MODEL_FLAT24)
9323 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9324 emitcode ("pop", "dph");
9325 emitcode ("pop", "dpl");
9328 _endLazyDPSEvaluation ();
9331 /* so dptr know contains the address */
9332 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9334 /* if bit then unpack */
9335 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9336 if (AOP_INDPTRn(left)) {
9337 genSetDPTR(AOP(left)->aopu.dptr);
9339 genUnpackBits (result, "dptr", FPOINTER);
9340 if (AOP_INDPTRn(left)) {
9345 size = AOP_SIZE (result);
9348 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9350 genSetDPTR(AOP(left)->aopu.dptr);
9351 emitcode ("movx", "a,@dptr");
9352 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9353 emitcode ("inc", "dptr");
9355 aopPut (AOP (result), "a", offset++);
9358 _startLazyDPSEvaluation ();
9360 if (AOP_INDPTRn(left)) {
9361 genSetDPTR(AOP(left)->aopu.dptr);
9367 emitcode ("movx", "a,@dptr");
9368 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9369 emitcode ("inc", "dptr");
9371 aopPut (AOP (result), "a", offset++);
9373 _endLazyDPSEvaluation ();
9376 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9377 if (!AOP_INDPTRn(left)) {
9378 aopPut ( AOP (left), "dpl", 0);
9379 aopPut ( AOP (left), "dph", 1);
9380 if (options.model == MODEL_FLAT24)
9381 aopPut ( AOP (left), "dpx", 2);
9384 } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
9385 AOP_SIZE(result) > 1 &&
9386 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9388 size = AOP_SIZE (result) - 1;
9389 if (AOP_INDPTRn(left)) {
9390 genSetDPTR(AOP(left)->aopu.dptr);
9392 while (size--) emitcode ("lcall","__decdptr");
9393 if (AOP_INDPTRn(left)) {
9398 freeAsmop (left, NULL, ic, TRUE);
9399 freeAsmop (result, NULL, ic, TRUE);
9402 /*-----------------------------------------------------------------*/
9403 /* genCodePointerGet - get value from code space */
9404 /*-----------------------------------------------------------------*/
9406 genCodePointerGet (operand * left,
9407 operand * result, iCode * ic, iCode *pi)
9409 int size, offset, dopi=1;
9410 sym_link *retype = getSpec (operandType (result));
9412 aopOp (left, ic, FALSE, FALSE);
9414 /* if the operand is already in dptr
9415 then we do nothing else we move the value to dptr */
9416 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
9418 /* if this is remateriazable */
9419 if (AOP_TYPE (left) == AOP_IMMD)
9421 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9424 { /* we need to get it byte by byte */
9425 _startLazyDPSEvaluation ();
9426 if (AOP_TYPE (left) != AOP_DPTR)
9428 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9429 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9430 if (options.model == MODEL_FLAT24)
9431 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9435 /* We need to generate a load to DPTR indirect through DPTR. */
9436 D (emitcode (";", "gencodePointerGet -- indirection special case.");
9438 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9439 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9440 if (options.model == MODEL_FLAT24)
9441 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9442 emitcode ("pop", "dph");
9443 emitcode ("pop", "dpl");
9446 _endLazyDPSEvaluation ();
9449 /* so dptr know contains the address */
9450 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9452 /* if bit then unpack */
9453 if (IS_BITVAR (retype)) {
9454 if (AOP_INDPTRn(left)) {
9455 genSetDPTR(AOP(left)->aopu.dptr);
9457 genUnpackBits (result, "dptr", CPOINTER);
9458 if (AOP_INDPTRn(left)) {
9463 size = AOP_SIZE (result);
9465 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9467 genSetDPTR(AOP(left)->aopu.dptr);
9468 emitcode ("clr", "a");
9469 emitcode ("movc", "a,@a+dptr");
9470 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9471 emitcode ("inc", "dptr");
9473 aopPut (AOP (result), "a", offset++);
9476 _startLazyDPSEvaluation ();
9479 if (AOP_INDPTRn(left)) {
9480 genSetDPTR(AOP(left)->aopu.dptr);
9486 emitcode ("clr", "a");
9487 emitcode ("movc", "a,@a+dptr");
9488 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9489 emitcode ("inc", "dptr");
9490 aopPut (AOP (result), "a", offset++);
9492 _endLazyDPSEvaluation ();
9495 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9496 if (!AOP_INDPTRn(left)) {
9497 aopPut ( AOP (left), "dpl", 0);
9498 aopPut ( AOP (left), "dph", 1);
9499 if (options.model == MODEL_FLAT24)
9500 aopPut ( AOP (left), "dpx", 2);
9503 } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
9504 AOP_SIZE(result) > 1 &&
9505 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9507 size = AOP_SIZE (result) - 1;
9508 if (AOP_INDPTRn(left)) {
9509 genSetDPTR(AOP(left)->aopu.dptr);
9511 while (size--) emitcode ("lcall","__decdptr");
9512 if (AOP_INDPTRn(left)) {
9517 freeAsmop (left, NULL, ic, TRUE);
9518 freeAsmop (result, NULL, ic, TRUE);
9521 /*-----------------------------------------------------------------*/
9522 /* genGenPointerGet - gget value from generic pointer space */
9523 /*-----------------------------------------------------------------*/
9525 genGenPointerGet (operand * left,
9526 operand * result, iCode * ic, iCode * pi)
9529 sym_link *retype = getSpec (operandType (result));
9530 sym_link *letype = getSpec (operandType (left));
9532 D (emitcode (";", "genGenPointerGet "); );
9534 aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
9536 /* if the operand is already in dptr
9537 then we do nothing else we move the value to dptr */
9538 if (AOP_TYPE (left) != AOP_STR)
9540 /* if this is remateriazable */
9541 if (AOP_TYPE (left) == AOP_IMMD)
9543 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9544 if (AOP(left)->aopu.aop_immd.from_cast_remat)
9546 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
9550 emitcode ("mov", "b,#%d", pointerCode (retype));
9554 { /* we need to get it byte by byte */
9555 _startLazyDPSEvaluation ();
9556 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
9557 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
9558 if (options.model == MODEL_FLAT24) {
9559 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9560 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
9562 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9564 _endLazyDPSEvaluation ();
9568 /* so dptr-b now contains the address */
9570 aopOp (result, ic, FALSE, TRUE);
9573 /* if bit then unpack */
9574 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9576 genUnpackBits (result, "dptr", GPOINTER);
9580 size = AOP_SIZE (result);
9587 // Get two bytes at a time, results in _AP & A.
9588 // dptr will be incremented ONCE by __gptrgetWord.
9590 // Note: any change here must be coordinated
9591 // with the implementation of __gptrgetWord
9592 // in device/lib/_gptrget.c
9593 emitcode ("lcall", "__gptrgetWord");
9594 aopPut (AOP (result), DP2_RESULT_REG, offset++);
9595 aopPut (AOP (result), "a", offset++);
9600 // Only one byte to get.
9601 emitcode ("lcall", "__gptrget");
9602 aopPut (AOP (result), "a", offset++);
9605 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9607 emitcode ("inc", "dptr");
9612 if (pi && AOP_TYPE (left) != AOP_IMMD) {
9613 aopPut ( AOP (left), "dpl", 0);
9614 aopPut ( AOP (left), "dph", 1);
9615 if (options.model == MODEL_FLAT24) {
9616 aopPut ( AOP (left), "dpx", 2);
9617 aopPut ( AOP (left), "b", 3);
9618 } else aopPut ( AOP (left), "b", 2);
9620 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9621 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9623 size = AOP_SIZE (result) - 1;
9624 while (size--) emitcode ("lcall","__decdptr");
9627 freeAsmop (left, NULL, ic, TRUE);
9628 freeAsmop (result, NULL, ic, TRUE);
9631 /*-----------------------------------------------------------------*/
9632 /* genPointerGet - generate code for pointer get */
9633 /*-----------------------------------------------------------------*/
9635 genPointerGet (iCode * ic, iCode *pi)
9637 operand *left, *result;
9638 sym_link *type, *etype;
9641 D (emitcode (";", "genPointerGet ");
9644 left = IC_LEFT (ic);
9645 result = IC_RESULT (ic);
9647 /* depending on the type of pointer we need to
9648 move it to the correct pointer register */
9649 type = operandType (left);
9650 etype = getSpec (type);
9651 /* if left is of type of pointer then it is simple */
9652 if (IS_PTR (type) && !IS_FUNC (type->next))
9653 p_type = DCL_TYPE (type);
9656 /* we have to go by the storage class */
9657 p_type = PTR_TYPE (SPEC_OCLS (etype));
9659 /* special case when cast remat */
9660 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9661 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9662 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9663 type = operandType (left);
9664 p_type = DCL_TYPE (type);
9666 /* now that we have the pointer type we assign
9667 the pointer values */
9673 genNearPointerGet (left, result, ic, pi);
9677 genPagedPointerGet (left, result, ic, pi);
9681 genFarPointerGet (left, result, ic, pi);
9685 genCodePointerGet (left, result, ic, pi);
9689 genGenPointerGet (left, result, ic, pi);
9695 /*-----------------------------------------------------------------*/
9696 /* genPackBits - generates code for packed bit storage */
9697 /*-----------------------------------------------------------------*/
9699 genPackBits (sym_link * etype,
9701 char *rname, int p_type)
9708 blen = SPEC_BLEN (etype);
9709 bstr = SPEC_BSTR (etype);
9711 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9713 /* if the bit lenth is less than or */
9714 /* it exactly fits a byte then */
9715 if (SPEC_BLEN (etype) <= 8)
9717 /* shift left acc */
9718 AccLsh (SPEC_BSTR (etype));
9720 if (SPEC_BLEN (etype) < 8)
9721 { /* if smaller than a byte */
9727 emitcode ("mov", "b,a");
9728 emitcode ("mov", "a,@%s", rname);
9732 emitcode ("mov", "b,a");
9733 emitcode ("movx", "a,@dptr");
9737 emitcode ("push", "b");
9738 emitcode ("push", "acc");
9739 emitcode ("lcall", "__gptrget");
9740 emitcode ("pop", "b");
9744 emitcode ("anl", "a,#!constbyte", (unsigned char)
9745 ((unsigned char) (0xFF << (blen + bstr)) |
9746 (unsigned char) (0xFF >> (8 - bstr))));
9747 emitcode ("orl", "a,b");
9748 if (p_type == GPOINTER)
9749 emitcode ("pop", "b");
9756 emitcode ("mov", "@%s,a", rname);
9760 emitcode ("movx", "@dptr,a");
9764 emitcode ("lcall", "__gptrput");
9769 if (SPEC_BLEN (etype) <= 8)
9772 emitcode ("inc", "%s", rname);
9773 rLen = SPEC_BLEN (etype);
9775 /* now generate for lengths greater than one byte */
9779 l = aopGet (AOP (right), offset++, FALSE, TRUE, NULL);
9791 emitcode ("mov", "@%s,a", rname);
9794 emitcode ("mov", "@%s,%s", rname, l);
9799 emitcode ("movx", "@dptr,a");
9804 emitcode ("lcall", "__gptrput");
9807 emitcode ("inc", "%s", rname);
9812 /* last last was not complete */
9815 /* save the byte & read byte */
9819 emitcode ("mov", "b,a");
9820 emitcode ("mov", "a,@%s", rname);
9824 emitcode ("mov", "b,a");
9825 emitcode ("movx", "a,@dptr");
9829 emitcode ("push", "b");
9830 emitcode ("push", "acc");
9831 emitcode ("lcall", "__gptrget");
9832 emitcode ("pop", "b");
9836 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1 << rLen));
9837 emitcode ("orl", "a,b");
9840 if (p_type == GPOINTER)
9841 emitcode ("pop", "b");
9847 emitcode ("mov", "@%s,a", rname);
9851 emitcode ("movx", "@dptr,a");
9855 emitcode ("lcall", "__gptrput");
9859 /*-----------------------------------------------------------------*/
9860 /* genDataPointerSet - remat pointer to data space */
9861 /*-----------------------------------------------------------------*/
9863 genDataPointerSet (operand * right,
9867 int size, offset = 0;
9870 aopOp (right, ic, FALSE, FALSE);
9872 l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
9873 size = AOP_SIZE (right);
9878 SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
9882 SNPRINTF (buff, sizeof(buff), "%s", l + 1);
9885 emitcode ("mov", "%s,%s", buff,
9886 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9889 freeAsmop (right, NULL, ic, TRUE);
9890 freeAsmop (result, NULL, ic, TRUE);
9893 /*-----------------------------------------------------------------*/
9894 /* genNearPointerSet - emitcode for near pointer put */
9895 /*-----------------------------------------------------------------*/
9897 genNearPointerSet (operand * right,
9904 sym_link *retype, *letype;
9905 sym_link *ptype = operandType (result);
9907 retype = getSpec (operandType (right));
9908 letype = getSpec (ptype);
9910 aopOp (result, ic, FALSE, FALSE);
9912 /* if the result is rematerializable &
9913 in data space & not a bit variable */
9914 if (AOP_TYPE (result) == AOP_IMMD &&
9915 DCL_TYPE (ptype) == POINTER &&
9916 !IS_BITVAR (retype) &&
9917 !IS_BITVAR (letype))
9919 genDataPointerSet (right, result, ic);
9923 /* if the value is already in a pointer register
9924 then don't need anything more */
9925 if (!AOP_INPREG (AOP (result)))
9927 /* otherwise get a free pointer register */
9931 preg = getFreePtr (ic, &aop, FALSE);
9932 emitcode ("mov", "%s,%s",
9934 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
9938 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
9940 aopOp (right, ic, FALSE, FALSE);
9942 /* if bitfield then unpack the bits */
9943 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9944 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9947 /* we have can just get the values */
9948 int size = AOP_SIZE (right);
9953 l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
9957 emitcode ("mov", "@%s,a", rname);
9960 emitcode ("mov", "@%s,%s", rname, l);
9962 emitcode ("inc", "%s", rname);
9967 /* now some housekeeping stuff */
9970 /* we had to allocate for this iCode */
9971 if (pi) aopPut (AOP (result),rname,0);
9972 freeAsmop (NULL, aop, ic, TRUE);
9976 /* we did not allocate which means left
9977 already in a pointer register, then
9978 if size > 0 && this could be used again
9979 we have to point it back to where it
9981 if (AOP_SIZE (right) > 1 &&
9982 !OP_SYMBOL (result)->remat &&
9983 (OP_SYMBOL (result)->liveTo > ic->seq ||
9987 int size = AOP_SIZE (right) - 1;
9989 emitcode ("dec", "%s", rname);
9994 if (pi) pi->generated = 1;
9995 freeAsmop (result, NULL, ic, TRUE);
9996 freeAsmop (right, NULL, ic, TRUE);
10001 /*-----------------------------------------------------------------*/
10002 /* genPagedPointerSet - emitcode for Paged pointer put */
10003 /*-----------------------------------------------------------------*/
10005 genPagedPointerSet (operand * right,
10012 sym_link *retype, *letype;
10014 retype = getSpec (operandType (right));
10015 letype = getSpec (operandType (result));
10017 aopOp (result, ic, FALSE, FALSE);
10019 /* if the value is already in a pointer register
10020 then don't need anything more */
10021 if (!AOP_INPREG (AOP (result)))
10023 /* otherwise get a free pointer register */
10026 aop = newAsmop (0);
10027 preg = getFreePtr (ic, &aop, FALSE);
10028 emitcode ("mov", "%s,%s",
10030 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10031 rname = preg->name;
10034 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10036 aopOp (right, ic, FALSE, FALSE);
10038 /* if bitfield then unpack the bits */
10039 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10040 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
10043 /* we have can just get the values */
10044 int size = AOP_SIZE (right);
10049 MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10051 emitcode ("movx", "@%s,a", rname);
10054 emitcode ("inc", "%s", rname);
10060 /* now some housekeeping stuff */
10063 if (pi) aopPut (AOP (result),rname,0);
10064 /* we had to allocate for this iCode */
10065 freeAsmop (NULL, aop, ic, TRUE);
10069 /* we did not allocate which means left
10070 already in a pointer register, then
10071 if size > 0 && this could be used again
10072 we have to point it back to where it
10074 if (AOP_SIZE (right) > 1 &&
10075 !OP_SYMBOL (result)->remat &&
10076 (OP_SYMBOL (result)->liveTo > ic->seq ||
10080 int size = AOP_SIZE (right) - 1;
10082 emitcode ("dec", "%s", rname);
10087 if (pi) pi->generated = 1;
10088 freeAsmop (result, NULL, ic, TRUE);
10089 freeAsmop (right, NULL, ic, TRUE);
10094 /*-----------------------------------------------------------------*/
10095 /* genFarPointerSet - set value from far space */
10096 /*-----------------------------------------------------------------*/
10098 genFarPointerSet (operand * right,
10099 operand * result, iCode * ic, iCode *pi)
10101 int size, offset, dopi=1;
10102 sym_link *retype = getSpec (operandType (right));
10103 sym_link *letype = getSpec (operandType (result));
10105 aopOp (result, ic, FALSE, FALSE);
10107 /* if the operand is already in dptr
10108 then we do nothing else we move the value to dptr */
10109 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10111 /* if this is remateriazable */
10112 if (AOP_TYPE (result) == AOP_IMMD)
10113 emitcode ("mov", "dptr,%s",
10114 aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10117 /* we need to get it byte by byte */
10118 _startLazyDPSEvaluation ();
10119 if (AOP_TYPE (result) != AOP_DPTR)
10121 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10122 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10123 if (options.model == MODEL_FLAT24)
10124 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10128 /* We need to generate a load to DPTR indirect through DPTR. */
10129 D (emitcode (";", "genFarPointerSet -- indirection special case."););
10131 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10132 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10133 if (options.model == MODEL_FLAT24)
10134 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10135 emitcode ("pop", "dph");
10136 emitcode ("pop", "dpl");
10139 _endLazyDPSEvaluation ();
10142 /* so dptr know contains the address */
10143 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10145 /* if bit then unpack */
10146 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
10147 if (AOP_INDPTRn(result)) {
10148 genSetDPTR(AOP(result)->aopu.dptr);
10150 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
10151 if (AOP_INDPTRn(result)) {
10155 size = AOP_SIZE (right);
10157 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10159 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10161 genSetDPTR(AOP(result)->aopu.dptr);
10162 emitcode ("movx", "@dptr,a");
10163 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10164 emitcode ("inc", "dptr");
10168 _startLazyDPSEvaluation ();
10170 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10172 if (AOP_INDPTRn(result)) {
10173 genSetDPTR(AOP(result)->aopu.dptr);
10179 emitcode ("movx", "@dptr,a");
10180 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10181 emitcode ("inc", "dptr");
10183 _endLazyDPSEvaluation ();
10187 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10188 if (!AOP_INDPTRn(result)) {
10189 aopPut (AOP(result),"dpl",0);
10190 aopPut (AOP(result),"dph",1);
10191 if (options.model == MODEL_FLAT24)
10192 aopPut (AOP(result),"dpx",2);
10195 } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
10196 AOP_SIZE(right) > 1 &&
10197 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10199 size = AOP_SIZE (right) - 1;
10200 if (AOP_INDPTRn(result)) {
10201 genSetDPTR(AOP(result)->aopu.dptr);
10203 while (size--) emitcode ("lcall","__decdptr");
10204 if (AOP_INDPTRn(result)) {
10208 freeAsmop (result, NULL, ic, TRUE);
10209 freeAsmop (right, NULL, ic, TRUE);
10212 /*-----------------------------------------------------------------*/
10213 /* genGenPointerSet - set value from generic pointer space */
10214 /*-----------------------------------------------------------------*/
10216 genGenPointerSet (operand * right,
10217 operand * result, iCode * ic, iCode *pi)
10220 sym_link *retype = getSpec (operandType (right));
10221 sym_link *letype = getSpec (operandType (result));
10223 aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10225 /* if the operand is already in dptr
10226 then we do nothing else we move the value to dptr */
10227 if (AOP_TYPE (result) != AOP_STR)
10229 _startLazyDPSEvaluation ();
10230 /* if this is remateriazable */
10231 if (AOP_TYPE (result) == AOP_IMMD)
10233 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10234 if (AOP(result)->aopu.aop_immd.from_cast_remat)
10236 MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10241 "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10245 { /* we need to get it byte by byte */
10246 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10247 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10248 if (options.model == MODEL_FLAT24) {
10249 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10250 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10252 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10255 _endLazyDPSEvaluation ();
10257 /* so dptr know contains the address */
10258 aopOp (right, ic, FALSE, TRUE);
10260 /* if bit then unpack */
10261 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10262 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
10265 size = AOP_SIZE (right);
10268 _startLazyDPSEvaluation ();
10271 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10276 emitcode ("lcall", "__gptrput");
10277 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10278 emitcode ("inc", "dptr");
10280 _endLazyDPSEvaluation ();
10283 if (pi && AOP_TYPE (result) != AOP_IMMD) {
10284 aopPut (AOP(result),"dpl",0);
10285 aopPut (AOP(result),"dph",1);
10286 if (options.model == MODEL_FLAT24) {
10287 aopPut (AOP(result),"dpx",2);
10288 aopPut (AOP(result),"b",3);
10290 aopPut (AOP(result),"b",2);
10293 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10294 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10296 size = AOP_SIZE (right) - 1;
10297 while (size--) emitcode ("lcall","__decdptr");
10299 freeAsmop (result, NULL, ic, TRUE);
10300 freeAsmop (right, NULL, ic, TRUE);
10303 /*-----------------------------------------------------------------*/
10304 /* genPointerSet - stores the value into a pointer location */
10305 /*-----------------------------------------------------------------*/
10307 genPointerSet (iCode * ic, iCode *pi)
10309 operand *right, *result;
10310 sym_link *type, *etype;
10313 D (emitcode (";", "genPointerSet "););
10315 right = IC_RIGHT (ic);
10316 result = IC_RESULT (ic);
10318 /* depending on the type of pointer we need to
10319 move it to the correct pointer register */
10320 type = operandType (result);
10321 etype = getSpec (type);
10322 /* if left is of type of pointer then it is simple */
10323 if (IS_PTR (type) && !IS_FUNC (type->next))
10325 p_type = DCL_TYPE (type);
10329 /* we have to go by the storage class */
10330 p_type = PTR_TYPE (SPEC_OCLS (etype));
10332 /* special case when cast remat */
10333 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10334 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10335 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10336 type = operandType (result);
10337 p_type = DCL_TYPE (type);
10340 /* now that we have the pointer type we assign
10341 the pointer values */
10347 genNearPointerSet (right, result, ic, pi);
10351 genPagedPointerSet (right, result, ic, pi);
10355 genFarPointerSet (right, result, ic, pi);
10359 genGenPointerSet (right, result, ic, pi);
10363 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10364 "genPointerSet: illegal pointer type");
10369 /*-----------------------------------------------------------------*/
10370 /* genIfx - generate code for Ifx statement */
10371 /*-----------------------------------------------------------------*/
10373 genIfx (iCode * ic, iCode * popIc)
10375 operand *cond = IC_COND (ic);
10378 D (emitcode (";", "genIfx "););
10380 aopOp (cond, ic, FALSE, FALSE);
10382 /* get the value into acc */
10383 if (AOP_TYPE (cond) != AOP_CRY)
10392 /* the result is now in the accumulator */
10393 freeAsmop (cond, NULL, ic, TRUE);
10395 /* if there was something to be popped then do it */
10399 /* if the condition is a bit variable */
10400 if (isbit && IS_ITEMP (cond) &&
10403 genIfxJump (ic, SPIL_LOC (cond)->rname);
10405 else if (isbit && !IS_ITEMP (cond))
10407 genIfxJump (ic, OP_SYMBOL (cond)->rname);
10411 genIfxJump (ic, "a");
10417 /*-----------------------------------------------------------------*/
10418 /* genAddrOf - generates code for address of */
10419 /*-----------------------------------------------------------------*/
10421 genAddrOf (iCode * ic)
10423 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10426 D (emitcode (";", "genAddrOf ");
10429 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10431 /* if the operand is on the stack then we
10432 need to get the stack offset of this
10434 if (sym->onStack) {
10436 /* if 10 bit stack */
10437 if (options.stack10bit) {
10439 tsprintf(buff, sizeof(buff),
10440 "#!constbyte",(options.stack_loc >> 16) & 0xff);
10441 /* if it has an offset then we need to compute it */
10442 /* emitcode ("subb", "a,#!constbyte", */
10443 /* -((sym->stack < 0) ? */
10444 /* ((short) (sym->stack - _G.nRegsSaved)) : */
10445 /* ((short) sym->stack)) & 0xff); */
10446 /* emitcode ("mov","b,a"); */
10447 /* emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
10448 /* ((short) (sym->stack - _G.nRegsSaved)) : */
10449 /* ((short) sym->stack)) >> 8) & 0xff); */
10451 emitcode ("mov", "a,_bpx");
10452 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
10453 ((char) (sym->stack - _G.nRegsSaved)) :
10454 ((char) sym->stack )) & 0xff);
10455 emitcode ("mov", "b,a");
10456 emitcode ("mov", "a,_bpx+1");
10457 emitcode ("addc","a,#!constbyte", (((sym->stack < 0) ?
10458 ((short) (sym->stack - _G.nRegsSaved)) :
10459 ((short) sym->stack )) >> 8) & 0xff);
10460 aopPut (AOP (IC_RESULT (ic)), "b", 0);
10461 aopPut (AOP (IC_RESULT (ic)), "a", 1);
10462 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10464 /* we can just move _bp */
10465 aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10466 aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10467 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10470 /* if it has an offset then we need to compute it */
10472 emitcode ("mov", "a,_bp");
10473 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10474 aopPut (AOP (IC_RESULT (ic)), "a", 0);
10476 /* we can just move _bp */
10477 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10479 /* fill the result with zero */
10480 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10483 if (options.stack10bit && size < (FPTRSIZE - 1)) {
10485 "*** warning: pointer to stack var truncated.\n");
10490 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10496 /* object not on stack then we need the name */
10497 size = AOP_SIZE (IC_RESULT (ic));
10502 char s[SDCC_NAME_MAX];
10506 tsprintf(s, sizeof(s), "!his",sym->rname);
10509 tsprintf(s, sizeof(s), "!hihis",sym->rname);
10512 tsprintf(s, sizeof(s), "!hihihis",sym->rname);
10514 default: /* should not need this (just in case) */
10515 SNPRINTF (s, sizeof(s), "#(%s >> %d)",
10522 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10525 aopPut (AOP (IC_RESULT (ic)), s, offset++);
10529 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10533 /*-----------------------------------------------------------------*/
10534 /* genArrayInit - generates code for address of */
10535 /*-----------------------------------------------------------------*/
10537 genArrayInit (iCode * ic)
10539 literalList *iLoop;
10541 int elementSize = 0, eIndex;
10542 unsigned val, lastVal;
10544 operand *left=IC_LEFT(ic);
10546 D (emitcode (";", "genArrayInit "););
10548 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10550 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10552 // Load immediate value into DPTR.
10553 emitcode("mov", "dptr, %s",
10554 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
10556 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10559 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10560 "Unexpected operand to genArrayInit.\n");
10563 // a regression because of SDCCcse.c:1.52
10564 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10565 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10566 if (options.model == MODEL_FLAT24)
10567 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10571 type = operandType(IC_LEFT(ic));
10573 if (type && type->next)
10575 elementSize = getSize(type->next);
10579 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10580 "can't determine element size in genArrayInit.\n");
10584 iLoop = IC_ARRAYILIST(ic);
10589 bool firstpass = TRUE;
10591 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
10592 iLoop->count, (int)iLoop->literalValue, elementSize);
10598 symbol *tlbl = NULL;
10600 count = ix > 256 ? 256 : ix;
10604 tlbl = newiTempLabel (NULL);
10605 if (firstpass || (count & 0xff))
10607 emitcode("mov", "b, #!constbyte", count & 0xff);
10610 emitcode ("", "!tlabeldef", tlbl->key + 100);
10615 for (eIndex = 0; eIndex < elementSize; eIndex++)
10617 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10618 if (val != lastVal)
10620 emitcode("mov", "a, #!constbyte", val);
10624 emitcode("movx", "@dptr, a");
10625 emitcode("inc", "dptr");
10630 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10636 iLoop = iLoop->next;
10639 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10642 /*-----------------------------------------------------------------*/
10643 /* genFarFarAssign - assignment when both are in far space */
10644 /*-----------------------------------------------------------------*/
10646 genFarFarAssign (operand * result, operand * right, iCode * ic)
10648 int size = AOP_SIZE (right);
10650 symbol *rSym = NULL;
10654 /* quick & easy case. */
10655 D(emitcode(";","genFarFarAssign (1 byte case)"););
10656 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
10657 freeAsmop (right, NULL, ic, FALSE);
10658 /* now assign DPTR to result */
10660 aopOp(result, ic, FALSE, FALSE);
10662 aopPut(AOP(result), "a", 0);
10663 freeAsmop(result, NULL, ic, FALSE);
10667 /* See if we've got an underlying symbol to abuse. */
10668 if (IS_SYMOP(result) && OP_SYMBOL(result))
10670 if (IS_TRUE_SYMOP(result))
10672 rSym = OP_SYMBOL(result);
10674 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10676 rSym = OP_SYMBOL(result)->usl.spillLoc;
10680 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10682 /* We can use the '390 auto-toggle feature to good effect here. */
10684 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10685 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
10686 emitcode ("mov", "dptr,#%s", rSym->rname);
10687 /* DP2 = result, DP1 = right, DP1 is current. */
10690 emitcode("movx", "a,@dptr");
10691 emitcode("movx", "@dptr,a");
10694 emitcode("inc", "dptr");
10695 emitcode("inc", "dptr");
10698 emitcode("mov", "dps,#0");
10699 freeAsmop (right, NULL, ic, FALSE);
10701 some alternative code for processors without auto-toggle
10702 no time to test now, so later well put in...kpb
10703 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10704 emitcode("mov", "dps,#1"); /* Select DPTR2. */
10705 emitcode ("mov", "dptr,#%s", rSym->rname);
10706 /* DP2 = result, DP1 = right, DP1 is current. */
10710 emitcode("movx", "a,@dptr");
10712 emitcode("inc", "dptr");
10713 emitcode("inc", "dps");
10714 emitcode("movx", "@dptr,a");
10716 emitcode("inc", "dptr");
10717 emitcode("inc", "dps");
10719 emitcode("mov", "dps,#0");
10720 freeAsmop (right, NULL, ic, FALSE);
10725 D (emitcode (";", "genFarFarAssign"););
10726 aopOp (result, ic, TRUE, TRUE);
10728 _startLazyDPSEvaluation ();
10732 aopPut (AOP (result),
10733 aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
10736 _endLazyDPSEvaluation ();
10737 freeAsmop (result, NULL, ic, FALSE);
10738 freeAsmop (right, NULL, ic, FALSE);
10742 /*-----------------------------------------------------------------*/
10743 /* genAssign - generate code for assignment */
10744 /*-----------------------------------------------------------------*/
10746 genAssign (iCode * ic)
10748 operand *result, *right;
10750 unsigned long lit = 0L;
10752 D (emitcode (";", "genAssign ");
10755 result = IC_RESULT (ic);
10756 right = IC_RIGHT (ic);
10758 /* if they are the same */
10759 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10762 aopOp (right, ic, FALSE, FALSE);
10764 emitcode (";", "genAssign: resultIsFar = %s",
10765 isOperandInFarSpace (result) ?
10768 /* special case both in far space */
10769 if ((AOP_TYPE (right) == AOP_DPTR ||
10770 AOP_TYPE (right) == AOP_DPTR2) &&
10771 /* IS_TRUE_SYMOP(result) && */
10772 isOperandInFarSpace (result))
10774 genFarFarAssign (result, right, ic);
10778 aopOp (result, ic, TRUE, FALSE);
10780 /* if they are the same registers */
10781 if (sameRegs (AOP (right), AOP (result)))
10784 /* if the result is a bit */
10785 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10787 /* if the right size is a literal then
10788 we know what the value is */
10789 if (AOP_TYPE (right) == AOP_LIT)
10791 if (((int) operandLitValue (right)))
10792 aopPut (AOP (result), one, 0);
10794 aopPut (AOP (result), zero, 0);
10798 /* the right is also a bit variable */
10799 if (AOP_TYPE (right) == AOP_CRY)
10801 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10802 aopPut (AOP (result), "c", 0);
10806 /* we need to or */
10808 aopPut (AOP (result), "a", 0);
10812 /* bit variables done */
10814 size = AOP_SIZE (result);
10816 if (AOP_TYPE (right) == AOP_LIT)
10817 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10820 (AOP_TYPE (result) != AOP_REG) &&
10821 (AOP_TYPE (right) == AOP_LIT) &&
10822 !IS_FLOAT (operandType (right)))
10824 _startLazyDPSEvaluation ();
10825 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10827 aopPut (AOP (result),
10828 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10833 /* And now fill the rest with zeros. */
10836 emitcode ("clr", "a");
10840 aopPut (AOP (result), "a", offset++);
10842 _endLazyDPSEvaluation ();
10846 _startLazyDPSEvaluation ();
10849 aopPut (AOP (result),
10850 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10854 _endLazyDPSEvaluation ();
10858 freeAsmop (right, NULL, ic, FALSE);
10859 freeAsmop (result, NULL, ic, TRUE);
10862 /*-----------------------------------------------------------------*/
10863 /* genJumpTab - generates code for jump table */
10864 /*-----------------------------------------------------------------*/
10866 genJumpTab (iCode * ic)
10871 D (emitcode (";", "genJumpTab ");
10874 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10875 /* get the condition into accumulator */
10876 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
10878 /* multiply by four! */
10879 emitcode ("add", "a,acc");
10880 emitcode ("add", "a,acc");
10881 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10883 jtab = newiTempLabel (NULL);
10884 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
10885 emitcode ("jmp", "@a+dptr");
10886 emitcode ("", "!tlabeldef", jtab->key + 100);
10887 /* now generate the jump labels */
10888 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10889 jtab = setNextItem (IC_JTLABELS (ic)))
10890 emitcode ("ljmp", "!tlabel", jtab->key + 100);
10894 /*-----------------------------------------------------------------*/
10895 /* genCast - gen code for casting */
10896 /*-----------------------------------------------------------------*/
10898 genCast (iCode * ic)
10900 operand *result = IC_RESULT (ic);
10901 sym_link *ctype = operandType (IC_LEFT (ic));
10902 sym_link *rtype = operandType (IC_RIGHT (ic));
10903 operand *right = IC_RIGHT (ic);
10906 D (emitcode (";", "genCast "););
10908 /* if they are equivalent then do nothing */
10909 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10912 aopOp (right, ic, FALSE, FALSE);
10913 aopOp (result, ic, FALSE, AOP_USESDPTR(right));
10915 /* if the result is a bit */
10916 // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10917 if (IS_BITVAR(OP_SYMBOL(result)->type))
10919 /* if the right size is a literal then
10920 we know what the value is */
10921 if (AOP_TYPE (right) == AOP_LIT)
10923 if (((int) operandLitValue (right)))
10924 aopPut (AOP (result), one, 0);
10926 aopPut (AOP (result), zero, 0);
10931 /* the right is also a bit variable */
10932 if (AOP_TYPE (right) == AOP_CRY)
10934 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10935 aopPut (AOP (result), "c", 0);
10939 /* we need to or */
10941 aopPut (AOP (result), "a", 0);
10945 /* if they are the same size : or less */
10946 if (AOP_SIZE (result) <= AOP_SIZE (right))
10949 /* if they are in the same place */
10950 if (sameRegs (AOP (right), AOP (result)))
10953 /* if they in different places then copy */
10954 size = AOP_SIZE (result);
10956 _startLazyDPSEvaluation ();
10959 aopPut (AOP (result),
10960 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10964 _endLazyDPSEvaluation ();
10969 /* if the result is of type pointer */
10970 if (IS_PTR (ctype))
10974 sym_link *type = operandType (right);
10976 /* pointer to generic pointer */
10977 if (IS_GENPTR (ctype))
10981 p_type = DCL_TYPE (type);
10985 #if OLD_CAST_BEHAVIOR
10986 /* KV: we are converting a non-pointer type to
10987 * a generic pointer. This (ifdef'd out) code
10988 * says that the resulting generic pointer
10989 * should have the same class as the storage
10990 * location of the non-pointer variable.
10992 * For example, converting an int (which happens
10993 * to be stored in DATA space) to a pointer results
10994 * in a DATA generic pointer; if the original int
10995 * in XDATA space, so will be the resulting pointer.
10997 * I don't like that behavior, and thus this change:
10998 * all such conversions will be forced to XDATA and
10999 * throw a warning. If you want some non-XDATA
11000 * type, or you want to suppress the warning, you
11001 * must go through an intermediate cast, like so:
11003 * char _generic *gp = (char _xdata *)(intVar);
11005 sym_link *etype = getSpec (type);
11007 /* we have to go by the storage class */
11008 if (SPEC_OCLS (etype) != generic)
11010 p_type = PTR_TYPE (SPEC_OCLS (etype));
11015 /* Converting unknown class (i.e. register variable)
11016 * to generic pointer. This is not good, but
11017 * we'll make a guess (and throw a warning).
11020 werror (W_INT_TO_GEN_PTR_CAST);
11024 /* the first two bytes are known */
11025 size = GPTRSIZE - 1;
11027 _startLazyDPSEvaluation ();
11030 aopPut (AOP (result),
11031 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11035 _endLazyDPSEvaluation ();
11037 /* the last byte depending on type */
11039 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11044 // pointerTypeToGPByte will have bitched.
11048 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11049 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11054 /* just copy the pointers */
11055 size = AOP_SIZE (result);
11057 _startLazyDPSEvaluation ();
11060 aopPut (AOP (result),
11061 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11065 _endLazyDPSEvaluation ();
11069 /* so we now know that the size of destination is greater
11070 than the size of the source */
11071 /* we move to result for the size of source */
11072 size = AOP_SIZE (right);
11074 _startLazyDPSEvaluation ();
11077 aopPut (AOP (result),
11078 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11082 _endLazyDPSEvaluation ();
11084 /* now depending on the sign of the source && destination */
11085 size = AOP_SIZE (result) - AOP_SIZE (right);
11086 /* if unsigned or not an integral type */
11087 /* also, if the source is a bit, we don't need to sign extend, because
11088 * it can't possibly have set the sign bit.
11090 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
11094 aopPut (AOP (result), zero, offset++);
11099 /* we need to extend the sign :{ */
11100 MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11101 FALSE, FALSE, NULL));
11102 emitcode ("rlc", "a");
11103 emitcode ("subb", "a,acc");
11105 aopPut (AOP (result), "a", offset++);
11108 /* we are done hurray !!!! */
11111 freeAsmop (right, NULL, ic, TRUE);
11112 freeAsmop (result, NULL, ic, TRUE);
11116 /*-----------------------------------------------------------------*/
11117 /* genDjnz - generate decrement & jump if not zero instrucion */
11118 /*-----------------------------------------------------------------*/
11120 genDjnz (iCode * ic, iCode * ifx)
11122 symbol *lbl, *lbl1;
11126 /* if the if condition has a false label
11127 then we cannot save */
11128 if (IC_FALSE (ifx))
11131 /* if the minus is not of the form
11133 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11134 !IS_OP_LITERAL (IC_RIGHT (ic)))
11137 if (operandLitValue (IC_RIGHT (ic)) != 1)
11140 /* if the size of this greater than one then no
11142 if (getSize (operandType (IC_RESULT (ic))) > 1)
11145 /* otherwise we can save BIG */
11146 D(emitcode(";", "genDjnz"););
11148 lbl = newiTempLabel (NULL);
11149 lbl1 = newiTempLabel (NULL);
11151 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11153 if (AOP_NEEDSACC(IC_RESULT(ic)))
11155 /* If the result is accessed indirectly via
11156 * the accumulator, we must explicitly write
11157 * it back after the decrement.
11159 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11161 if (strcmp(rByte, "a"))
11163 /* Something is hopelessly wrong */
11164 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11165 __FILE__, __LINE__);
11166 /* We can just give up; the generated code will be inefficient,
11167 * but what the hey.
11169 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11172 emitcode ("dec", "%s", rByte);
11173 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11174 emitcode ("jnz", "!tlabel", lbl->key + 100);
11176 else if (IS_AOP_PREG (IC_RESULT (ic)))
11178 emitcode ("dec", "%s",
11179 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11180 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11181 emitcode ("jnz", "!tlabel", lbl->key + 100);
11185 emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11188 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11189 emitcode ("", "!tlabeldef", lbl->key + 100);
11190 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11191 emitcode ("", "!tlabeldef", lbl1->key + 100);
11193 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11194 ifx->generated = 1;
11198 /*-----------------------------------------------------------------*/
11199 /* genReceive - generate code for a receive iCode */
11200 /*-----------------------------------------------------------------*/
11202 genReceive (iCode * ic)
11205 int size = getSize (operandType (IC_RESULT (ic)));
11209 D (emitcode (";", "genReceive ");
11212 if (ic->argreg == 1) { /* first parameter */
11213 if (isOperandInFarSpace (IC_RESULT (ic)) &&
11214 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11215 IS_TRUE_SYMOP (IC_RESULT (ic))))
11217 offset = fReturnSizeDS390 - size;
11220 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
11221 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
11224 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11225 size = AOP_SIZE (IC_RESULT (ic));
11229 emitcode ("pop", "acc");
11230 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
11235 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11237 assignResultValue (IC_RESULT (ic));
11239 } else { /* second receive onwards */
11240 /* this gets a little tricky since unused recevies will be
11241 eliminated, we have saved the reg in the type field . and
11242 we use that to figure out which register to use */
11243 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11244 rb1off = ic->argreg;
11246 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11250 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11253 /*-----------------------------------------------------------------*/
11254 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
11255 /*-----------------------------------------------------------------*/
11256 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11258 operand *from , *to , *count;
11263 /* we know it has to be 3 parameters */
11264 assert (nparms == 3);
11266 rsave = newBitVect(16);
11267 /* save DPTR if it needs to be saved */
11268 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11269 if (bitVectBitValue(ic->rMask,i))
11270 rsave = bitVectSetBit(rsave,i);
11272 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11273 ds390_rUmaskForOp (IC_RESULT(ic))));
11280 aopOp (from, ic->next, FALSE, FALSE);
11282 /* get from into DPTR1 */
11283 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11284 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11285 if (options.model == MODEL_FLAT24) {
11286 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11289 freeAsmop (from, NULL, ic, FALSE);
11290 aopOp (to, ic, FALSE, FALSE);
11291 /* get "to" into DPTR */
11292 /* if the operand is already in dptr
11293 then we do nothing else we move the value to dptr */
11294 if (AOP_TYPE (to) != AOP_STR) {
11295 /* if already in DPTR then we need to push */
11296 if (AOP_TYPE(to) == AOP_DPTR) {
11297 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11298 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11299 if (options.model == MODEL_FLAT24)
11300 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11301 emitcode ("pop", "dph");
11302 emitcode ("pop", "dpl");
11304 _startLazyDPSEvaluation ();
11305 /* if this is remateriazable */
11306 if (AOP_TYPE (to) == AOP_IMMD) {
11307 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11308 } else { /* we need to get it byte by byte */
11309 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11310 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11311 if (options.model == MODEL_FLAT24) {
11312 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11315 _endLazyDPSEvaluation ();
11318 freeAsmop (to, NULL, ic, FALSE);
11319 _G.dptrInUse = _G.dptr1InUse = 1;
11320 aopOp (count, ic->next->next, FALSE,FALSE);
11321 lbl =newiTempLabel(NULL);
11323 /* now for the actual copy */
11324 if (AOP_TYPE(count) == AOP_LIT &&
11325 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11326 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11328 emitcode ("lcall","__bi_memcpyc2x_s");
11330 emitcode ("lcall","__bi_memcpyx2x_s");
11332 freeAsmop (count, NULL, ic, FALSE);
11334 symbol *lbl1 = newiTempLabel(NULL);
11336 emitcode (";"," Auto increment but no djnz");
11337 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11338 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11339 freeAsmop (count, NULL, ic, FALSE);
11340 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11341 emitcode ("","!tlabeldef",lbl->key+100);
11343 emitcode ("clr","a");
11344 emitcode ("movc", "a,@a+dptr");
11346 emitcode ("movx", "a,@dptr");
11347 emitcode ("movx", "@dptr,a");
11348 emitcode ("inc", "dptr");
11349 emitcode ("inc", "dptr");
11350 emitcode ("mov","a,b");
11351 emitcode ("orl","a,_ap");
11352 emitcode ("jz","!tlabel",lbl1->key+100);
11353 emitcode ("mov","a,_ap");
11354 emitcode ("add","a,#!constbyte",0xFF);
11355 emitcode ("mov","_ap,a");
11356 emitcode ("mov","a,b");
11357 emitcode ("addc","a,#!constbyte",0xFF);
11358 emitcode ("mov","b,a");
11359 emitcode ("sjmp","!tlabel",lbl->key+100);
11360 emitcode ("","!tlabeldef",lbl1->key+100);
11362 emitcode ("mov", "dps,#0");
11363 _G.dptrInUse = _G.dptr1InUse = 0;
11364 unsavermask(rsave);
11368 /*-----------------------------------------------------------------*/
11369 /* genMemcmpX2X - gen code for memcmp xdata to xdata */
11370 /*-----------------------------------------------------------------*/
11371 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11373 operand *from , *to , *count;
11378 /* we know it has to be 3 parameters */
11379 assert (nparms == 3);
11381 rsave = newBitVect(16);
11382 /* save DPTR if it needs to be saved */
11383 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11384 if (bitVectBitValue(ic->rMask,i))
11385 rsave = bitVectSetBit(rsave,i);
11387 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11388 ds390_rUmaskForOp (IC_RESULT(ic))));
11395 aopOp (from, ic->next, FALSE, FALSE);
11397 /* get from into DPTR1 */
11398 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11399 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11400 if (options.model == MODEL_FLAT24) {
11401 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11404 freeAsmop (from, NULL, ic, FALSE);
11405 aopOp (to, ic, FALSE, FALSE);
11406 /* get "to" into DPTR */
11407 /* if the operand is already in dptr
11408 then we do nothing else we move the value to dptr */
11409 if (AOP_TYPE (to) != AOP_STR) {
11410 /* if already in DPTR then we need to push */
11411 if (AOP_TYPE(to) == AOP_DPTR) {
11412 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11413 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11414 if (options.model == MODEL_FLAT24)
11415 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11416 emitcode ("pop", "dph");
11417 emitcode ("pop", "dpl");
11419 _startLazyDPSEvaluation ();
11420 /* if this is remateriazable */
11421 if (AOP_TYPE (to) == AOP_IMMD) {
11422 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11423 } else { /* we need to get it byte by byte */
11424 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11425 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11426 if (options.model == MODEL_FLAT24) {
11427 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11430 _endLazyDPSEvaluation ();
11433 freeAsmop (to, NULL, ic, FALSE);
11434 _G.dptrInUse = _G.dptr1InUse = 1;
11435 aopOp (count, ic->next->next, FALSE,FALSE);
11436 lbl =newiTempLabel(NULL);
11437 lbl2 =newiTempLabel(NULL);
11439 /* now for the actual compare */
11440 if (AOP_TYPE(count) == AOP_LIT &&
11441 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11442 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11444 emitcode("lcall","__bi_memcmpc2x_s");
11446 emitcode("lcall","__bi_memcmpx2x_s");
11447 freeAsmop (count, NULL, ic, FALSE);
11448 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11449 aopPut(AOP(IC_RESULT(ic)),"a",0);
11450 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11452 symbol *lbl1 = newiTempLabel(NULL);
11454 emitcode("push","ar0");
11455 emitcode (";"," Auto increment but no djnz");
11456 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11457 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11458 freeAsmop (count, NULL, ic, FALSE);
11459 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11460 emitcode ("","!tlabeldef",lbl->key+100);
11462 emitcode ("clr","a");
11463 emitcode ("movc", "a,@a+dptr");
11465 emitcode ("movx", "a,@dptr");
11466 emitcode ("mov","r0,a");
11467 emitcode ("movx", "a,@dptr");
11468 emitcode ("clr","c");
11469 emitcode ("subb","a,r0");
11470 emitcode ("jnz","!tlabel",lbl2->key+100);
11471 emitcode ("inc", "dptr");
11472 emitcode ("inc", "dptr");
11473 emitcode ("mov","a,b");
11474 emitcode ("orl","a,_ap");
11475 emitcode ("jz","!tlabel",lbl1->key+100);
11476 emitcode ("mov","a,_ap");
11477 emitcode ("add","a,#!constbyte",0xFF);
11478 emitcode ("mov","_ap,a");
11479 emitcode ("mov","a,b");
11480 emitcode ("addc","a,#!constbyte",0xFF);
11481 emitcode ("mov","b,a");
11482 emitcode ("sjmp","!tlabel",lbl->key+100);
11483 emitcode ("","!tlabeldef",lbl1->key+100);
11484 emitcode ("clr","a");
11485 emitcode ("","!tlabeldef",lbl2->key+100);
11486 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11487 aopPut(AOP(IC_RESULT(ic)),"a",0);
11488 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11489 emitcode("pop","ar0");
11490 emitcode ("mov", "dps,#0");
11492 _G.dptrInUse = _G.dptr1InUse = 0;
11493 unsavermask(rsave);
11497 /*-----------------------------------------------------------------*/
11498 /* genInp - gen code for __builtin_inp read data from a mem mapped */
11499 /* port, first parameter output area second parameter pointer to */
11500 /* port third parameter count */
11501 /*-----------------------------------------------------------------*/
11502 static void genInp( iCode *ic, int nparms, operand **parms)
11504 operand *from , *to , *count;
11509 /* we know it has to be 3 parameters */
11510 assert (nparms == 3);
11512 rsave = newBitVect(16);
11513 /* save DPTR if it needs to be saved */
11514 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11515 if (bitVectBitValue(ic->rMask,i))
11516 rsave = bitVectSetBit(rsave,i);
11518 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11519 ds390_rUmaskForOp (IC_RESULT(ic))));
11526 aopOp (from, ic->next, FALSE, FALSE);
11528 /* get from into DPTR1 */
11529 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11530 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11531 if (options.model == MODEL_FLAT24) {
11532 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11535 freeAsmop (from, NULL, ic, FALSE);
11536 aopOp (to, ic, FALSE, FALSE);
11537 /* get "to" into DPTR */
11538 /* if the operand is already in dptr
11539 then we do nothing else we move the value to dptr */
11540 if (AOP_TYPE (to) != AOP_STR) {
11541 /* if already in DPTR then we need to push */
11542 if (AOP_TYPE(to) == AOP_DPTR) {
11543 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11544 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11545 if (options.model == MODEL_FLAT24)
11546 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11547 emitcode ("pop", "dph");
11548 emitcode ("pop", "dpl");
11550 _startLazyDPSEvaluation ();
11551 /* if this is remateriazable */
11552 if (AOP_TYPE (to) == AOP_IMMD) {
11553 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11554 } else { /* we need to get it byte by byte */
11555 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11556 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11557 if (options.model == MODEL_FLAT24) {
11558 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11561 _endLazyDPSEvaluation ();
11564 freeAsmop (to, NULL, ic, FALSE);
11566 _G.dptrInUse = _G.dptr1InUse = 1;
11567 aopOp (count, ic->next->next, FALSE,FALSE);
11568 lbl =newiTempLabel(NULL);
11570 /* now for the actual copy */
11571 if (AOP_TYPE(count) == AOP_LIT &&
11572 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11573 emitcode (";","OH JOY auto increment with djnz (very fast)");
11574 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11575 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11576 freeAsmop (count, NULL, ic, FALSE);
11577 emitcode ("","!tlabeldef",lbl->key+100);
11578 emitcode ("movx", "a,@dptr"); /* read data from port */
11579 emitcode ("dec","dps"); /* switch to DPTR */
11580 emitcode ("movx", "@dptr,a"); /* save into location */
11581 emitcode ("inc", "dptr"); /* point to next area */
11582 emitcode ("inc","dps"); /* switch to DPTR2 */
11583 emitcode ("djnz","b,!tlabel",lbl->key+100);
11585 symbol *lbl1 = newiTempLabel(NULL);
11587 emitcode (";"," Auto increment but no djnz");
11588 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11589 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11590 freeAsmop (count, NULL, ic, FALSE);
11591 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11592 emitcode ("","!tlabeldef",lbl->key+100);
11593 emitcode ("movx", "a,@dptr");
11594 emitcode ("dec","dps"); /* switch to DPTR */
11595 emitcode ("movx", "@dptr,a");
11596 emitcode ("inc", "dptr");
11597 emitcode ("inc","dps"); /* switch to DPTR2 */
11598 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
11599 /* emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
11600 emitcode ("mov","a,b");
11601 emitcode ("orl","a,_ap");
11602 emitcode ("jz","!tlabel",lbl1->key+100);
11603 emitcode ("mov","a,_ap");
11604 emitcode ("add","a,#!constbyte",0xFF);
11605 emitcode ("mov","_ap,a");
11606 emitcode ("mov","a,b");
11607 emitcode ("addc","a,#!constbyte",0xFF);
11608 emitcode ("mov","b,a");
11609 emitcode ("sjmp","!tlabel",lbl->key+100);
11610 emitcode ("","!tlabeldef",lbl1->key+100);
11612 emitcode ("mov", "dps,#0");
11613 _G.dptrInUse = _G.dptr1InUse = 0;
11614 unsavermask(rsave);
11618 /*-----------------------------------------------------------------*/
11619 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
11620 /* port, first parameter output area second parameter pointer to */
11621 /* port third parameter count */
11622 /*-----------------------------------------------------------------*/
11623 static void genOutp( iCode *ic, int nparms, operand **parms)
11625 operand *from , *to , *count;
11630 /* we know it has to be 3 parameters */
11631 assert (nparms == 3);
11633 rsave = newBitVect(16);
11634 /* save DPTR if it needs to be saved */
11635 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11636 if (bitVectBitValue(ic->rMask,i))
11637 rsave = bitVectSetBit(rsave,i);
11639 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11640 ds390_rUmaskForOp (IC_RESULT(ic))));
11647 aopOp (from, ic->next, FALSE, FALSE);
11649 /* get from into DPTR1 */
11650 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11651 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11652 if (options.model == MODEL_FLAT24) {
11653 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11656 freeAsmop (from, NULL, ic, FALSE);
11657 aopOp (to, ic, FALSE, FALSE);
11658 /* get "to" into DPTR */
11659 /* if the operand is already in dptr
11660 then we do nothing else we move the value to dptr */
11661 if (AOP_TYPE (to) != AOP_STR) {
11662 /* if already in DPTR then we need to push */
11663 if (AOP_TYPE(to) == AOP_DPTR) {
11664 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11665 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11666 if (options.model == MODEL_FLAT24)
11667 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11668 emitcode ("pop", "dph");
11669 emitcode ("pop", "dpl");
11671 _startLazyDPSEvaluation ();
11672 /* if this is remateriazable */
11673 if (AOP_TYPE (to) == AOP_IMMD) {
11674 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11675 } else { /* we need to get it byte by byte */
11676 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11677 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11678 if (options.model == MODEL_FLAT24) {
11679 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11682 _endLazyDPSEvaluation ();
11685 freeAsmop (to, NULL, ic, FALSE);
11687 _G.dptrInUse = _G.dptr1InUse = 1;
11688 aopOp (count, ic->next->next, FALSE,FALSE);
11689 lbl =newiTempLabel(NULL);
11691 /* now for the actual copy */
11692 if (AOP_TYPE(count) == AOP_LIT &&
11693 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11694 emitcode (";","OH JOY auto increment with djnz (very fast)");
11695 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
11696 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11697 emitcode ("","!tlabeldef",lbl->key+100);
11698 emitcode ("movx", "a,@dptr"); /* read data from port */
11699 emitcode ("inc","dps"); /* switch to DPTR2 */
11700 emitcode ("movx", "@dptr,a"); /* save into location */
11701 emitcode ("inc", "dptr"); /* point to next area */
11702 emitcode ("dec","dps"); /* switch to DPTR */
11703 emitcode ("djnz","b,!tlabel",lbl->key+100);
11704 freeAsmop (count, NULL, ic, FALSE);
11706 symbol *lbl1 = newiTempLabel(NULL);
11708 emitcode (";"," Auto increment but no djnz");
11709 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11710 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11711 freeAsmop (count, NULL, ic, FALSE);
11712 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
11713 emitcode ("","!tlabeldef",lbl->key+100);
11714 emitcode ("movx", "a,@dptr");
11715 emitcode ("inc", "dptr");
11716 emitcode ("inc","dps"); /* switch to DPTR2 */
11717 emitcode ("movx", "@dptr,a");
11718 emitcode ("dec","dps"); /* switch to DPTR */
11719 emitcode ("mov","a,b");
11720 emitcode ("orl","a,_ap");
11721 emitcode ("jz","!tlabel",lbl1->key+100);
11722 emitcode ("mov","a,_ap");
11723 emitcode ("add","a,#!constbyte",0xFF);
11724 emitcode ("mov","_ap,a");
11725 emitcode ("mov","a,b");
11726 emitcode ("addc","a,#!constbyte",0xFF);
11727 emitcode ("mov","b,a");
11728 emitcode ("sjmp","!tlabel",lbl->key+100);
11729 emitcode ("","!tlabeldef",lbl1->key+100);
11731 emitcode ("mov", "dps,#0");
11732 _G.dptrInUse = _G.dptr1InUse = 0;
11733 unsavermask(rsave);
11737 /*-----------------------------------------------------------------*/
11738 /* genSwapW - swap lower & high order bytes */
11739 /*-----------------------------------------------------------------*/
11740 static void genSwapW(iCode *ic, int nparms, operand **parms)
11744 assert (nparms==1);
11747 dest=IC_RESULT(ic);
11749 assert(getSize(operandType(src))==2);
11751 aopOp (src, ic, FALSE, FALSE);
11752 emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
11754 MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
11756 freeAsmop (src, NULL, ic, FALSE);
11758 aopOp (dest,ic, FALSE, FALSE);
11759 aopPut(AOP(dest),"b",0);
11760 aopPut(AOP(dest),"a",1);
11761 freeAsmop (dest, NULL, ic, FALSE);
11764 /*-----------------------------------------------------------------*/
11765 /* genMemsetX - gencode for memSetX data */
11766 /*-----------------------------------------------------------------*/
11767 static void genMemsetX(iCode *ic, int nparms, operand **parms)
11769 operand *to , *val , *count;
11775 /* we know it has to be 3 parameters */
11776 assert (nparms == 3);
11782 /* save DPTR if it needs to be saved */
11783 rsave = newBitVect(16);
11784 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11785 if (bitVectBitValue(ic->rMask,i))
11786 rsave = bitVectSetBit(rsave,i);
11788 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11789 ds390_rUmaskForOp (IC_RESULT(ic))));
11792 aopOp (to, ic, FALSE, FALSE);
11793 /* get "to" into DPTR */
11794 /* if the operand is already in dptr
11795 then we do nothing else we move the value to dptr */
11796 if (AOP_TYPE (to) != AOP_STR) {
11797 /* if already in DPTR then we need to push */
11798 if (AOP_TYPE(to) == AOP_DPTR) {
11799 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11800 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11801 if (options.model == MODEL_FLAT24)
11802 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11803 emitcode ("pop", "dph");
11804 emitcode ("pop", "dpl");
11806 _startLazyDPSEvaluation ();
11807 /* if this is remateriazable */
11808 if (AOP_TYPE (to) == AOP_IMMD) {
11809 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11810 } else { /* we need to get it byte by byte */
11811 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11812 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11813 if (options.model == MODEL_FLAT24) {
11814 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11817 _endLazyDPSEvaluation ();
11820 freeAsmop (to, NULL, ic, FALSE);
11822 aopOp (val, ic->next->next, FALSE,FALSE);
11823 aopOp (count, ic->next->next, FALSE,FALSE);
11824 lbl =newiTempLabel(NULL);
11825 /* now for the actual copy */
11826 if (AOP_TYPE(count) == AOP_LIT &&
11827 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11828 l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
11829 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11831 emitcode ("","!tlabeldef",lbl->key+100);
11832 emitcode ("movx", "@dptr,a");
11833 emitcode ("inc", "dptr");
11834 emitcode ("djnz","b,!tlabel",lbl->key+100);
11836 symbol *lbl1 = newiTempLabel(NULL);
11838 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11839 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11840 emitcode ("","!tlabeldef",lbl->key+100);
11841 MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
11842 emitcode ("movx", "@dptr,a");
11843 emitcode ("inc", "dptr");
11844 emitcode ("mov","a,b");
11845 emitcode ("orl","a,_ap");
11846 emitcode ("jz","!tlabel",lbl1->key+100);
11847 emitcode ("mov","a,_ap");
11848 emitcode ("add","a,#!constbyte",0xFF);
11849 emitcode ("mov","_ap,a");
11850 emitcode ("mov","a,b");
11851 emitcode ("addc","a,#!constbyte",0xFF);
11852 emitcode ("mov","b,a");
11853 emitcode ("sjmp","!tlabel",lbl->key+100);
11854 emitcode ("","!tlabeldef",lbl1->key+100);
11856 freeAsmop (count, NULL, ic, FALSE);
11857 unsavermask(rsave);
11860 /*-----------------------------------------------------------------*/
11861 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
11862 /*-----------------------------------------------------------------*/
11863 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
11866 operand *pnum, *result;
11869 assert (nparms==1);
11870 /* save registers that need to be saved */
11871 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11872 ds390_rUmaskForOp (IC_RESULT(ic))));
11875 aopOp (pnum, ic, FALSE, FALSE);
11876 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
11877 freeAsmop (pnum, NULL, ic, FALSE);
11878 emitcode ("lcall","NatLib_LoadPrimitive");
11879 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11880 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
11881 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
11882 for (i = (size-1) ; i >= 0 ; i-- ) {
11883 emitcode ("push","a%s",javaRet[i]);
11885 for (i=0; i < size ; i++ ) {
11886 emitcode ("pop","a%s",
11887 aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
11890 for (i = 0 ; i < size ; i++ ) {
11891 aopPut(AOP(result),javaRet[i],i);
11894 freeAsmop (result, NULL, ic, FALSE);
11895 unsavermask(rsave);
11898 /*-----------------------------------------------------------------*/
11899 /* genNatLibLoadPointer - calls TINI api function to load pointer */
11900 /*-----------------------------------------------------------------*/
11901 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
11904 operand *pnum, *result;
11908 assert (nparms==1);
11909 /* save registers that need to be saved */
11910 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11911 ds390_rUmaskForOp (IC_RESULT(ic))));
11914 aopOp (pnum, ic, FALSE, FALSE);
11915 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
11916 freeAsmop (pnum, NULL, ic, FALSE);
11917 emitcode ("lcall","NatLib_LoadPointer");
11918 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11919 if (AOP_TYPE(result)!=AOP_STR) {
11920 for (i = 0 ; i < size ; i++ ) {
11921 aopPut(AOP(result),fReturn[i],i);
11924 freeAsmop (result, NULL, ic, FALSE);
11925 unsavermask(rsave);
11928 /*-----------------------------------------------------------------*/
11929 /* genNatLibInstallStateBlock - */
11930 /*-----------------------------------------------------------------*/
11931 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
11932 operand **parms, const char *name)
11935 operand *psb, *handle;
11936 assert (nparms==2);
11938 /* save registers that need to be saved */
11939 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11940 ds390_rUmaskForOp (IC_RESULT(ic))));
11944 /* put pointer to state block into DPTR1 */
11945 aopOp (psb, ic, FALSE, FALSE);
11946 if (AOP_TYPE (psb) == AOP_IMMD) {
11947 emitcode ("mov","dps,#1");
11948 emitcode ("mov", "dptr,%s",
11949 aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
11950 emitcode ("mov","dps,#0");
11952 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
11953 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
11954 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
11956 freeAsmop (psb, NULL, ic, FALSE);
11958 /* put libraryID into DPTR */
11959 emitcode ("mov","dptr,#LibraryID");
11961 /* put handle into r3:r2 */
11962 aopOp (handle, ic, FALSE, FALSE);
11963 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11964 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
11965 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
11966 emitcode ("pop","ar3");
11967 emitcode ("pop","ar2");
11969 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
11970 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
11972 freeAsmop (psb, NULL, ic, FALSE);
11974 /* make the call */
11975 emitcode ("lcall","NatLib_Install%sStateBlock",name);
11977 /* put return value into place*/
11979 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
11981 aopPut(AOP(IC_RESULT(ic)),"a",0);
11982 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11983 unsavermask(rsave);
11986 /*-----------------------------------------------------------------*/
11987 /* genNatLibRemoveStateBlock - */
11988 /*-----------------------------------------------------------------*/
11989 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
11995 /* save registers that need to be saved */
11996 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11997 ds390_rUmaskForOp (IC_RESULT(ic))));
11999 /* put libraryID into DPTR */
12000 emitcode ("mov","dptr,#LibraryID");
12001 /* make the call */
12002 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12003 unsavermask(rsave);
12006 /*-----------------------------------------------------------------*/
12007 /* genNatLibGetStateBlock - */
12008 /*-----------------------------------------------------------------*/
12009 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12010 operand **parms,const char *name)
12013 symbol *lbl = newiTempLabel(NULL);
12016 /* save registers that need to be saved */
12017 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12018 ds390_rUmaskForOp (IC_RESULT(ic))));
12020 /* put libraryID into DPTR */
12021 emitcode ("mov","dptr,#LibraryID");
12022 /* make the call */
12023 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12024 emitcode ("jnz","!tlabel",lbl->key+100);
12026 /* put return value into place */
12027 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12028 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12029 emitcode ("push","ar3");
12030 emitcode ("push","ar2");
12031 emitcode ("pop","%s",
12032 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12033 emitcode ("pop","%s",
12034 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12036 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12037 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12039 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12040 emitcode ("","!tlabeldef",lbl->key+100);
12041 unsavermask(rsave);
12044 /*-----------------------------------------------------------------*/
12045 /* genMMMalloc - */
12046 /*-----------------------------------------------------------------*/
12047 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12048 int size, const char *name)
12053 symbol *lbl = newiTempLabel(NULL);
12055 assert (nparms == 1);
12056 /* save registers that need to be saved */
12057 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12058 ds390_rUmaskForOp (IC_RESULT(ic))));
12061 aopOp (bsize,ic,FALSE,FALSE);
12063 /* put the size in R4-R2 */
12064 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12065 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12066 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12068 emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12069 emitcode("pop","ar4");
12071 emitcode("pop","ar3");
12072 emitcode("pop","ar2");
12074 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12075 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12077 emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12080 freeAsmop (bsize, NULL, ic, FALSE);
12082 /* make the call */
12083 emitcode ("lcall","MM_%s",name);
12084 emitcode ("jz","!tlabel",lbl->key+100);
12085 emitcode ("mov","r2,#!constbyte",0xff);
12086 emitcode ("mov","r3,#!constbyte",0xff);
12087 emitcode ("","!tlabeldef",lbl->key+100);
12088 /* we don't care about the pointer : we just save the handle */
12089 rsym = OP_SYMBOL(IC_RESULT(ic));
12090 if (rsym->liveFrom != rsym->liveTo) {
12091 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12092 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12093 emitcode ("push","ar3");
12094 emitcode ("push","ar2");
12095 emitcode ("pop","%s",
12096 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12097 emitcode ("pop","%s",
12098 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12100 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12101 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12103 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12105 unsavermask(rsave);
12108 /*-----------------------------------------------------------------*/
12110 /*-----------------------------------------------------------------*/
12111 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12116 assert (nparms == 1);
12117 /* save registers that need to be saved */
12118 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12119 ds390_rUmaskForOp (IC_RESULT(ic))));
12122 aopOp (handle,ic,FALSE,FALSE);
12124 /* put the size in R4-R2 */
12125 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12126 emitcode("push","%s",
12127 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12128 emitcode("push","%s",
12129 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12130 emitcode("pop","ar3");
12131 emitcode("pop","ar2");
12133 emitcode ("mov","r2,%s",
12134 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12135 emitcode ("mov","r3,%s",
12136 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12138 freeAsmop (handle, NULL, ic, FALSE);
12140 /* make the call */
12141 emitcode ("lcall","MM_Deref");
12144 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12145 if (rsym->liveFrom != rsym->liveTo) {
12146 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12147 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12148 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12149 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12150 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12154 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12155 unsavermask(rsave);
12158 /*-----------------------------------------------------------------*/
12159 /* genMMUnrestrictedPersist - */
12160 /*-----------------------------------------------------------------*/
12161 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12166 assert (nparms == 1);
12167 /* save registers that need to be saved */
12168 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12169 ds390_rUmaskForOp (IC_RESULT(ic))));
12172 aopOp (handle,ic,FALSE,FALSE);
12174 /* put the size in R3-R2 */
12175 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12176 emitcode("push","%s",
12177 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12178 emitcode("push","%s",
12179 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12180 emitcode("pop","ar3");
12181 emitcode("pop","ar2");
12183 emitcode ("mov","r2,%s",
12184 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12185 emitcode ("mov","r3,%s",
12186 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12188 freeAsmop (handle, NULL, ic, FALSE);
12190 /* make the call */
12191 emitcode ("lcall","MM_UnrestrictedPersist");
12194 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12195 if (rsym->liveFrom != rsym->liveTo) {
12196 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12197 aopPut(AOP(IC_RESULT(ic)),"a",0);
12198 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12201 unsavermask(rsave);
12204 /*-----------------------------------------------------------------*/
12205 /* genSystemExecJavaProcess - */
12206 /*-----------------------------------------------------------------*/
12207 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12210 operand *handle, *pp;
12212 assert (nparms==2);
12213 /* save registers that need to be saved */
12214 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12215 ds390_rUmaskForOp (IC_RESULT(ic))));
12220 /* put the handle in R3-R2 */
12221 aopOp (handle,ic,FALSE,FALSE);
12222 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12223 emitcode("push","%s",
12224 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12225 emitcode("push","%s",
12226 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12227 emitcode("pop","ar3");
12228 emitcode("pop","ar2");
12230 emitcode ("mov","r2,%s",
12231 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12232 emitcode ("mov","r3,%s",
12233 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12235 freeAsmop (handle, NULL, ic, FALSE);
12237 /* put pointer in DPTR */
12238 aopOp (pp,ic,FALSE,FALSE);
12239 if (AOP_TYPE(pp) == AOP_IMMD) {
12240 emitcode ("mov", "dptr,%s",
12241 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12242 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12243 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12244 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12245 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12247 freeAsmop (handle, NULL, ic, FALSE);
12249 /* make the call */
12250 emitcode ("lcall","System_ExecJavaProcess");
12252 /* put result in place */
12254 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12255 if (rsym->liveFrom != rsym->liveTo) {
12256 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12257 aopPut(AOP(IC_RESULT(ic)),"a",0);
12258 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12262 unsavermask(rsave);
12265 /*-----------------------------------------------------------------*/
12266 /* genSystemRTCRegisters - */
12267 /*-----------------------------------------------------------------*/
12268 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12274 assert (nparms==1);
12275 /* save registers that need to be saved */
12276 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12277 ds390_rUmaskForOp (IC_RESULT(ic))));
12280 /* put pointer in DPTR */
12281 aopOp (pp,ic,FALSE,FALSE);
12282 if (AOP_TYPE (pp) == AOP_IMMD) {
12283 emitcode ("mov","dps,#1");
12284 emitcode ("mov", "dptr,%s",
12285 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12286 emitcode ("mov","dps,#0");
12288 emitcode ("mov","dpl1,%s",
12289 aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12290 emitcode ("mov","dph1,%s",
12291 aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12292 emitcode ("mov","dpx1,%s",
12293 aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12295 freeAsmop (pp, NULL, ic, FALSE);
12297 /* make the call */
12298 emitcode ("lcall","System_%sRTCRegisters",name);
12300 unsavermask(rsave);
12303 /*-----------------------------------------------------------------*/
12304 /* genSystemThreadSleep - */
12305 /*-----------------------------------------------------------------*/
12306 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12311 assert (nparms==1);
12312 /* save registers that need to be saved */
12313 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12314 ds390_rUmaskForOp (IC_RESULT(ic))));
12317 aopOp(to,ic,FALSE,FALSE);
12318 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12319 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12320 emitcode ("push","%s",
12321 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12322 emitcode ("push","%s",
12323 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12324 emitcode ("push","%s",
12325 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12326 emitcode ("push","%s",
12327 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12328 emitcode ("pop","ar3");
12329 emitcode ("pop","ar2");
12330 emitcode ("pop","ar1");
12331 emitcode ("pop","ar0");
12333 emitcode ("mov","r0,%s",
12334 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12335 emitcode ("mov","r1,%s",
12336 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12337 emitcode ("mov","r2,%s",
12338 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12339 emitcode ("mov","r3,%s",
12340 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12342 freeAsmop (to, NULL, ic, FALSE);
12344 /* suspend in acc */
12346 aopOp(s,ic,FALSE,FALSE);
12347 emitcode ("mov","a,%s",
12348 aopGet(AOP(s),0,FALSE,TRUE,NULL));
12349 freeAsmop (s, NULL, ic, FALSE);
12351 /* make the call */
12352 emitcode ("lcall","System_%s",name);
12354 unsavermask(rsave);
12357 /*-----------------------------------------------------------------*/
12358 /* genSystemThreadResume - */
12359 /*-----------------------------------------------------------------*/
12360 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12365 assert (nparms==2);
12366 /* save registers that need to be saved */
12367 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12368 ds390_rUmaskForOp (IC_RESULT(ic))));
12374 aopOp(pid,ic,FALSE,FALSE);
12375 emitcode ("mov","r0,%s",
12376 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12377 freeAsmop (pid, NULL, ic, FALSE);
12380 aopOp(tid,ic,FALSE,FALSE);
12381 emitcode ("mov","a,%s",
12382 aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
12383 freeAsmop (tid, NULL, ic, FALSE);
12385 emitcode ("lcall","System_ThreadResume");
12387 /* put result into place */
12389 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12390 if (rsym->liveFrom != rsym->liveTo) {
12391 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12392 aopPut(AOP(IC_RESULT(ic)),"a",0);
12393 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12396 unsavermask(rsave);
12399 /*-----------------------------------------------------------------*/
12400 /* genSystemProcessResume - */
12401 /*-----------------------------------------------------------------*/
12402 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
12407 assert (nparms==1);
12408 /* save registers that need to be saved */
12409 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12410 ds390_rUmaskForOp (IC_RESULT(ic))));
12415 aopOp(pid,ic,FALSE,FALSE);
12416 emitcode ("mov","a,%s",
12417 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12418 freeAsmop (pid, NULL, ic, FALSE);
12420 emitcode ("lcall","System_ProcessResume");
12422 unsavermask(rsave);
12425 /*-----------------------------------------------------------------*/
12427 /*-----------------------------------------------------------------*/
12428 static void genSystem (iCode *ic,int nparms,char *name)
12430 assert(nparms == 0);
12432 emitcode ("lcall","System_%s",name);
12435 /*-----------------------------------------------------------------*/
12436 /* genSystemPoll - */
12437 /*-----------------------------------------------------------------*/
12438 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
12443 assert (nparms==1);
12444 /* save registers that need to be saved */
12445 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12446 ds390_rUmaskForOp (IC_RESULT(ic))));
12449 aopOp (fp,ic,FALSE,FALSE);
12450 if (AOP_TYPE (fp) == AOP_IMMD) {
12451 emitcode ("mov", "dptr,%s",
12452 aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
12453 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
12454 emitcode ("mov","dpl,%s",
12455 aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
12456 emitcode ("mov","dph,%s",
12457 aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
12458 emitcode ("mov","dpx,%s",
12459 aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
12461 freeAsmop (fp, NULL, ic, FALSE);
12463 emitcode ("lcall","System_%sPoll",name);
12465 /* put result into place */
12467 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12468 if (rsym->liveFrom != rsym->liveTo) {
12469 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12470 aopPut(AOP(IC_RESULT(ic)),"a",0);
12471 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12474 unsavermask(rsave);
12477 /*-----------------------------------------------------------------*/
12478 /* genSystemGetCurrentID - */
12479 /*-----------------------------------------------------------------*/
12480 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
12482 assert (nparms==0);
12484 emitcode ("lcall","System_GetCurrent%sId",name);
12485 /* put result into place */
12487 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12488 if (rsym->liveFrom != rsym->liveTo) {
12489 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12490 aopPut(AOP(IC_RESULT(ic)),"a",0);
12491 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12496 /*-----------------------------------------------------------------*/
12497 /* genBuiltIn - calls the appropriate function to generating code */
12498 /* for a built in function */
12499 /*-----------------------------------------------------------------*/
12500 static void genBuiltIn (iCode *ic)
12502 operand *bi_parms[MAX_BUILTIN_ARGS];
12507 /* get all the arguments for a built in function */
12508 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
12510 /* which function is it */
12511 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
12512 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
12513 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
12514 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
12515 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
12516 } else if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
12517 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
12518 } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
12519 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
12520 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
12521 genMemsetX(bi_iCode,nbi_parms,bi_parms);
12522 } else if (strcmp(bif->name,"__builtin_inp")==0) {
12523 genInp(bi_iCode,nbi_parms,bi_parms);
12524 } else if (strcmp(bif->name,"__builtin_outp")==0) {
12525 genOutp(bi_iCode,nbi_parms,bi_parms);
12526 } else if (strcmp(bif->name,"__builtin_swapw")==0) {
12527 genSwapW(bi_iCode,nbi_parms,bi_parms);
12528 /* JavaNative builtIns */
12529 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
12530 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
12531 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
12532 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
12533 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
12534 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
12535 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
12536 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
12537 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
12538 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12539 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
12540 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12541 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
12542 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
12543 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
12544 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
12545 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
12546 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12547 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
12548 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12549 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
12550 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
12551 } else if (strcmp(bif->name,"MM_Malloc")==0) {
12552 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
12553 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
12554 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
12555 } else if (strcmp(bif->name,"MM_Free")==0) {
12556 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
12557 } else if (strcmp(bif->name,"MM_Deref")==0) {
12558 genMMDeref(bi_iCode,nbi_parms,bi_parms);
12559 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
12560 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
12561 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
12562 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
12563 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
12564 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
12565 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
12566 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
12567 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
12568 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
12569 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
12570 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
12571 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
12572 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
12573 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
12574 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
12575 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12576 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12577 } else if (strcmp(bif->name,"System_SaveThread")==0) {
12578 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12579 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12580 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12581 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
12582 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
12583 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
12584 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
12585 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
12586 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
12587 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
12588 genSystem(bi_iCode,nbi_parms,"ProcessYield");
12589 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
12590 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
12591 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
12592 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
12593 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
12594 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
12595 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
12596 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
12597 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
12598 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
12600 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
12606 /*-----------------------------------------------------------------*/
12607 /* gen390Code - generate code for Dallas 390 based controllers */
12608 /*-----------------------------------------------------------------*/
12610 gen390Code (iCode * lic)
12615 lineHead = lineCurr = NULL;
12616 dptrn[1][0] = "dpl1";
12617 dptrn[1][1] = "dph1";
12618 dptrn[1][2] = "dpx1";
12620 if (options.model == MODEL_FLAT24) {
12621 fReturnSizeDS390 = 5;
12622 fReturn = fReturn24;
12624 fReturnSizeDS390 = 4;
12625 fReturn = fReturn16;
12626 options.stack10bit=0;
12629 /* print the allocation information */
12631 printAllocInfo (currFunc, codeOutFile);
12633 /* if debug information required */
12634 if (options.debug && currFunc)
12636 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
12638 if (IS_STATIC (currFunc->etype))
12639 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
12641 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
12644 /* stack pointer name */
12645 if (options.useXstack)
12651 for (ic = lic; ic; ic = ic->next)
12654 if (ic->lineno && cln != ic->lineno)
12659 emitcode ("", "C$%s$%d$%d$%d ==.",
12660 FileBaseName (ic->filename), ic->lineno,
12661 ic->level, ic->block);
12664 if (!options.noCcodeInAsm) {
12665 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
12666 printCLine(ic->filename, ic->lineno));
12670 if (options.iCodeInAsm) {
12671 emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
12673 /* if the result is marked as
12674 spilt and rematerializable or code for
12675 this has already been generated then
12677 if (resultRemat (ic) || ic->generated)
12680 /* depending on the operation */
12700 /* IPOP happens only when trying to restore a
12701 spilt live range, if there is an ifx statement
12702 following this pop then the if statement might
12703 be using some of the registers being popped which
12704 would destory the contents of the register so
12705 we need to check for this condition and handle it */
12707 ic->next->op == IFX &&
12708 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
12709 genIfx (ic->next, ic);
12727 genEndFunction (ic);
12747 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
12764 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
12768 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
12775 /* note these two are xlated by algebraic equivalence
12776 during parsing SDCC.y */
12777 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12778 "got '>=' or '<=' shouldn't have come here");
12782 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
12794 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
12798 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
12802 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
12826 genRightShift (ic);
12829 case GET_VALUE_AT_ADDRESS:
12830 genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
12834 if (POINTER_SET (ic))
12835 genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
12861 if (ic->builtinSEND) genBuiltIn(ic);
12862 else addSet (&_G.sendSet, ic);
12875 /* now we are ready to call the
12876 peep hole optimizer */
12877 if (!options.nopeep)
12878 peepHole (&lineHead);
12880 /* now do the actual printing */
12881 printLine (lineHead, codeOutFile);