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)
1614 D (emitcode (";", "genNotFloat "););
1616 /* we will put 127 in the first byte of
1618 aopPut (AOP (res), "#127", 0);
1619 size = AOP_SIZE (op) - 1;
1622 _startLazyDPSEvaluation ();
1623 MOVA(aopGet(op->aop, offset++, FALSE, FALSE, NULL));
1627 emitcode ("orl", "a,%s",
1629 offset++, FALSE, FALSE,
1632 _endLazyDPSEvaluation ();
1634 tlbl = newiTempLabel (NULL);
1635 aopPut (res->aop, one, 1);
1636 emitcode ("jz", "!tlabel", (tlbl->key + 100));
1637 aopPut (res->aop, zero, 1);
1638 emitcode ("", "!tlabeldef", (tlbl->key + 100));
1640 size = res->aop->size - 2;
1642 /* put zeros in the rest */
1644 aopPut (res->aop, zero, offset++);
1647 /*-----------------------------------------------------------------*/
1648 /* opIsGptr: returns non-zero if the passed operand is */
1649 /* a generic pointer type. */
1650 /*-----------------------------------------------------------------*/
1652 opIsGptr (operand * op)
1654 sym_link *type = operandType (op);
1656 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1663 /*-----------------------------------------------------------------*/
1664 /* getDataSize - get the operand data size */
1665 /*-----------------------------------------------------------------*/
1667 getDataSize (operand * op)
1670 size = AOP_SIZE (op);
1671 if (size == GPTRSIZE)
1673 sym_link *type = operandType (op);
1674 if (IS_GENPTR (type))
1676 /* generic pointer; arithmetic operations
1677 * should ignore the high byte (pointer type).
1685 /*-----------------------------------------------------------------*/
1686 /* outAcc - output Acc */
1687 /*-----------------------------------------------------------------*/
1689 outAcc (operand * result)
1692 size = getDataSize (result);
1695 aopPut (AOP (result), "a", 0);
1698 /* unsigned or positive */
1701 aopPut (AOP (result), zero, offset++);
1706 /*-----------------------------------------------------------------*/
1707 /* outBitC - output a bit C */
1708 /*-----------------------------------------------------------------*/
1710 outBitC (operand * result)
1712 /* if the result is bit */
1713 if (AOP_TYPE (result) == AOP_CRY)
1715 aopPut (AOP (result), "c", 0);
1719 emitcode ("clr", "a");
1720 emitcode ("rlc", "a");
1725 /*-----------------------------------------------------------------*/
1726 /* toBoolean - emit code for orl a,operator(sizeop) */
1727 /*-----------------------------------------------------------------*/
1729 toBoolean (operand * oper)
1731 int size = AOP_SIZE (oper) - 1;
1735 /* The generic part of a generic pointer should
1736 * not participate in it's truth value.
1738 * i.e. 0x10000000 is zero.
1740 if (opIsGptr (oper))
1742 D (emitcode (";", "toBoolean: generic ptr special case."););
1746 _startLazyDPSEvaluation ();
1747 if (AOP_NEEDSACC (oper) && size)
1752 emitcode ("push", "b");
1754 MOVB (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1758 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1765 emitcode ("orl", "b,%s",
1766 aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1770 emitcode ("orl", "a,%s",
1771 aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1774 _endLazyDPSEvaluation ();
1778 emitcode ("mov", "a,b");
1781 emitcode ("pop", "b");
1788 /*-----------------------------------------------------------------*/
1789 /* genNot - generate code for ! operation */
1790 /*-----------------------------------------------------------------*/
1795 sym_link *optype = operandType (IC_LEFT (ic));
1797 D (emitcode (";", "genNot "););
1799 /* assign asmOps to operand & result */
1800 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1801 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1803 /* if in bit space then a special case */
1804 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1806 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1807 emitcode ("cpl", "c");
1808 outBitC (IC_RESULT (ic));
1812 /* if type float then do float */
1813 if (IS_FLOAT (optype))
1815 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1819 toBoolean (IC_LEFT (ic));
1821 tlbl = newiTempLabel (NULL);
1822 emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1823 emitcode ("", "!tlabeldef", tlbl->key + 100);
1824 outBitC (IC_RESULT (ic));
1827 /* release the aops */
1828 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1829 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1833 /*-----------------------------------------------------------------*/
1834 /* genCpl - generate code for complement */
1835 /*-----------------------------------------------------------------*/
1843 D (emitcode (";", "genCpl "););
1846 /* assign asmOps to operand & result */
1847 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1848 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1850 /* special case if in bit space */
1851 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1852 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1853 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1854 emitcode ("cpl", "c");
1855 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1858 tlbl=newiTempLabel(NULL);
1859 emitcode ("cjne", "%s,#0x01,%05d$",
1860 aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE,NULL), tlbl->key+100);
1861 emitcode ("", "%05d$:", tlbl->key+100);
1862 outBitC (IC_RESULT(ic));
1866 size = AOP_SIZE (IC_RESULT (ic));
1867 _startLazyDPSEvaluation ();
1870 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
1871 emitcode ("cpl", "a");
1872 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1874 _endLazyDPSEvaluation ();
1878 /* release the aops */
1879 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1880 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1883 /*-----------------------------------------------------------------*/
1884 /* genUminusFloat - unary minus for floating points */
1885 /*-----------------------------------------------------------------*/
1887 genUminusFloat (operand * op, operand * result)
1889 int size, offset = 0;
1891 D(emitcode (";", "genUminusFloat"););
1893 /* for this we just copy and then flip the bit */
1895 _startLazyDPSEvaluation ();
1896 size = AOP_SIZE (op) - 1;
1900 aopPut (AOP (result),
1901 aopGet (AOP (op), offset, FALSE, FALSE, NULL),
1906 MOVA(aopGet (AOP (op), offset, FALSE, FALSE, NULL));
1908 emitcode ("cpl", "acc.7");
1909 aopPut (AOP (result), "a", offset);
1910 _endLazyDPSEvaluation ();
1913 /*-----------------------------------------------------------------*/
1914 /* genUminus - unary minus code generation */
1915 /*-----------------------------------------------------------------*/
1917 genUminus (iCode * ic)
1922 D (emitcode (";", "genUminus "););
1925 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1926 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1928 /* if both in bit space then special
1930 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1931 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1934 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1935 emitcode ("cpl", "c");
1936 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1940 optype = operandType (IC_LEFT (ic));
1942 /* if float then do float stuff */
1943 if (IS_FLOAT (optype))
1945 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1949 /* otherwise subtract from zero */
1950 size = AOP_SIZE (IC_LEFT (ic));
1952 _startLazyDPSEvaluation ();
1955 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL);
1956 if (!strcmp (l, "a"))
1960 emitcode ("cpl", "a");
1961 emitcode ("addc", "a,#0");
1967 emitcode ("clr", "a");
1968 emitcode ("subb", "a,%s", l);
1970 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1972 _endLazyDPSEvaluation ();
1974 /* if any remaining bytes in the result */
1975 /* we just need to propagate the sign */
1976 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic)))) != 0)
1978 emitcode ("rlc", "a");
1979 emitcode ("subb", "a,acc");
1981 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1985 /* release the aops */
1986 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1987 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1990 /*-----------------------------------------------------------------*/
1991 /* savermask - saves registers in the mask */
1992 /*-----------------------------------------------------------------*/
1993 static void savermask(bitVect *rs_mask)
1996 if (options.useXstack) {
1997 if (bitVectBitValue (rs_mask, R0_IDX))
1998 emitcode ("mov", "b,r0");
1999 emitcode ("mov", "r0,%s", spname);
2000 for (i = 0; i < ds390_nRegs; i++) {
2001 if (bitVectBitValue (rs_mask, i)) {
2003 emitcode ("mov", "a,b");
2005 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
2006 emitcode ("movx", "@r0,a");
2007 emitcode ("inc", "r0");
2010 emitcode ("mov", "%s,r0", spname);
2011 if (bitVectBitValue (rs_mask, R0_IDX))
2012 emitcode ("mov", "r0,b");
2014 for (i = 0; i < ds390_nRegs; i++) {
2015 if (bitVectBitValue (rs_mask, i))
2016 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2021 /*-----------------------------------------------------------------*/
2022 /* saveRegisters - will look for a call and save the registers */
2023 /*-----------------------------------------------------------------*/
2025 saveRegisters (iCode * lic)
2031 for (ic = lic; ic; ic = ic->next)
2032 if (ic->op == CALL || ic->op == PCALL)
2037 fprintf (stderr, "found parameter push with no function call\n");
2041 /* if the registers have been saved already then
2043 if (ic->regsSaved || IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic)))) return ;
2045 /* special case if DPTR alive across a function call then must save it
2046 even though callee saves */
2047 if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2049 rsave = newBitVect(ic->rMask->size);
2050 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2051 if (bitVectBitValue(ic->rMask,i))
2052 rsave = bitVectSetBit(rsave,i);
2054 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2056 /* safe the registers in use at this time but skip the
2057 ones for the result */
2058 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2059 ds390_rUmaskForOp (IC_RESULT(ic)));
2065 /*-----------------------------------------------------------------*/
2066 /* usavermask - restore registers with mask */
2067 /*-----------------------------------------------------------------*/
2068 static void unsavermask(bitVect *rs_mask)
2071 if (options.useXstack) {
2072 emitcode ("mov", "r0,%s", spname);
2073 for (i = ds390_nRegs; i >= 0; i--) {
2074 if (bitVectBitValue (rs_mask, i)) {
2075 emitcode ("dec", "r0");
2076 emitcode ("movx", "a,@r0");
2078 emitcode ("mov", "b,a");
2080 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
2083 emitcode ("mov", "%s,r0", spname);
2084 if (bitVectBitValue (rs_mask, R0_IDX))
2085 emitcode ("mov", "r0,b");
2087 for (i = ds390_nRegs; i >= 0; i--) {
2088 if (bitVectBitValue (rs_mask, i))
2089 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2094 /*-----------------------------------------------------------------*/
2095 /* unsaveRegisters - pop the pushed registers */
2096 /*-----------------------------------------------------------------*/
2098 unsaveRegisters (iCode * ic)
2102 if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2104 rsave = newBitVect(ic->rMask->size);
2105 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2106 if (bitVectBitValue(ic->rMask,i))
2107 rsave = bitVectSetBit(rsave,i);
2109 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2111 /* restore the registers in use at this time but skip the
2112 ones for the result */
2113 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2114 ds390_rUmaskForOp (IC_RESULT(ic)));
2120 /*-----------------------------------------------------------------*/
2122 /*-----------------------------------------------------------------*/
2124 pushSide (operand * oper, int size)
2127 _startLazyDPSEvaluation ();
2130 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, NULL);
2131 if (AOP_TYPE (oper) != AOP_REG &&
2132 AOP_TYPE (oper) != AOP_DIR &&
2135 emitcode ("mov", "a,%s", l);
2136 emitcode ("push", "acc");
2139 emitcode ("push", "%s", l);
2141 _endLazyDPSEvaluation ();
2144 /*-----------------------------------------------------------------*/
2145 /* assignResultValue - */
2146 /*-----------------------------------------------------------------*/
2148 assignResultValue (operand * oper)
2151 int size = AOP_SIZE (oper);
2152 bool pushedAcc = FALSE;
2154 if (size == fReturnSizeDS390)
2156 /* I don't think this case can ever happen... */
2157 /* ACC is the last part of this. If writing the result
2158 * uses AC, we must preserve it.
2160 if (AOP_NEEDSACC(oper))
2162 emitcode(";", "assignResultValue special case for ACC.");
2163 emitcode("push", "acc");
2170 _startLazyDPSEvaluation ();
2173 aopPut (AOP (oper), fReturn[offset], offset);
2176 _endLazyDPSEvaluation ();
2180 emitcode("pop", "acc");
2181 aopPut(AOP(oper), "a", offset);
2186 /*-----------------------------------------------------------------*/
2187 /* genXpush - pushes onto the external stack */
2188 /*-----------------------------------------------------------------*/
2190 genXpush (iCode * ic)
2192 asmop *aop = newAsmop (0);
2194 int size, offset = 0;
2196 D (emitcode (";", "genXpush ");
2199 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2200 r = getFreePtr (ic, &aop, FALSE);
2203 emitcode ("mov", "%s,_spx", r->name);
2205 size = AOP_SIZE (IC_LEFT (ic));
2206 _startLazyDPSEvaluation ();
2210 MOVA (aopGet (AOP (IC_LEFT (ic)),
2211 offset++, FALSE, FALSE, NULL));
2212 emitcode ("movx", "@%s,a", r->name);
2213 emitcode ("inc", "%s", r->name);
2216 _endLazyDPSEvaluation ();
2219 emitcode ("mov", "_spx,%s", r->name);
2221 freeAsmop (NULL, aop, ic, TRUE);
2222 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2225 /*-----------------------------------------------------------------*/
2226 /* genIpush - generate code for pushing this gets a little complex */
2227 /*-----------------------------------------------------------------*/
2229 genIpush (iCode * ic)
2231 int size, offset = 0;
2234 D (emitcode (";", "genIpush ");
2237 /* if this is not a parm push : ie. it is spill push
2238 and spill push is always done on the local stack */
2242 /* and the item is spilt then do nothing */
2243 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2246 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2247 size = AOP_SIZE (IC_LEFT (ic));
2248 /* push it on the stack */
2249 _startLazyDPSEvaluation ();
2252 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2258 emitcode ("push", "%s", l);
2260 _endLazyDPSEvaluation ();
2264 /* this is a paramter push: in this case we call
2265 the routine to find the call and save those
2266 registers that need to be saved */
2269 /* if use external stack then call the external
2270 stack pushing routine */
2271 if (options.useXstack)
2277 /* then do the push */
2278 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2280 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2281 size = AOP_SIZE (IC_LEFT (ic));
2283 _startLazyDPSEvaluation ();
2286 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2287 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2288 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2291 emitcode ("mov", "a,%s", l);
2292 emitcode ("push", "acc");
2296 emitcode ("push", "%s", l);
2299 _endLazyDPSEvaluation ();
2301 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2304 /*-----------------------------------------------------------------*/
2305 /* genIpop - recover the registers: can happen only for spilling */
2306 /*-----------------------------------------------------------------*/
2308 genIpop (iCode * ic)
2312 D (emitcode (";", "genIpop ");
2316 /* if the temp was not pushed then */
2317 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2320 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2321 size = AOP_SIZE (IC_LEFT (ic));
2322 offset = (size - 1);
2323 _startLazyDPSEvaluation ();
2326 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2327 FALSE, TRUE, NULL));
2329 _endLazyDPSEvaluation ();
2331 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2334 /*-----------------------------------------------------------------*/
2335 /* unsaveRBank - restores the resgister bank from stack */
2336 /*-----------------------------------------------------------------*/
2338 unsaveRBank (int bank, iCode * ic, bool popPsw)
2344 if (options.useXstack)
2348 /* Assume r0 is available for use. */
2349 r = ds390_regWithIdx (R0_IDX);;
2354 r = getFreePtr (ic, &aop, FALSE);
2356 emitcode ("mov", "%s,_spx", r->name);
2361 if (options.useXstack)
2363 emitcode ("movx", "a,@%s", r->name);
2364 emitcode ("mov", "psw,a");
2365 emitcode ("dec", "%s", r->name);
2369 emitcode ("pop", "psw");
2373 for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2375 if (options.useXstack)
2377 emitcode ("movx", "a,@%s", r->name);
2378 emitcode ("mov", "(%s+%d),a",
2379 regs390[i].base, 8 * bank + regs390[i].offset);
2380 emitcode ("dec", "%s", r->name);
2384 emitcode ("pop", "(%s+%d)",
2385 regs390[i].base, 8 * bank + regs390[i].offset);
2388 if (options.useXstack)
2390 emitcode ("mov", "_spx,%s", r->name);
2395 freeAsmop (NULL, aop, ic, TRUE);
2399 /*-----------------------------------------------------------------*/
2400 /* saveRBank - saves an entire register bank on the stack */
2401 /*-----------------------------------------------------------------*/
2403 saveRBank (int bank, iCode * ic, bool pushPsw)
2409 if (options.useXstack)
2413 /* Assume r0 is available for use. */
2414 r = ds390_regWithIdx (R0_IDX);;
2419 r = getFreePtr (ic, &aop, FALSE);
2421 emitcode ("mov", "%s,_spx", r->name);
2424 for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2426 if (options.useXstack)
2428 emitcode ("inc", "%s", r->name);
2429 emitcode ("mov", "a,(%s+%d)",
2430 regs390[i].base, 8 * bank + regs390[i].offset);
2431 emitcode ("movx", "@%s,a", r->name);
2434 emitcode ("push", "(%s+%d)",
2435 regs390[i].base, 8 * bank + regs390[i].offset);
2440 if (options.useXstack)
2442 emitcode ("mov", "a,psw");
2443 emitcode ("movx", "@%s,a", r->name);
2444 emitcode ("inc", "%s", r->name);
2445 emitcode ("mov", "_spx,%s", r->name);
2449 emitcode ("push", "psw");
2452 emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2457 freeAsmop (NULL, aop, ic, TRUE);
2466 /*-----------------------------------------------------------------*/
2467 /* genSend - gen code for SEND */
2468 /*-----------------------------------------------------------------*/
2469 static void genSend(set *sendSet)
2473 static int rb1_count = 0;
2475 for (sic = setFirstItem (sendSet); sic;
2476 sic = setNextItem (sendSet)) {
2477 int size, offset = 0;
2479 size=getSize(operandType(IC_LEFT(sic)));
2480 D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2481 if (sendCount == 0) { /* first parameter */
2482 // we know that dpl(hxb) is the result, so
2484 _startLazyDPSEvaluation ();
2486 aopOp (IC_LEFT (sic), sic, FALSE,
2487 (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2489 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2492 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2493 FALSE, FALSE, NULL);
2494 if (strcmp (l, fReturn[offset])) {
2495 emitcode ("mov", "%s,%s",
2501 _endLazyDPSEvaluation ();
2502 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2504 } else { /* if more parameter in registers */
2505 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2507 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
2508 FALSE, FALSE, NULL));
2510 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2516 /*-----------------------------------------------------------------*/
2517 /* genCall - generates a call statement */
2518 /*-----------------------------------------------------------------*/
2520 genCall (iCode * ic)
2523 bool restoreBank = FALSE;
2524 bool swapBanks = FALSE;
2526 D (emitcode (";", "genCall "););
2528 /* if we are calling a not _naked function that is not using
2529 the same register bank then we need to save the
2530 destination registers on the stack */
2531 dtype = operandType (IC_LEFT (ic));
2532 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2533 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2534 IFFUNC_ISISR (currFunc->type))
2538 /* This is unexpected; the bank should have been saved in
2541 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2547 /* if caller saves & we have not saved then */
2551 /* if send set is not empty the assign */
2552 /* We've saved all the registers we care about;
2553 * therefore, we may clobber any register not used
2554 * in the calling convention (i.e. anything not in
2559 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2560 genSend(reverseSet(_G.sendSet));
2562 genSend(_G.sendSet);
2569 emitcode ("mov", "psw,#!constbyte",
2570 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2574 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2575 OP_SYMBOL (IC_LEFT (ic))->rname :
2576 OP_SYMBOL (IC_LEFT (ic))->name));
2580 emitcode ("mov", "psw,#!constbyte",
2581 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2584 /* if we need assign a result value */
2585 if ((IS_ITEMP (IC_RESULT (ic)) &&
2586 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2587 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2588 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2589 IS_TRUE_SYMOP (IC_RESULT (ic)))
2591 if (isOperandInFarSpace (IC_RESULT (ic))
2592 && getSize (operandType (IC_RESULT (ic))) <= 2)
2594 int size = getSize (operandType (IC_RESULT (ic)));
2596 /* Special case for 1 or 2 byte return in far space. */
2600 emitcode ("mov", "b,%s", fReturn[1]);
2603 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2604 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2608 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2610 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2615 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2618 assignResultValue (IC_RESULT (ic));
2620 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2624 /* adjust the stack for parameters if
2626 if (ic->parmBytes) {
2628 if (options.stack10bit) {
2629 if (ic->parmBytes <= 10) {
2630 emitcode(";","stack adjustment for parms");
2631 for (i=0; i < ic->parmBytes ; i++) {
2632 emitcode("pop","acc");
2636 emitcode ("clr","c");
2637 emitcode ("mov","a,sp");
2638 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2639 emitcode ("mov","sp,a");
2640 emitcode ("mov","a,esp");
2641 emitcode ("anl","a,#3");
2642 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2643 emitcode ("mov","esp,a");
2647 if (ic->parmBytes > 3) {
2648 emitcode ("mov", "a,%s", spname);
2649 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2650 emitcode ("mov", "%s,a", spname);
2652 for (i = 0; i < ic->parmBytes; i++)
2653 emitcode ("dec", "%s", spname);
2657 /* if we hade saved some registers then unsave them */
2659 unsaveRegisters (ic);
2661 /* if register bank was saved then pop them */
2663 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2666 /*-----------------------------------------------------------------*/
2667 /* genPcall - generates a call by pointer statement */
2668 /*-----------------------------------------------------------------*/
2670 genPcall (iCode * ic)
2673 symbol *rlbl = newiTempLabel (NULL);
2674 bool restoreBank=FALSE;
2676 D (emitcode (";", "genPcall ");
2680 /* if caller saves & we have not saved then */
2684 /* if we are calling a function that is not using
2685 the same register bank then we need to save the
2686 destination registers on the stack */
2687 dtype = operandType (IC_LEFT (ic));
2688 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2689 IFFUNC_ISISR (currFunc->type) &&
2690 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2691 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2695 /* push the return address on to the stack */
2696 emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2697 emitcode ("push", "acc");
2698 emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2699 emitcode ("push", "acc");
2701 if (options.model == MODEL_FLAT24)
2703 emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2704 emitcode ("push", "acc");
2707 /* now push the calling address */
2708 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2710 pushSide (IC_LEFT (ic), FPTRSIZE);
2712 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2714 /* if send set is not empty the assign */
2717 genSend(reverseSet(_G.sendSet));
2721 emitcode ("ret", "");
2722 emitcode ("", "!tlabeldef", (rlbl->key + 100));
2725 /* if we need assign a result value */
2726 if ((IS_ITEMP (IC_RESULT (ic)) &&
2727 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2728 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2729 IS_TRUE_SYMOP (IC_RESULT (ic)))
2733 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2736 assignResultValue (IC_RESULT (ic));
2738 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2741 /* adjust the stack for parameters if
2746 if (options.stack10bit) {
2747 if (ic->parmBytes <= 10) {
2748 emitcode(";","stack adjustment for parms");
2749 for (i=0; i < ic->parmBytes ; i++) {
2750 emitcode("pop","acc");
2754 emitcode ("clr","c");
2755 emitcode ("mov","a,sp");
2756 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2757 emitcode ("mov","sp,a");
2758 emitcode ("mov","a,esp");
2759 emitcode ("anl","a,#3");
2760 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2761 emitcode ("mov","esp,a");
2765 if (ic->parmBytes > 3) {
2766 emitcode ("mov", "a,%s", spname);
2767 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2768 emitcode ("mov", "%s,a", spname);
2771 for (i = 0; i < ic->parmBytes; i++)
2772 emitcode ("dec", "%s", spname);
2776 /* if register bank was saved then unsave them */
2778 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2780 /* if we hade saved some registers then
2783 unsaveRegisters (ic);
2787 /*-----------------------------------------------------------------*/
2788 /* resultRemat - result is rematerializable */
2789 /*-----------------------------------------------------------------*/
2791 resultRemat (iCode * ic)
2793 if (SKIP_IC (ic) || ic->op == IFX)
2796 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2798 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2799 if (sym->remat && !POINTER_SET (ic))
2806 #if defined(__BORLANDC__) || defined(_MSC_VER)
2807 #define STRCASECMP stricmp
2809 #define STRCASECMP strcasecmp
2812 /*-----------------------------------------------------------------*/
2813 /* inExcludeList - return 1 if the string is in exclude Reg list */
2814 /*-----------------------------------------------------------------*/
2816 inExcludeList (char *s)
2820 if (options.excludeRegs[i] &&
2821 STRCASECMP (options.excludeRegs[i], "none") == 0)
2824 for (i = 0; options.excludeRegs[i]; i++)
2826 if (options.excludeRegs[i] &&
2827 STRCASECMP (s, options.excludeRegs[i]) == 0)
2833 /*-----------------------------------------------------------------*/
2834 /* genFunction - generated code for function entry */
2835 /*-----------------------------------------------------------------*/
2837 genFunction (iCode * ic)
2841 bool switchedPSW = FALSE;
2843 D (emitcode (";", "genFunction "););
2846 /* create the function header */
2847 emitcode (";", "-----------------------------------------");
2848 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2849 emitcode (";", "-----------------------------------------");
2851 emitcode ("", "%s:", sym->rname);
2852 ftype = operandType (IC_LEFT (ic));
2854 if (IFFUNC_ISNAKED(ftype))
2856 emitcode(";", "naked function: no prologue.");
2860 if (options.stack_probe)
2861 emitcode ("lcall","__stack_probe");
2862 /* if critical function then turn interrupts off */
2863 if (IFFUNC_ISCRITICAL (ftype))
2864 emitcode ("clr", "ea");
2866 /* here we need to generate the equates for the
2867 register bank if required */
2868 if (FUNC_REGBANK (ftype) != rbank)
2872 rbank = FUNC_REGBANK (ftype);
2873 for (i = 0; i < ds390_nRegs; i++)
2875 if (regs390[i].print) {
2876 if (strcmp (regs390[i].base, "0") == 0)
2877 emitcode ("", "%s !equ !constbyte",
2879 8 * rbank + regs390[i].offset);
2881 emitcode ("", "%s !equ %s + !constbyte",
2884 8 * rbank + regs390[i].offset);
2889 /* if this is an interrupt service routine then
2890 save acc, b, dpl, dph */
2891 if (IFFUNC_ISISR (sym->type))
2893 if (!inExcludeList ("acc"))
2894 emitcode ("push", "acc");
2895 if (!inExcludeList ("b"))
2896 emitcode ("push", "b");
2897 if (!inExcludeList ("dpl"))
2898 emitcode ("push", "dpl");
2899 if (!inExcludeList ("dph"))
2900 emitcode ("push", "dph");
2901 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2903 emitcode ("push", "dpx");
2904 /* Make sure we're using standard DPTR */
2905 emitcode ("push", "dps");
2906 emitcode ("mov", "dps,#0");
2907 if (options.stack10bit)
2909 /* This ISR could conceivably use DPTR2. Better save it. */
2910 emitcode ("push", "dpl1");
2911 emitcode ("push", "dph1");
2912 emitcode ("push", "dpx1");
2913 emitcode ("push", DP2_RESULT_REG);
2916 /* if this isr has no bank i.e. is going to
2917 run with bank 0 , then we need to save more
2919 if (!FUNC_REGBANK (sym->type))
2923 /* if this function does not call any other
2924 function then we can be economical and
2925 save only those registers that are used */
2926 if (!IFFUNC_HASFCALL(sym->type))
2929 /* if any registers used */
2932 /* save the registers used */
2933 for (i = 0; i < sym->regsUsed->size; i++)
2935 if (bitVectBitValue (sym->regsUsed, i) ||
2936 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2937 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2944 /* this function has a function call cannot
2945 determines register usage so we will have to push the
2947 saveRBank (0, ic, FALSE);
2948 if (options.parms_in_bank1) {
2949 for (i=0; i < 8 ; i++ ) {
2950 emitcode ("push","%s",rb1regs[i]);
2957 /* This ISR uses a non-zero bank.
2959 * We assume that the bank is available for our
2962 * However, if this ISR calls a function which uses some
2963 * other bank, we must save that bank entirely.
2965 unsigned long banksToSave = 0;
2967 if (IFFUNC_HASFCALL(sym->type))
2970 #define MAX_REGISTER_BANKS 4
2975 for (i = ic; i; i = i->next)
2977 if (i->op == ENDFUNCTION)
2979 /* we got to the end OK. */
2987 dtype = operandType (IC_LEFT(i));
2989 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2991 /* Mark this bank for saving. */
2992 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2994 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2998 banksToSave |= (1 << FUNC_REGBANK(dtype));
3001 /* And note that we don't need to do it in
3009 /* This is a mess; we have no idea what
3010 * register bank the called function might
3013 * The only thing I can think of to do is
3014 * throw a warning and hope.
3016 werror(W_FUNCPTR_IN_USING_ISR);
3020 if (banksToSave && options.useXstack)
3022 /* Since we aren't passing it an ic,
3023 * saveRBank will assume r0 is available to abuse.
3025 * So switch to our (trashable) bank now, so
3026 * the caller's R0 isn't trashed.
3028 emitcode ("push", "psw");
3029 emitcode ("mov", "psw,#!constbyte",
3030 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3034 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3036 if (banksToSave & (1 << ix))
3038 saveRBank(ix, NULL, FALSE);
3042 // jwk: this needs a closer look
3043 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3048 /* if callee-save to be used for this function
3049 then save the registers being used in this function */
3050 if (IFFUNC_CALLEESAVES(sym->type))
3054 /* if any registers used */
3057 /* save the registers used */
3058 for (i = 0; i < sym->regsUsed->size; i++)
3060 if (bitVectBitValue (sym->regsUsed, i) ||
3061 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3063 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3071 /* set the register bank to the desired value */
3072 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3075 emitcode ("push", "psw");
3076 emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3079 if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3080 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3081 if (options.stack10bit) {
3082 emitcode ("push","_bpx");
3083 emitcode ("push","_bpx+1");
3084 emitcode ("mov","_bpx,%s",spname);
3085 emitcode ("mov","_bpx+1,esp");
3086 emitcode ("anl","_bpx+1,#3");
3088 if (options.useXstack) {
3089 emitcode ("mov", "r0,%s", spname);
3090 emitcode ("mov", "a,_bp");
3091 emitcode ("movx", "@r0,a");
3092 emitcode ("inc", "%s", spname);
3094 /* set up the stack */
3095 emitcode ("push", "_bp"); /* save the callers stack */
3097 emitcode ("mov", "_bp,%s", spname);
3101 /* adjust the stack for the function */
3104 if (options.stack10bit) {
3105 if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
3106 assert (sym->recvSize <= 4);
3107 if (sym->stack <= 8) {
3108 while (i--) emitcode ("push","acc");
3111 emitcode ("mov","a,sp");
3112 emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3113 emitcode ("mov","sp,a");
3114 emitcode ("mov","a,esp");
3115 emitcode ("anl","a,#3");
3116 emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3117 emitcode ("mov","esp,a");
3122 werror (W_STACK_OVERFLOW, sym->name);
3124 if (i > 3 && sym->recvSize < 4) {
3126 emitcode ("mov", "a,sp");
3127 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3128 emitcode ("mov", "sp,a");
3132 emitcode ("inc", "sp");
3139 emitcode ("mov", "a,_spx");
3140 emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3141 emitcode ("mov", "_spx,a");
3146 /*-----------------------------------------------------------------*/
3147 /* genEndFunction - generates epilogue for functions */
3148 /*-----------------------------------------------------------------*/
3150 genEndFunction (iCode * ic)
3152 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3154 D (emitcode (";", "genEndFunction "););
3156 if (IFFUNC_ISNAKED(sym->type))
3158 emitcode(";", "naked function: no epilogue.");
3162 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3163 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3165 if (options.stack10bit) {
3167 emitcode ("mov", "sp,_bpx", spname);
3168 emitcode ("mov", "esp,_bpx+1", spname);
3171 emitcode ("mov", "%s,_bp", spname);
3175 /* if use external stack but some variables were
3176 added to the local stack then decrement the
3178 if (options.useXstack && sym->stack) {
3179 emitcode ("mov", "a,sp");
3180 emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3181 emitcode ("mov", "sp,a");
3185 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3186 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3188 if (options.useXstack) {
3189 emitcode ("mov", "r0,%s", spname);
3190 emitcode ("movx", "a,@r0");
3191 emitcode ("mov", "_bp,a");
3192 emitcode ("dec", "%s", spname);
3194 if (options.stack10bit) {
3195 emitcode ("pop", "_bpx+1");
3196 emitcode ("pop", "_bpx");
3198 emitcode ("pop", "_bp");
3203 /* restore the register bank */
3204 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3206 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3207 || !options.useXstack)
3209 /* Special case of ISR using non-zero bank with useXstack
3212 emitcode ("pop", "psw");
3216 if (IFFUNC_ISISR (sym->type))
3219 /* now we need to restore the registers */
3220 /* if this isr has no bank i.e. is going to
3221 run with bank 0 , then we need to save more
3223 if (!FUNC_REGBANK (sym->type))
3226 /* if this function does not call any other
3227 function then we can be economical and
3228 save only those registers that are used */
3229 if (!IFFUNC_HASFCALL(sym->type))
3232 /* if any registers used */
3235 /* save the registers used */
3236 for (i = sym->regsUsed->size; i >= 0; i--)
3238 if (bitVectBitValue (sym->regsUsed, i) ||
3239 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3240 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3247 /* this function has a function call cannot
3248 determines register usage so we will have to pop the
3250 if (options.parms_in_bank1) {
3251 for (i = 7 ; i >= 0 ; i-- ) {
3252 emitcode ("pop","%s",rb1regs[i]);
3255 unsaveRBank (0, ic, FALSE);
3260 /* This ISR uses a non-zero bank.
3262 * Restore any register banks saved by genFunction
3265 // jwk: this needs a closer look
3266 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3269 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3271 if (savedBanks & (1 << ix))
3273 unsaveRBank(ix, NULL, FALSE);
3277 if (options.useXstack)
3279 /* Restore bank AFTER calling unsaveRBank,
3280 * since it can trash r0.
3282 emitcode ("pop", "psw");
3286 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3288 if (options.stack10bit)
3290 emitcode ("pop", DP2_RESULT_REG);
3291 emitcode ("pop", "dpx1");
3292 emitcode ("pop", "dph1");
3293 emitcode ("pop", "dpl1");
3295 emitcode ("pop", "dps");
3296 emitcode ("pop", "dpx");
3298 if (!inExcludeList ("dph"))
3299 emitcode ("pop", "dph");
3300 if (!inExcludeList ("dpl"))
3301 emitcode ("pop", "dpl");
3302 if (!inExcludeList ("b"))
3303 emitcode ("pop", "b");
3304 if (!inExcludeList ("acc"))
3305 emitcode ("pop", "acc");
3307 if (IFFUNC_ISCRITICAL (sym->type))
3308 emitcode ("setb", "ea");
3310 /* if debug then send end of function */
3311 if (options.debug && currFunc) {
3313 emitcode ("", "C$%s$%d$%d$%d ==.",
3314 FileBaseName (ic->filename), currFunc->lastLine,
3315 ic->level, ic->block);
3316 if (IS_STATIC (currFunc->etype))
3317 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3319 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3323 emitcode ("reti", "");
3327 if (IFFUNC_ISCRITICAL (sym->type))
3328 emitcode ("setb", "ea");
3330 if (IFFUNC_CALLEESAVES(sym->type))
3334 /* if any registers used */
3337 /* save the registers used */
3338 for (i = sym->regsUsed->size; i >= 0; i--)
3340 if (bitVectBitValue (sym->regsUsed, i) ||
3341 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3342 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3348 /* if debug then send end of function */
3349 if (options.debug && currFunc)
3352 emitcode ("", "C$%s$%d$%d$%d ==.",
3353 FileBaseName (ic->filename), currFunc->lastLine,
3354 ic->level, ic->block);
3355 if (IS_STATIC (currFunc->etype))
3356 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3358 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3362 emitcode ("ret", "");
3367 /*-----------------------------------------------------------------*/
3368 /* genJavaNativeRet - generate code for return JavaNative */
3369 /*-----------------------------------------------------------------*/
3370 static void genJavaNativeRet(iCode *ic)
3374 aopOp (IC_LEFT (ic), ic, FALSE,
3375 AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
3376 size = AOP_SIZE (IC_LEFT (ic));
3380 /* it is assigned to GPR0-R3 then push them */
3381 if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3382 aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3383 for (i = 0 ; i < size ; i++ ) {
3384 emitcode ("push","%s",
3385 aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3387 for (i = (size-1) ; i >= 0 ; i--) {
3388 emitcode ("pop","a%s",javaRet[i]);
3391 for (i = 0 ; i < size ; i++)
3392 emitcode ("mov","%s,%s",javaRet[i],
3393 aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3395 for (i = size ; i < 4 ; i++ )
3396 emitcode ("mov","%s,#0",javaRet[i]);
3400 /*-----------------------------------------------------------------*/
3401 /* genRet - generate code for return statement */
3402 /*-----------------------------------------------------------------*/
3406 int size, offset = 0, pushed = 0;
3408 D (emitcode (";", "genRet "););
3410 /* if we have no return value then
3411 just generate the "ret" */
3415 /* if this is a JavaNative function then return
3416 value in different register */
3417 if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3418 genJavaNativeRet(ic);
3421 /* we have something to return then
3422 move the return value into place */
3423 aopOp (IC_LEFT (ic), ic, FALSE,
3424 (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
3425 size = AOP_SIZE (IC_LEFT (ic));
3427 _startLazyDPSEvaluation ();
3431 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3433 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3435 emitcode ("push", "%s", l);
3440 /* Since A is the last element of fReturn,
3441 * is is OK to clobber it in the aopGet.
3443 l = aopGet (AOP (IC_LEFT (ic)), offset,
3444 FALSE, FALSE, NULL);
3445 if (strcmp (fReturn[offset], l))
3446 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3449 _endLazyDPSEvaluation ();
3456 if (strcmp (fReturn[pushed], "a"))
3457 emitcode ("pop", fReturn[pushed]);
3459 emitcode ("pop", "acc");
3462 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3465 /* generate a jump to the return label
3466 if the next is not the return statement */
3467 if (!(ic->next && ic->next->op == LABEL &&
3468 IC_LABEL (ic->next) == returnLabel))
3470 emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3474 /*-----------------------------------------------------------------*/
3475 /* genLabel - generates a label */
3476 /*-----------------------------------------------------------------*/
3478 genLabel (iCode * ic)
3480 /* special case never generate */
3481 if (IC_LABEL (ic) == entryLabel)
3484 D (emitcode (";", "genLabel ");
3487 emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3490 /*-----------------------------------------------------------------*/
3491 /* genGoto - generates a ljmp */
3492 /*-----------------------------------------------------------------*/
3494 genGoto (iCode * ic)
3496 D (emitcode (";", "genGoto ");
3498 emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3501 /*-----------------------------------------------------------------*/
3502 /* findLabelBackwards: walks back through the iCode chain looking */
3503 /* for the given label. Returns number of iCode instructions */
3504 /* between that label and given ic. */
3505 /* Returns zero if label not found. */
3506 /*-----------------------------------------------------------------*/
3508 findLabelBackwards (iCode * ic, int key)
3517 /* If we have any pushes or pops, we cannot predict the distance.
3518 I don't like this at all, this should be dealt with in the
3520 if (ic->op == IPUSH || ic->op == IPOP) {
3524 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3526 /* printf("findLabelBackwards = %d\n", count); */
3534 /*-----------------------------------------------------------------*/
3535 /* genPlusIncr :- does addition with increment if possible */
3536 /*-----------------------------------------------------------------*/
3538 genPlusIncr (iCode * ic)
3540 unsigned int icount;
3541 unsigned int size = getDataSize (IC_RESULT (ic));
3543 /* will try to generate an increment */
3544 /* if the right side is not a literal
3546 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3549 /* if the literal value of the right hand side
3550 is greater than 4 then it is not worth it */
3551 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3554 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3555 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3557 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
3561 /* if increment 16 bits in register */
3563 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3564 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3565 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3574 /* If the next instruction is a goto and the goto target
3575 * is <= 5 instructions previous to this, we can generate
3576 * jumps straight to that target.
3578 if (ic->next && ic->next->op == GOTO
3579 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3582 D(emitcode (";", "tail increment optimized (range %d)", labelRange););
3583 tlbl = IC_LABEL (ic->next);
3588 tlbl = newiTempLabel (NULL);
3592 l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
3593 emitcode ("inc", "%s", l);
3595 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3596 IS_AOP_PREG (IC_RESULT (ic)))
3598 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3602 emitcode ("clr", "a");
3603 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3606 l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
3607 emitcode ("inc", "%s", l);
3610 if (!strcmp(l, "acc"))
3612 emitcode("jnz", "!tlabel", tlbl->key + 100);
3614 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3615 IS_AOP_PREG (IC_RESULT (ic)))
3617 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3621 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3624 l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
3625 emitcode ("inc", "%s", l);
3629 if (!strcmp(l, "acc"))
3631 emitcode("jnz", "!tlabel", tlbl->key + 100);
3633 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3634 IS_AOP_PREG (IC_RESULT (ic)))
3636 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3640 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3643 l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
3644 emitcode ("inc", "%s", l); }
3648 emitcode ("", "!tlabeldef", tlbl->key + 100);
3653 if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3654 !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 &&
3655 options.model == MODEL_FLAT24 ) {
3659 emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, NULL));
3661 emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, NULL));
3663 emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3666 while (icount--) emitcode ("inc","dptr");
3670 if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3671 AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3673 emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3674 while (icount--) emitcode ("inc","dptr");
3675 emitcode ("mov","dps,#0");
3679 /* if the sizes are greater than 1 then we cannot */
3680 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3681 AOP_SIZE (IC_LEFT (ic)) > 1)
3684 /* we can if the aops of the left & result match or
3685 if they are in registers and the registers are the
3688 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3689 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3690 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3695 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3696 emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3697 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3702 _startLazyDPSEvaluation ();
3705 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3707 _endLazyDPSEvaluation ();
3716 /*-----------------------------------------------------------------*/
3717 /* outBitAcc - output a bit in acc */
3718 /*-----------------------------------------------------------------*/
3720 outBitAcc (operand * result)
3722 symbol *tlbl = newiTempLabel (NULL);
3723 /* if the result is a bit */
3724 if (AOP_TYPE (result) == AOP_CRY)
3726 aopPut (AOP (result), "a", 0);
3730 emitcode ("jz", "!tlabel", tlbl->key + 100);
3731 emitcode ("mov", "a,%s", one);
3732 emitcode ("", "!tlabeldef", tlbl->key + 100);
3737 /*-----------------------------------------------------------------*/
3738 /* genPlusBits - generates code for addition of two bits */
3739 /*-----------------------------------------------------------------*/
3741 genPlusBits (iCode * ic)
3743 D (emitcode (";", "genPlusBits "););
3745 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3747 symbol *lbl = newiTempLabel (NULL);
3748 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3749 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3750 emitcode ("cpl", "c");
3751 emitcode ("", "!tlabeldef", (lbl->key + 100));
3752 outBitC (IC_RESULT (ic));
3756 emitcode ("clr", "a");
3757 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3758 emitcode ("rlc", "a");
3759 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3760 emitcode ("addc", "a,#0");
3761 outAcc (IC_RESULT (ic));
3766 adjustArithmeticResult (iCode * ic)
3768 if (opIsGptr (IC_RESULT (ic)) &&
3769 opIsGptr (IC_LEFT (ic)) &&
3770 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3772 aopPut (AOP (IC_RESULT (ic)),
3773 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3777 if (opIsGptr (IC_RESULT (ic)) &&
3778 opIsGptr (IC_RIGHT (ic)) &&
3779 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3781 aopPut (AOP (IC_RESULT (ic)),
3782 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3786 if (opIsGptr (IC_RESULT (ic)) &&
3787 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3788 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3789 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3790 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3793 SNPRINTF (buff, sizeof(buff),
3794 "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3795 aopPut (AOP (IC_RESULT (ic)), buff, GPTRSIZE - 1);
3799 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
3800 // generates the result if possible. If result is generated, returns TRUE; otherwise
3801 // returns false and caller must deal with fact that result isn't aopOp'd.
3802 bool aopOp3(iCode * ic)
3804 bool dp1InUse, dp2InUse;
3807 // First, generate the right opcode. DPTR may be used if neither left nor result are
3810 // D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
3811 // AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
3812 // AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
3813 // AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
3815 // D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
3816 // AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
3817 // AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
3818 // AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
3822 // Right uses DPTR unless left or result is an AOP_STR.
3823 aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)));
3825 // if the right used DPTR, left MUST use DPTR2.
3826 // if the right used DPTR2, left MUST use DPTR.
3827 // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
3828 // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
3829 // enabling us to assign DPTR to result.
3831 if (AOP_USESDPTR(IC_RIGHT(ic)))
3835 else if (AOP_USESDPTR2(IC_RIGHT(ic)))
3841 if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
3851 aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
3853 // We've op'd the left & right. So, if left or right are the same operand as result,
3854 // we know aopOp will succeed, and we can just do it & bail.
3855 if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)) ||
3856 isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
3858 // D(emitcode(";", "aopOp3: (left | right) & result equal"););
3859 aopOp(IC_RESULT(ic),ic,TRUE, FALSE);
3863 // Note which dptrs are currently in use.
3864 dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
3865 dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
3867 // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot
3869 if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
3874 // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
3875 if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
3880 // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck
3881 if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
3886 aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
3888 // Some sanity checking...
3889 if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
3892 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
3893 __FILE__, __LINE__, ic->filename, ic->lineno);
3894 emitcode(";", ">>> unexpected DPTR here.");
3897 if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
3900 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
3901 __FILE__, __LINE__, ic->filename, ic->lineno);
3902 emitcode(";", ">>> unexpected DPTR2 here.");
3908 // Macro to aopOp all three operands of an ic. If this cannot be done,
3909 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3910 // will be set TRUE. The caller must then handle the case specially, noting
3911 // that the IC_RESULT operand is not aopOp'd.
3913 #define AOP_OP_3_NOFATAL(ic, rc) \
3914 do { rc = !aopOp3(ic); } while (0)
3916 // aopOp the left & right operands of an ic.
3917 #define AOP_OP_2(ic) \
3918 aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
3919 aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
3921 // convienience macro.
3922 #define AOP_SET_LOCALS(ic) \
3923 left = IC_LEFT(ic); \
3924 right = IC_RIGHT(ic); \
3925 result = IC_RESULT(ic);
3928 // Given an integer value of pushedSize bytes on the stack,
3929 // adjust it to be resultSize bytes, either by discarding
3930 // the most significant bytes or by zero-padding.
3932 // On exit from this macro, pushedSize will have been adjusted to
3933 // equal resultSize, and ACC may be trashed.
3934 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3935 /* If the pushed data is bigger than the result, \
3936 * simply discard unused bytes. Icky, but works. \
3938 while (pushedSize > resultSize) \
3940 D (emitcode (";", "discarding unused result byte."););\
3941 emitcode ("pop", "acc"); \
3944 if (pushedSize < resultSize) \
3946 emitcode ("clr", "a"); \
3947 /* Conversly, we haven't pushed enough here. \
3948 * just zero-pad, and all is well. \
3950 while (pushedSize < resultSize) \
3952 emitcode("push", "acc"); \
3956 assert(pushedSize == resultSize);
3958 /*-----------------------------------------------------------------*/
3959 /* genPlus - generates code for addition */
3960 /*-----------------------------------------------------------------*/
3962 genPlus (iCode * ic)
3964 int size, offset = 0;
3968 D (emitcode (";", "genPlus "););
3970 /* special cases :- */
3971 if ( AOP_IS_STR(IC_LEFT(ic)) &&
3972 isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
3973 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
3974 size = floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
3976 while (size--) emitcode ("inc","dptr");
3978 emitcode ("mov","a,dpl");
3979 emitcode ("add","a,#!constbyte",size & 0xff);
3980 emitcode ("mov","dpl,a");
3981 emitcode ("mov","a,dph");
3982 emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
3983 emitcode ("mov","dph,a");
3984 emitcode ("mov","a,dpx");
3985 emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
3986 emitcode ("mov","dpx,a");
3988 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
3991 if ( IS_SYMOP(IC_LEFT(ic)) &&
3992 OP_SYMBOL(IC_LEFT(ic))->remat &&
3993 isOperandInFarSpace(IC_RIGHT(ic))) {
3994 operand *op = IC_RIGHT(ic);
3995 IC_RIGHT(ic) = IC_LEFT(ic);
3999 AOP_OP_3_NOFATAL (ic, pushResult);
4003 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
4008 /* if literal, literal on the right or
4009 if left requires ACC or right is already
4011 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4012 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
4013 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4015 operand *t = IC_RIGHT (ic);
4016 IC_RIGHT (ic) = IC_LEFT (ic);
4018 emitcode (";", "Swapped plus args.");
4021 /* if both left & right are in bit
4023 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4024 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4030 /* if left in bit space & right literal */
4031 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4032 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4034 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4035 /* if result in bit space */
4036 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4038 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4039 emitcode ("cpl", "c");
4040 outBitC (IC_RESULT (ic));
4044 size = getDataSize (IC_RESULT (ic));
4045 _startLazyDPSEvaluation ();
4048 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4049 emitcode ("addc", "a,#0");
4050 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4052 _endLazyDPSEvaluation ();
4057 /* if I can do an increment instead
4058 of add then GOOD for ME */
4059 if (genPlusIncr (ic) == TRUE)
4061 emitcode (";", "did genPlusIncr");
4066 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4068 _startLazyDPSEvaluation ();
4071 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4073 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4075 emitcode ("add", "a,%s",
4076 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4078 emitcode ("addc", "a,%s",
4079 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4083 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4085 /* right is going to use ACC or we would have taken the
4088 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4090 D(emitcode(";", "+ AOP_ACC special case."););
4091 emitcode("xch", "a, %s", DP2_RESULT_REG);
4093 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4096 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4099 emitcode("add", "a, %s", DP2_RESULT_REG);
4103 emitcode ("add", "a,%s",
4104 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE,
4110 emitcode ("addc", "a,%s",
4111 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE,
4117 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4121 emitcode ("push", "acc");
4125 _endLazyDPSEvaluation ();
4129 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4131 size = getDataSize (IC_LEFT (ic));
4132 rSize = getDataSize (IC_RESULT (ic));
4134 ADJUST_PUSHED_RESULT(size, rSize);
4136 _startLazyDPSEvaluation ();
4139 emitcode ("pop", "acc");
4140 aopPut (AOP (IC_RESULT (ic)), "a", size);
4142 _endLazyDPSEvaluation ();
4145 adjustArithmeticResult (ic);
4148 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4149 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4150 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4153 /*-----------------------------------------------------------------*/
4154 /* genMinusDec :- does subtraction with deccrement if possible */
4155 /*-----------------------------------------------------------------*/
4157 genMinusDec (iCode * ic)
4159 unsigned int icount;
4160 unsigned int size = getDataSize (IC_RESULT (ic));
4162 /* will try to generate an increment */
4163 /* if the right side is not a literal
4165 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4168 /* if the literal value of the right hand side
4169 is greater than 4 then it is not worth it */
4170 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4173 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4174 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4176 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
4180 /* if decrement 16 bits in register */
4181 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4182 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4183 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4192 /* If the next instruction is a goto and the goto target
4193 * is <= 5 instructions previous to this, we can generate
4194 * jumps straight to that target.
4196 if (ic->next && ic->next->op == GOTO
4197 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4200 emitcode (";", "tail decrement optimized (range %d)", labelRange);
4201 tlbl = IC_LABEL (ic->next);
4206 tlbl = newiTempLabel (NULL);
4210 l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
4211 emitcode ("dec", "%s", l);
4213 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4214 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4215 IS_AOP_PREG (IC_RESULT (ic)))
4217 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4221 emitcode ("mov", "a,#!constbyte",0xff);
4222 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4224 l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
4225 emitcode ("dec", "%s", l);
4228 if (!strcmp(l, "acc"))
4230 emitcode("jnz", "!tlabel", tlbl->key + 100);
4232 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4233 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4234 IS_AOP_PREG (IC_RESULT (ic)))
4236 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4240 emitcode ("mov", "a,#!constbyte",0xff);
4241 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4243 l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
4244 emitcode ("dec", "%s", l);
4248 if (!strcmp(l, "acc"))
4250 emitcode("jnz", "!tlabel", tlbl->key + 100);
4252 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4253 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4254 IS_AOP_PREG (IC_RESULT (ic)))
4256 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4260 emitcode ("mov", "a,#!constbyte",0xff);
4261 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4263 l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
4264 emitcode ("dec", "%s", l);
4268 emitcode ("", "!tlabeldef", tlbl->key + 100);
4273 /* if the sizes are greater than 1 then we cannot */
4274 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4275 AOP_SIZE (IC_LEFT (ic)) > 1)
4278 /* we can if the aops of the left & result match or
4279 if they are in registers and the registers are the
4282 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4283 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4284 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4287 _startLazyDPSEvaluation ();
4290 emitcode ("dec", "%s",
4291 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
4293 _endLazyDPSEvaluation ();
4301 /*-----------------------------------------------------------------*/
4302 /* addSign - complete with sign */
4303 /*-----------------------------------------------------------------*/
4305 addSign (operand * result, int offset, int sign)
4307 int size = (getDataSize (result) - offset);
4310 _startLazyDPSEvaluation();
4313 emitcode ("rlc", "a");
4314 emitcode ("subb", "a,acc");
4317 aopPut (AOP (result), "a", offset++);
4324 aopPut (AOP (result), zero, offset++);
4327 _endLazyDPSEvaluation();
4331 /*-----------------------------------------------------------------*/
4332 /* genMinusBits - generates code for subtraction of two bits */
4333 /*-----------------------------------------------------------------*/
4335 genMinusBits (iCode * ic)
4337 symbol *lbl = newiTempLabel (NULL);
4339 D (emitcode (";", "genMinusBits "););
4341 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4343 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4344 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4345 emitcode ("cpl", "c");
4346 emitcode ("", "!tlabeldef", (lbl->key + 100));
4347 outBitC (IC_RESULT (ic));
4351 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4352 emitcode ("subb", "a,acc");
4353 emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4354 emitcode ("inc", "a");
4355 emitcode ("", "!tlabeldef", (lbl->key + 100));
4356 aopPut (AOP (IC_RESULT (ic)), "a", 0);
4357 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4361 /*-----------------------------------------------------------------*/
4362 /* genMinus - generates code for subtraction */
4363 /*-----------------------------------------------------------------*/
4365 genMinus (iCode * ic)
4367 int size, offset = 0;
4372 D (emitcode (";", "genMinus "););
4374 AOP_OP_3_NOFATAL(ic, pushResult);
4378 /* special cases :- */
4379 /* if both left & right are in bit space */
4380 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4381 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4387 /* if I can do an decrement instead
4388 of subtract then GOOD for ME */
4389 if (genMinusDec (ic) == TRUE)
4394 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4396 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4402 lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4407 /* if literal, add a,#-lit, else normal subb */
4408 _startLazyDPSEvaluation ();
4410 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4411 if (AOP_USESDPTR(IC_RIGHT(ic))) {
4412 emitcode ("mov","b,%s",
4413 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4414 MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4415 emitcode ("subb","a,b");
4417 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4418 emitcode ("subb", "a,%s",
4419 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE,
4423 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4424 /* first add without previous c */
4426 if (!size && lit==-1) {
4427 emitcode ("dec", "a");
4429 emitcode ("add", "a,#!constbyte",
4430 (unsigned int) (lit & 0x0FFL));
4433 emitcode ("addc", "a,#!constbyte",
4434 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4439 emitcode ("push", "acc");
4441 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4445 _endLazyDPSEvaluation ();
4449 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4451 size = getDataSize (IC_LEFT (ic));
4452 rSize = getDataSize (IC_RESULT (ic));
4454 ADJUST_PUSHED_RESULT(size, rSize);
4456 _startLazyDPSEvaluation ();
4459 emitcode ("pop", "acc");
4460 aopPut (AOP (IC_RESULT (ic)), "a", size);
4462 _endLazyDPSEvaluation ();
4465 adjustArithmeticResult (ic);
4468 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4469 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4470 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4474 /*-----------------------------------------------------------------*/
4475 /* genMultbits :- multiplication of bits */
4476 /*-----------------------------------------------------------------*/
4478 genMultbits (operand * left,
4483 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4484 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4485 aopOp(result, ic, TRUE, FALSE);
4490 /*-----------------------------------------------------------------*/
4491 /* genMultOneByte : 8*8=8/16 bit multiplication */
4492 /*-----------------------------------------------------------------*/
4494 genMultOneByte (operand * left,
4499 sym_link *opetype = operandType (result);
4503 /* (if two literals: the value is computed before) */
4504 /* if one literal, literal on the right */
4505 if (AOP_TYPE (left) == AOP_LIT)
4510 emitcode (";", "swapped left and right");
4513 if (SPEC_USIGN(opetype)
4514 // ignore the sign of left and right, what else can we do?
4515 || (SPEC_USIGN(operandType(left)) &&
4516 SPEC_USIGN(operandType(right)))) {
4517 // just an unsigned 8*8=8/16 multiply
4518 //emitcode (";","unsigned");
4519 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4520 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4521 emitcode ("mul", "ab");
4523 _G.accInUse++; _G.bInUse++;
4524 aopOp(result, ic, TRUE, FALSE);
4526 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4528 // this should never happen
4529 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4530 AOP_SIZE(result), __FILE__, lineno);
4534 aopPut (AOP (result), "a", 0);
4535 _G.accInUse--; _G.bInUse--;
4536 if (AOP_SIZE(result)==2)
4538 aopPut (AOP (result), "b", 1);
4543 // we have to do a signed multiply
4545 emitcode (";", "signed");
4546 emitcode ("clr", "F0"); // reset sign flag
4547 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4549 lbl=newiTempLabel(NULL);
4550 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4551 // left side is negative, 8-bit two's complement, this fails for -128
4552 emitcode ("setb", "F0"); // set sign flag
4553 emitcode ("cpl", "a");
4554 emitcode ("inc", "a");
4556 emitcode ("", "!tlabeldef", lbl->key+100);
4559 if (AOP_TYPE(right)==AOP_LIT) {
4560 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4561 /* AND literal negative */
4562 if ((int) val < 0) {
4563 emitcode ("cpl", "F0"); // complement sign flag
4564 emitcode ("mov", "b,#!constbyte", -val);
4566 emitcode ("mov", "b,#!constbyte", val);
4569 lbl=newiTempLabel(NULL);
4570 emitcode ("mov", "b,a");
4571 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4572 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4573 // right side is negative, 8-bit two's complement
4574 emitcode ("cpl", "F0"); // complement sign flag
4575 emitcode ("cpl", "a");
4576 emitcode ("inc", "a");
4577 emitcode ("", "!tlabeldef", lbl->key+100);
4579 emitcode ("mul", "ab");
4581 _G.accInUse++;_G.bInUse++;
4582 aopOp(result, ic, TRUE, FALSE);
4584 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4586 // this should never happen
4587 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4588 AOP_SIZE(result), __FILE__, lineno);
4592 lbl=newiTempLabel(NULL);
4593 emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4594 // only ONE op was negative, we have to do a 8/16-bit two's complement
4595 emitcode ("cpl", "a"); // lsb
4596 if (AOP_SIZE(result)==1) {
4597 emitcode ("inc", "a");
4599 emitcode ("add", "a,#1");
4600 emitcode ("xch", "a,b");
4601 emitcode ("cpl", "a"); // msb
4602 emitcode ("addc", "a,#0");
4603 emitcode ("xch", "a,b");
4606 emitcode ("", "!tlabeldef", lbl->key+100);
4607 aopPut (AOP (result), "a", 0);
4608 _G.accInUse--;_G.bInUse--;
4609 if (AOP_SIZE(result)==2) {
4610 aopPut (AOP (result), "b", 1);
4614 /*-----------------------------------------------------------------*/
4615 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
4616 /*-----------------------------------------------------------------*/
4617 static void genMultTwoByte (operand *left, operand *right,
4618 operand *result, iCode *ic)
4620 sym_link *retype = getSpec(operandType(right));
4621 sym_link *letype = getSpec(operandType(left));
4622 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4625 if (AOP_TYPE (left) == AOP_LIT) {
4630 /* save EA bit in F1 */
4631 lbl = newiTempLabel(NULL);
4632 emitcode ("setb","F1");
4633 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4634 emitcode ("clr","F1");
4635 emitcode("","!tlabeldef",lbl->key+100);
4637 /* load up MB with right */
4639 emitcode("clr","F0");
4640 if (AOP_TYPE(right) == AOP_LIT) {
4641 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4643 emitcode("setb","F0");
4646 emitcode ("mov","mb,#!constbyte",val & 0xff);
4647 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4649 lbl = newiTempLabel(NULL);
4650 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4651 emitcode ("mov","a,%s",aopGet(AOP(right),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 ("setb","F0");
4660 emitcode ("","!tlabeldef",lbl->key+100);
4661 emitcode ("mov","mb,b");
4662 emitcode ("mov","mb,a");
4665 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4666 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4668 /* load up MA with left */
4670 lbl = newiTempLabel(NULL);
4671 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4672 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4673 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4674 emitcode ("xch", "a,b");
4675 emitcode ("cpl","a");
4676 emitcode ("add", "a,#1");
4677 emitcode ("xch", "a,b");
4678 emitcode ("cpl", "a"); // msb
4679 emitcode ("addc","a,#0");
4680 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4681 emitcode ("setb","F0");
4682 emitcode ("","!tlabeldef",lbl->key+100);
4683 emitcode ("mov","ma,b");
4684 emitcode ("mov","ma,a");
4686 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4687 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4689 /* wait for multiplication to finish */
4690 lbl = newiTempLabel(NULL);
4691 emitcode("","!tlabeldef", lbl->key+100);
4692 emitcode("mov","a,mcnt1");
4693 emitcode("anl","a,#!constbyte",0x80);
4694 emitcode("jnz","!tlabel",lbl->key+100);
4696 freeAsmop (left, NULL, ic, TRUE);
4697 freeAsmop (right, NULL, ic,TRUE);
4698 aopOp(result, ic, TRUE, FALSE);
4700 /* if unsigned then simple */
4702 emitcode ("mov","a,ma");
4703 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4704 emitcode ("mov","a,ma");
4705 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4706 aopPut(AOP(result),"ma",1);
4707 aopPut(AOP(result),"ma",0);
4709 emitcode("push","ma");
4710 emitcode("push","ma");
4711 emitcode("push","ma");
4713 /* negate result if needed */
4714 lbl = newiTempLabel(NULL);
4715 emitcode("jnb","F0,!tlabel",lbl->key+100);
4716 emitcode("cpl","a");
4717 emitcode("add","a,#1");
4718 emitcode("","!tlabeldef", lbl->key+100);
4719 if (AOP_TYPE(result) == AOP_ACC)
4721 D(emitcode(";", "ACC special case."););
4722 /* We know result is the only live aop, and
4723 * it's obviously not a DPTR2, so AP is available.
4725 emitcode("mov", "%s,acc", DP2_RESULT_REG);
4729 aopPut(AOP(result),"a",0);
4732 emitcode("pop","acc");
4733 lbl = newiTempLabel(NULL);
4734 emitcode("jnb","F0,!tlabel",lbl->key+100);
4735 emitcode("cpl","a");
4736 emitcode("addc","a,#0");
4737 emitcode("","!tlabeldef", lbl->key+100);
4738 aopPut(AOP(result),"a",1);
4739 emitcode("pop","acc");
4740 if (AOP_SIZE(result) >= 3) {
4741 lbl = newiTempLabel(NULL);
4742 emitcode("jnb","F0,!tlabel",lbl->key+100);
4743 emitcode("cpl","a");
4744 emitcode("addc","a,#0");
4745 emitcode("","!tlabeldef", lbl->key+100);
4746 aopPut(AOP(result),"a",2);
4748 emitcode("pop","acc");
4749 if (AOP_SIZE(result) >= 4) {
4750 lbl = newiTempLabel(NULL);
4751 emitcode("jnb","F0,!tlabel",lbl->key+100);
4752 emitcode("cpl","a");
4753 emitcode("addc","a,#0");
4754 emitcode("","!tlabeldef", lbl->key+100);
4755 aopPut(AOP(result),"a",3);
4757 if (AOP_TYPE(result) == AOP_ACC)
4759 /* We stashed the result away above. */
4760 emitcode("mov", "acc,%s", DP2_RESULT_REG);
4764 freeAsmop (result, NULL, ic, TRUE);
4766 /* restore EA bit in F1 */
4767 lbl = newiTempLabel(NULL);
4768 emitcode ("jnb","F1,!tlabel",lbl->key+100);
4769 emitcode ("setb","EA");
4770 emitcode("","!tlabeldef",lbl->key+100);
4774 /*-----------------------------------------------------------------*/
4775 /* genMult - generates code for multiplication */
4776 /*-----------------------------------------------------------------*/
4778 genMult (iCode * ic)
4780 operand *left = IC_LEFT (ic);
4781 operand *right = IC_RIGHT (ic);
4782 operand *result = IC_RESULT (ic);
4784 D (emitcode (";", "genMult "););
4786 /* assign the amsops */
4789 /* special cases first */
4791 if (AOP_TYPE (left) == AOP_CRY &&
4792 AOP_TYPE (right) == AOP_CRY)
4794 genMultbits (left, right, result, ic);
4798 /* if both are of size == 1 */
4799 if (AOP_SIZE (left) == 1 &&
4800 AOP_SIZE (right) == 1)
4802 genMultOneByte (left, right, result, ic);
4806 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4807 /* use the ds390 ARITHMETIC accel UNIT */
4808 genMultTwoByte (left, right, result, ic);
4811 /* should have been converted to function call */
4815 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4816 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4817 freeAsmop (result, NULL, ic, TRUE);
4820 /*-----------------------------------------------------------------*/
4821 /* genDivbits :- division of bits */
4822 /*-----------------------------------------------------------------*/
4824 genDivbits (operand * left,
4832 /* the result must be bit */
4833 LOAD_AB_FOR_DIV (left, right, l);
4834 emitcode ("div", "ab");
4835 emitcode ("rrc", "a");
4836 aopOp(result, ic, TRUE, FALSE);
4838 aopPut (AOP (result), "c", 0);
4841 /*-----------------------------------------------------------------*/
4842 /* genDivOneByte : 8 bit division */
4843 /*-----------------------------------------------------------------*/
4845 genDivOneByte (operand * left,
4850 sym_link *opetype = operandType (result);
4856 /* signed or unsigned */
4857 if (SPEC_USIGN (opetype))
4859 /* unsigned is easy */
4860 LOAD_AB_FOR_DIV (left, right, l);
4861 emitcode ("div", "ab");
4864 aopOp(result, ic, TRUE, FALSE);
4865 aopPut (AOP (result), "a", 0);
4868 size = AOP_SIZE (result) - 1;
4872 aopPut (AOP (result), zero, offset++);
4877 /* signed is a little bit more difficult */
4879 /* save the signs of the operands */
4880 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4881 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4882 emitcode ("push", "acc"); /* save it on the stack */
4884 /* now sign adjust for both left & right */
4885 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4886 lbl = newiTempLabel (NULL);
4887 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4888 emitcode ("cpl", "a");
4889 emitcode ("inc", "a");
4890 emitcode ("", "!tlabeldef", (lbl->key + 100));
4891 emitcode ("mov", "b,a");
4893 /* sign adjust left side */
4894 MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4896 lbl = newiTempLabel (NULL);
4897 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4898 emitcode ("cpl", "a");
4899 emitcode ("inc", "a");
4900 emitcode ("", "!tlabeldef", (lbl->key + 100));
4902 /* now the division */
4903 emitcode ("nop", "; workaround for DS80C390 div bug.");
4904 emitcode ("div", "ab");
4905 /* we are interested in the lower order
4907 emitcode ("mov", "b,a");
4908 lbl = newiTempLabel (NULL);
4909 emitcode ("pop", "acc");
4910 /* if there was an over flow we don't
4911 adjust the sign of the result */
4912 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4913 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4915 emitcode ("clr", "a");
4916 emitcode ("subb", "a,b");
4917 emitcode ("mov", "b,a");
4918 emitcode ("", "!tlabeldef", (lbl->key + 100));
4920 /* now we are done */
4921 _G.accInUse++; _G.bInUse++;
4922 aopOp(result, ic, TRUE, FALSE);
4924 aopPut (AOP (result), "b", 0);
4926 size = AOP_SIZE (result) - 1;
4930 emitcode ("mov", "c,b.7");
4931 emitcode ("subb", "a,acc");
4935 aopPut (AOP (result), "a", offset++);
4937 _G.accInUse--; _G.bInUse--;
4941 /*-----------------------------------------------------------------*/
4942 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
4943 /*-----------------------------------------------------------------*/
4944 static void genDivTwoByte (operand *left, operand *right,
4945 operand *result, iCode *ic)
4947 sym_link *retype = getSpec(operandType(right));
4948 sym_link *letype = getSpec(operandType(left));
4949 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4952 /* save EA bit in F1 */
4953 lbl = newiTempLabel(NULL);
4954 emitcode ("setb","F1");
4955 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4956 emitcode ("clr","F1");
4957 emitcode("","!tlabeldef",lbl->key+100);
4959 /* load up MA with left */
4961 emitcode("clr","F0");
4962 lbl = newiTempLabel(NULL);
4963 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4964 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4965 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4966 emitcode ("xch", "a,b");
4967 emitcode ("cpl","a");
4968 emitcode ("add", "a,#1");
4969 emitcode ("xch", "a,b");
4970 emitcode ("cpl", "a"); // msb
4971 emitcode ("addc","a,#0");
4972 emitcode ("setb","F0");
4973 emitcode ("","!tlabeldef",lbl->key+100);
4974 emitcode ("mov","ma,b");
4975 emitcode ("mov","ma,a");
4977 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4978 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4981 /* load up MB with right */
4983 if (AOP_TYPE(right) == AOP_LIT) {
4984 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4986 lbl = newiTempLabel(NULL);
4987 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4988 emitcode("setb","F0");
4989 emitcode ("","!tlabeldef",lbl->key+100);
4992 emitcode ("mov","mb,#!constbyte",val & 0xff);
4993 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4995 lbl = newiTempLabel(NULL);
4996 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4997 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4998 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4999 emitcode ("xch", "a,b");
5000 emitcode ("cpl","a");
5001 emitcode ("add", "a,#1");
5002 emitcode ("xch", "a,b");
5003 emitcode ("cpl", "a"); // msb
5004 emitcode ("addc", "a,#0");
5005 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5006 emitcode ("setb","F0");
5007 emitcode ("","!tlabeldef",lbl->key+100);
5008 emitcode ("mov","mb,b");
5009 emitcode ("mov","mb,a");
5012 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5013 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5016 /* wait for multiplication to finish */
5017 lbl = newiTempLabel(NULL);
5018 emitcode("","!tlabeldef", lbl->key+100);
5019 emitcode("mov","a,mcnt1");
5020 emitcode("anl","a,#!constbyte",0x80);
5021 emitcode("jnz","!tlabel",lbl->key+100);
5023 freeAsmop (left, NULL, ic, TRUE);
5024 freeAsmop (right, NULL, ic,TRUE);
5025 aopOp(result, ic, TRUE, FALSE);
5027 /* if unsigned then simple */
5029 aopPut(AOP(result),"ma",1);
5030 aopPut(AOP(result),"ma",0);
5032 emitcode("push","ma");
5034 /* negate result if needed */
5035 lbl = newiTempLabel(NULL);
5036 emitcode("jnb","F0,!tlabel",lbl->key+100);
5037 emitcode("cpl","a");
5038 emitcode("add","a,#1");
5039 emitcode("","!tlabeldef", lbl->key+100);
5040 aopPut(AOP(result),"a",0);
5041 emitcode("pop","acc");
5042 lbl = newiTempLabel(NULL);
5043 emitcode("jnb","F0,!tlabel",lbl->key+100);
5044 emitcode("cpl","a");
5045 emitcode("addc","a,#0");
5046 emitcode("","!tlabeldef", lbl->key+100);
5047 aopPut(AOP(result),"a",1);
5049 freeAsmop (result, NULL, ic, TRUE);
5050 /* restore EA bit in F1 */
5051 lbl = newiTempLabel(NULL);
5052 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5053 emitcode ("setb","EA");
5054 emitcode("","!tlabeldef",lbl->key+100);
5058 /*-----------------------------------------------------------------*/
5059 /* genDiv - generates code for division */
5060 /*-----------------------------------------------------------------*/
5064 operand *left = IC_LEFT (ic);
5065 operand *right = IC_RIGHT (ic);
5066 operand *result = IC_RESULT (ic);
5068 D (emitcode (";", "genDiv "););
5070 /* assign the amsops */
5073 /* special cases first */
5075 if (AOP_TYPE (left) == AOP_CRY &&
5076 AOP_TYPE (right) == AOP_CRY)
5078 genDivbits (left, right, result, ic);
5082 /* if both are of size == 1 */
5083 if (AOP_SIZE (left) == 1 &&
5084 AOP_SIZE (right) == 1)
5086 genDivOneByte (left, right, result, ic);
5090 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5091 /* use the ds390 ARITHMETIC accel UNIT */
5092 genDivTwoByte (left, right, result, ic);
5095 /* should have been converted to function call */
5098 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5099 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5100 freeAsmop (result, NULL, ic, TRUE);
5103 /*-----------------------------------------------------------------*/
5104 /* genModbits :- modulus of bits */
5105 /*-----------------------------------------------------------------*/
5107 genModbits (operand * left,
5115 /* the result must be bit */
5116 LOAD_AB_FOR_DIV (left, right, l);
5117 emitcode ("div", "ab");
5118 emitcode ("mov", "a,b");
5119 emitcode ("rrc", "a");
5120 aopOp(result, ic, TRUE, FALSE);
5121 aopPut (AOP (result), "c", 0);
5124 /*-----------------------------------------------------------------*/
5125 /* genModOneByte : 8 bit modulus */
5126 /*-----------------------------------------------------------------*/
5128 genModOneByte (operand * left,
5133 sym_link *opetype = operandType (result);
5137 /* signed or unsigned */
5138 if (SPEC_USIGN (opetype))
5140 /* unsigned is easy */
5141 LOAD_AB_FOR_DIV (left, right, l);
5142 emitcode ("div", "ab");
5143 aopOp(result, ic, TRUE, FALSE);
5144 aopPut (AOP (result), "b", 0);
5148 /* signed is a little bit more difficult */
5150 /* save the signs of the operands */
5151 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5153 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
5154 emitcode ("push", "acc"); /* save it on the stack */
5156 /* now sign adjust for both left & right */
5157 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5159 lbl = newiTempLabel (NULL);
5160 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5161 emitcode ("cpl", "a");
5162 emitcode ("inc", "a");
5163 emitcode ("", "!tlabeldef", (lbl->key + 100));
5164 emitcode ("mov", "b,a");
5166 /* sign adjust left side */
5167 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5169 lbl = newiTempLabel (NULL);
5170 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5171 emitcode ("cpl", "a");
5172 emitcode ("inc", "a");
5173 emitcode ("", "!tlabeldef", (lbl->key + 100));
5175 /* now the multiplication */
5176 emitcode ("nop", "; workaround for DS80C390 div bug.");
5177 emitcode ("div", "ab");
5178 /* we are interested in the lower order
5180 lbl = newiTempLabel (NULL);
5181 emitcode ("pop", "acc");
5182 /* if there was an over flow we don't
5183 adjust the sign of the result */
5184 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
5185 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5187 emitcode ("clr", "a");
5188 emitcode ("subb", "a,b");
5189 emitcode ("mov", "b,a");
5190 emitcode ("", "!tlabeldef", (lbl->key + 100));
5193 /* now we are done */
5194 aopOp(result, ic, TRUE, FALSE);
5195 aopPut (AOP (result), "b", 0);
5200 /*-----------------------------------------------------------------*/
5201 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
5202 /*-----------------------------------------------------------------*/
5203 static void genModTwoByte (operand *left, operand *right,
5204 operand *result, iCode *ic)
5206 sym_link *retype = getSpec(operandType(right));
5207 sym_link *letype = getSpec(operandType(left));
5208 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5211 /* load up MA with left */
5212 /* save EA bit in F1 */
5213 lbl = newiTempLabel(NULL);
5214 emitcode ("setb","F1");
5215 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5216 emitcode ("clr","F1");
5217 emitcode("","!tlabeldef",lbl->key+100);
5220 lbl = newiTempLabel(NULL);
5221 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5222 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5223 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5224 emitcode ("xch", "a,b");
5225 emitcode ("cpl","a");
5226 emitcode ("add", "a,#1");
5227 emitcode ("xch", "a,b");
5228 emitcode ("cpl", "a"); // msb
5229 emitcode ("addc","a,#0");
5230 emitcode ("","!tlabeldef",lbl->key+100);
5231 emitcode ("mov","ma,b");
5232 emitcode ("mov","ma,a");
5234 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5235 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5238 /* load up MB with right */
5240 if (AOP_TYPE(right) == AOP_LIT) {
5241 int val=floatFromVal (AOP (right)->aopu.aop_lit);
5245 emitcode ("mov","mb,#!constbyte",val & 0xff);
5246 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5248 lbl = newiTempLabel(NULL);
5249 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5250 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5251 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5252 emitcode ("xch", "a,b");
5253 emitcode ("cpl","a");
5254 emitcode ("add", "a,#1");
5255 emitcode ("xch", "a,b");
5256 emitcode ("cpl", "a"); // msb
5257 emitcode ("addc", "a,#0");
5258 emitcode ("","!tlabeldef",lbl->key+100);
5259 emitcode ("mov","mb,b");
5260 emitcode ("mov","mb,a");
5263 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5264 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5267 /* wait for multiplication to finish */
5268 lbl = newiTempLabel(NULL);
5269 emitcode("","!tlabeldef", lbl->key+100);
5270 emitcode("mov","a,mcnt1");
5271 emitcode("anl","a,#!constbyte",0x80);
5272 emitcode("jnz","!tlabel",lbl->key+100);
5274 freeAsmop (left, NULL, ic, TRUE);
5275 freeAsmop (right, NULL, ic,TRUE);
5276 aopOp(result, ic, TRUE, FALSE);
5278 aopPut(AOP(result),"mb",1);
5279 aopPut(AOP(result),"mb",0);
5280 freeAsmop (result, NULL, ic, TRUE);
5282 /* restore EA bit in F1 */
5283 lbl = newiTempLabel(NULL);
5284 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5285 emitcode ("setb","EA");
5286 emitcode("","!tlabeldef",lbl->key+100);
5290 /*-----------------------------------------------------------------*/
5291 /* genMod - generates code for division */
5292 /*-----------------------------------------------------------------*/
5296 operand *left = IC_LEFT (ic);
5297 operand *right = IC_RIGHT (ic);
5298 operand *result = IC_RESULT (ic);
5300 D (emitcode (";", "genMod "); );
5302 /* assign the amsops */
5305 /* special cases first */
5307 if (AOP_TYPE (left) == AOP_CRY &&
5308 AOP_TYPE (right) == AOP_CRY)
5310 genModbits (left, right, result, ic);
5314 /* if both are of size == 1 */
5315 if (AOP_SIZE (left) == 1 &&
5316 AOP_SIZE (right) == 1)
5318 genModOneByte (left, right, result, ic);
5322 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5323 /* use the ds390 ARITHMETIC accel UNIT */
5324 genModTwoByte (left, right, result, ic);
5328 /* should have been converted to function call */
5332 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5333 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5334 freeAsmop (result, NULL, ic, TRUE);
5337 /*-----------------------------------------------------------------*/
5338 /* genIfxJump :- will create a jump depending on the ifx */
5339 /*-----------------------------------------------------------------*/
5341 genIfxJump (iCode * ic, char *jval)
5344 symbol *tlbl = newiTempLabel (NULL);
5347 D (emitcode (";", "genIfxJump"););
5349 /* if true label then we jump if condition
5353 jlbl = IC_TRUE (ic);
5354 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5355 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5359 /* false label is present */
5360 jlbl = IC_FALSE (ic);
5361 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5362 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5364 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5365 emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5367 emitcode (inst, "!tlabel", tlbl->key + 100);
5368 emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5369 emitcode ("", "!tlabeldef", tlbl->key + 100);
5371 /* mark the icode as generated */
5375 /*-----------------------------------------------------------------*/
5376 /* genCmp :- greater or less than comparison */
5377 /*-----------------------------------------------------------------*/
5379 genCmp (operand * left, operand * right,
5380 iCode * ic, iCode * ifx, int sign)
5382 int size, offset = 0;
5383 unsigned long lit = 0L;
5386 D (emitcode (";", "genCmp"););
5388 result = IC_RESULT (ic);
5390 /* if left & right are bit variables */
5391 if (AOP_TYPE (left) == AOP_CRY &&
5392 AOP_TYPE (right) == AOP_CRY)
5394 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5395 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
5399 /* subtract right from left if at the
5400 end the carry flag is set then we know that
5401 left is greater than right */
5402 size = max (AOP_SIZE (left), AOP_SIZE (right));
5404 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5405 if ((size == 1) && !sign
5406 && (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5408 symbol *lbl = newiTempLabel (NULL);
5409 emitcode ("cjne", "%s,%s,!tlabel",
5410 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
5411 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5413 emitcode ("", "!tlabeldef", lbl->key + 100);
5417 if (AOP_TYPE (right) == AOP_LIT)
5419 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5420 /* optimize if(x < 0) or if(x >= 0) */
5429 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
5431 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5432 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5434 aopOp (result, ic, FALSE, FALSE);
5436 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5438 freeAsmop (result, NULL, ic, TRUE);
5439 genIfxJump (ifx, "acc.7");
5444 emitcode ("rlc", "a");
5446 goto release_freedLR;
5454 // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5455 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5456 // emitcode (";", "genCmp #2");
5457 if (sign && (size == 0))
5459 // emitcode (";", "genCmp #3");
5460 emitcode ("xrl", "a,#!constbyte",0x80);
5461 if (AOP_TYPE (right) == AOP_LIT)
5463 unsigned long lit = (unsigned long)
5464 floatFromVal (AOP (right)->aopu.aop_lit);
5465 // emitcode (";", "genCmp #3.1");
5466 emitcode ("subb", "a,#!constbyte",
5467 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5471 // emitcode (";", "genCmp #3.2");
5473 MOVB(aopGet (AOP (right), offset++, FALSE, FALSE, "b"));
5474 saveAccWarn = DEFAULT_ACC_WARNING;
5475 emitcode ("xrl", "b,#!constbyte",0x80);
5476 emitcode ("subb", "a,b");
5483 // emitcode (";", "genCmp #4");
5485 s = aopGet (AOP (right), offset++, FALSE, FALSE, "b");
5486 saveAccWarn = DEFAULT_ACC_WARNING;
5488 emitcode ("subb", "a,%s", s);
5495 /* Don't need the left & right operands any more; do need the result. */
5496 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5497 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5499 aopOp (result, ic, FALSE, FALSE);
5503 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5509 /* if the result is used in the next
5510 ifx conditional branch then generate
5511 code a little differently */
5514 genIfxJump (ifx, "c");
5520 /* leave the result in acc */
5522 freeAsmop (result, NULL, ic, TRUE);
5525 /*-----------------------------------------------------------------*/
5526 /* genCmpGt :- greater than comparison */
5527 /*-----------------------------------------------------------------*/
5529 genCmpGt (iCode * ic, iCode * ifx)
5531 operand *left, *right;
5532 sym_link *letype, *retype;
5535 D (emitcode (";", "genCmpGt ");
5538 left = IC_LEFT (ic);
5539 right = IC_RIGHT (ic);
5541 letype = getSpec (operandType (left));
5542 retype = getSpec (operandType (right));
5543 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5545 /* assign the left & right amsops */
5548 genCmp (right, left, ic, ifx, sign);
5551 /*-----------------------------------------------------------------*/
5552 /* genCmpLt - less than comparisons */
5553 /*-----------------------------------------------------------------*/
5555 genCmpLt (iCode * ic, iCode * ifx)
5557 operand *left, *right;
5558 sym_link *letype, *retype;
5561 D (emitcode (";", "genCmpLt "););
5563 left = IC_LEFT (ic);
5564 right = IC_RIGHT (ic);
5566 letype = getSpec (operandType (left));
5567 retype = getSpec (operandType (right));
5568 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5570 /* assign the left & right amsops */
5573 genCmp (left, right, ic, ifx, sign);
5576 /*-----------------------------------------------------------------*/
5577 /* gencjneshort - compare and jump if not equal */
5578 /*-----------------------------------------------------------------*/
5580 gencjneshort (operand * left, operand * right, symbol * lbl)
5582 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5584 unsigned long lit = 0L;
5586 D (emitcode (";", "gencjneshort");
5589 /* if the left side is a literal or
5590 if the right is in a pointer register and left
5592 if ((AOP_TYPE (left) == AOP_LIT) ||
5593 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5600 if (AOP_TYPE (right) == AOP_LIT)
5601 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5603 if (opIsGptr (left) || opIsGptr (right))
5605 /* We are comparing a generic pointer to something.
5606 * Exclude the generic type byte from the comparison.
5609 D (emitcode (";", "cjneshort: generic ptr special case."););
5613 /* if the right side is a literal then anything goes */
5614 if (AOP_TYPE (right) == AOP_LIT &&
5615 AOP_TYPE (left) != AOP_DIR)
5619 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5620 emitcode ("cjne", "a,%s,!tlabel",
5621 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5627 /* if the right side is in a register or in direct space or
5628 if the left is a pointer register & right is not */
5629 else if (AOP_TYPE (right) == AOP_REG ||
5630 AOP_TYPE (right) == AOP_DIR ||
5631 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5632 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5636 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5637 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5638 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5639 emitcode ("jnz", "!tlabel", lbl->key + 100);
5641 emitcode ("cjne", "a,%s,!tlabel",
5642 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
5649 /* right is a pointer reg need both a & b */
5652 MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5653 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
5654 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5660 /*-----------------------------------------------------------------*/
5661 /* gencjne - compare and jump if not equal */
5662 /*-----------------------------------------------------------------*/
5664 gencjne (operand * left, operand * right, symbol * lbl)
5666 symbol *tlbl = newiTempLabel (NULL);
5668 D (emitcode (";", "gencjne");
5671 gencjneshort (left, right, lbl);
5673 emitcode ("mov", "a,%s", one);
5674 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5675 emitcode ("", "!tlabeldef", lbl->key + 100);
5676 emitcode ("clr", "a");
5677 emitcode ("", "!tlabeldef", tlbl->key + 100);
5680 /*-----------------------------------------------------------------*/
5681 /* genCmpEq - generates code for equal to */
5682 /*-----------------------------------------------------------------*/
5684 genCmpEq (iCode * ic, iCode * ifx)
5686 operand *left, *right, *result;
5688 D (emitcode (";", "genCmpEq ");
5692 AOP_SET_LOCALS (ic);
5694 /* if literal, literal on the right or
5695 if the right is in a pointer register and left
5697 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5698 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5700 operand *t = IC_RIGHT (ic);
5701 IC_RIGHT (ic) = IC_LEFT (ic);
5705 if (ifx && /* !AOP_SIZE(result) */
5706 OP_SYMBOL (result) &&
5707 OP_SYMBOL (result)->regType == REG_CND)
5710 /* if they are both bit variables */
5711 if (AOP_TYPE (left) == AOP_CRY &&
5712 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5714 if (AOP_TYPE (right) == AOP_LIT)
5716 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5719 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5720 emitcode ("cpl", "c");
5724 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5728 emitcode ("clr", "c");
5730 /* AOP_TYPE(right) == AOP_CRY */
5734 symbol *lbl = newiTempLabel (NULL);
5735 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5736 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5737 emitcode ("cpl", "c");
5738 emitcode ("", "!tlabeldef", (lbl->key + 100));
5740 /* if true label then we jump if condition
5742 tlbl = newiTempLabel (NULL);
5745 emitcode ("jnc", "!tlabel", tlbl->key + 100);
5746 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5750 emitcode ("jc", "!tlabel", tlbl->key + 100);
5751 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5753 emitcode ("", "!tlabeldef", tlbl->key + 100);
5757 tlbl = newiTempLabel (NULL);
5758 gencjneshort (left, right, tlbl);
5761 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5762 emitcode ("", "!tlabeldef", tlbl->key + 100);
5766 symbol *lbl = newiTempLabel (NULL);
5767 emitcode ("sjmp", "!tlabel", lbl->key + 100);
5768 emitcode ("", "!tlabeldef", tlbl->key + 100);
5769 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5770 emitcode ("", "!tlabeldef", lbl->key + 100);
5773 /* mark the icode as generated */
5776 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5777 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5781 /* if they are both bit variables */
5782 if (AOP_TYPE (left) == AOP_CRY &&
5783 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5785 if (AOP_TYPE (right) == AOP_LIT)
5787 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5790 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5791 emitcode ("cpl", "c");
5795 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5799 emitcode ("clr", "c");
5801 /* AOP_TYPE(right) == AOP_CRY */
5805 symbol *lbl = newiTempLabel (NULL);
5806 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5807 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5808 emitcode ("cpl", "c");
5809 emitcode ("", "!tlabeldef", (lbl->key + 100));
5812 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5813 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5815 aopOp (result, ic, TRUE, FALSE);
5818 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5825 genIfxJump (ifx, "c");
5828 /* if the result is used in an arithmetic operation
5829 then put the result in place */
5834 gencjne (left, right, newiTempLabel (NULL));
5836 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5837 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5839 aopOp (result, ic, TRUE, FALSE);
5841 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5843 aopPut (AOP (result), "a", 0);
5848 genIfxJump (ifx, "a");
5851 /* if the result is used in an arithmetic operation
5852 then put the result in place */
5853 if (AOP_TYPE (result) != AOP_CRY)
5855 /* leave the result in acc */
5859 freeAsmop (result, NULL, ic, TRUE);
5862 /*-----------------------------------------------------------------*/
5863 /* ifxForOp - returns the icode containing the ifx for operand */
5864 /*-----------------------------------------------------------------*/
5866 ifxForOp (operand * op, iCode * ic)
5868 /* if true symbol then needs to be assigned */
5869 if (IS_TRUE_SYMOP (op))
5872 /* if this has register type condition and
5873 the next instruction is ifx with the same operand
5874 and live to of the operand is upto the ifx only then */
5876 ic->next->op == IFX &&
5877 IC_COND (ic->next)->key == op->key &&
5878 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5883 /*-----------------------------------------------------------------*/
5884 /* hasInc - operand is incremented before any other use */
5885 /*-----------------------------------------------------------------*/
5887 hasInc (operand *op, iCode *ic, int osize)
5889 sym_link *type = operandType(op);
5890 sym_link *retype = getSpec (type);
5891 iCode *lic = ic->next;
5894 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5895 if (!IS_SYMOP(op)) return NULL;
5897 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5898 if (IS_AGGREGATE(type->next)) return NULL;
5899 if (osize != (isize = getSize(type->next))) return NULL;
5902 /* if operand of the form op = op + <sizeof *op> */
5903 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5904 isOperandEqual(IC_RESULT(lic),op) &&
5905 isOperandLiteral(IC_RIGHT(lic)) &&
5906 operandLitValue(IC_RIGHT(lic)) == isize) {
5909 /* if the operand used or deffed */
5910 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5913 /* if GOTO or IFX */
5914 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5920 /*-----------------------------------------------------------------*/
5921 /* genAndOp - for && operation */
5922 /*-----------------------------------------------------------------*/
5924 genAndOp (iCode * ic)
5926 operand *left, *right, *result;
5929 D (emitcode (";", "genAndOp "););
5931 /* note here that && operations that are in an
5932 if statement are taken away by backPatchLabels
5933 only those used in arthmetic operations remain */
5935 AOP_SET_LOCALS (ic);
5937 /* if both are bit variables */
5938 if (AOP_TYPE (left) == AOP_CRY &&
5939 AOP_TYPE (right) == AOP_CRY)
5941 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5942 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5943 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5944 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5946 aopOp (result,ic,FALSE, FALSE);
5951 tlbl = newiTempLabel (NULL);
5953 emitcode ("jz", "!tlabel", tlbl->key + 100);
5955 emitcode ("", "!tlabeldef", tlbl->key + 100);
5956 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5957 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5959 aopOp (result,ic,FALSE, FALSE);
5962 freeAsmop (result, NULL, ic, TRUE);
5966 /*-----------------------------------------------------------------*/
5967 /* genOrOp - for || operation */
5968 /*-----------------------------------------------------------------*/
5970 genOrOp (iCode * ic)
5972 operand *left, *right, *result;
5975 D (emitcode (";", "genOrOp "););
5977 /* note here that || operations that are in an
5978 if statement are taken away by backPatchLabels
5979 only those used in arthmetic operations remain */
5981 AOP_SET_LOCALS (ic);
5983 /* if both are bit variables */
5984 if (AOP_TYPE (left) == AOP_CRY &&
5985 AOP_TYPE (right) == AOP_CRY)
5987 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5988 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5989 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5990 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5992 aopOp (result,ic,FALSE, FALSE);
5998 tlbl = newiTempLabel (NULL);
6000 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6002 emitcode ("", "!tlabeldef", tlbl->key + 100);
6003 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6004 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6006 aopOp (result,ic,FALSE, FALSE);
6011 freeAsmop (result, NULL, ic, TRUE);
6014 /*-----------------------------------------------------------------*/
6015 /* isLiteralBit - test if lit == 2^n */
6016 /*-----------------------------------------------------------------*/
6018 isLiteralBit (unsigned long lit)
6020 unsigned long pw[32] =
6021 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6022 0x100L, 0x200L, 0x400L, 0x800L,
6023 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6024 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6025 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6026 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6027 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6030 for (idx = 0; idx < 32; idx++)
6036 /*-----------------------------------------------------------------*/
6037 /* continueIfTrue - */
6038 /*-----------------------------------------------------------------*/
6040 continueIfTrue (iCode * ic)
6043 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6047 /*-----------------------------------------------------------------*/
6049 /*-----------------------------------------------------------------*/
6051 jumpIfTrue (iCode * ic)
6054 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6058 /*-----------------------------------------------------------------*/
6059 /* jmpTrueOrFalse - */
6060 /*-----------------------------------------------------------------*/
6062 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6064 // ugly but optimized by peephole
6067 symbol *nlbl = newiTempLabel (NULL);
6068 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6069 emitcode ("", "!tlabeldef", tlbl->key + 100);
6070 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6071 emitcode ("", "!tlabeldef", nlbl->key + 100);
6075 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6076 emitcode ("", "!tlabeldef", tlbl->key + 100);
6081 // Generate code to perform a bit-wise logic operation
6082 // on two operands in far space (assumed to already have been
6083 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6084 // in far space. This requires pushing the result on the stack
6085 // then popping it into the result.
6087 genFarFarLogicOp(iCode *ic, char *logicOp)
6089 int size, resultSize, compSize;
6093 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6094 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
6095 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6097 _startLazyDPSEvaluation();
6098 for (size = compSize; (size--); offset++)
6100 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6101 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6102 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6104 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6105 emitcode ("push", "acc");
6107 _endLazyDPSEvaluation();
6109 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6110 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6111 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6113 resultSize = AOP_SIZE(IC_RESULT(ic));
6115 ADJUST_PUSHED_RESULT(compSize, resultSize);
6117 _startLazyDPSEvaluation();
6120 emitcode ("pop", "acc");
6121 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6123 _endLazyDPSEvaluation();
6124 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6128 /*-----------------------------------------------------------------*/
6129 /* genAnd - code for and */
6130 /*-----------------------------------------------------------------*/
6132 genAnd (iCode * ic, iCode * ifx)
6134 operand *left, *right, *result;
6135 int size, offset = 0;
6136 unsigned long lit = 0L;
6141 D (emitcode (";", "genAnd "););
6143 AOP_OP_3_NOFATAL (ic, pushResult);
6144 AOP_SET_LOCALS (ic);
6148 genFarFarLogicOp(ic, "anl");
6153 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6155 AOP_TYPE (left), AOP_TYPE (right));
6156 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6158 AOP_SIZE (left), AOP_SIZE (right));
6161 /* if left is a literal & right is not then exchange them */
6162 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6163 #ifdef LOGIC_OPS_BROKEN
6164 || AOP_NEEDSACC (left)
6168 operand *tmp = right;
6173 /* if result = right then exchange them */
6174 if (sameRegs (AOP (result), AOP (right)))
6176 operand *tmp = right;
6181 /* if right is bit then exchange them */
6182 if (AOP_TYPE (right) == AOP_CRY &&
6183 AOP_TYPE (left) != AOP_CRY)
6185 operand *tmp = right;
6189 if (AOP_TYPE (right) == AOP_LIT)
6190 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6192 size = AOP_SIZE (result);
6195 // result = bit & yy;
6196 if (AOP_TYPE (left) == AOP_CRY)
6198 // c = bit & literal;
6199 if (AOP_TYPE (right) == AOP_LIT)
6203 if (size && sameRegs (AOP (result), AOP (left)))
6206 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6211 if (size && (AOP_TYPE (result) == AOP_CRY))
6213 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6216 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6221 emitcode ("clr", "c");
6226 if (AOP_TYPE (right) == AOP_CRY)
6229 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6230 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6235 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6237 emitcode ("rrc", "a");
6238 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6246 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6247 genIfxJump (ifx, "c");
6251 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6252 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6253 if ((AOP_TYPE (right) == AOP_LIT) &&
6254 (AOP_TYPE (result) == AOP_CRY) &&
6255 (AOP_TYPE (left) != AOP_CRY))
6257 int posbit = isLiteralBit (lit);
6262 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6265 emitcode ("mov", "c,acc.%d", posbit & 0x07);
6271 SNPRINTF (buff, sizeof(buff),
6272 "acc.%d", posbit & 0x07);
6273 genIfxJump (ifx, buff);
6277 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6284 symbol *tlbl = newiTempLabel (NULL);
6285 int sizel = AOP_SIZE (left);
6287 emitcode ("setb", "c");
6290 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6292 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6294 if ((posbit = isLiteralBit (bytelit)) != 0)
6295 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6298 if (bytelit != 0x0FFL)
6299 emitcode ("anl", "a,%s",
6300 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6301 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6306 // bit = left & literal
6309 emitcode ("clr", "c");
6310 emitcode ("", "!tlabeldef", tlbl->key + 100);
6312 // if(left & literal)
6316 jmpTrueOrFalse (ifx, tlbl);
6324 /* if left is same as result */
6325 if (sameRegs (AOP (result), AOP (left)))
6327 for (; size--; offset++)
6329 if (AOP_TYPE (right) == AOP_LIT)
6331 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6333 else if (bytelit == 0)
6334 aopPut (AOP (result), zero, offset);
6335 else if (IS_AOP_PREG (result))
6337 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6338 emitcode ("anl", "a,%s",
6339 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6340 aopPut (AOP (result), "a", offset);
6343 emitcode ("anl", "%s,%s",
6344 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6345 aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6349 if (AOP_TYPE (left) == AOP_ACC)
6350 emitcode ("anl", "a,%s",
6351 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6354 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6355 if (IS_AOP_PREG (result))
6357 emitcode ("anl", "a,%s",
6358 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6359 aopPut (AOP (result), "a", offset);
6362 emitcode ("anl", "%s,a",
6363 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6370 // left & result in different registers
6371 if (AOP_TYPE (result) == AOP_CRY)
6374 // if(size), result in bit
6375 // if(!size && ifx), conditional oper: if(left & right)
6376 symbol *tlbl = newiTempLabel (NULL);
6377 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6379 emitcode ("setb", "c");
6382 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6383 emitcode ("anl", "a,%s",
6384 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6386 if (AOP_TYPE(left)==AOP_ACC) {
6387 emitcode("mov", "b,a");
6388 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6389 emitcode("anl", "a,b");
6391 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6392 emitcode ("anl", "a,%s",
6393 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6396 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6402 emitcode ("", "!tlabeldef", tlbl->key + 100);
6406 jmpTrueOrFalse (ifx, tlbl);
6410 for (; (size--); offset++)
6413 // result = left & right
6414 if (AOP_TYPE (right) == AOP_LIT)
6416 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6418 aopPut (AOP (result),
6419 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6423 else if (bytelit == 0)
6425 aopPut (AOP (result), zero, offset);
6428 D (emitcode (";", "better literal AND."););
6429 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6430 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6431 FALSE, FALSE, DP2_RESULT_REG));
6436 // faster than result <- left, anl result,right
6437 // and better if result is SFR
6438 if (AOP_TYPE (left) == AOP_ACC)
6440 emitcode ("anl", "a,%s",
6441 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6445 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6446 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6448 emitcode("mov", "b,a");
6452 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6453 emitcode ("anl", "a,%s", rOp);
6456 aopPut (AOP (result), "a", offset);
6462 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6463 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6464 freeAsmop (result, NULL, ic, TRUE);
6468 /*-----------------------------------------------------------------*/
6469 /* genOr - code for or */
6470 /*-----------------------------------------------------------------*/
6472 genOr (iCode * ic, iCode * ifx)
6474 operand *left, *right, *result;
6475 int size, offset = 0;
6476 unsigned long lit = 0L;
6479 D (emitcode (";", "genOr "););
6481 AOP_OP_3_NOFATAL (ic, pushResult);
6482 AOP_SET_LOCALS (ic);
6486 genFarFarLogicOp(ic, "orl");
6492 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6494 AOP_TYPE (left), AOP_TYPE (right));
6495 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6497 AOP_SIZE (left), AOP_SIZE (right));
6500 /* if left is a literal & right is not then exchange them */
6501 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6502 #ifdef LOGIC_OPS_BROKEN
6503 || AOP_NEEDSACC (left) // I think this is a net loss now.
6507 operand *tmp = right;
6512 /* if result = right then exchange them */
6513 if (sameRegs (AOP (result), AOP (right)))
6515 operand *tmp = right;
6520 /* if right is bit then exchange them */
6521 if (AOP_TYPE (right) == AOP_CRY &&
6522 AOP_TYPE (left) != AOP_CRY)
6524 operand *tmp = right;
6528 if (AOP_TYPE (right) == AOP_LIT)
6529 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6531 size = AOP_SIZE (result);
6535 if (AOP_TYPE (left) == AOP_CRY)
6537 if (AOP_TYPE (right) == AOP_LIT)
6539 // c = bit & literal;
6542 // lit != 0 => result = 1
6543 if (AOP_TYPE (result) == AOP_CRY)
6546 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6548 continueIfTrue (ifx);
6551 emitcode ("setb", "c");
6555 // lit == 0 => result = left
6556 if (size && sameRegs (AOP (result), AOP (left)))
6558 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6563 if (AOP_TYPE (right) == AOP_CRY)
6566 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6567 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6572 symbol *tlbl = newiTempLabel (NULL);
6573 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6574 emitcode ("setb", "c");
6575 emitcode ("jb", "%s,!tlabel",
6576 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6578 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6579 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6581 jmpTrueOrFalse (ifx, tlbl);
6587 emitcode ("", "!tlabeldef", tlbl->key + 100);
6596 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6597 genIfxJump (ifx, "c");
6601 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6602 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6603 if ((AOP_TYPE (right) == AOP_LIT) &&
6604 (AOP_TYPE (result) == AOP_CRY) &&
6605 (AOP_TYPE (left) != AOP_CRY))
6611 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6613 continueIfTrue (ifx);
6618 // lit = 0, result = boolean(left)
6620 emitcode ("setb", "c");
6624 symbol *tlbl = newiTempLabel (NULL);
6625 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6627 emitcode ("", "!tlabeldef", tlbl->key + 100);
6631 genIfxJump (ifx, "a");
6639 /* if left is same as result */
6640 if (sameRegs (AOP (result), AOP (left)))
6642 for (; size--; offset++)
6644 if (AOP_TYPE (right) == AOP_LIT)
6646 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6652 if (IS_AOP_PREG (left))
6654 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6655 emitcode ("orl", "a,%s",
6656 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6657 aopPut (AOP (result), "a", offset);
6661 emitcode ("orl", "%s,%s",
6662 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6663 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6669 if (AOP_TYPE (left) == AOP_ACC)
6671 emitcode ("orl", "a,%s",
6672 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6676 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6677 if (IS_AOP_PREG (left))
6679 emitcode ("orl", "a,%s",
6680 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6681 aopPut (AOP (result), "a", offset);
6685 emitcode ("orl", "%s,a",
6686 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6694 // left & result in different registers
6695 if (AOP_TYPE (result) == AOP_CRY)
6698 // if(size), result in bit
6699 // if(!size && ifx), conditional oper: if(left | right)
6700 symbol *tlbl = newiTempLabel (NULL);
6701 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6703 emitcode ("setb", "c");
6706 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6707 emitcode ("orl", "a,%s",
6708 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6710 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6711 emitcode ("orl", "a,%s",
6712 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6714 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6720 emitcode ("", "!tlabeldef", tlbl->key + 100);
6724 jmpTrueOrFalse (ifx, tlbl);
6728 _startLazyDPSEvaluation();
6729 for (; (size--); offset++)
6732 // result = left & right
6733 if (AOP_TYPE (right) == AOP_LIT)
6735 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6737 aopPut (AOP (result),
6738 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6742 D (emitcode (";", "better literal OR."););
6743 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6744 emitcode ("orl", "a, %s",
6745 aopGet (AOP (right), offset,
6746 FALSE, FALSE, DP2_RESULT_REG));
6751 // faster than result <- left, anl result,right
6752 // and better if result is SFR
6753 if (AOP_TYPE (left) == AOP_ACC)
6755 emitcode ("orl", "a,%s",
6756 aopGet (AOP (right), offset,
6757 FALSE, FALSE, DP2_RESULT_REG));
6761 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6763 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6765 emitcode("mov", "b,a");
6769 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6770 emitcode ("orl", "a,%s", rOp);
6773 aopPut (AOP (result), "a", offset);
6775 _endLazyDPSEvaluation();
6780 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6781 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6782 freeAsmop (result, NULL, ic, TRUE);
6785 /*-----------------------------------------------------------------*/
6786 /* genXor - code for xclusive or */
6787 /*-----------------------------------------------------------------*/
6789 genXor (iCode * ic, iCode * ifx)
6791 operand *left, *right, *result;
6792 int size, offset = 0;
6793 unsigned long lit = 0L;
6796 D (emitcode (";", "genXor "););
6798 AOP_OP_3_NOFATAL (ic, pushResult);
6799 AOP_SET_LOCALS (ic);
6803 genFarFarLogicOp(ic, "xrl");
6808 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6810 AOP_TYPE (left), AOP_TYPE (right));
6811 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6813 AOP_SIZE (left), AOP_SIZE (right));
6816 /* if left is a literal & right is not ||
6817 if left needs acc & right does not */
6818 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6819 #ifdef LOGIC_OPS_BROKEN
6820 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6824 operand *tmp = right;
6829 /* if result = right then exchange them */
6830 if (sameRegs (AOP (result), AOP (right)))
6832 operand *tmp = right;
6837 /* if right is bit then exchange them */
6838 if (AOP_TYPE (right) == AOP_CRY &&
6839 AOP_TYPE (left) != AOP_CRY)
6841 operand *tmp = right;
6845 if (AOP_TYPE (right) == AOP_LIT)
6846 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6848 size = AOP_SIZE (result);
6852 if (AOP_TYPE (left) == AOP_CRY)
6854 if (AOP_TYPE (right) == AOP_LIT)
6856 // c = bit & literal;
6859 // lit>>1 != 0 => result = 1
6860 if (AOP_TYPE (result) == AOP_CRY)
6863 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6865 continueIfTrue (ifx);
6868 emitcode ("setb", "c");
6875 // lit == 0, result = left
6876 if (size && sameRegs (AOP (result), AOP (left)))
6878 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6882 // lit == 1, result = not(left)
6883 if (size && sameRegs (AOP (result), AOP (left)))
6885 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6890 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6891 emitcode ("cpl", "c");
6900 symbol *tlbl = newiTempLabel (NULL);
6901 if (AOP_TYPE (right) == AOP_CRY)
6904 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6908 int sizer = AOP_SIZE (right);
6910 // if val>>1 != 0, result = 1
6911 emitcode ("setb", "c");
6914 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
6916 // test the msb of the lsb
6917 emitcode ("anl", "a,#!constbyte",0xfe);
6918 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6922 emitcode ("rrc", "a");
6924 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6925 emitcode ("cpl", "c");
6926 emitcode ("", "!tlabeldef", (tlbl->key + 100));
6933 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6934 genIfxJump (ifx, "c");
6938 if (sameRegs (AOP (result), AOP (left)))
6940 /* if left is same as result */
6941 for (; size--; offset++)
6943 if (AOP_TYPE (right) == AOP_LIT)
6945 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6947 else if (IS_AOP_PREG (left))
6949 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6950 emitcode ("xrl", "a,%s",
6951 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6952 aopPut (AOP (result), "a", offset);
6955 emitcode ("xrl", "%s,%s",
6956 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6957 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6961 if (AOP_TYPE (left) == AOP_ACC)
6962 emitcode ("xrl", "a,%s",
6963 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6966 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6967 if (IS_AOP_PREG (left))
6969 emitcode ("xrl", "a,%s",
6970 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6971 aopPut (AOP (result), "a", offset);
6974 emitcode ("xrl", "%s,a",
6975 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6982 // left & result in different registers
6983 if (AOP_TYPE (result) == AOP_CRY)
6986 // if(size), result in bit
6987 // if(!size && ifx), conditional oper: if(left ^ right)
6988 symbol *tlbl = newiTempLabel (NULL);
6989 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6992 emitcode ("setb", "c");
6995 if ((AOP_TYPE (right) == AOP_LIT) &&
6996 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6998 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7002 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7003 emitcode ("xrl", "a,%s",
7004 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7006 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7007 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7009 emitcode("mov", "b,a");
7013 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7014 emitcode ("xrl", "a,%s", rOp);
7017 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7023 emitcode ("", "!tlabeldef", tlbl->key + 100);
7027 jmpTrueOrFalse (ifx, tlbl);
7031 for (; (size--); offset++)
7034 // result = left & right
7035 if (AOP_TYPE (right) == AOP_LIT)
7037 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7039 aopPut (AOP (result),
7040 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7044 D (emitcode (";", "better literal XOR."););
7045 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7046 emitcode ("xrl", "a, %s",
7047 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7051 // faster than result <- left, anl result,right
7052 // and better if result is SFR
7053 if (AOP_TYPE (left) == AOP_ACC)
7055 emitcode ("xrl", "a,%s",
7056 aopGet (AOP (right), offset,
7057 FALSE, FALSE, DP2_RESULT_REG));
7061 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7062 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7064 emitcode("mov", "b,a");
7068 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7069 emitcode ("xrl", "a,%s", rOp);
7072 aopPut (AOP (result), "a", offset);
7079 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7080 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7081 freeAsmop (result, NULL, ic, TRUE);
7084 /*-----------------------------------------------------------------*/
7085 /* genInline - write the inline code out */
7086 /*-----------------------------------------------------------------*/
7088 genInline (iCode * ic)
7090 char *buffer, *bp, *bp1;
7092 D (emitcode (";", "genInline "); );
7094 _G.inLine += (!options.asmpeep);
7096 buffer = Safe_strdup(IC_INLINE(ic));
7100 /* emit each line as a code */
7125 /* emitcode("",buffer); */
7126 _G.inLine -= (!options.asmpeep);
7129 /*-----------------------------------------------------------------*/
7130 /* genRRC - rotate right with carry */
7131 /*-----------------------------------------------------------------*/
7135 operand *left, *result;
7138 D (emitcode (";", "genRRC "););
7140 /* rotate right with carry */
7141 left = IC_LEFT (ic);
7142 result = IC_RESULT (ic);
7143 aopOp (left, ic, FALSE, FALSE);
7144 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7146 /* move it to the result */
7147 size = AOP_SIZE (result);
7151 _startLazyDPSEvaluation ();
7154 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7155 emitcode ("rrc", "a");
7156 if (AOP_SIZE (result) > 1)
7157 aopPut (AOP (result), "a", offset--);
7159 _endLazyDPSEvaluation ();
7161 /* now we need to put the carry into the
7162 highest order byte of the result */
7163 if (AOP_SIZE (result) > 1)
7165 MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7167 emitcode ("mov", "acc.7,c");
7168 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7169 freeAsmop (left, NULL, ic, TRUE);
7170 freeAsmop (result, NULL, ic, TRUE);
7173 /*-----------------------------------------------------------------*/
7174 /* genRLC - generate code for rotate left with carry */
7175 /*-----------------------------------------------------------------*/
7179 operand *left, *result;
7183 D (emitcode (";", "genRLC "););
7185 /* rotate right with carry */
7186 left = IC_LEFT (ic);
7187 result = IC_RESULT (ic);
7188 aopOp (left, ic, FALSE, FALSE);
7189 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7191 /* move it to the result */
7192 size = AOP_SIZE (result);
7196 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7198 emitcode ("add", "a,acc");
7199 if (AOP_SIZE (result) > 1)
7201 aopPut (AOP (result), "a", offset++);
7204 _startLazyDPSEvaluation ();
7207 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7209 emitcode ("rlc", "a");
7210 if (AOP_SIZE (result) > 1)
7211 aopPut (AOP (result), "a", offset++);
7213 _endLazyDPSEvaluation ();
7215 /* now we need to put the carry into the
7216 highest order byte of the result */
7217 if (AOP_SIZE (result) > 1)
7219 l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7222 emitcode ("mov", "acc.0,c");
7223 aopPut (AOP (result), "a", 0);
7224 freeAsmop (left, NULL, ic, TRUE);
7225 freeAsmop (result, NULL, ic, TRUE);
7228 /*-----------------------------------------------------------------*/
7229 /* genGetHbit - generates code get highest order bit */
7230 /*-----------------------------------------------------------------*/
7232 genGetHbit (iCode * ic)
7234 operand *left, *result;
7235 left = IC_LEFT (ic);
7236 result = IC_RESULT (ic);
7237 aopOp (left, ic, FALSE, FALSE);
7238 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7240 D (emitcode (";", "genGetHbit "););
7242 /* get the highest order byte into a */
7243 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7244 if (AOP_TYPE (result) == AOP_CRY)
7246 emitcode ("rlc", "a");
7251 emitcode ("rl", "a");
7252 emitcode ("anl", "a,#1");
7257 freeAsmop (left, NULL, ic, TRUE);
7258 freeAsmop (result, NULL, ic, TRUE);
7261 /*-----------------------------------------------------------------*/
7262 /* AccRol - rotate left accumulator by known count */
7263 /*-----------------------------------------------------------------*/
7265 AccRol (int shCount)
7267 shCount &= 0x0007; // shCount : 0..7
7274 emitcode ("rl", "a");
7277 emitcode ("rl", "a");
7278 emitcode ("rl", "a");
7281 emitcode ("swap", "a");
7282 emitcode ("rr", "a");
7285 emitcode ("swap", "a");
7288 emitcode ("swap", "a");
7289 emitcode ("rl", "a");
7292 emitcode ("rr", "a");
7293 emitcode ("rr", "a");
7296 emitcode ("rr", "a");
7301 /*-----------------------------------------------------------------*/
7302 /* AccLsh - left shift accumulator by known count */
7303 /*-----------------------------------------------------------------*/
7305 AccLsh (int shCount)
7310 emitcode ("add", "a,acc");
7311 else if (shCount == 2)
7313 emitcode ("add", "a,acc");
7314 emitcode ("add", "a,acc");
7318 /* rotate left accumulator */
7320 /* and kill the lower order bits */
7321 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7326 /*-----------------------------------------------------------------*/
7327 /* AccRsh - right shift accumulator by known count */
7328 /*-----------------------------------------------------------------*/
7330 AccRsh (int shCount)
7337 emitcode ("rrc", "a");
7341 /* rotate right accumulator */
7342 AccRol (8 - shCount);
7343 /* and kill the higher order bits */
7344 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7349 #ifdef BETTER_LITERAL_SHIFT
7350 /*-----------------------------------------------------------------*/
7351 /* AccSRsh - signed right shift accumulator by known count */
7352 /*-----------------------------------------------------------------*/
7354 AccSRsh (int shCount)
7361 emitcode ("mov", "c,acc.7");
7362 emitcode ("rrc", "a");
7364 else if (shCount == 2)
7366 emitcode ("mov", "c,acc.7");
7367 emitcode ("rrc", "a");
7368 emitcode ("mov", "c,acc.7");
7369 emitcode ("rrc", "a");
7373 tlbl = newiTempLabel (NULL);
7374 /* rotate right accumulator */
7375 AccRol (8 - shCount);
7376 /* and kill the higher order bits */
7377 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7378 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7379 emitcode ("orl", "a,#!constbyte",
7380 (unsigned char) ~SRMask[shCount]);
7381 emitcode ("", "!tlabeldef", tlbl->key + 100);
7387 #ifdef BETTER_LITERAL_SHIFT
7388 /*-----------------------------------------------------------------*/
7389 /* shiftR1Left2Result - shift right one byte from left to result */
7390 /*-----------------------------------------------------------------*/
7392 shiftR1Left2Result (operand * left, int offl,
7393 operand * result, int offr,
7394 int shCount, int sign)
7396 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7397 /* shift right accumulator */
7402 aopPut (AOP (result), "a", offr);
7406 #ifdef BETTER_LITERAL_SHIFT
7407 /*-----------------------------------------------------------------*/
7408 /* shiftL1Left2Result - shift left one byte from left to result */
7409 /*-----------------------------------------------------------------*/
7411 shiftL1Left2Result (operand * left, int offl,
7412 operand * result, int offr, int shCount)
7414 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7415 /* shift left accumulator */
7417 aopPut (AOP (result), "a", offr);
7421 #ifdef BETTER_LITERAL_SHIFT
7422 /*-----------------------------------------------------------------*/
7423 /* movLeft2Result - move byte from left to result */
7424 /*-----------------------------------------------------------------*/
7426 movLeft2Result (operand * left, int offl,
7427 operand * result, int offr, int sign)
7430 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7432 l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
7434 if (*l == '@' && (IS_AOP_PREG (result)))
7436 emitcode ("mov", "a,%s", l);
7437 aopPut (AOP (result), "a", offr);
7443 aopPut (AOP (result), l, offr);
7447 /* MSB sign in acc.7 ! */
7448 if (getDataSize (left) == offl + 1)
7450 emitcode ("mov", "a,%s", l);
7451 aopPut (AOP (result), "a", offr);
7459 #ifdef BETTER_LITERAL_SHIFT
7460 /*-----------------------------------------------------------------*/
7461 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7462 /*-----------------------------------------------------------------*/
7466 emitcode ("rrc", "a");
7467 emitcode ("xch", "a,%s", x);
7468 emitcode ("rrc", "a");
7469 emitcode ("xch", "a,%s", x);
7473 #ifdef BETTER_LITERAL_SHIFT
7475 /*-----------------------------------------------------------------*/
7476 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7477 /*-----------------------------------------------------------------*/
7481 emitcode ("xch", "a,%s", x);
7482 emitcode ("rlc", "a");
7483 emitcode ("xch", "a,%s", x);
7484 emitcode ("rlc", "a");
7488 #ifdef BETTER_LITERAL_SHIFT
7489 /*-----------------------------------------------------------------*/
7490 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7491 /*-----------------------------------------------------------------*/
7495 emitcode ("xch", "a,%s", x);
7496 emitcode ("add", "a,acc");
7497 emitcode ("xch", "a,%s", x);
7498 emitcode ("rlc", "a");
7502 #ifdef BETTER_LITERAL_SHIFT
7503 /*-----------------------------------------------------------------*/
7504 /* AccAXLsh - left shift a:x by known count (0..7) */
7505 /*-----------------------------------------------------------------*/
7507 AccAXLsh (char *x, int shCount)
7522 case 5: // AAAAABBB:CCCCCDDD
7524 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7526 emitcode ("anl", "a,#!constbyte",
7527 SLMask[shCount]); // BBB00000:CCCCCDDD
7529 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7531 AccRol (shCount); // DDDCCCCC:BBB00000
7533 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7535 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7537 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7539 emitcode ("anl", "a,#!constbyte",
7540 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7542 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7544 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7547 case 6: // AAAAAABB:CCCCCCDD
7548 emitcode ("anl", "a,#!constbyte",
7549 SRMask[shCount]); // 000000BB:CCCCCCDD
7550 emitcode ("mov", "c,acc.0"); // c = B
7551 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7553 AccAXRrl1 (x); // BCCCCCCD:D000000B
7554 AccAXRrl1 (x); // BBCCCCCC:DD000000
7556 emitcode("rrc","a");
7557 emitcode("xch","a,%s", x);
7558 emitcode("rrc","a");
7559 emitcode("mov","c,acc.0"); //<< get correct bit
7560 emitcode("xch","a,%s", x);
7562 emitcode("rrc","a");
7563 emitcode("xch","a,%s", x);
7564 emitcode("rrc","a");
7565 emitcode("xch","a,%s", x);
7568 case 7: // a:x <<= 7
7570 emitcode ("anl", "a,#!constbyte",
7571 SRMask[shCount]); // 0000000B:CCCCCCCD
7573 emitcode ("mov", "c,acc.0"); // c = B
7575 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7577 AccAXRrl1 (x); // BCCCCCCC:D0000000
7586 #ifdef BETTER_LITERAL_SHIFT
7588 /*-----------------------------------------------------------------*/
7589 /* AccAXRsh - right shift a:x known count (0..7) */
7590 /*-----------------------------------------------------------------*/
7592 AccAXRsh (char *x, int shCount)
7600 AccAXRrl1 (x); // 0->a:x
7605 AccAXRrl1 (x); // 0->a:x
7608 AccAXRrl1 (x); // 0->a:x
7613 case 5: // AAAAABBB:CCCCCDDD = a:x
7615 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7617 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7619 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7621 emitcode ("anl", "a,#!constbyte",
7622 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7624 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7626 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7628 emitcode ("anl", "a,#!constbyte",
7629 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7631 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7633 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7635 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7638 case 6: // AABBBBBB:CCDDDDDD
7640 emitcode ("mov", "c,acc.7");
7641 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7643 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7645 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7647 emitcode ("anl", "a,#!constbyte",
7648 SRMask[shCount]); // 000000AA:BBBBBBCC
7651 case 7: // ABBBBBBB:CDDDDDDD
7653 emitcode ("mov", "c,acc.7"); // c = A
7655 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7657 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7659 emitcode ("anl", "a,#!constbyte",
7660 SRMask[shCount]); // 0000000A:BBBBBBBC
7669 #ifdef BETTER_LITERAL_SHIFT
7670 /*-----------------------------------------------------------------*/
7671 /* AccAXRshS - right shift signed a:x known count (0..7) */
7672 /*-----------------------------------------------------------------*/
7674 AccAXRshS (char *x, int shCount)
7682 emitcode ("mov", "c,acc.7");
7683 AccAXRrl1 (x); // s->a:x
7687 emitcode ("mov", "c,acc.7");
7688 AccAXRrl1 (x); // s->a:x
7690 emitcode ("mov", "c,acc.7");
7691 AccAXRrl1 (x); // s->a:x
7696 case 5: // AAAAABBB:CCCCCDDD = a:x
7698 tlbl = newiTempLabel (NULL);
7699 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7701 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7703 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7705 emitcode ("anl", "a,#!constbyte",
7706 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7708 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7710 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7712 emitcode ("anl", "a,#!constbyte",
7713 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7715 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7717 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7719 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7721 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7722 emitcode ("orl", "a,#!constbyte",
7723 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7725 emitcode ("", "!tlabeldef", tlbl->key + 100);
7726 break; // SSSSAAAA:BBBCCCCC
7728 case 6: // AABBBBBB:CCDDDDDD
7730 tlbl = newiTempLabel (NULL);
7731 emitcode ("mov", "c,acc.7");
7732 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7734 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7736 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7738 emitcode ("anl", "a,#!constbyte",
7739 SRMask[shCount]); // 000000AA:BBBBBBCC
7741 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7742 emitcode ("orl", "a,#!constbyte",
7743 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7745 emitcode ("", "!tlabeldef", tlbl->key + 100);
7747 case 7: // ABBBBBBB:CDDDDDDD
7749 tlbl = newiTempLabel (NULL);
7750 emitcode ("mov", "c,acc.7"); // c = A
7752 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7754 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7756 emitcode ("anl", "a,#!constbyte",
7757 SRMask[shCount]); // 0000000A:BBBBBBBC
7759 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7760 emitcode ("orl", "a,#!constbyte",
7761 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7763 emitcode ("", "!tlabeldef", tlbl->key + 100);
7771 #ifdef BETTER_LITERAL_SHIFT
7773 _loadLeftIntoAx(char **lsb,
7779 // Get the initial value from left into a pair of registers.
7780 // MSB must be in A, LSB can be any register.
7782 // If the result is held in registers, it is an optimization
7783 // if the LSB can be held in the register which will hold the,
7784 // result LSB since this saves us from having to copy it into
7785 // the result following AccAXLsh.
7787 // If the result is addressed indirectly, this is not a gain.
7788 if (AOP_NEEDSACC(result))
7792 _startLazyDPSEvaluation();
7793 if (AOP_TYPE(left) == AOP_DPTR2)
7796 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
7797 // get LSB in DP2_RESULT_REG.
7798 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
7799 assert(!strcmp(leftByte, DP2_RESULT_REG));
7803 // get LSB into DP2_RESULT_REG
7804 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
7805 if (strcmp(leftByte, DP2_RESULT_REG))
7808 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7811 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
7812 assert(strcmp(leftByte, DP2_RESULT_REG));
7815 _endLazyDPSEvaluation();
7816 *lsb = DP2_RESULT_REG;
7820 if (sameRegs (AOP (result), AOP (left)) &&
7821 ((offl + MSB16) == offr))
7823 /* don't crash result[offr] */
7824 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
7825 emitcode ("xch", "a,%s",
7826 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
7830 movLeft2Result (left, offl, result, offr, 0);
7831 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
7833 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
7834 assert(strcmp(*lsb,"a"));
7839 _storeAxResults(char *lsb,
7843 _startLazyDPSEvaluation();
7844 if (AOP_NEEDSACC(result))
7846 /* We have to explicitly update the result LSB.
7848 emitcode("xch","a,%s", lsb);
7849 aopPut(AOP(result), "a", offr);
7850 emitcode("mov","a,%s", lsb);
7852 if (getDataSize (result) > 1)
7854 aopPut (AOP (result), "a", offr + MSB16);
7856 _endLazyDPSEvaluation();
7859 /*-----------------------------------------------------------------*/
7860 /* shiftL2Left2Result - shift left two bytes from left to result */
7861 /*-----------------------------------------------------------------*/
7863 shiftL2Left2Result (operand * left, int offl,
7864 operand * result, int offr, int shCount)
7868 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7870 AccAXLsh (lsb, shCount);
7872 _storeAxResults(lsb, result, offr);
7876 #ifdef BETTER_LITERAL_SHIFT
7877 /*-----------------------------------------------------------------*/
7878 /* shiftR2Left2Result - shift right two bytes from left to result */
7879 /*-----------------------------------------------------------------*/
7881 shiftR2Left2Result (operand * left, int offl,
7882 operand * result, int offr,
7883 int shCount, int sign)
7887 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7889 /* a:x >> shCount (x = lsb(result)) */
7892 AccAXRshS(lsb, shCount);
7896 AccAXRsh(lsb, shCount);
7899 _storeAxResults(lsb, result, offr);
7905 /*-----------------------------------------------------------------*/
7906 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7907 /*-----------------------------------------------------------------*/
7909 shiftLLeftOrResult (operand * left, int offl,
7910 operand * result, int offr, int shCount)
7912 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7913 /* shift left accumulator */
7915 /* or with result */
7916 emitcode ("orl", "a,%s",
7917 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7918 /* back to result */
7919 aopPut (AOP (result), "a", offr);
7925 /*-----------------------------------------------------------------*/
7926 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7927 /*-----------------------------------------------------------------*/
7929 shiftRLeftOrResult (operand * left, int offl,
7930 operand * result, int offr, int shCount)
7932 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7933 /* shift right accumulator */
7935 /* or with result */
7936 emitcode ("orl", "a,%s",
7937 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7938 /* back to result */
7939 aopPut (AOP (result), "a", offr);
7943 #ifdef BETTER_LITERAL_SHIFT
7944 /*-----------------------------------------------------------------*/
7945 /* genlshOne - left shift a one byte quantity by known count */
7946 /*-----------------------------------------------------------------*/
7948 genlshOne (operand * result, operand * left, int shCount)
7950 D (emitcode (";", "genlshOne "););
7951 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7955 #ifdef BETTER_LITERAL_SHIFT
7956 /*-----------------------------------------------------------------*/
7957 /* genlshTwo - left shift two bytes by known amount != 0 */
7958 /*-----------------------------------------------------------------*/
7960 genlshTwo (operand * result, operand * left, int shCount)
7964 D (emitcode (";", "genlshTwo "););
7966 size = getDataSize (result);
7968 /* if shCount >= 8 */
7973 _startLazyDPSEvaluation();
7979 _endLazyDPSEvaluation();
7980 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7981 aopPut (AOP (result), zero, LSB);
7985 movLeft2Result (left, LSB, result, MSB16, 0);
7986 aopPut (AOP (result), zero, LSB);
7987 _endLazyDPSEvaluation();
7992 aopPut (AOP (result), zero, LSB);
7993 _endLazyDPSEvaluation();
7997 /* 1 <= shCount <= 7 */
8002 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8006 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8014 /*-----------------------------------------------------------------*/
8015 /* shiftLLong - shift left one long from left to result */
8016 /* offl = LSB or MSB16 */
8017 /*-----------------------------------------------------------------*/
8019 shiftLLong (operand * left, operand * result, int offr)
8022 int size = AOP_SIZE (result);
8024 if (size >= LSB + offr)
8026 l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8028 emitcode ("add", "a,acc");
8029 if (sameRegs (AOP (left), AOP (result)) &&
8030 size >= MSB16 + offr && offr != LSB)
8031 emitcode ("xch", "a,%s",
8032 aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8034 aopPut (AOP (result), "a", LSB + offr);
8037 if (size >= MSB16 + offr)
8039 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8041 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8043 emitcode ("rlc", "a");
8044 if (sameRegs (AOP (left), AOP (result)) &&
8045 size >= MSB24 + offr && offr != LSB)
8046 emitcode ("xch", "a,%s",
8047 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8049 aopPut (AOP (result), "a", MSB16 + offr);
8052 if (size >= MSB24 + offr)
8054 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8056 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8058 emitcode ("rlc", "a");
8059 if (sameRegs (AOP (left), AOP (result)) &&
8060 size >= MSB32 + offr && offr != LSB)
8061 emitcode ("xch", "a,%s",
8062 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8064 aopPut (AOP (result), "a", MSB24 + offr);
8067 if (size > MSB32 + offr)
8069 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8071 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8073 emitcode ("rlc", "a");
8074 aopPut (AOP (result), "a", MSB32 + offr);
8077 aopPut (AOP (result), zero, LSB);
8083 /*-----------------------------------------------------------------*/
8084 /* genlshFour - shift four byte by a known amount != 0 */
8085 /*-----------------------------------------------------------------*/
8087 genlshFour (operand * result, operand * left, int shCount)
8091 D (emitcode (";", "genlshFour ");
8094 size = AOP_SIZE (result);
8096 /* if shifting more that 3 bytes */
8101 /* lowest order of left goes to the highest
8102 order of the destination */
8103 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8105 movLeft2Result (left, LSB, result, MSB32, 0);
8106 aopPut (AOP (result), zero, LSB);
8107 aopPut (AOP (result), zero, MSB16);
8108 aopPut (AOP (result), zero, MSB24);
8112 /* more than two bytes */
8113 else if (shCount >= 16)
8115 /* lower order two bytes goes to higher order two bytes */
8117 /* if some more remaining */
8119 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8122 movLeft2Result (left, MSB16, result, MSB32, 0);
8123 movLeft2Result (left, LSB, result, MSB24, 0);
8125 aopPut (AOP (result), zero, MSB16);
8126 aopPut (AOP (result), zero, LSB);
8130 /* if more than 1 byte */
8131 else if (shCount >= 8)
8133 /* lower order three bytes goes to higher order three bytes */
8138 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8140 movLeft2Result (left, LSB, result, MSB16, 0);
8146 movLeft2Result (left, MSB24, result, MSB32, 0);
8147 movLeft2Result (left, MSB16, result, MSB24, 0);
8148 movLeft2Result (left, LSB, result, MSB16, 0);
8149 aopPut (AOP (result), zero, LSB);
8151 else if (shCount == 1)
8152 shiftLLong (left, result, MSB16);
8155 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8156 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8157 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8158 aopPut (AOP (result), zero, LSB);
8163 /* 1 <= shCount <= 7 */
8164 else if (shCount <= 2)
8166 shiftLLong (left, result, LSB);
8168 shiftLLong (result, result, LSB);
8170 /* 3 <= shCount <= 7, optimize */
8173 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8174 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8175 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8180 #ifdef BETTER_LITERAL_SHIFT
8181 /*-----------------------------------------------------------------*/
8182 /* genLeftShiftLiteral - left shifting by known count */
8183 /*-----------------------------------------------------------------*/
8185 genLeftShiftLiteral (operand * left,
8190 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8193 size = getSize (operandType (result));
8195 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8197 /* We only handle certain easy cases so far. */
8199 && (shCount < (size * 8))
8203 D(emitcode (";", "genLeftShiftLiteral wimping out"););
8207 freeAsmop (right, NULL, ic, TRUE);
8209 aopOp(left, ic, FALSE, FALSE);
8210 aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8213 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8215 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8216 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8218 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8221 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8223 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8224 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8226 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8232 emitcode ("; shift left ", "result %d, left %d", size,
8236 /* I suppose that the left size >= result size */
8239 _startLazyDPSEvaluation();
8242 movLeft2Result (left, size, result, size, 0);
8244 _endLazyDPSEvaluation();
8246 else if (shCount >= (size * 8))
8248 _startLazyDPSEvaluation();
8251 aopPut (AOP (result), zero, size);
8253 _endLazyDPSEvaluation();
8260 genlshOne (result, left, shCount);
8264 genlshTwo (result, left, shCount);
8268 genlshFour (result, left, shCount);
8272 fprintf(stderr, "*** ack! mystery literal shift!\n");
8276 freeAsmop (left, NULL, ic, TRUE);
8277 freeAsmop (result, NULL, ic, TRUE);
8282 /*-----------------------------------------------------------------*/
8283 /* genLeftShift - generates code for left shifting */
8284 /*-----------------------------------------------------------------*/
8286 genLeftShift (iCode * ic)
8288 operand *left, *right, *result;
8291 symbol *tlbl, *tlbl1;
8293 D (emitcode (";", "genLeftShift "););
8295 right = IC_RIGHT (ic);
8296 left = IC_LEFT (ic);
8297 result = IC_RESULT (ic);
8299 aopOp (right, ic, FALSE, FALSE);
8302 #ifdef BETTER_LITERAL_SHIFT
8303 /* if the shift count is known then do it
8304 as efficiently as possible */
8305 if (AOP_TYPE (right) == AOP_LIT)
8307 if (genLeftShiftLiteral (left, right, result, ic))
8314 /* shift count is unknown then we have to form
8315 a loop get the loop count in B : Note: we take
8316 only the lower order byte since shifting
8317 more that 32 bits make no sense anyway, ( the
8318 largest size of an object can be only 32 bits ) */
8320 if (AOP_TYPE (right) == AOP_LIT)
8322 /* Really should be handled by genLeftShiftLiteral,
8323 * but since I'm too lazy to fix that today, at least we can make
8324 * some small improvement.
8326 emitcode("mov", "b,#!constbyte",
8327 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8331 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8332 emitcode ("inc", "b");
8334 freeAsmop (right, NULL, ic, TRUE);
8335 aopOp (left, ic, FALSE, FALSE);
8336 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8338 /* now move the left to the result if they are not the
8340 if (!sameRegs (AOP (left), AOP (result)) &&
8341 AOP_SIZE (result) > 1)
8344 size = AOP_SIZE (result);
8346 _startLazyDPSEvaluation ();
8349 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8350 if (*l == '@' && (IS_AOP_PREG (result)))
8353 emitcode ("mov", "a,%s", l);
8354 aopPut (AOP (result), "a", offset);
8357 aopPut (AOP (result), l, offset);
8360 _endLazyDPSEvaluation ();
8363 tlbl = newiTempLabel (NULL);
8364 size = AOP_SIZE (result);
8366 tlbl1 = newiTempLabel (NULL);
8368 /* if it is only one byte then */
8371 symbol *tlbl1 = newiTempLabel (NULL);
8373 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8374 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8375 emitcode ("", "!tlabeldef", tlbl->key + 100);
8376 emitcode ("add", "a,acc");
8377 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8378 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8379 aopPut (AOP (result), "a", 0);
8383 reAdjustPreg (AOP (result));
8385 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8386 emitcode ("", "!tlabeldef", tlbl->key + 100);
8387 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8388 emitcode ("add", "a,acc");
8389 aopPut (AOP (result), "a", offset++);
8390 _startLazyDPSEvaluation ();
8393 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8394 emitcode ("rlc", "a");
8395 aopPut (AOP (result), "a", offset++);
8397 _endLazyDPSEvaluation ();
8398 reAdjustPreg (AOP (result));
8400 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8401 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8403 freeAsmop (left, NULL, ic, TRUE);
8404 freeAsmop (result, NULL, ic, TRUE);
8407 #ifdef BETTER_LITERAL_SHIFT
8408 /*-----------------------------------------------------------------*/
8409 /* genrshOne - right shift a one byte quantity by known count */
8410 /*-----------------------------------------------------------------*/
8412 genrshOne (operand * result, operand * left,
8413 int shCount, int sign)
8415 D (emitcode (";", "genrshOne"););
8416 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8420 #ifdef BETTER_LITERAL_SHIFT
8421 /*-----------------------------------------------------------------*/
8422 /* genrshTwo - right shift two bytes by known amount != 0 */
8423 /*-----------------------------------------------------------------*/
8425 genrshTwo (operand * result, operand * left,
8426 int shCount, int sign)
8428 D (emitcode (";", "genrshTwo"););
8430 /* if shCount >= 8 */
8434 _startLazyDPSEvaluation();
8437 shiftR1Left2Result (left, MSB16, result, LSB,
8442 movLeft2Result (left, MSB16, result, LSB, sign);
8444 addSign (result, MSB16, sign);
8445 _endLazyDPSEvaluation();
8448 /* 1 <= shCount <= 7 */
8451 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8458 /*-----------------------------------------------------------------*/
8459 /* shiftRLong - shift right one long from left to result */
8460 /* offl = LSB or MSB16 */
8461 /*-----------------------------------------------------------------*/
8463 shiftRLong (operand * left, int offl,
8464 operand * result, int sign)
8466 int isSameRegs=sameRegs(AOP(left),AOP(result));
8468 if (isSameRegs && offl>1) {
8469 // we are in big trouble, but this shouldn't happen
8470 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8473 MOVA (aopGet (AOP (left), MSB32, FALSE, NULL));
8478 emitcode ("rlc", "a");
8479 emitcode ("subb", "a,acc");
8480 emitcode ("xch", "a,%s",
8481 aopGet(AOP(left), MSB32, FALSE, DP2_RESULT_REG));
8483 aopPut (AOP(result), zero, MSB32);
8488 emitcode ("clr", "c");
8490 emitcode ("mov", "c,acc.7");
8493 emitcode ("rrc", "a");
8495 if (isSameRegs && offl==MSB16) {
8497 "a,%s",aopGet (AOP (left), MSB24, FALSE, DP2_RESULT_REG));
8499 aopPut (AOP (result), "a", MSB32);
8500 MOVA (aopGet (AOP (left), MSB24, FALSE, NULL));
8503 emitcode ("rrc", "a");
8504 if (isSameRegs && offl==1) {
8505 emitcode ("xch", "a,%s",
8506 aopGet (AOP (left), MSB16, FALSE, DP2_RESULT_REG));
8508 aopPut (AOP (result), "a", MSB24);
8509 MOVA (aopGet (AOP (left), MSB16, FALSE, NULL));
8511 emitcode ("rrc", "a");
8512 aopPut (AOP (result), "a", MSB16 - offl);
8516 MOVA (aopGet (AOP (left), LSB, FALSE, NULL));
8517 emitcode ("rrc", "a");
8518 aopPut (AOP (result), "a", LSB);
8525 /*-----------------------------------------------------------------*/
8526 /* genrshFour - shift four byte by a known amount != 0 */
8527 /*-----------------------------------------------------------------*/
8529 genrshFour (operand * result, operand * left,
8530 int shCount, int sign)
8532 D (emitcode (";", "genrshFour");
8535 /* if shifting more that 3 bytes */
8540 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8542 movLeft2Result (left, MSB32, result, LSB, sign);
8543 addSign (result, MSB16, sign);
8545 else if (shCount >= 16)
8549 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8552 movLeft2Result (left, MSB24, result, LSB, 0);
8553 movLeft2Result (left, MSB32, result, MSB16, sign);
8555 addSign (result, MSB24, sign);
8557 else if (shCount >= 8)
8561 shiftRLong (left, MSB16, result, sign);
8562 else if (shCount == 0)
8564 movLeft2Result (left, MSB16, result, LSB, 0);
8565 movLeft2Result (left, MSB24, result, MSB16, 0);
8566 movLeft2Result (left, MSB32, result, MSB24, sign);
8567 addSign (result, MSB32, sign);
8571 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8572 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8573 /* the last shift is signed */
8574 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8575 addSign (result, MSB32, sign);
8579 { /* 1 <= shCount <= 7 */
8582 shiftRLong (left, LSB, result, sign);
8584 shiftRLong (result, LSB, result, sign);
8588 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8589 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8590 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8596 #ifdef BETTER_LITERAL_SHIFT
8597 /*-----------------------------------------------------------------*/
8598 /* genRightShiftLiteral - right shifting by known count */
8599 /*-----------------------------------------------------------------*/
8601 genRightShiftLiteral (operand * left,
8607 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8610 size = getSize (operandType (result));
8612 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8614 /* We only handle certain easy cases so far. */
8616 && (shCount < (size * 8))
8620 D(emitcode (";", "genRightShiftLiteral wimping out"););
8624 freeAsmop (right, NULL, ic, TRUE);
8626 aopOp (left, ic, FALSE, FALSE);
8627 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8630 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8634 /* test the LEFT size !!! */
8636 /* I suppose that the left size >= result size */
8639 size = getDataSize (result);
8640 _startLazyDPSEvaluation();
8643 movLeft2Result (left, size, result, size, 0);
8645 _endLazyDPSEvaluation();
8647 else if (shCount >= (size * 8))
8651 /* get sign in acc.7 */
8652 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
8654 addSign (result, LSB, sign);
8661 genrshOne (result, left, shCount, sign);
8665 genrshTwo (result, left, shCount, sign);
8669 genrshFour (result, left, shCount, sign);
8676 freeAsmop (left, NULL, ic, TRUE);
8677 freeAsmop (result, NULL, ic, TRUE);
8683 /*-----------------------------------------------------------------*/
8684 /* genSignedRightShift - right shift of signed number */
8685 /*-----------------------------------------------------------------*/
8687 genSignedRightShift (iCode * ic)
8689 operand *right, *left, *result;
8692 symbol *tlbl, *tlbl1;
8694 D (emitcode (";", "genSignedRightShift "););
8696 /* we do it the hard way put the shift count in b
8697 and loop thru preserving the sign */
8699 right = IC_RIGHT (ic);
8700 left = IC_LEFT (ic);
8701 result = IC_RESULT (ic);
8703 aopOp (right, ic, FALSE, FALSE);
8705 #ifdef BETTER_LITERAL_SHIFT
8706 if (AOP_TYPE (right) == AOP_LIT)
8708 if (genRightShiftLiteral (left, right, result, ic, 1))
8714 /* shift count is unknown then we have to form
8715 a loop get the loop count in B : Note: we take
8716 only the lower order byte since shifting
8717 more that 32 bits make no sense anyway, ( the
8718 largest size of an object can be only 32 bits ) */
8720 if (AOP_TYPE (right) == AOP_LIT)
8722 /* Really should be handled by genRightShiftLiteral,
8723 * but since I'm too lazy to fix that today, at least we can make
8724 * some small improvement.
8726 emitcode("mov", "b,#!constbyte",
8727 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8731 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8732 emitcode ("inc", "b");
8734 freeAsmop (right, NULL, ic, TRUE);
8735 aopOp (left, ic, FALSE, FALSE);
8736 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8738 /* now move the left to the result if they are not the
8740 if (!sameRegs (AOP (left), AOP (result)) &&
8741 AOP_SIZE (result) > 1)
8744 size = AOP_SIZE (result);
8746 _startLazyDPSEvaluation ();
8749 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8750 if (*l == '@' && IS_AOP_PREG (result))
8753 emitcode ("mov", "a,%s", l);
8754 aopPut (AOP (result), "a", offset);
8757 aopPut (AOP (result), l, offset);
8760 _endLazyDPSEvaluation ();
8763 /* mov the highest order bit to OVR */
8764 tlbl = newiTempLabel (NULL);
8765 tlbl1 = newiTempLabel (NULL);
8767 size = AOP_SIZE (result);
8769 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
8770 emitcode ("rlc", "a");
8771 emitcode ("mov", "ov,c");
8772 /* if it is only one byte then */
8775 MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8776 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8777 emitcode ("", "!tlabeldef", tlbl->key + 100);
8778 emitcode ("mov", "c,ov");
8779 emitcode ("rrc", "a");
8780 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8781 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8782 aopPut (AOP (result), "a", 0);
8786 reAdjustPreg (AOP (result));
8787 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8788 emitcode ("", "!tlabeldef", tlbl->key + 100);
8789 emitcode ("mov", "c,ov");
8790 _startLazyDPSEvaluation ();
8793 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8794 emitcode ("rrc", "a");
8795 aopPut (AOP (result), "a", offset--);
8797 _endLazyDPSEvaluation ();
8798 reAdjustPreg (AOP (result));
8799 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8800 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8803 freeAsmop (left, NULL, ic, TRUE);
8804 freeAsmop (result, NULL, ic, TRUE);
8807 /*-----------------------------------------------------------------*/
8808 /* genRightShift - generate code for right shifting */
8809 /*-----------------------------------------------------------------*/
8811 genRightShift (iCode * ic)
8813 operand *right, *left, *result;
8817 symbol *tlbl, *tlbl1;
8819 D (emitcode (";", "genRightShift "););
8821 /* if signed then we do it the hard way preserve the
8822 sign bit moving it inwards */
8823 retype = getSpec (operandType (IC_RESULT (ic)));
8825 if (!SPEC_USIGN (retype))
8827 genSignedRightShift (ic);
8831 /* signed & unsigned types are treated the same : i.e. the
8832 signed is NOT propagated inwards : quoting from the
8833 ANSI - standard : "for E1 >> E2, is equivalent to division
8834 by 2**E2 if unsigned or if it has a non-negative value,
8835 otherwise the result is implementation defined ", MY definition
8836 is that the sign does not get propagated */
8838 right = IC_RIGHT (ic);
8839 left = IC_LEFT (ic);
8840 result = IC_RESULT (ic);
8842 aopOp (right, ic, FALSE, FALSE);
8844 #ifdef BETTER_LITERAL_SHIFT
8845 /* if the shift count is known then do it
8846 as efficiently as possible */
8847 if (AOP_TYPE (right) == AOP_LIT)
8849 if (genRightShiftLiteral (left, right, result, ic, 0))
8856 /* shift count is unknown then we have to form
8857 a loop get the loop count in B : Note: we take
8858 only the lower order byte since shifting
8859 more that 32 bits make no sense anyway, ( the
8860 largest size of an object can be only 32 bits ) */
8862 if (AOP_TYPE (right) == AOP_LIT)
8864 /* Really should be handled by genRightShiftLiteral,
8865 * but since I'm too lazy to fix that today, at least we can make
8866 * some small improvement.
8868 emitcode("mov", "b,#!constbyte",
8869 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8873 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8874 emitcode ("inc", "b");
8876 freeAsmop (right, NULL, ic, TRUE);
8877 aopOp (left, ic, FALSE, FALSE);
8878 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8880 /* now move the left to the result if they are not the
8882 if (!sameRegs (AOP (left), AOP (result)) &&
8883 AOP_SIZE (result) > 1)
8886 size = AOP_SIZE (result);
8888 _startLazyDPSEvaluation ();
8891 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8892 if (*l == '@' && IS_AOP_PREG (result))
8895 emitcode ("mov", "a,%s", l);
8896 aopPut (AOP (result), "a", offset);
8899 aopPut (AOP (result), l, offset);
8902 _endLazyDPSEvaluation ();
8905 tlbl = newiTempLabel (NULL);
8906 tlbl1 = newiTempLabel (NULL);
8907 size = AOP_SIZE (result);
8910 /* if it is only one byte then */
8913 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8914 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8915 emitcode ("", "!tlabeldef", tlbl->key + 100);
8917 emitcode ("rrc", "a");
8918 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8919 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8920 aopPut (AOP (result), "a", 0);
8924 reAdjustPreg (AOP (result));
8925 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8926 emitcode ("", "!tlabeldef", tlbl->key + 100);
8928 _startLazyDPSEvaluation ();
8931 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8932 emitcode ("rrc", "a");
8933 aopPut (AOP (result), "a", offset--);
8935 _endLazyDPSEvaluation ();
8936 reAdjustPreg (AOP (result));
8938 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8939 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8942 freeAsmop (left, NULL, ic, TRUE);
8943 freeAsmop (result, NULL, ic, TRUE);
8946 /*-----------------------------------------------------------------*/
8947 /* genUnpackBits - generates code for unpacking bits */
8948 /*-----------------------------------------------------------------*/
8950 genUnpackBits (operand * result, char *rname, int ptype)
8957 D (emitcode (";", "genUnpackBits "););
8959 etype = getSpec (operandType (result));
8961 /* read the first byte */
8967 emitcode ("mov", "a,@%s", rname);
8971 emitcode ("movx", "a,@%s", rname);
8975 emitcode ("movx", "a,@dptr");
8979 emitcode ("clr", "a");
8980 emitcode ("movc", "a,@a+dptr");
8984 emitcode ("lcall", "__gptrget");
8988 /* if we have bitdisplacement then it fits */
8989 /* into this byte completely or if length is */
8990 /* less than a byte */
8991 if (((shCnt = SPEC_BSTR (etype)) != 0) || (SPEC_BLEN (etype) <= 8))
8994 /* shift right acc */
8997 emitcode ("anl", "a,#!constbyte",
8998 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8999 aopPut (AOP (result), "a", offset);
9003 /* bit field did not fit in a byte */
9004 rlen = SPEC_BLEN (etype) - 8;
9005 aopPut (AOP (result), "a", offset++);
9014 emitcode ("inc", "%s", rname);
9015 emitcode ("mov", "a,@%s", rname);
9019 emitcode ("inc", "%s", rname);
9020 emitcode ("movx", "a,@%s", rname);
9024 emitcode ("inc", "dptr");
9025 emitcode ("movx", "a,@dptr");
9029 emitcode ("clr", "a");
9030 emitcode ("inc", "dptr");
9031 emitcode ("movc", "a,@a+dptr");
9035 emitcode ("inc", "dptr");
9036 emitcode ("lcall", "__gptrget");
9041 /* if we are done */
9045 aopPut (AOP (result), "a", offset++);
9051 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (rlen));
9052 aopPut (AOP (result), "a", offset);
9059 /*-----------------------------------------------------------------*/
9060 /* genDataPointerGet - generates code when ptr offset is known */
9061 /*-----------------------------------------------------------------*/
9063 genDataPointerGet (operand * left,
9069 int size, offset = 0;
9070 aopOp (result, ic, TRUE, FALSE);
9072 /* get the string representation of the name */
9073 l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9074 size = AOP_SIZE (result);
9075 _startLazyDPSEvaluation ();
9080 SNPRINTF (buff, sizeof(buff),
9081 "(%s + %d)", l + 1, offset);
9085 SNPRINTF (buff, sizeof(buff),
9088 aopPut (AOP (result), buff, offset++);
9090 _endLazyDPSEvaluation ();
9092 freeAsmop (left, NULL, ic, TRUE);
9093 freeAsmop (result, NULL, ic, TRUE);
9096 /*-----------------------------------------------------------------*/
9097 /* genNearPointerGet - emitcode for near pointer fetch */
9098 /*-----------------------------------------------------------------*/
9100 genNearPointerGet (operand * left,
9108 sym_link *rtype, *retype, *letype;
9109 sym_link *ltype = operandType (left);
9112 rtype = operandType (result);
9113 retype = getSpec (rtype);
9114 letype = getSpec (ltype);
9116 aopOp (left, ic, FALSE, FALSE);
9118 /* if left is rematerialisable and
9119 result is not bit variable type and
9120 the left is pointer to data space i.e
9121 lower 128 bytes of space */
9122 if (AOP_TYPE (left) == AOP_IMMD &&
9123 !IS_BITVAR (retype) &&
9124 !IS_BITVAR (letype) &&
9125 DCL_TYPE (ltype) == POINTER)
9127 genDataPointerGet (left, result, ic);
9131 /* if the value is already in a pointer register
9132 then don't need anything more */
9133 if (!AOP_INPREG (AOP (left)))
9135 /* otherwise get a free pointer register */
9137 preg = getFreePtr (ic, &aop, FALSE);
9138 emitcode ("mov", "%s,%s",
9140 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9144 rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9146 freeAsmop (left, NULL, ic, TRUE);
9147 aopOp (result, ic, FALSE, FALSE);
9149 /* if bitfield then unpack the bits */
9150 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9151 genUnpackBits (result, rname, POINTER);
9154 /* we have can just get the values */
9155 int size = AOP_SIZE (result);
9160 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9163 emitcode ("mov", "a,@%s", rname);
9164 aopPut (AOP (result), "a", offset);
9168 SNPRINTF (buff, sizeof(buff), "@%s", rname);
9169 aopPut (AOP (result), buff, offset);
9174 emitcode ("inc", "%s", rname);
9179 /* now some housekeeping stuff */
9182 /* we had to allocate for this iCode */
9183 if (pi) { /* post increment present */
9184 aopPut(AOP ( left ),rname,0);
9186 freeAsmop (NULL, aop, ic, TRUE);
9190 /* we did not allocate which means left
9191 already in a pointer register, then
9192 if size > 0 && this could be used again
9193 we have to point it back to where it
9195 if (AOP_SIZE (result) > 1 &&
9196 !OP_SYMBOL (left)->remat &&
9197 (OP_SYMBOL (left)->liveTo > ic->seq ||
9201 int size = AOP_SIZE (result) - 1;
9203 emitcode ("dec", "%s", rname);
9208 freeAsmop (result, NULL, ic, TRUE);
9209 if (pi) pi->generated = 1;
9212 /*-----------------------------------------------------------------*/
9213 /* genPagedPointerGet - emitcode for paged pointer fetch */
9214 /*-----------------------------------------------------------------*/
9216 genPagedPointerGet (operand * left,
9224 sym_link *rtype, *retype, *letype;
9226 rtype = operandType (result);
9227 retype = getSpec (rtype);
9228 letype = getSpec (operandType (left));
9229 aopOp (left, ic, FALSE, FALSE);
9231 /* if the value is already in a pointer register
9232 then don't need anything more */
9233 if (!AOP_INPREG (AOP (left)))
9235 /* otherwise get a free pointer register */
9237 preg = getFreePtr (ic, &aop, FALSE);
9238 emitcode ("mov", "%s,%s",
9240 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9244 rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9246 freeAsmop (left, NULL, ic, TRUE);
9247 aopOp (result, ic, FALSE, FALSE);
9249 /* if bitfield then unpack the bits */
9250 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9251 genUnpackBits (result, rname, PPOINTER);
9254 /* we have can just get the values */
9255 int size = AOP_SIZE (result);
9261 emitcode ("movx", "a,@%s", rname);
9262 aopPut (AOP (result), "a", offset);
9267 emitcode ("inc", "%s", rname);
9271 /* now some housekeeping stuff */
9274 /* we had to allocate for this iCode */
9275 if (pi) aopPut ( AOP (left), rname, 0);
9276 freeAsmop (NULL, aop, ic, TRUE);
9280 /* we did not allocate which means left
9281 already in a pointer register, then
9282 if size > 0 && this could be used again
9283 we have to point it back to where it
9285 if (AOP_SIZE (result) > 1 &&
9286 !OP_SYMBOL (left)->remat &&
9287 (OP_SYMBOL (left)->liveTo > ic->seq ||
9291 int size = AOP_SIZE (result) - 1;
9293 emitcode ("dec", "%s", rname);
9298 freeAsmop (result, NULL, ic, TRUE);
9299 if (pi) pi->generated = 1;
9302 /*-----------------------------------------------------------------*/
9303 /* genFarPointerGet - gget value from far space */
9304 /*-----------------------------------------------------------------*/
9306 genFarPointerGet (operand * left,
9307 operand * result, iCode * ic, iCode *pi)
9309 int size, offset, dopi=1;
9310 sym_link *retype = getSpec (operandType (result));
9311 sym_link *letype = getSpec (operandType (left));
9312 D (emitcode (";", "genFarPointerGet"););
9314 aopOp (left, ic, FALSE, FALSE);
9316 /* if the operand is already in dptr
9317 then we do nothing else we move the value to dptr */
9318 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9320 /* if this is remateriazable */
9321 if (AOP_TYPE (left) == AOP_IMMD)
9323 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9327 /* we need to get it byte by byte */
9328 _startLazyDPSEvaluation ();
9329 if (AOP_TYPE (left) != AOP_DPTR)
9331 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9332 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9333 if (options.model == MODEL_FLAT24)
9334 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9338 /* We need to generate a load to DPTR indirect through DPTR. */
9339 D (emitcode (";", "genFarPointerGet -- indirection special case."););
9340 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9341 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9342 if (options.model == MODEL_FLAT24)
9343 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9344 emitcode ("pop", "dph");
9345 emitcode ("pop", "dpl");
9348 _endLazyDPSEvaluation ();
9351 /* so dptr know contains the address */
9352 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9354 /* if bit then unpack */
9355 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9356 if (AOP_INDPTRn(left)) {
9357 genSetDPTR(AOP(left)->aopu.dptr);
9359 genUnpackBits (result, "dptr", FPOINTER);
9360 if (AOP_INDPTRn(left)) {
9365 size = AOP_SIZE (result);
9368 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9370 genSetDPTR(AOP(left)->aopu.dptr);
9371 emitcode ("movx", "a,@dptr");
9372 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9373 emitcode ("inc", "dptr");
9375 aopPut (AOP (result), "a", offset++);
9378 _startLazyDPSEvaluation ();
9380 if (AOP_INDPTRn(left)) {
9381 genSetDPTR(AOP(left)->aopu.dptr);
9387 emitcode ("movx", "a,@dptr");
9388 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9389 emitcode ("inc", "dptr");
9391 aopPut (AOP (result), "a", offset++);
9393 _endLazyDPSEvaluation ();
9396 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9397 if (!AOP_INDPTRn(left)) {
9398 _startLazyDPSEvaluation ();
9399 aopPut ( AOP (left), "dpl", 0);
9400 aopPut ( AOP (left), "dph", 1);
9401 if (options.model == MODEL_FLAT24)
9402 aopPut ( AOP (left), "dpx", 2);
9403 _endLazyDPSEvaluation ();
9406 } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
9407 AOP_SIZE(result) > 1 &&
9408 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9410 size = AOP_SIZE (result) - 1;
9411 if (AOP_INDPTRn(left)) {
9412 genSetDPTR(AOP(left)->aopu.dptr);
9414 while (size--) emitcode ("lcall","__decdptr");
9415 if (AOP_INDPTRn(left)) {
9420 freeAsmop (left, NULL, ic, TRUE);
9421 freeAsmop (result, NULL, ic, TRUE);
9424 /*-----------------------------------------------------------------*/
9425 /* genCodePointerGet - get value from code space */
9426 /*-----------------------------------------------------------------*/
9428 genCodePointerGet (operand * left,
9429 operand * result, iCode * ic, iCode *pi)
9431 int size, offset, dopi=1;
9432 sym_link *retype = getSpec (operandType (result));
9434 aopOp (left, ic, FALSE, FALSE);
9436 /* if the operand is already in dptr
9437 then we do nothing else we move the value to dptr */
9438 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
9440 /* if this is remateriazable */
9441 if (AOP_TYPE (left) == AOP_IMMD)
9443 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9446 { /* we need to get it byte by byte */
9447 _startLazyDPSEvaluation ();
9448 if (AOP_TYPE (left) != AOP_DPTR)
9450 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9451 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9452 if (options.model == MODEL_FLAT24)
9453 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9457 /* We need to generate a load to DPTR indirect through DPTR. */
9458 D (emitcode (";", "gencodePointerGet -- indirection special case."););
9459 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9460 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9461 if (options.model == MODEL_FLAT24)
9462 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9463 emitcode ("pop", "dph");
9464 emitcode ("pop", "dpl");
9467 _endLazyDPSEvaluation ();
9470 /* so dptr know contains the address */
9471 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9473 /* if bit then unpack */
9474 if (IS_BITVAR (retype)) {
9475 if (AOP_INDPTRn(left)) {
9476 genSetDPTR(AOP(left)->aopu.dptr);
9478 genUnpackBits (result, "dptr", CPOINTER);
9479 if (AOP_INDPTRn(left)) {
9484 size = AOP_SIZE (result);
9486 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9488 genSetDPTR(AOP(left)->aopu.dptr);
9489 emitcode ("clr", "a");
9490 emitcode ("movc", "a,@a+dptr");
9491 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9492 emitcode ("inc", "dptr");
9494 aopPut (AOP (result), "a", offset++);
9497 _startLazyDPSEvaluation ();
9500 if (AOP_INDPTRn(left)) {
9501 genSetDPTR(AOP(left)->aopu.dptr);
9507 emitcode ("clr", "a");
9508 emitcode ("movc", "a,@a+dptr");
9509 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9510 emitcode ("inc", "dptr");
9511 aopPut (AOP (result), "a", offset++);
9513 _endLazyDPSEvaluation ();
9516 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9517 if (!AOP_INDPTRn(left)) {
9518 _startLazyDPSEvaluation ();
9520 aopPut ( AOP (left), "dpl", 0);
9521 aopPut ( AOP (left), "dph", 1);
9522 if (options.model == MODEL_FLAT24)
9523 aopPut ( AOP (left), "dpx", 2);
9525 _endLazyDPSEvaluation ();
9528 } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
9529 AOP_SIZE(result) > 1 &&
9530 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9532 size = AOP_SIZE (result) - 1;
9533 if (AOP_INDPTRn(left)) {
9534 genSetDPTR(AOP(left)->aopu.dptr);
9536 while (size--) emitcode ("lcall","__decdptr");
9537 if (AOP_INDPTRn(left)) {
9542 freeAsmop (left, NULL, ic, TRUE);
9543 freeAsmop (result, NULL, ic, TRUE);
9546 /*-----------------------------------------------------------------*/
9547 /* genGenPointerGet - gget value from generic pointer space */
9548 /*-----------------------------------------------------------------*/
9550 genGenPointerGet (operand * left,
9551 operand * result, iCode * ic, iCode * pi)
9554 sym_link *retype = getSpec (operandType (result));
9555 sym_link *letype = getSpec (operandType (left));
9557 D (emitcode (";", "genGenPointerGet "); );
9559 aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
9561 /* if the operand is already in dptr
9562 then we do nothing else we move the value to dptr */
9563 if (AOP_TYPE (left) != AOP_STR)
9565 /* if this is remateriazable */
9566 if (AOP_TYPE (left) == AOP_IMMD)
9568 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9569 if (AOP(left)->aopu.aop_immd.from_cast_remat)
9571 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
9575 emitcode ("mov", "b,#%d", pointerCode (retype));
9579 { /* we need to get it byte by byte */
9580 _startLazyDPSEvaluation ();
9581 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
9582 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
9583 if (options.model == MODEL_FLAT24) {
9584 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9585 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
9587 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9589 _endLazyDPSEvaluation ();
9593 /* so dptr-b now contains the address */
9595 aopOp (result, ic, FALSE, TRUE);
9598 /* if bit then unpack */
9599 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9601 genUnpackBits (result, "dptr", GPOINTER);
9605 size = AOP_SIZE (result);
9612 // Get two bytes at a time, results in _AP & A.
9613 // dptr will be incremented ONCE by __gptrgetWord.
9615 // Note: any change here must be coordinated
9616 // with the implementation of __gptrgetWord
9617 // in device/lib/_gptrget.c
9618 emitcode ("lcall", "__gptrgetWord");
9619 aopPut (AOP (result), DP2_RESULT_REG, offset++);
9620 aopPut (AOP (result), "a", offset++);
9625 // Only one byte to get.
9626 emitcode ("lcall", "__gptrget");
9627 aopPut (AOP (result), "a", offset++);
9630 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9632 emitcode ("inc", "dptr");
9637 if (pi && AOP_TYPE (left) != AOP_IMMD) {
9638 _startLazyDPSEvaluation ();
9640 aopPut ( AOP (left), "dpl", 0);
9641 aopPut ( AOP (left), "dph", 1);
9642 if (options.model == MODEL_FLAT24) {
9643 aopPut ( AOP (left), "dpx", 2);
9644 aopPut ( AOP (left), "b", 3);
9645 } else aopPut ( AOP (left), "b", 2);
9647 _endLazyDPSEvaluation ();
9650 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9651 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9653 size = AOP_SIZE (result) - 1;
9654 while (size--) emitcode ("lcall","__decdptr");
9657 freeAsmop (left, NULL, ic, TRUE);
9658 freeAsmop (result, NULL, ic, TRUE);
9661 /*-----------------------------------------------------------------*/
9662 /* genPointerGet - generate code for pointer get */
9663 /*-----------------------------------------------------------------*/
9665 genPointerGet (iCode * ic, iCode *pi)
9667 operand *left, *result;
9668 sym_link *type, *etype;
9671 D (emitcode (";", "genPointerGet ");
9674 left = IC_LEFT (ic);
9675 result = IC_RESULT (ic);
9677 /* depending on the type of pointer we need to
9678 move it to the correct pointer register */
9679 type = operandType (left);
9680 etype = getSpec (type);
9681 /* if left is of type of pointer then it is simple */
9682 if (IS_PTR (type) && !IS_FUNC (type->next))
9683 p_type = DCL_TYPE (type);
9686 /* we have to go by the storage class */
9687 p_type = PTR_TYPE (SPEC_OCLS (etype));
9689 /* special case when cast remat */
9690 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9691 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9692 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9693 type = operandType (left);
9694 p_type = DCL_TYPE (type);
9696 /* now that we have the pointer type we assign
9697 the pointer values */
9703 genNearPointerGet (left, result, ic, pi);
9707 genPagedPointerGet (left, result, ic, pi);
9711 genFarPointerGet (left, result, ic, pi);
9715 genCodePointerGet (left, result, ic, pi);
9719 genGenPointerGet (left, result, ic, pi);
9725 /*-----------------------------------------------------------------*/
9726 /* genPackBits - generates code for packed bit storage */
9727 /*-----------------------------------------------------------------*/
9729 genPackBits (sym_link * etype,
9731 char *rname, int p_type)
9738 blen = SPEC_BLEN (etype);
9739 bstr = SPEC_BSTR (etype);
9741 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9743 /* if the bit lenth is less than or */
9744 /* it exactly fits a byte then */
9745 if (SPEC_BLEN (etype) <= 8)
9747 /* shift left acc */
9748 AccLsh (SPEC_BSTR (etype));
9750 if (SPEC_BLEN (etype) < 8)
9751 { /* if smaller than a byte */
9757 emitcode ("mov", "b,a");
9758 emitcode ("mov", "a,@%s", rname);
9762 emitcode ("mov", "b,a");
9763 emitcode ("movx", "a,@dptr");
9767 emitcode ("push", "b");
9768 emitcode ("push", "acc");
9769 emitcode ("lcall", "__gptrget");
9770 emitcode ("pop", "b");
9774 emitcode ("anl", "a,#!constbyte", (unsigned char)
9775 ((unsigned char) (0xFF << (blen + bstr)) |
9776 (unsigned char) (0xFF >> (8 - bstr))));
9777 emitcode ("orl", "a,b");
9778 if (p_type == GPOINTER)
9779 emitcode ("pop", "b");
9786 emitcode ("mov", "@%s,a", rname);
9790 emitcode ("movx", "@dptr,a");
9794 emitcode ("lcall", "__gptrput");
9799 if (SPEC_BLEN (etype) <= 8)
9802 emitcode ("inc", "%s", rname);
9803 rLen = SPEC_BLEN (etype);
9805 /* now generate for lengths greater than one byte */
9809 l = aopGet (AOP (right), offset++, FALSE, TRUE, NULL);
9821 emitcode ("mov", "@%s,a", rname);
9824 emitcode ("mov", "@%s,%s", rname, l);
9829 emitcode ("movx", "@dptr,a");
9834 emitcode ("lcall", "__gptrput");
9837 emitcode ("inc", "%s", rname);
9842 /* last last was not complete */
9845 /* save the byte & read byte */
9849 emitcode ("mov", "b,a");
9850 emitcode ("mov", "a,@%s", rname);
9854 emitcode ("mov", "b,a");
9855 emitcode ("movx", "a,@dptr");
9859 emitcode ("push", "b");
9860 emitcode ("push", "acc");
9861 emitcode ("lcall", "__gptrget");
9862 emitcode ("pop", "b");
9866 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1 << rLen));
9867 emitcode ("orl", "a,b");
9870 if (p_type == GPOINTER)
9871 emitcode ("pop", "b");
9877 emitcode ("mov", "@%s,a", rname);
9881 emitcode ("movx", "@dptr,a");
9885 emitcode ("lcall", "__gptrput");
9889 /*-----------------------------------------------------------------*/
9890 /* genDataPointerSet - remat pointer to data space */
9891 /*-----------------------------------------------------------------*/
9893 genDataPointerSet (operand * right,
9897 int size, offset = 0;
9900 aopOp (right, ic, FALSE, FALSE);
9902 l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
9903 size = AOP_SIZE (right);
9908 SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
9912 SNPRINTF (buff, sizeof(buff), "%s", l + 1);
9915 emitcode ("mov", "%s,%s", buff,
9916 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9919 freeAsmop (right, NULL, ic, TRUE);
9920 freeAsmop (result, NULL, ic, TRUE);
9923 /*-----------------------------------------------------------------*/
9924 /* genNearPointerSet - emitcode for near pointer put */
9925 /*-----------------------------------------------------------------*/
9927 genNearPointerSet (operand * right,
9934 sym_link *retype, *letype;
9935 sym_link *ptype = operandType (result);
9937 retype = getSpec (operandType (right));
9938 letype = getSpec (ptype);
9940 aopOp (result, ic, FALSE, FALSE);
9942 /* if the result is rematerializable &
9943 in data space & not a bit variable */
9944 if (AOP_TYPE (result) == AOP_IMMD &&
9945 DCL_TYPE (ptype) == POINTER &&
9946 !IS_BITVAR (retype) &&
9947 !IS_BITVAR (letype))
9949 genDataPointerSet (right, result, ic);
9953 /* if the value is already in a pointer register
9954 then don't need anything more */
9955 if (!AOP_INPREG (AOP (result)))
9957 /* otherwise get a free pointer register */
9961 preg = getFreePtr (ic, &aop, FALSE);
9962 emitcode ("mov", "%s,%s",
9964 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
9968 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
9970 aopOp (right, ic, FALSE, FALSE);
9972 /* if bitfield then unpack the bits */
9973 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9974 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9977 /* we have can just get the values */
9978 int size = AOP_SIZE (right);
9983 l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
9987 emitcode ("mov", "@%s,a", rname);
9990 emitcode ("mov", "@%s,%s", rname, l);
9992 emitcode ("inc", "%s", rname);
9997 /* now some housekeeping stuff */
10000 /* we had to allocate for this iCode */
10001 if (pi) aopPut (AOP (result),rname,0);
10002 freeAsmop (NULL, aop, ic, TRUE);
10006 /* we did not allocate which means left
10007 already in a pointer register, then
10008 if size > 0 && this could be used again
10009 we have to point it back to where it
10011 if (AOP_SIZE (right) > 1 &&
10012 !OP_SYMBOL (result)->remat &&
10013 (OP_SYMBOL (result)->liveTo > ic->seq ||
10017 int size = AOP_SIZE (right) - 1;
10019 emitcode ("dec", "%s", rname);
10024 if (pi) pi->generated = 1;
10025 freeAsmop (result, NULL, ic, TRUE);
10026 freeAsmop (right, NULL, ic, TRUE);
10031 /*-----------------------------------------------------------------*/
10032 /* genPagedPointerSet - emitcode for Paged pointer put */
10033 /*-----------------------------------------------------------------*/
10035 genPagedPointerSet (operand * right,
10042 sym_link *retype, *letype;
10044 retype = getSpec (operandType (right));
10045 letype = getSpec (operandType (result));
10047 aopOp (result, ic, FALSE, FALSE);
10049 /* if the value is already in a pointer register
10050 then don't need anything more */
10051 if (!AOP_INPREG (AOP (result)))
10053 /* otherwise get a free pointer register */
10056 aop = newAsmop (0);
10057 preg = getFreePtr (ic, &aop, FALSE);
10058 emitcode ("mov", "%s,%s",
10060 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10061 rname = preg->name;
10064 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10066 aopOp (right, ic, FALSE, FALSE);
10068 /* if bitfield then unpack the bits */
10069 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10070 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
10073 /* we have can just get the values */
10074 int size = AOP_SIZE (right);
10079 MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10081 emitcode ("movx", "@%s,a", rname);
10084 emitcode ("inc", "%s", rname);
10090 /* now some housekeeping stuff */
10093 if (pi) aopPut (AOP (result),rname,0);
10094 /* we had to allocate for this iCode */
10095 freeAsmop (NULL, aop, ic, TRUE);
10099 /* we did not allocate which means left
10100 already in a pointer register, then
10101 if size > 0 && this could be used again
10102 we have to point it back to where it
10104 if (AOP_SIZE (right) > 1 &&
10105 !OP_SYMBOL (result)->remat &&
10106 (OP_SYMBOL (result)->liveTo > ic->seq ||
10110 int size = AOP_SIZE (right) - 1;
10112 emitcode ("dec", "%s", rname);
10117 if (pi) pi->generated = 1;
10118 freeAsmop (result, NULL, ic, TRUE);
10119 freeAsmop (right, NULL, ic, TRUE);
10124 /*-----------------------------------------------------------------*/
10125 /* genFarPointerSet - set value from far space */
10126 /*-----------------------------------------------------------------*/
10128 genFarPointerSet (operand * right,
10129 operand * result, iCode * ic, iCode *pi)
10131 int size, offset, dopi=1;
10132 sym_link *retype = getSpec (operandType (right));
10133 sym_link *letype = getSpec (operandType (result));
10135 aopOp (result, ic, FALSE, FALSE);
10137 /* if the operand is already in dptr
10138 then we do nothing else we move the value to dptr */
10139 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10141 /* if this is remateriazable */
10142 if (AOP_TYPE (result) == AOP_IMMD)
10143 emitcode ("mov", "dptr,%s",
10144 aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10147 /* we need to get it byte by byte */
10148 _startLazyDPSEvaluation ();
10149 if (AOP_TYPE (result) != AOP_DPTR)
10151 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10152 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10153 if (options.model == MODEL_FLAT24)
10154 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10158 /* We need to generate a load to DPTR indirect through DPTR. */
10159 D (emitcode (";", "genFarPointerSet -- indirection special case."););
10161 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10162 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10163 if (options.model == MODEL_FLAT24)
10164 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10165 emitcode ("pop", "dph");
10166 emitcode ("pop", "dpl");
10169 _endLazyDPSEvaluation ();
10172 /* so dptr know contains the address */
10173 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10175 /* if bit then unpack */
10176 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
10177 if (AOP_INDPTRn(result)) {
10178 genSetDPTR(AOP(result)->aopu.dptr);
10180 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
10181 if (AOP_INDPTRn(result)) {
10185 size = AOP_SIZE (right);
10187 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10189 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10191 genSetDPTR(AOP(result)->aopu.dptr);
10192 emitcode ("movx", "@dptr,a");
10193 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10194 emitcode ("inc", "dptr");
10198 _startLazyDPSEvaluation ();
10200 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10202 if (AOP_INDPTRn(result)) {
10203 genSetDPTR(AOP(result)->aopu.dptr);
10209 emitcode ("movx", "@dptr,a");
10210 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10211 emitcode ("inc", "dptr");
10213 _endLazyDPSEvaluation ();
10217 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10218 if (!AOP_INDPTRn(result)) {
10219 _startLazyDPSEvaluation ();
10221 aopPut (AOP(result),"dpl",0);
10222 aopPut (AOP(result),"dph",1);
10223 if (options.model == MODEL_FLAT24)
10224 aopPut (AOP(result),"dpx",2);
10226 _endLazyDPSEvaluation ();
10229 } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
10230 AOP_SIZE(right) > 1 &&
10231 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10233 size = AOP_SIZE (right) - 1;
10234 if (AOP_INDPTRn(result)) {
10235 genSetDPTR(AOP(result)->aopu.dptr);
10237 while (size--) emitcode ("lcall","__decdptr");
10238 if (AOP_INDPTRn(result)) {
10242 freeAsmop (result, NULL, ic, TRUE);
10243 freeAsmop (right, NULL, ic, TRUE);
10246 /*-----------------------------------------------------------------*/
10247 /* genGenPointerSet - set value from generic pointer space */
10248 /*-----------------------------------------------------------------*/
10250 genGenPointerSet (operand * right,
10251 operand * result, iCode * ic, iCode *pi)
10254 sym_link *retype = getSpec (operandType (right));
10255 sym_link *letype = getSpec (operandType (result));
10257 aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10259 /* if the operand is already in dptr
10260 then we do nothing else we move the value to dptr */
10261 if (AOP_TYPE (result) != AOP_STR)
10263 _startLazyDPSEvaluation ();
10264 /* if this is remateriazable */
10265 if (AOP_TYPE (result) == AOP_IMMD)
10267 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10268 if (AOP(result)->aopu.aop_immd.from_cast_remat)
10270 MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10275 "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10279 { /* we need to get it byte by byte */
10280 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10281 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10282 if (options.model == MODEL_FLAT24) {
10283 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10284 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10286 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10289 _endLazyDPSEvaluation ();
10291 /* so dptr + b now contains the address */
10293 aopOp (right, ic, FALSE, TRUE);
10297 /* if bit then unpack */
10298 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10300 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
10304 size = AOP_SIZE (right);
10307 _startLazyDPSEvaluation ();
10312 // Set two bytes at a time, passed in _AP & A.
10313 // dptr will be incremented ONCE by __gptrputWord.
10315 // Note: any change here must be coordinated
10316 // with the implementation of __gptrputWord
10317 // in device/lib/_gptrput.c
10318 emitcode("mov", "_ap, %s",
10319 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10320 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10324 emitcode ("lcall", "__gptrputWord");
10329 // Only one byte to put.
10330 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10334 emitcode ("lcall", "__gptrput");
10337 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10339 emitcode ("inc", "dptr");
10342 _endLazyDPSEvaluation ();
10345 if (pi && AOP_TYPE (result) != AOP_IMMD) {
10346 _startLazyDPSEvaluation ();
10348 aopPut (AOP(result),"dpl",0);
10349 aopPut (AOP(result),"dph",1);
10350 if (options.model == MODEL_FLAT24) {
10351 aopPut (AOP(result),"dpx",2);
10352 aopPut (AOP(result),"b",3);
10354 aopPut (AOP(result),"b",2);
10356 _endLazyDPSEvaluation ();
10359 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10360 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10362 size = AOP_SIZE (right) - 1;
10363 while (size--) emitcode ("lcall","__decdptr");
10365 freeAsmop (result, NULL, ic, TRUE);
10366 freeAsmop (right, NULL, ic, TRUE);
10369 /*-----------------------------------------------------------------*/
10370 /* genPointerSet - stores the value into a pointer location */
10371 /*-----------------------------------------------------------------*/
10373 genPointerSet (iCode * ic, iCode *pi)
10375 operand *right, *result;
10376 sym_link *type, *etype;
10379 D (emitcode (";", "genPointerSet "););
10381 right = IC_RIGHT (ic);
10382 result = IC_RESULT (ic);
10384 /* depending on the type of pointer we need to
10385 move it to the correct pointer register */
10386 type = operandType (result);
10387 etype = getSpec (type);
10388 /* if left is of type of pointer then it is simple */
10389 if (IS_PTR (type) && !IS_FUNC (type->next))
10391 p_type = DCL_TYPE (type);
10395 /* we have to go by the storage class */
10396 p_type = PTR_TYPE (SPEC_OCLS (etype));
10398 /* special case when cast remat */
10399 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10400 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10401 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10402 type = operandType (result);
10403 p_type = DCL_TYPE (type);
10406 /* now that we have the pointer type we assign
10407 the pointer values */
10413 genNearPointerSet (right, result, ic, pi);
10417 genPagedPointerSet (right, result, ic, pi);
10421 genFarPointerSet (right, result, ic, pi);
10425 genGenPointerSet (right, result, ic, pi);
10429 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10430 "genPointerSet: illegal pointer type");
10435 /*-----------------------------------------------------------------*/
10436 /* genIfx - generate code for Ifx statement */
10437 /*-----------------------------------------------------------------*/
10439 genIfx (iCode * ic, iCode * popIc)
10441 operand *cond = IC_COND (ic);
10444 D (emitcode (";", "genIfx "););
10446 aopOp (cond, ic, FALSE, FALSE);
10448 /* get the value into acc */
10449 if (AOP_TYPE (cond) != AOP_CRY)
10458 /* the result is now in the accumulator */
10459 freeAsmop (cond, NULL, ic, TRUE);
10461 /* if there was something to be popped then do it */
10465 /* if the condition is a bit variable */
10466 if (isbit && IS_ITEMP (cond) &&
10469 genIfxJump (ic, SPIL_LOC (cond)->rname);
10471 else if (isbit && !IS_ITEMP (cond))
10473 genIfxJump (ic, OP_SYMBOL (cond)->rname);
10477 genIfxJump (ic, "a");
10483 /*-----------------------------------------------------------------*/
10484 /* genAddrOf - generates code for address of */
10485 /*-----------------------------------------------------------------*/
10487 genAddrOf (iCode * ic)
10489 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10492 D (emitcode (";", "genAddrOf ");
10495 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10497 /* if the operand is on the stack then we
10498 need to get the stack offset of this
10500 if (sym->onStack) {
10502 /* if 10 bit stack */
10503 if (options.stack10bit) {
10505 tsprintf(buff, sizeof(buff),
10506 "#!constbyte",(options.stack_loc >> 16) & 0xff);
10507 /* if it has an offset then we need to compute it */
10508 /* emitcode ("subb", "a,#!constbyte", */
10509 /* -((sym->stack < 0) ? */
10510 /* ((short) (sym->stack - _G.nRegsSaved)) : */
10511 /* ((short) sym->stack)) & 0xff); */
10512 /* emitcode ("mov","b,a"); */
10513 /* emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
10514 /* ((short) (sym->stack - _G.nRegsSaved)) : */
10515 /* ((short) sym->stack)) >> 8) & 0xff); */
10517 emitcode ("mov", "a,_bpx");
10518 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
10519 ((char) (sym->stack - _G.nRegsSaved)) :
10520 ((char) sym->stack )) & 0xff);
10521 emitcode ("mov", "b,a");
10522 emitcode ("mov", "a,_bpx+1");
10523 emitcode ("addc","a,#!constbyte", (((sym->stack < 0) ?
10524 ((short) (sym->stack - _G.nRegsSaved)) :
10525 ((short) sym->stack )) >> 8) & 0xff);
10526 aopPut (AOP (IC_RESULT (ic)), "b", 0);
10527 aopPut (AOP (IC_RESULT (ic)), "a", 1);
10528 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10530 /* we can just move _bp */
10531 aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10532 aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10533 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10536 /* if it has an offset then we need to compute it */
10538 emitcode ("mov", "a,_bp");
10539 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10540 aopPut (AOP (IC_RESULT (ic)), "a", 0);
10542 /* we can just move _bp */
10543 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10545 /* fill the result with zero */
10546 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10549 if (options.stack10bit && size < (FPTRSIZE - 1)) {
10551 "*** warning: pointer to stack var truncated.\n");
10556 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10562 /* object not on stack then we need the name */
10563 size = AOP_SIZE (IC_RESULT (ic));
10568 char s[SDCC_NAME_MAX];
10572 tsprintf(s, sizeof(s), "!his",sym->rname);
10575 tsprintf(s, sizeof(s), "!hihis",sym->rname);
10578 tsprintf(s, sizeof(s), "!hihihis",sym->rname);
10580 default: /* should not need this (just in case) */
10581 SNPRINTF (s, sizeof(s), "#(%s >> %d)",
10588 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10591 aopPut (AOP (IC_RESULT (ic)), s, offset++);
10595 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10599 /*-----------------------------------------------------------------*/
10600 /* genArrayInit - generates code for address of */
10601 /*-----------------------------------------------------------------*/
10603 genArrayInit (iCode * ic)
10605 literalList *iLoop;
10607 int elementSize = 0, eIndex;
10608 unsigned val, lastVal;
10610 operand *left=IC_LEFT(ic);
10612 D (emitcode (";", "genArrayInit "););
10614 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10616 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10618 // Load immediate value into DPTR.
10619 emitcode("mov", "dptr, %s",
10620 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
10622 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10625 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10626 "Unexpected operand to genArrayInit.\n");
10629 // a regression because of SDCCcse.c:1.52
10630 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10631 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10632 if (options.model == MODEL_FLAT24)
10633 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10637 type = operandType(IC_LEFT(ic));
10639 if (type && type->next)
10641 elementSize = getSize(type->next);
10645 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10646 "can't determine element size in genArrayInit.\n");
10650 iLoop = IC_ARRAYILIST(ic);
10655 bool firstpass = TRUE;
10657 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
10658 iLoop->count, (int)iLoop->literalValue, elementSize);
10664 symbol *tlbl = NULL;
10666 count = ix > 256 ? 256 : ix;
10670 tlbl = newiTempLabel (NULL);
10671 if (firstpass || (count & 0xff))
10673 emitcode("mov", "b, #!constbyte", count & 0xff);
10676 emitcode ("", "!tlabeldef", tlbl->key + 100);
10681 for (eIndex = 0; eIndex < elementSize; eIndex++)
10683 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10684 if (val != lastVal)
10686 emitcode("mov", "a, #!constbyte", val);
10690 emitcode("movx", "@dptr, a");
10691 emitcode("inc", "dptr");
10696 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10702 iLoop = iLoop->next;
10705 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10708 /*-----------------------------------------------------------------*/
10709 /* genFarFarAssign - assignment when both are in far space */
10710 /*-----------------------------------------------------------------*/
10712 genFarFarAssign (operand * result, operand * right, iCode * ic)
10714 int size = AOP_SIZE (right);
10716 symbol *rSym = NULL;
10720 /* quick & easy case. */
10721 D(emitcode(";","genFarFarAssign (1 byte case)"););
10722 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
10723 freeAsmop (right, NULL, ic, FALSE);
10724 /* now assign DPTR to result */
10726 aopOp(result, ic, FALSE, FALSE);
10728 aopPut(AOP(result), "a", 0);
10729 freeAsmop(result, NULL, ic, FALSE);
10733 /* See if we've got an underlying symbol to abuse. */
10734 if (IS_SYMOP(result) && OP_SYMBOL(result))
10736 if (IS_TRUE_SYMOP(result))
10738 rSym = OP_SYMBOL(result);
10740 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10742 rSym = OP_SYMBOL(result)->usl.spillLoc;
10746 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10748 /* We can use the '390 auto-toggle feature to good effect here. */
10750 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10751 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
10752 emitcode ("mov", "dptr,#%s", rSym->rname);
10753 /* DP2 = result, DP1 = right, DP1 is current. */
10756 emitcode("movx", "a,@dptr");
10757 emitcode("movx", "@dptr,a");
10760 emitcode("inc", "dptr");
10761 emitcode("inc", "dptr");
10764 emitcode("mov", "dps,#0");
10765 freeAsmop (right, NULL, ic, FALSE);
10767 some alternative code for processors without auto-toggle
10768 no time to test now, so later well put in...kpb
10769 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10770 emitcode("mov", "dps,#1"); /* Select DPTR2. */
10771 emitcode ("mov", "dptr,#%s", rSym->rname);
10772 /* DP2 = result, DP1 = right, DP1 is current. */
10776 emitcode("movx", "a,@dptr");
10778 emitcode("inc", "dptr");
10779 emitcode("inc", "dps");
10780 emitcode("movx", "@dptr,a");
10782 emitcode("inc", "dptr");
10783 emitcode("inc", "dps");
10785 emitcode("mov", "dps,#0");
10786 freeAsmop (right, NULL, ic, FALSE);
10791 D (emitcode (";", "genFarFarAssign"););
10792 aopOp (result, ic, TRUE, TRUE);
10794 _startLazyDPSEvaluation ();
10798 aopPut (AOP (result),
10799 aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
10802 _endLazyDPSEvaluation ();
10803 freeAsmop (result, NULL, ic, FALSE);
10804 freeAsmop (right, NULL, ic, FALSE);
10808 /*-----------------------------------------------------------------*/
10809 /* genAssign - generate code for assignment */
10810 /*-----------------------------------------------------------------*/
10812 genAssign (iCode * ic)
10814 operand *result, *right;
10816 unsigned long lit = 0L;
10818 D (emitcode (";", "genAssign ");
10821 result = IC_RESULT (ic);
10822 right = IC_RIGHT (ic);
10824 /* if they are the same */
10825 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10828 aopOp (right, ic, FALSE, FALSE);
10830 emitcode (";", "genAssign: resultIsFar = %s",
10831 isOperandInFarSpace (result) ?
10834 /* special case both in far space */
10835 if ((AOP_TYPE (right) == AOP_DPTR ||
10836 AOP_TYPE (right) == AOP_DPTR2) &&
10837 /* IS_TRUE_SYMOP(result) && */
10838 isOperandInFarSpace (result))
10840 genFarFarAssign (result, right, ic);
10844 aopOp (result, ic, TRUE, FALSE);
10846 /* if they are the same registers */
10847 if (sameRegs (AOP (right), AOP (result)))
10850 /* if the result is a bit */
10851 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10853 /* if the right size is a literal then
10854 we know what the value is */
10855 if (AOP_TYPE (right) == AOP_LIT)
10857 if (((int) operandLitValue (right)))
10858 aopPut (AOP (result), one, 0);
10860 aopPut (AOP (result), zero, 0);
10864 /* the right is also a bit variable */
10865 if (AOP_TYPE (right) == AOP_CRY)
10867 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10868 aopPut (AOP (result), "c", 0);
10872 /* we need to or */
10874 aopPut (AOP (result), "a", 0);
10878 /* bit variables done */
10880 size = AOP_SIZE (result);
10882 if (AOP_TYPE (right) == AOP_LIT)
10883 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10886 (AOP_TYPE (result) != AOP_REG) &&
10887 (AOP_TYPE (right) == AOP_LIT) &&
10888 !IS_FLOAT (operandType (right)))
10890 _startLazyDPSEvaluation ();
10891 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10893 aopPut (AOP (result),
10894 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10899 /* And now fill the rest with zeros. */
10902 emitcode ("clr", "a");
10906 aopPut (AOP (result), "a", offset++);
10908 _endLazyDPSEvaluation ();
10912 _startLazyDPSEvaluation ();
10915 aopPut (AOP (result),
10916 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10920 _endLazyDPSEvaluation ();
10924 freeAsmop (right, NULL, ic, FALSE);
10925 freeAsmop (result, NULL, ic, TRUE);
10928 /*-----------------------------------------------------------------*/
10929 /* genJumpTab - generates code for jump table */
10930 /*-----------------------------------------------------------------*/
10932 genJumpTab (iCode * ic)
10937 D (emitcode (";", "genJumpTab ");
10940 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10941 /* get the condition into accumulator */
10942 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
10944 /* multiply by four! */
10945 emitcode ("add", "a,acc");
10946 emitcode ("add", "a,acc");
10947 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10949 jtab = newiTempLabel (NULL);
10950 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
10951 emitcode ("jmp", "@a+dptr");
10952 emitcode ("", "!tlabeldef", jtab->key + 100);
10953 /* now generate the jump labels */
10954 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10955 jtab = setNextItem (IC_JTLABELS (ic)))
10956 emitcode ("ljmp", "!tlabel", jtab->key + 100);
10960 /*-----------------------------------------------------------------*/
10961 /* genCast - gen code for casting */
10962 /*-----------------------------------------------------------------*/
10964 genCast (iCode * ic)
10966 operand *result = IC_RESULT (ic);
10967 sym_link *ctype = operandType (IC_LEFT (ic));
10968 sym_link *rtype = operandType (IC_RIGHT (ic));
10969 operand *right = IC_RIGHT (ic);
10972 D (emitcode (";", "genCast "););
10974 /* if they are equivalent then do nothing */
10975 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10978 aopOp (right, ic, FALSE, FALSE);
10979 aopOp (result, ic, FALSE, AOP_USESDPTR(right));
10981 /* if the result is a bit */
10982 // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10983 if (IS_BITVAR(OP_SYMBOL(result)->type))
10985 /* if the right size is a literal then
10986 we know what the value is */
10987 if (AOP_TYPE (right) == AOP_LIT)
10989 if (((int) operandLitValue (right)))
10990 aopPut (AOP (result), one, 0);
10992 aopPut (AOP (result), zero, 0);
10997 /* the right is also a bit variable */
10998 if (AOP_TYPE (right) == AOP_CRY)
11000 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11001 aopPut (AOP (result), "c", 0);
11005 /* we need to or */
11007 aopPut (AOP (result), "a", 0);
11011 /* if they are the same size : or less */
11012 if (AOP_SIZE (result) <= AOP_SIZE (right))
11015 /* if they are in the same place */
11016 if (sameRegs (AOP (right), AOP (result)))
11019 /* if they in different places then copy */
11020 size = AOP_SIZE (result);
11022 _startLazyDPSEvaluation ();
11025 aopPut (AOP (result),
11026 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11030 _endLazyDPSEvaluation ();
11035 /* if the result is of type pointer */
11036 if (IS_PTR (ctype))
11040 sym_link *type = operandType (right);
11042 /* pointer to generic pointer */
11043 if (IS_GENPTR (ctype))
11047 p_type = DCL_TYPE (type);
11051 #if OLD_CAST_BEHAVIOR
11052 /* KV: we are converting a non-pointer type to
11053 * a generic pointer. This (ifdef'd out) code
11054 * says that the resulting generic pointer
11055 * should have the same class as the storage
11056 * location of the non-pointer variable.
11058 * For example, converting an int (which happens
11059 * to be stored in DATA space) to a pointer results
11060 * in a DATA generic pointer; if the original int
11061 * in XDATA space, so will be the resulting pointer.
11063 * I don't like that behavior, and thus this change:
11064 * all such conversions will be forced to XDATA and
11065 * throw a warning. If you want some non-XDATA
11066 * type, or you want to suppress the warning, you
11067 * must go through an intermediate cast, like so:
11069 * char _generic *gp = (char _xdata *)(intVar);
11071 sym_link *etype = getSpec (type);
11073 /* we have to go by the storage class */
11074 if (SPEC_OCLS (etype) != generic)
11076 p_type = PTR_TYPE (SPEC_OCLS (etype));
11081 /* Converting unknown class (i.e. register variable)
11082 * to generic pointer. This is not good, but
11083 * we'll make a guess (and throw a warning).
11086 werror (W_INT_TO_GEN_PTR_CAST);
11090 /* the first two bytes are known */
11091 size = GPTRSIZE - 1;
11093 _startLazyDPSEvaluation ();
11096 aopPut (AOP (result),
11097 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11101 _endLazyDPSEvaluation ();
11103 /* the last byte depending on type */
11105 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11110 // pointerTypeToGPByte will have bitched.
11114 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11115 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11120 /* just copy the pointers */
11121 size = AOP_SIZE (result);
11123 _startLazyDPSEvaluation ();
11126 aopPut (AOP (result),
11127 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11131 _endLazyDPSEvaluation ();
11135 /* so we now know that the size of destination is greater
11136 than the size of the source */
11137 /* we move to result for the size of source */
11138 size = AOP_SIZE (right);
11140 _startLazyDPSEvaluation ();
11143 aopPut (AOP (result),
11144 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11148 _endLazyDPSEvaluation ();
11150 /* now depending on the sign of the source && destination */
11151 size = AOP_SIZE (result) - AOP_SIZE (right);
11152 /* if unsigned or not an integral type */
11153 /* also, if the source is a bit, we don't need to sign extend, because
11154 * it can't possibly have set the sign bit.
11156 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
11160 aopPut (AOP (result), zero, offset++);
11165 /* we need to extend the sign :{ */
11166 MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11167 FALSE, FALSE, NULL));
11168 emitcode ("rlc", "a");
11169 emitcode ("subb", "a,acc");
11171 aopPut (AOP (result), "a", offset++);
11174 /* we are done hurray !!!! */
11177 freeAsmop (right, NULL, ic, TRUE);
11178 freeAsmop (result, NULL, ic, TRUE);
11182 /*-----------------------------------------------------------------*/
11183 /* genDjnz - generate decrement & jump if not zero instrucion */
11184 /*-----------------------------------------------------------------*/
11186 genDjnz (iCode * ic, iCode * ifx)
11188 symbol *lbl, *lbl1;
11192 /* if the if condition has a false label
11193 then we cannot save */
11194 if (IC_FALSE (ifx))
11197 /* if the minus is not of the form
11199 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11200 !IS_OP_LITERAL (IC_RIGHT (ic)))
11203 if (operandLitValue (IC_RIGHT (ic)) != 1)
11206 /* if the size of this greater than one then no
11208 if (getSize (operandType (IC_RESULT (ic))) > 1)
11211 /* otherwise we can save BIG */
11212 D(emitcode(";", "genDjnz"););
11214 lbl = newiTempLabel (NULL);
11215 lbl1 = newiTempLabel (NULL);
11217 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11219 if (AOP_NEEDSACC(IC_RESULT(ic)))
11221 /* If the result is accessed indirectly via
11222 * the accumulator, we must explicitly write
11223 * it back after the decrement.
11225 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11227 if (strcmp(rByte, "a"))
11229 /* Something is hopelessly wrong */
11230 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11231 __FILE__, __LINE__);
11232 /* We can just give up; the generated code will be inefficient,
11233 * but what the hey.
11235 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11238 emitcode ("dec", "%s", rByte);
11239 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11240 emitcode ("jnz", "!tlabel", lbl->key + 100);
11242 else if (IS_AOP_PREG (IC_RESULT (ic)))
11244 emitcode ("dec", "%s",
11245 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11246 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11247 emitcode ("jnz", "!tlabel", lbl->key + 100);
11251 emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11254 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11255 emitcode ("", "!tlabeldef", lbl->key + 100);
11256 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11257 emitcode ("", "!tlabeldef", lbl1->key + 100);
11259 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11260 ifx->generated = 1;
11264 /*-----------------------------------------------------------------*/
11265 /* genReceive - generate code for a receive iCode */
11266 /*-----------------------------------------------------------------*/
11268 genReceive (iCode * ic)
11270 int size = getSize (operandType (IC_RESULT (ic)));
11274 D (emitcode (";", "genReceive "););
11276 if (ic->argreg == 1)
11278 /* first parameter */
11279 if (AOP_IS_STR(IC_RESULT(ic)))
11281 /* Nothing to do: it's already in the proper place. */
11288 useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11289 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11290 IS_TRUE_SYMOP (IC_RESULT (ic)));
11293 aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11296 /* Sanity checking... */
11297 if (AOP_USESDPTR(IC_RESULT(ic)))
11299 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11300 "genReceive got unexpected DPTR.");
11302 assignResultValue (IC_RESULT (ic));
11307 /* second receive onwards */
11308 /* this gets a little tricky since unused recevies will be
11309 eliminated, we have saved the reg in the type field . and
11310 we use that to figure out which register to use */
11311 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11312 rb1off = ic->argreg;
11315 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11318 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11321 /*-----------------------------------------------------------------*/
11322 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
11323 /*-----------------------------------------------------------------*/
11324 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11326 operand *from , *to , *count;
11331 /* we know it has to be 3 parameters */
11332 assert (nparms == 3);
11334 rsave = newBitVect(16);
11335 /* save DPTR if it needs to be saved */
11336 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11337 if (bitVectBitValue(ic->rMask,i))
11338 rsave = bitVectSetBit(rsave,i);
11340 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11341 ds390_rUmaskForOp (IC_RESULT(ic))));
11348 aopOp (from, ic->next, FALSE, FALSE);
11350 /* get from into DPTR1 */
11351 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11352 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11353 if (options.model == MODEL_FLAT24) {
11354 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11357 freeAsmop (from, NULL, ic, FALSE);
11358 aopOp (to, ic, FALSE, FALSE);
11359 /* get "to" into DPTR */
11360 /* if the operand is already in dptr
11361 then we do nothing else we move the value to dptr */
11362 if (AOP_TYPE (to) != AOP_STR) {
11363 /* if already in DPTR then we need to push */
11364 if (AOP_TYPE(to) == AOP_DPTR) {
11365 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11366 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11367 if (options.model == MODEL_FLAT24)
11368 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11369 emitcode ("pop", "dph");
11370 emitcode ("pop", "dpl");
11372 _startLazyDPSEvaluation ();
11373 /* if this is remateriazable */
11374 if (AOP_TYPE (to) == AOP_IMMD) {
11375 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11376 } else { /* we need to get it byte by byte */
11377 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11378 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11379 if (options.model == MODEL_FLAT24) {
11380 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11383 _endLazyDPSEvaluation ();
11386 freeAsmop (to, NULL, ic, FALSE);
11387 _G.dptrInUse = _G.dptr1InUse = 1;
11388 aopOp (count, ic->next->next, FALSE,FALSE);
11389 lbl =newiTempLabel(NULL);
11391 /* now for the actual copy */
11392 if (AOP_TYPE(count) == AOP_LIT &&
11393 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11394 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11396 emitcode ("lcall","__bi_memcpyc2x_s");
11398 emitcode ("lcall","__bi_memcpyx2x_s");
11400 freeAsmop (count, NULL, ic, FALSE);
11402 symbol *lbl1 = newiTempLabel(NULL);
11404 emitcode (";"," Auto increment but no djnz");
11405 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11406 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11407 freeAsmop (count, NULL, ic, FALSE);
11408 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11409 emitcode ("","!tlabeldef",lbl->key+100);
11411 emitcode ("clr","a");
11412 emitcode ("movc", "a,@a+dptr");
11414 emitcode ("movx", "a,@dptr");
11415 emitcode ("movx", "@dptr,a");
11416 emitcode ("inc", "dptr");
11417 emitcode ("inc", "dptr");
11418 emitcode ("mov","a,b");
11419 emitcode ("orl","a,_ap");
11420 emitcode ("jz","!tlabel",lbl1->key+100);
11421 emitcode ("mov","a,_ap");
11422 emitcode ("add","a,#!constbyte",0xFF);
11423 emitcode ("mov","_ap,a");
11424 emitcode ("mov","a,b");
11425 emitcode ("addc","a,#!constbyte",0xFF);
11426 emitcode ("mov","b,a");
11427 emitcode ("sjmp","!tlabel",lbl->key+100);
11428 emitcode ("","!tlabeldef",lbl1->key+100);
11430 emitcode ("mov", "dps,#0");
11431 _G.dptrInUse = _G.dptr1InUse = 0;
11432 unsavermask(rsave);
11436 /*-----------------------------------------------------------------*/
11437 /* genMemcmpX2X - gen code for memcmp xdata to xdata */
11438 /*-----------------------------------------------------------------*/
11439 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11441 operand *from , *to , *count;
11446 /* we know it has to be 3 parameters */
11447 assert (nparms == 3);
11449 rsave = newBitVect(16);
11450 /* save DPTR if it needs to be saved */
11451 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11452 if (bitVectBitValue(ic->rMask,i))
11453 rsave = bitVectSetBit(rsave,i);
11455 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11456 ds390_rUmaskForOp (IC_RESULT(ic))));
11463 aopOp (from, ic->next, FALSE, FALSE);
11465 /* get from into DPTR1 */
11466 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11467 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11468 if (options.model == MODEL_FLAT24) {
11469 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11472 freeAsmop (from, NULL, ic, FALSE);
11473 aopOp (to, ic, FALSE, FALSE);
11474 /* get "to" into DPTR */
11475 /* if the operand is already in dptr
11476 then we do nothing else we move the value to dptr */
11477 if (AOP_TYPE (to) != AOP_STR) {
11478 /* if already in DPTR then we need to push */
11479 if (AOP_TYPE(to) == AOP_DPTR) {
11480 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11481 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11482 if (options.model == MODEL_FLAT24)
11483 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11484 emitcode ("pop", "dph");
11485 emitcode ("pop", "dpl");
11487 _startLazyDPSEvaluation ();
11488 /* if this is remateriazable */
11489 if (AOP_TYPE (to) == AOP_IMMD) {
11490 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11491 } else { /* we need to get it byte by byte */
11492 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11493 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11494 if (options.model == MODEL_FLAT24) {
11495 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11498 _endLazyDPSEvaluation ();
11501 freeAsmop (to, NULL, ic, FALSE);
11502 _G.dptrInUse = _G.dptr1InUse = 1;
11503 aopOp (count, ic->next->next, FALSE,FALSE);
11504 lbl =newiTempLabel(NULL);
11505 lbl2 =newiTempLabel(NULL);
11507 /* now for the actual compare */
11508 if (AOP_TYPE(count) == AOP_LIT &&
11509 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11510 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11512 emitcode("lcall","__bi_memcmpc2x_s");
11514 emitcode("lcall","__bi_memcmpx2x_s");
11515 freeAsmop (count, NULL, ic, FALSE);
11516 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11517 aopPut(AOP(IC_RESULT(ic)),"a",0);
11518 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11520 symbol *lbl1 = newiTempLabel(NULL);
11522 emitcode("push","ar0");
11523 emitcode (";"," Auto increment but no djnz");
11524 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11525 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11526 freeAsmop (count, NULL, ic, FALSE);
11527 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11528 emitcode ("","!tlabeldef",lbl->key+100);
11530 emitcode ("clr","a");
11531 emitcode ("movc", "a,@a+dptr");
11533 emitcode ("movx", "a,@dptr");
11534 emitcode ("mov","r0,a");
11535 emitcode ("movx", "a,@dptr");
11536 emitcode ("clr","c");
11537 emitcode ("subb","a,r0");
11538 emitcode ("jnz","!tlabel",lbl2->key+100);
11539 emitcode ("inc", "dptr");
11540 emitcode ("inc", "dptr");
11541 emitcode ("mov","a,b");
11542 emitcode ("orl","a,_ap");
11543 emitcode ("jz","!tlabel",lbl1->key+100);
11544 emitcode ("mov","a,_ap");
11545 emitcode ("add","a,#!constbyte",0xFF);
11546 emitcode ("mov","_ap,a");
11547 emitcode ("mov","a,b");
11548 emitcode ("addc","a,#!constbyte",0xFF);
11549 emitcode ("mov","b,a");
11550 emitcode ("sjmp","!tlabel",lbl->key+100);
11551 emitcode ("","!tlabeldef",lbl1->key+100);
11552 emitcode ("clr","a");
11553 emitcode ("","!tlabeldef",lbl2->key+100);
11554 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11555 aopPut(AOP(IC_RESULT(ic)),"a",0);
11556 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11557 emitcode("pop","ar0");
11558 emitcode ("mov", "dps,#0");
11560 _G.dptrInUse = _G.dptr1InUse = 0;
11561 unsavermask(rsave);
11565 /*-----------------------------------------------------------------*/
11566 /* genInp - gen code for __builtin_inp read data from a mem mapped */
11567 /* port, first parameter output area second parameter pointer to */
11568 /* port third parameter count */
11569 /*-----------------------------------------------------------------*/
11570 static void genInp( iCode *ic, int nparms, operand **parms)
11572 operand *from , *to , *count;
11577 /* we know it has to be 3 parameters */
11578 assert (nparms == 3);
11580 rsave = newBitVect(16);
11581 /* save DPTR if it needs to be saved */
11582 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11583 if (bitVectBitValue(ic->rMask,i))
11584 rsave = bitVectSetBit(rsave,i);
11586 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11587 ds390_rUmaskForOp (IC_RESULT(ic))));
11594 aopOp (from, ic->next, FALSE, FALSE);
11596 /* get from into DPTR1 */
11597 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11598 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11599 if (options.model == MODEL_FLAT24) {
11600 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11603 freeAsmop (from, NULL, ic, FALSE);
11604 aopOp (to, ic, FALSE, FALSE);
11605 /* get "to" into DPTR */
11606 /* if the operand is already in dptr
11607 then we do nothing else we move the value to dptr */
11608 if (AOP_TYPE (to) != AOP_STR) {
11609 /* if already in DPTR then we need to push */
11610 if (AOP_TYPE(to) == AOP_DPTR) {
11611 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11612 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11613 if (options.model == MODEL_FLAT24)
11614 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11615 emitcode ("pop", "dph");
11616 emitcode ("pop", "dpl");
11618 _startLazyDPSEvaluation ();
11619 /* if this is remateriazable */
11620 if (AOP_TYPE (to) == AOP_IMMD) {
11621 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11622 } else { /* we need to get it byte by byte */
11623 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11624 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11625 if (options.model == MODEL_FLAT24) {
11626 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11629 _endLazyDPSEvaluation ();
11632 freeAsmop (to, NULL, ic, FALSE);
11634 _G.dptrInUse = _G.dptr1InUse = 1;
11635 aopOp (count, ic->next->next, FALSE,FALSE);
11636 lbl =newiTempLabel(NULL);
11638 /* now for the actual copy */
11639 if (AOP_TYPE(count) == AOP_LIT &&
11640 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11641 emitcode (";","OH JOY auto increment with djnz (very fast)");
11642 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11643 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11644 freeAsmop (count, NULL, ic, FALSE);
11645 emitcode ("","!tlabeldef",lbl->key+100);
11646 emitcode ("movx", "a,@dptr"); /* read data from port */
11647 emitcode ("dec","dps"); /* switch to DPTR */
11648 emitcode ("movx", "@dptr,a"); /* save into location */
11649 emitcode ("inc", "dptr"); /* point to next area */
11650 emitcode ("inc","dps"); /* switch to DPTR2 */
11651 emitcode ("djnz","b,!tlabel",lbl->key+100);
11653 symbol *lbl1 = newiTempLabel(NULL);
11655 emitcode (";"," Auto increment but no djnz");
11656 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11657 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11658 freeAsmop (count, NULL, ic, FALSE);
11659 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11660 emitcode ("","!tlabeldef",lbl->key+100);
11661 emitcode ("movx", "a,@dptr");
11662 emitcode ("dec","dps"); /* switch to DPTR */
11663 emitcode ("movx", "@dptr,a");
11664 emitcode ("inc", "dptr");
11665 emitcode ("inc","dps"); /* switch to DPTR2 */
11666 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
11667 /* emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
11668 emitcode ("mov","a,b");
11669 emitcode ("orl","a,_ap");
11670 emitcode ("jz","!tlabel",lbl1->key+100);
11671 emitcode ("mov","a,_ap");
11672 emitcode ("add","a,#!constbyte",0xFF);
11673 emitcode ("mov","_ap,a");
11674 emitcode ("mov","a,b");
11675 emitcode ("addc","a,#!constbyte",0xFF);
11676 emitcode ("mov","b,a");
11677 emitcode ("sjmp","!tlabel",lbl->key+100);
11678 emitcode ("","!tlabeldef",lbl1->key+100);
11680 emitcode ("mov", "dps,#0");
11681 _G.dptrInUse = _G.dptr1InUse = 0;
11682 unsavermask(rsave);
11686 /*-----------------------------------------------------------------*/
11687 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
11688 /* port, first parameter output area second parameter pointer to */
11689 /* port third parameter count */
11690 /*-----------------------------------------------------------------*/
11691 static void genOutp( iCode *ic, int nparms, operand **parms)
11693 operand *from , *to , *count;
11698 /* we know it has to be 3 parameters */
11699 assert (nparms == 3);
11701 rsave = newBitVect(16);
11702 /* save DPTR if it needs to be saved */
11703 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11704 if (bitVectBitValue(ic->rMask,i))
11705 rsave = bitVectSetBit(rsave,i);
11707 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11708 ds390_rUmaskForOp (IC_RESULT(ic))));
11715 aopOp (from, ic->next, FALSE, FALSE);
11717 /* get from into DPTR1 */
11718 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11719 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11720 if (options.model == MODEL_FLAT24) {
11721 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11724 freeAsmop (from, NULL, ic, FALSE);
11725 aopOp (to, ic, FALSE, FALSE);
11726 /* get "to" into DPTR */
11727 /* if the operand is already in dptr
11728 then we do nothing else we move the value to dptr */
11729 if (AOP_TYPE (to) != AOP_STR) {
11730 /* if already in DPTR then we need to push */
11731 if (AOP_TYPE(to) == AOP_DPTR) {
11732 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11733 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11734 if (options.model == MODEL_FLAT24)
11735 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11736 emitcode ("pop", "dph");
11737 emitcode ("pop", "dpl");
11739 _startLazyDPSEvaluation ();
11740 /* if this is remateriazable */
11741 if (AOP_TYPE (to) == AOP_IMMD) {
11742 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11743 } else { /* we need to get it byte by byte */
11744 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11745 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11746 if (options.model == MODEL_FLAT24) {
11747 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11750 _endLazyDPSEvaluation ();
11753 freeAsmop (to, NULL, ic, FALSE);
11755 _G.dptrInUse = _G.dptr1InUse = 1;
11756 aopOp (count, ic->next->next, FALSE,FALSE);
11757 lbl =newiTempLabel(NULL);
11759 /* now for the actual copy */
11760 if (AOP_TYPE(count) == AOP_LIT &&
11761 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11762 emitcode (";","OH JOY auto increment with djnz (very fast)");
11763 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
11764 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11765 emitcode ("","!tlabeldef",lbl->key+100);
11766 emitcode ("movx", "a,@dptr"); /* read data from port */
11767 emitcode ("inc","dps"); /* switch to DPTR2 */
11768 emitcode ("movx", "@dptr,a"); /* save into location */
11769 emitcode ("inc", "dptr"); /* point to next area */
11770 emitcode ("dec","dps"); /* switch to DPTR */
11771 emitcode ("djnz","b,!tlabel",lbl->key+100);
11772 freeAsmop (count, NULL, ic, FALSE);
11774 symbol *lbl1 = newiTempLabel(NULL);
11776 emitcode (";"," Auto increment but no djnz");
11777 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11778 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11779 freeAsmop (count, NULL, ic, FALSE);
11780 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
11781 emitcode ("","!tlabeldef",lbl->key+100);
11782 emitcode ("movx", "a,@dptr");
11783 emitcode ("inc", "dptr");
11784 emitcode ("inc","dps"); /* switch to DPTR2 */
11785 emitcode ("movx", "@dptr,a");
11786 emitcode ("dec","dps"); /* switch to DPTR */
11787 emitcode ("mov","a,b");
11788 emitcode ("orl","a,_ap");
11789 emitcode ("jz","!tlabel",lbl1->key+100);
11790 emitcode ("mov","a,_ap");
11791 emitcode ("add","a,#!constbyte",0xFF);
11792 emitcode ("mov","_ap,a");
11793 emitcode ("mov","a,b");
11794 emitcode ("addc","a,#!constbyte",0xFF);
11795 emitcode ("mov","b,a");
11796 emitcode ("sjmp","!tlabel",lbl->key+100);
11797 emitcode ("","!tlabeldef",lbl1->key+100);
11799 emitcode ("mov", "dps,#0");
11800 _G.dptrInUse = _G.dptr1InUse = 0;
11801 unsavermask(rsave);
11805 /*-----------------------------------------------------------------*/
11806 /* genSwapW - swap lower & high order bytes */
11807 /*-----------------------------------------------------------------*/
11808 static void genSwapW(iCode *ic, int nparms, operand **parms)
11812 assert (nparms==1);
11815 dest=IC_RESULT(ic);
11817 assert(getSize(operandType(src))==2);
11819 aopOp (src, ic, FALSE, FALSE);
11820 emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
11822 MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
11824 freeAsmop (src, NULL, ic, FALSE);
11826 aopOp (dest,ic, FALSE, FALSE);
11827 aopPut(AOP(dest),"b",0);
11828 aopPut(AOP(dest),"a",1);
11829 freeAsmop (dest, NULL, ic, FALSE);
11832 /*-----------------------------------------------------------------*/
11833 /* genMemsetX - gencode for memSetX data */
11834 /*-----------------------------------------------------------------*/
11835 static void genMemsetX(iCode *ic, int nparms, operand **parms)
11837 operand *to , *val , *count;
11843 /* we know it has to be 3 parameters */
11844 assert (nparms == 3);
11850 /* save DPTR if it needs to be saved */
11851 rsave = newBitVect(16);
11852 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11853 if (bitVectBitValue(ic->rMask,i))
11854 rsave = bitVectSetBit(rsave,i);
11856 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11857 ds390_rUmaskForOp (IC_RESULT(ic))));
11860 aopOp (to, ic, FALSE, FALSE);
11861 /* get "to" into DPTR */
11862 /* if the operand is already in dptr
11863 then we do nothing else we move the value to dptr */
11864 if (AOP_TYPE (to) != AOP_STR) {
11865 /* if already in DPTR then we need to push */
11866 if (AOP_TYPE(to) == AOP_DPTR) {
11867 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11868 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11869 if (options.model == MODEL_FLAT24)
11870 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11871 emitcode ("pop", "dph");
11872 emitcode ("pop", "dpl");
11874 _startLazyDPSEvaluation ();
11875 /* if this is remateriazable */
11876 if (AOP_TYPE (to) == AOP_IMMD) {
11877 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11878 } else { /* we need to get it byte by byte */
11879 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11880 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11881 if (options.model == MODEL_FLAT24) {
11882 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11885 _endLazyDPSEvaluation ();
11888 freeAsmop (to, NULL, ic, FALSE);
11890 aopOp (val, ic->next->next, FALSE,FALSE);
11891 aopOp (count, ic->next->next, FALSE,FALSE);
11892 lbl =newiTempLabel(NULL);
11893 /* now for the actual copy */
11894 if (AOP_TYPE(count) == AOP_LIT &&
11895 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11896 l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
11897 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11899 emitcode ("","!tlabeldef",lbl->key+100);
11900 emitcode ("movx", "@dptr,a");
11901 emitcode ("inc", "dptr");
11902 emitcode ("djnz","b,!tlabel",lbl->key+100);
11904 symbol *lbl1 = newiTempLabel(NULL);
11906 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11907 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11908 emitcode ("","!tlabeldef",lbl->key+100);
11909 MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
11910 emitcode ("movx", "@dptr,a");
11911 emitcode ("inc", "dptr");
11912 emitcode ("mov","a,b");
11913 emitcode ("orl","a,_ap");
11914 emitcode ("jz","!tlabel",lbl1->key+100);
11915 emitcode ("mov","a,_ap");
11916 emitcode ("add","a,#!constbyte",0xFF);
11917 emitcode ("mov","_ap,a");
11918 emitcode ("mov","a,b");
11919 emitcode ("addc","a,#!constbyte",0xFF);
11920 emitcode ("mov","b,a");
11921 emitcode ("sjmp","!tlabel",lbl->key+100);
11922 emitcode ("","!tlabeldef",lbl1->key+100);
11924 freeAsmop (count, NULL, ic, FALSE);
11925 unsavermask(rsave);
11928 /*-----------------------------------------------------------------*/
11929 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
11930 /*-----------------------------------------------------------------*/
11931 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
11934 operand *pnum, *result;
11937 assert (nparms==1);
11938 /* save registers that need to be saved */
11939 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11940 ds390_rUmaskForOp (IC_RESULT(ic))));
11943 aopOp (pnum, ic, FALSE, FALSE);
11944 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
11945 freeAsmop (pnum, NULL, ic, FALSE);
11946 emitcode ("lcall","NatLib_LoadPrimitive");
11947 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11948 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
11949 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
11950 for (i = (size-1) ; i >= 0 ; i-- ) {
11951 emitcode ("push","a%s",javaRet[i]);
11953 for (i=0; i < size ; i++ ) {
11954 emitcode ("pop","a%s",
11955 aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
11958 for (i = 0 ; i < size ; i++ ) {
11959 aopPut(AOP(result),javaRet[i],i);
11962 freeAsmop (result, NULL, ic, FALSE);
11963 unsavermask(rsave);
11966 /*-----------------------------------------------------------------*/
11967 /* genNatLibLoadPointer - calls TINI api function to load pointer */
11968 /*-----------------------------------------------------------------*/
11969 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
11972 operand *pnum, *result;
11976 assert (nparms==1);
11977 /* save registers that need to be saved */
11978 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11979 ds390_rUmaskForOp (IC_RESULT(ic))));
11982 aopOp (pnum, ic, FALSE, FALSE);
11983 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
11984 freeAsmop (pnum, NULL, ic, FALSE);
11985 emitcode ("lcall","NatLib_LoadPointer");
11986 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11987 if (AOP_TYPE(result)!=AOP_STR) {
11988 for (i = 0 ; i < size ; i++ ) {
11989 aopPut(AOP(result),fReturn[i],i);
11992 freeAsmop (result, NULL, ic, FALSE);
11993 unsavermask(rsave);
11996 /*-----------------------------------------------------------------*/
11997 /* genNatLibInstallStateBlock - */
11998 /*-----------------------------------------------------------------*/
11999 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
12000 operand **parms, const char *name)
12003 operand *psb, *handle;
12004 assert (nparms==2);
12006 /* save registers that need to be saved */
12007 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12008 ds390_rUmaskForOp (IC_RESULT(ic))));
12012 /* put pointer to state block into DPTR1 */
12013 aopOp (psb, ic, FALSE, FALSE);
12014 if (AOP_TYPE (psb) == AOP_IMMD) {
12015 emitcode ("mov","dps,#1");
12016 emitcode ("mov", "dptr,%s",
12017 aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12018 emitcode ("mov","dps,#0");
12020 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12021 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12022 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12024 freeAsmop (psb, NULL, ic, FALSE);
12026 /* put libraryID into DPTR */
12027 emitcode ("mov","dptr,#LibraryID");
12029 /* put handle into r3:r2 */
12030 aopOp (handle, ic, FALSE, FALSE);
12031 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12032 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12033 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12034 emitcode ("pop","ar3");
12035 emitcode ("pop","ar2");
12037 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12038 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12040 freeAsmop (psb, NULL, ic, FALSE);
12042 /* make the call */
12043 emitcode ("lcall","NatLib_Install%sStateBlock",name);
12045 /* put return value into place*/
12047 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12049 aopPut(AOP(IC_RESULT(ic)),"a",0);
12050 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12051 unsavermask(rsave);
12054 /*-----------------------------------------------------------------*/
12055 /* genNatLibRemoveStateBlock - */
12056 /*-----------------------------------------------------------------*/
12057 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12063 /* save registers that need to be saved */
12064 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12065 ds390_rUmaskForOp (IC_RESULT(ic))));
12067 /* put libraryID into DPTR */
12068 emitcode ("mov","dptr,#LibraryID");
12069 /* make the call */
12070 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12071 unsavermask(rsave);
12074 /*-----------------------------------------------------------------*/
12075 /* genNatLibGetStateBlock - */
12076 /*-----------------------------------------------------------------*/
12077 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12078 operand **parms,const char *name)
12081 symbol *lbl = newiTempLabel(NULL);
12084 /* save registers that need to be saved */
12085 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12086 ds390_rUmaskForOp (IC_RESULT(ic))));
12088 /* put libraryID into DPTR */
12089 emitcode ("mov","dptr,#LibraryID");
12090 /* make the call */
12091 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12092 emitcode ("jnz","!tlabel",lbl->key+100);
12094 /* put return value into place */
12095 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12096 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12097 emitcode ("push","ar3");
12098 emitcode ("push","ar2");
12099 emitcode ("pop","%s",
12100 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12101 emitcode ("pop","%s",
12102 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12104 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12105 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12107 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12108 emitcode ("","!tlabeldef",lbl->key+100);
12109 unsavermask(rsave);
12112 /*-----------------------------------------------------------------*/
12113 /* genMMMalloc - */
12114 /*-----------------------------------------------------------------*/
12115 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12116 int size, const char *name)
12121 symbol *lbl = newiTempLabel(NULL);
12123 assert (nparms == 1);
12124 /* save registers that need to be saved */
12125 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12126 ds390_rUmaskForOp (IC_RESULT(ic))));
12129 aopOp (bsize,ic,FALSE,FALSE);
12131 /* put the size in R4-R2 */
12132 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12133 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12134 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12136 emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12137 emitcode("pop","ar4");
12139 emitcode("pop","ar3");
12140 emitcode("pop","ar2");
12142 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12143 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12145 emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12148 freeAsmop (bsize, NULL, ic, FALSE);
12150 /* make the call */
12151 emitcode ("lcall","MM_%s",name);
12152 emitcode ("jz","!tlabel",lbl->key+100);
12153 emitcode ("mov","r2,#!constbyte",0xff);
12154 emitcode ("mov","r3,#!constbyte",0xff);
12155 emitcode ("","!tlabeldef",lbl->key+100);
12156 /* we don't care about the pointer : we just save the handle */
12157 rsym = OP_SYMBOL(IC_RESULT(ic));
12158 if (rsym->liveFrom != rsym->liveTo) {
12159 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12160 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12161 emitcode ("push","ar3");
12162 emitcode ("push","ar2");
12163 emitcode ("pop","%s",
12164 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12165 emitcode ("pop","%s",
12166 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12168 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12169 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12171 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12173 unsavermask(rsave);
12176 /*-----------------------------------------------------------------*/
12178 /*-----------------------------------------------------------------*/
12179 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12184 assert (nparms == 1);
12185 /* save registers that need to be saved */
12186 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12187 ds390_rUmaskForOp (IC_RESULT(ic))));
12190 aopOp (handle,ic,FALSE,FALSE);
12192 /* put the size in R4-R2 */
12193 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12194 emitcode("push","%s",
12195 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12196 emitcode("push","%s",
12197 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12198 emitcode("pop","ar3");
12199 emitcode("pop","ar2");
12201 emitcode ("mov","r2,%s",
12202 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12203 emitcode ("mov","r3,%s",
12204 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12206 freeAsmop (handle, NULL, ic, FALSE);
12208 /* make the call */
12209 emitcode ("lcall","MM_Deref");
12212 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12213 if (rsym->liveFrom != rsym->liveTo) {
12214 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12215 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12216 _startLazyDPSEvaluation ();
12218 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12219 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12220 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12222 _endLazyDPSEvaluation ();
12227 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12228 unsavermask(rsave);
12231 /*-----------------------------------------------------------------*/
12232 /* genMMUnrestrictedPersist - */
12233 /*-----------------------------------------------------------------*/
12234 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12239 assert (nparms == 1);
12240 /* save registers that need to be saved */
12241 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12242 ds390_rUmaskForOp (IC_RESULT(ic))));
12245 aopOp (handle,ic,FALSE,FALSE);
12247 /* put the size in R3-R2 */
12248 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12249 emitcode("push","%s",
12250 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12251 emitcode("push","%s",
12252 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12253 emitcode("pop","ar3");
12254 emitcode("pop","ar2");
12256 emitcode ("mov","r2,%s",
12257 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12258 emitcode ("mov","r3,%s",
12259 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12261 freeAsmop (handle, NULL, ic, FALSE);
12263 /* make the call */
12264 emitcode ("lcall","MM_UnrestrictedPersist");
12267 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12268 if (rsym->liveFrom != rsym->liveTo) {
12269 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12270 aopPut(AOP(IC_RESULT(ic)),"a",0);
12271 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12274 unsavermask(rsave);
12277 /*-----------------------------------------------------------------*/
12278 /* genSystemExecJavaProcess - */
12279 /*-----------------------------------------------------------------*/
12280 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12283 operand *handle, *pp;
12285 assert (nparms==2);
12286 /* save registers that need to be saved */
12287 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12288 ds390_rUmaskForOp (IC_RESULT(ic))));
12293 /* put the handle in R3-R2 */
12294 aopOp (handle,ic,FALSE,FALSE);
12295 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12296 emitcode("push","%s",
12297 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12298 emitcode("push","%s",
12299 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12300 emitcode("pop","ar3");
12301 emitcode("pop","ar2");
12303 emitcode ("mov","r2,%s",
12304 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12305 emitcode ("mov","r3,%s",
12306 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12308 freeAsmop (handle, NULL, ic, FALSE);
12310 /* put pointer in DPTR */
12311 aopOp (pp,ic,FALSE,FALSE);
12312 if (AOP_TYPE(pp) == AOP_IMMD) {
12313 emitcode ("mov", "dptr,%s",
12314 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12315 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12316 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12317 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12318 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12320 freeAsmop (handle, NULL, ic, FALSE);
12322 /* make the call */
12323 emitcode ("lcall","System_ExecJavaProcess");
12325 /* put result in place */
12327 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12328 if (rsym->liveFrom != rsym->liveTo) {
12329 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12330 aopPut(AOP(IC_RESULT(ic)),"a",0);
12331 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12335 unsavermask(rsave);
12338 /*-----------------------------------------------------------------*/
12339 /* genSystemRTCRegisters - */
12340 /*-----------------------------------------------------------------*/
12341 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12347 assert (nparms==1);
12348 /* save registers that need to be saved */
12349 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12350 ds390_rUmaskForOp (IC_RESULT(ic))));
12353 /* put pointer in DPTR */
12354 aopOp (pp,ic,FALSE,FALSE);
12355 if (AOP_TYPE (pp) == AOP_IMMD) {
12356 emitcode ("mov","dps,#1");
12357 emitcode ("mov", "dptr,%s",
12358 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12359 emitcode ("mov","dps,#0");
12361 emitcode ("mov","dpl1,%s",
12362 aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12363 emitcode ("mov","dph1,%s",
12364 aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12365 emitcode ("mov","dpx1,%s",
12366 aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12368 freeAsmop (pp, NULL, ic, FALSE);
12370 /* make the call */
12371 emitcode ("lcall","System_%sRTCRegisters",name);
12373 unsavermask(rsave);
12376 /*-----------------------------------------------------------------*/
12377 /* genSystemThreadSleep - */
12378 /*-----------------------------------------------------------------*/
12379 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12384 assert (nparms==1);
12385 /* save registers that need to be saved */
12386 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12387 ds390_rUmaskForOp (IC_RESULT(ic))));
12390 aopOp(to,ic,FALSE,FALSE);
12391 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12392 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12393 emitcode ("push","%s",
12394 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12395 emitcode ("push","%s",
12396 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12397 emitcode ("push","%s",
12398 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12399 emitcode ("push","%s",
12400 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12401 emitcode ("pop","ar3");
12402 emitcode ("pop","ar2");
12403 emitcode ("pop","ar1");
12404 emitcode ("pop","ar0");
12406 emitcode ("mov","r0,%s",
12407 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12408 emitcode ("mov","r1,%s",
12409 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12410 emitcode ("mov","r2,%s",
12411 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12412 emitcode ("mov","r3,%s",
12413 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12415 freeAsmop (to, NULL, ic, FALSE);
12417 /* suspend in acc */
12419 aopOp(s,ic,FALSE,FALSE);
12420 emitcode ("mov","a,%s",
12421 aopGet(AOP(s),0,FALSE,TRUE,NULL));
12422 freeAsmop (s, NULL, ic, FALSE);
12424 /* make the call */
12425 emitcode ("lcall","System_%s",name);
12427 unsavermask(rsave);
12430 /*-----------------------------------------------------------------*/
12431 /* genSystemThreadResume - */
12432 /*-----------------------------------------------------------------*/
12433 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12438 assert (nparms==2);
12439 /* save registers that need to be saved */
12440 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12441 ds390_rUmaskForOp (IC_RESULT(ic))));
12447 aopOp(pid,ic,FALSE,FALSE);
12448 emitcode ("mov","r0,%s",
12449 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12450 freeAsmop (pid, NULL, ic, FALSE);
12453 aopOp(tid,ic,FALSE,FALSE);
12454 emitcode ("mov","a,%s",
12455 aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
12456 freeAsmop (tid, NULL, ic, FALSE);
12458 emitcode ("lcall","System_ThreadResume");
12460 /* put result into place */
12462 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12463 if (rsym->liveFrom != rsym->liveTo) {
12464 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12465 aopPut(AOP(IC_RESULT(ic)),"a",0);
12466 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12469 unsavermask(rsave);
12472 /*-----------------------------------------------------------------*/
12473 /* genSystemProcessResume - */
12474 /*-----------------------------------------------------------------*/
12475 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
12480 assert (nparms==1);
12481 /* save registers that need to be saved */
12482 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12483 ds390_rUmaskForOp (IC_RESULT(ic))));
12488 aopOp(pid,ic,FALSE,FALSE);
12489 emitcode ("mov","a,%s",
12490 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12491 freeAsmop (pid, NULL, ic, FALSE);
12493 emitcode ("lcall","System_ProcessResume");
12495 unsavermask(rsave);
12498 /*-----------------------------------------------------------------*/
12500 /*-----------------------------------------------------------------*/
12501 static void genSystem (iCode *ic,int nparms,char *name)
12503 assert(nparms == 0);
12505 emitcode ("lcall","System_%s",name);
12508 /*-----------------------------------------------------------------*/
12509 /* genSystemPoll - */
12510 /*-----------------------------------------------------------------*/
12511 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
12516 assert (nparms==1);
12517 /* save registers that need to be saved */
12518 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12519 ds390_rUmaskForOp (IC_RESULT(ic))));
12522 aopOp (fp,ic,FALSE,FALSE);
12523 if (AOP_TYPE (fp) == AOP_IMMD) {
12524 emitcode ("mov", "dptr,%s",
12525 aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
12526 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
12527 emitcode ("mov","dpl,%s",
12528 aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
12529 emitcode ("mov","dph,%s",
12530 aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
12531 emitcode ("mov","dpx,%s",
12532 aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
12534 freeAsmop (fp, NULL, ic, FALSE);
12536 emitcode ("lcall","System_%sPoll",name);
12538 /* put result into place */
12540 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12541 if (rsym->liveFrom != rsym->liveTo) {
12542 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12543 aopPut(AOP(IC_RESULT(ic)),"a",0);
12544 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12547 unsavermask(rsave);
12550 /*-----------------------------------------------------------------*/
12551 /* genSystemGetCurrentID - */
12552 /*-----------------------------------------------------------------*/
12553 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
12555 assert (nparms==0);
12557 emitcode ("lcall","System_GetCurrent%sId",name);
12558 /* put result into place */
12560 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12561 if (rsym->liveFrom != rsym->liveTo) {
12562 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12563 aopPut(AOP(IC_RESULT(ic)),"a",0);
12564 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12569 /*-----------------------------------------------------------------*/
12570 /* genBuiltIn - calls the appropriate function to generating code */
12571 /* for a built in function */
12572 /*-----------------------------------------------------------------*/
12573 static void genBuiltIn (iCode *ic)
12575 operand *bi_parms[MAX_BUILTIN_ARGS];
12580 /* get all the arguments for a built in function */
12581 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
12583 /* which function is it */
12584 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
12585 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
12586 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
12587 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
12588 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
12589 } else if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
12590 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
12591 } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
12592 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
12593 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
12594 genMemsetX(bi_iCode,nbi_parms,bi_parms);
12595 } else if (strcmp(bif->name,"__builtin_inp")==0) {
12596 genInp(bi_iCode,nbi_parms,bi_parms);
12597 } else if (strcmp(bif->name,"__builtin_outp")==0) {
12598 genOutp(bi_iCode,nbi_parms,bi_parms);
12599 } else if (strcmp(bif->name,"__builtin_swapw")==0) {
12600 genSwapW(bi_iCode,nbi_parms,bi_parms);
12601 /* JavaNative builtIns */
12602 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
12603 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
12604 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
12605 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
12606 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
12607 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
12608 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
12609 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
12610 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
12611 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12612 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
12613 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12614 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
12615 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
12616 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
12617 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
12618 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
12619 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12620 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
12621 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12622 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
12623 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
12624 } else if (strcmp(bif->name,"MM_Malloc")==0) {
12625 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
12626 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
12627 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
12628 } else if (strcmp(bif->name,"MM_Free")==0) {
12629 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
12630 } else if (strcmp(bif->name,"MM_Deref")==0) {
12631 genMMDeref(bi_iCode,nbi_parms,bi_parms);
12632 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
12633 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
12634 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
12635 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
12636 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
12637 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
12638 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
12639 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
12640 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
12641 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
12642 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
12643 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
12644 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
12645 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
12646 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
12647 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
12648 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12649 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12650 } else if (strcmp(bif->name,"System_SaveThread")==0) {
12651 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12652 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12653 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12654 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
12655 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
12656 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
12657 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
12658 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
12659 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
12660 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
12661 genSystem(bi_iCode,nbi_parms,"ProcessYield");
12662 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
12663 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
12664 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
12665 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
12666 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
12667 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
12668 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
12669 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
12670 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
12671 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
12673 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
12679 /*-----------------------------------------------------------------*/
12680 /* gen390Code - generate code for Dallas 390 based controllers */
12681 /*-----------------------------------------------------------------*/
12683 gen390Code (iCode * lic)
12688 lineHead = lineCurr = NULL;
12689 dptrn[1][0] = "dpl1";
12690 dptrn[1][1] = "dph1";
12691 dptrn[1][2] = "dpx1";
12693 if (options.model == MODEL_FLAT24) {
12694 fReturnSizeDS390 = 5;
12695 fReturn = fReturn24;
12697 fReturnSizeDS390 = 4;
12698 fReturn = fReturn16;
12699 options.stack10bit=0;
12702 /* print the allocation information */
12704 printAllocInfo (currFunc, codeOutFile);
12706 /* if debug information required */
12707 if (options.debug && currFunc)
12709 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
12711 if (IS_STATIC (currFunc->etype))
12712 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
12714 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
12717 /* stack pointer name */
12718 if (options.useXstack)
12724 for (ic = lic; ic; ic = ic->next)
12727 if (ic->lineno && cln != ic->lineno)
12732 emitcode ("", "C$%s$%d$%d$%d ==.",
12733 FileBaseName (ic->filename), ic->lineno,
12734 ic->level, ic->block);
12737 if (!options.noCcodeInAsm) {
12738 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
12739 printCLine(ic->filename, ic->lineno));
12743 if (options.iCodeInAsm) {
12744 emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
12746 /* if the result is marked as
12747 spilt and rematerializable or code for
12748 this has already been generated then
12750 if (resultRemat (ic) || ic->generated)
12753 /* depending on the operation */
12773 /* IPOP happens only when trying to restore a
12774 spilt live range, if there is an ifx statement
12775 following this pop then the if statement might
12776 be using some of the registers being popped which
12777 would destory the contents of the register so
12778 we need to check for this condition and handle it */
12780 ic->next->op == IFX &&
12781 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
12782 genIfx (ic->next, ic);
12800 genEndFunction (ic);
12820 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
12837 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
12841 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
12848 /* note these two are xlated by algebraic equivalence
12849 during parsing SDCC.y */
12850 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12851 "got '>=' or '<=' shouldn't have come here");
12855 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
12867 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
12871 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
12875 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
12899 genRightShift (ic);
12902 case GET_VALUE_AT_ADDRESS:
12903 genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
12907 if (POINTER_SET (ic))
12908 genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
12934 if (ic->builtinSEND) genBuiltIn(ic);
12935 else addSet (&_G.sendSet, ic);
12948 /* now we are ready to call the
12949 peep hole optimizer */
12950 if (!options.nopeep)
12951 peepHole (&lineHead);
12953 /* now do the actual printing */
12954 printLine (lineHead, codeOutFile);