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); */
113 #define MOVA(x) { char *_mova_tmp = strdup(x); \
114 if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \
116 emitcode("mov","a,%s",_mova_tmp); \
120 #define CLRC emitcode("clr","c")
121 #define SETC emitcode("setb","c")
123 // A scratch register which will be used to hold
124 // result bytes from operands in far space via DPTR2.
125 #define DP2_RESULT_REG "_ap"
127 static lineNode *lineHead = NULL;
128 static lineNode *lineCurr = NULL;
130 static unsigned char SLMask[] =
131 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
132 0xE0, 0xC0, 0x80, 0x00};
133 static unsigned char SRMask[] =
134 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
135 0x07, 0x03, 0x01, 0x00};
141 #define PROTECT_SP {if (options.protect_sp_update) { \
142 symbol *lbl = newiTempLabel(NULL); \
143 emitcode ("setb","F1"); \
144 emitcode ("jbc","EA,!tlabel",lbl->key+100); \
145 emitcode ("clr","F1"); \
146 emitcode ("","!tlabeldef",lbl->key+100); \
148 #define UNPROTECT_SP { if (options.protect_sp_update) { \
149 symbol *lbl = newiTempLabel(NULL); \
150 emitcode ("jnb","F1,!tlabel",lbl->key+100); \
151 emitcode ("setb","EA"); \
152 emitcode ("","!tlabeldef",lbl->key+100); \
156 /*-----------------------------------------------------------------*/
157 /* emitcode - writes the code into a file : for now it is simple */
158 /*-----------------------------------------------------------------*/
160 emitcode (char *inst, char *fmt,...)
163 char lb[INITIAL_INLINEASM];
172 SNPRINTF (lb, sizeof(lb), "%s\t", inst);
176 SNPRINTF (lb, sizeof(lb), "%s", inst);
179 tvsprintf (lb + strlen(lb), sizeof(lb) - strlen(lb),
184 tvsprintf (lb, sizeof(lb), fmt, ap);
188 while (isspace (*lbp))
195 lineCurr = (lineCurr ?
196 connectLine (lineCurr, newLineNode (lb)) :
197 (lineHead = newLineNode (lb)));
200 lineCurr->isInline = _G.inLine;
201 lineCurr->isDebug = _G.debugLine;
205 /*-----------------------------------------------------------------*/
206 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
207 /*-----------------------------------------------------------------*/
209 getFreePtr (iCode * ic, asmop ** aopp, bool result)
211 bool r0iu = FALSE, r1iu = FALSE;
212 bool r0ou = FALSE, r1ou = FALSE;
214 /* the logic: if r0 & r1 used in the instruction
215 then we are in trouble otherwise */
217 /* first check if r0 & r1 are used by this
218 instruction, in which case we are in trouble */
219 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
220 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
225 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
226 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
228 /* if no usage of r0 then return it */
231 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
232 (*aopp)->type = AOP_R0;
234 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
237 /* if no usage of r1 then return it */
240 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
241 (*aopp)->type = AOP_R1;
243 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
246 /* now we know they both have usage */
247 /* if r0 not used in this instruction */
250 /* push it if not already pushed */
253 emitcode ("push", "%s",
254 ds390_regWithIdx (R0_IDX)->dname);
258 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
259 (*aopp)->type = AOP_R0;
261 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
264 /* if r1 not used then */
268 /* push it if not already pushed */
271 emitcode ("push", "%s",
272 ds390_regWithIdx (R1_IDX)->dname);
276 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
277 (*aopp)->type = AOP_R1;
278 return ds390_regWithIdx (R1_IDX);
282 /* I said end of world but not quite end of world yet */
283 /* if this is a result then we can push it on the stack */
286 (*aopp)->type = AOP_STK;
290 /* other wise this is true end of the world */
291 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
292 "getFreePtr should never reach here");
296 /*-----------------------------------------------------------------*/
297 /* newAsmop - creates a new asmOp */
298 /*-----------------------------------------------------------------*/
300 newAsmop (short type)
304 aop = Safe_calloc (1, sizeof (asmop));
309 static int _currentDPS; /* Current processor DPS. */
310 static int _desiredDPS; /* DPS value compiler thinks we should be using. */
311 static int _lazyDPS = 0; /* if non-zero, we are doing lazy evaluation of DPS changes. */
313 /*-----------------------------------------------------------------*/
314 /* genSetDPTR: generate code to select which DPTR is in use (zero */
315 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390 */
316 /* alternate DPTR (DPL1/DPH1/DPX1). */
317 /*-----------------------------------------------------------------*/
322 /* If we are doing lazy evaluation, simply note the desired
323 * change, but don't emit any code yet.
333 emitcode ("mov", "dps,#0");
338 emitcode ("mov", "dps,#1");
342 /*-----------------------------------------------------------------*/
343 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
345 /* Any code that operates on DPTR (NB: not on the individual */
346 /* components, like DPH) *must* call _flushLazyDPS() before using */
347 /* DPTR within a lazy DPS evaluation block. */
349 /* Note that aopPut and aopGet already contain the proper calls to */
350 /* _flushLazyDPS, so it is safe to use these calls within a lazy */
351 /* DPS evaluation block. */
353 /* Also, _flushLazyDPS must be called before any flow control */
354 /* operations that could potentially branch out of the block. */
356 /* Lazy DPS evaluation is simply an optimization (though an */
357 /* important one), so if in doubt, leave it out. */
358 /*-----------------------------------------------------------------*/
360 _startLazyDPSEvaluation (void)
364 #ifdef BETTER_LITERAL_SHIFT
371 /*-----------------------------------------------------------------*/
372 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
373 /* desired one. Call before using DPTR within a lazy DPS evaluation */
375 /*-----------------------------------------------------------------*/
385 if (_desiredDPS != _currentDPS)
389 emitcode ("inc", "dps");
393 emitcode ("dec", "dps");
395 _currentDPS = _desiredDPS;
399 /*-----------------------------------------------------------------*/
400 /* _endLazyDPSEvaluation: end lazy DPS evaluation block. */
402 /* Forces us back to the safe state (standard DPTR selected). */
403 /*-----------------------------------------------------------------*/
405 _endLazyDPSEvaluation (void)
407 #ifdef BETTER_LITERAL_SHIFT
426 /*-----------------------------------------------------------------*/
427 /* pointerCode - returns the code for a pointer type */
428 /*-----------------------------------------------------------------*/
430 pointerCode (sym_link * etype)
433 return PTR_TYPE (SPEC_OCLS (etype));
437 /*-----------------------------------------------------------------*/
438 /* aopForSym - for a true symbol */
439 /*-----------------------------------------------------------------*/
441 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
444 memmap *space = SPEC_OCLS (sym->etype);
446 /* if already has one */
450 /* assign depending on the storage class */
451 /* if it is on the stack or indirectly addressable */
452 /* space we need to assign either r0 or r1 to it */
453 if ((sym->onStack && !options.stack10bit) || sym->iaccess)
455 sym->aop = aop = newAsmop (0);
456 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
457 aop->size = getSize (sym->type);
459 /* now assign the address of the variable to
460 the pointer register */
461 if (aop->type != AOP_STK)
467 emitcode ("push", "acc");
470 emitcode ("push", "b");
472 emitcode ("mov", "a,_bp");
473 emitcode ("add", "a,#!constbyte",
475 ((char) (sym->stack - _G.nRegsSaved)) :
476 ((char) sym->stack)) & 0xff);
477 emitcode ("mov", "%s,a",
478 aop->aopu.aop_ptr->name);
481 emitcode ("pop", "b");
484 emitcode ("pop", "acc");
487 emitcode ("mov", "%s,#%s",
488 aop->aopu.aop_ptr->name,
490 aop->paged = space->paged;
493 aop->aopu.aop_stk = sym->stack;
497 if (sym->onStack && options.stack10bit)
499 short stack_val = -((sym->stack < 0) ?
500 ((short) (sym->stack - _G.nRegsSaved)) :
501 ((short) sym->stack)) ;
502 if (useDP2 && _G.dptr1InUse) {
503 emitcode ("push","dpl1");
504 emitcode ("push","dph1");
505 emitcode ("push","dpx1");
506 } else if (_G.dptrInUse ) {
507 emitcode ("push","dpl");
508 emitcode ("push","dph");
509 emitcode ("push","dpx");
511 /* It's on the 10 bit stack, which is located in
514 if (stack_val < 0 && stack_val > -5) { /* between -5 & -1 */
516 if (options.model == MODEL_FLAT24)
517 emitcode ("mov", "dpx1,#!constbyte", (options.stack_loc >> 16) & 0xff);
519 emitcode ("mov", "dph1,_bpx+1");
520 emitcode ("mov", "dpl1,_bpx");
521 emitcode ("mov","dps,#1");
523 if (options.model == MODEL_FLAT24)
524 emitcode ("mov", "dpx,#!constbyte", (options.stack_loc >> 16) & 0xff);
525 emitcode ("mov", "dph,_bpx+1");
526 emitcode ("mov", "dpl,_bpx");
528 stack_val = -stack_val;
529 while (stack_val--) {
530 emitcode ("inc","dptr");
533 emitcode("mov","dps,#0");
537 emitcode ("push", "acc");
540 emitcode ("push", "b");
542 emitcode ("mov", "a,_bpx");
543 emitcode ("clr","c");
544 emitcode ("subb", "a,#!constbyte", stack_val & 0xff);
545 emitcode ("mov","b,a");
546 emitcode ("mov","a,_bpx+1");
547 emitcode ("subb","a,#!constbyte",(stack_val >> 8) & 0xff);
549 if (options.model == MODEL_FLAT24)
550 emitcode ("mov", "dpx1,#!constbyte", (options.stack_loc >> 16) & 0xff);
552 emitcode ("mov", "dph1,a");
553 emitcode ("mov", "dpl1,b");
555 if (options.model == MODEL_FLAT24)
556 emitcode ("mov", "dpx,#!constbyte", (options.stack_loc >> 16) & 0xff);
557 emitcode ("mov", "dph,a");
558 emitcode ("mov", "dpl,b");
562 emitcode ("pop", "b");
565 emitcode ("pop", "acc");
567 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
568 aop->size = getSize (sym->type);
572 /* if in bit space */
573 if (IN_BITSPACE (space))
575 sym->aop = aop = newAsmop (AOP_CRY);
576 aop->aopu.aop_dir = sym->rname;
577 aop->size = getSize (sym->type);
580 /* if it is in direct space */
581 if (IN_DIRSPACE (space))
583 sym->aop = aop = newAsmop (AOP_DIR);
584 aop->aopu.aop_dir = sym->rname;
585 aop->size = getSize (sym->type);
589 /* special case for a function */
590 if (IS_FUNC (sym->type))
592 sym->aop = aop = newAsmop (AOP_IMMD);
593 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
594 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
595 aop->size = FPTRSIZE;
599 /* only remaining is far space */
600 /* in which case DPTR gets the address */
601 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
606 emitcode ("mov", "dptr,#%s", sym->rname);
611 emitcode ("mov", "dptr,#%s", sym->rname);
613 aop->size = getSize (sym->type);
615 /* if it is in code space */
616 if (IN_CODESPACE (space))
622 /*-----------------------------------------------------------------*/
623 /* aopForRemat - rematerialzes an object */
624 /*-----------------------------------------------------------------*/
626 aopForRemat (symbol * sym)
628 iCode *ic = sym->rematiCode;
629 asmop *aop = newAsmop (AOP_IMMD);
636 val += (int) operandLitValue (IC_RIGHT (ic));
637 else if (ic->op == '-')
638 val -= (int) operandLitValue (IC_RIGHT (ic));
639 else if (IS_CAST_ICODE(ic)) {
640 sym_link *from_type = operandType(IC_RIGHT(ic));
641 aop->aopu.aop_immd.from_cast_remat = 1;
642 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
643 ptr_type = DCL_TYPE(from_type);
644 if (ptr_type == IPOINTER) {
651 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
655 sprintf (buffer, "(%s %c 0x%04x)",
656 OP_SYMBOL (IC_LEFT (ic))->rname,
657 val >= 0 ? '+' : '-',
660 if (IS_ASSIGN_ICODE(ic) && isOperandLiteral(IC_RIGHT(ic)))
661 sprintf(buffer,"0x%x",(int) operandLitValue (IC_RIGHT (ic)));
663 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
666 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
667 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
668 /* set immd2 field if required */
669 if (aop->aopu.aop_immd.from_cast_remat)
671 tsprintf(buffer, sizeof(buffer), "#!constbyte",ptr_type);
672 aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
678 /*-----------------------------------------------------------------*/
679 /* aopHasRegs - returns true if aop has regs between from-to */
680 /*-----------------------------------------------------------------*/
681 static int aopHasRegs(asmop *aop, int from, int to)
685 if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
687 for (; size < aop->size ; size++) {
689 for (reg = from ; reg <= to ; reg++)
690 if (aop->aopu.aop_reg[size] == ds390_regWithIdx(reg)) return 1;
695 /*-----------------------------------------------------------------*/
696 /* regsInCommon - two operands have some registers in common */
697 /*-----------------------------------------------------------------*/
699 regsInCommon (operand * op1, operand * op2)
704 /* if they have registers in common */
705 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
708 sym1 = OP_SYMBOL (op1);
709 sym2 = OP_SYMBOL (op2);
711 if (sym1->nRegs == 0 || sym2->nRegs == 0)
714 for (i = 0; i < sym1->nRegs; i++)
720 for (j = 0; j < sym2->nRegs; j++)
725 if (sym2->regs[j] == sym1->regs[i])
733 /*-----------------------------------------------------------------*/
734 /* operandsEqu - equivalent */
735 /*-----------------------------------------------------------------*/
737 operandsEqu (operand * op1, operand * op2)
741 /* if they not symbols */
742 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
745 sym1 = OP_SYMBOL (op1);
746 sym2 = OP_SYMBOL (op2);
748 /* if both are itemps & one is spilt
749 and the other is not then false */
750 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
751 sym1->isspilt != sym2->isspilt)
754 /* if they are the same */
758 if (strcmp (sym1->rname, sym2->rname) == 0)
762 /* if left is a tmp & right is not */
763 if (IS_ITEMP (op1) &&
766 (sym1->usl.spillLoc == sym2))
769 if (IS_ITEMP (op2) &&
773 (sym2->usl.spillLoc == sym1))
779 /*-----------------------------------------------------------------*/
780 /* sameRegs - two asmops have the same registers */
781 /*-----------------------------------------------------------------*/
783 sameRegs (asmop * aop1, asmop * aop2)
789 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
796 if (aop1->type != AOP_REG ||
797 aop2->type != AOP_REG)
800 if (aop1->size != aop2->size)
803 for (i = 0; i < aop1->size; i++)
804 if (aop1->aopu.aop_reg[i] !=
805 aop2->aopu.aop_reg[i])
811 /*-----------------------------------------------------------------*/
812 /* aopOp - allocates an asmop for an operand : */
813 /*-----------------------------------------------------------------*/
815 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
824 /* if this a literal */
825 if (IS_OP_LITERAL (op))
827 op->aop = aop = newAsmop (AOP_LIT);
828 aop->aopu.aop_lit = op->operand.valOperand;
829 aop->size = getSize (operandType (op));
833 /* if already has a asmop then continue */
837 /* if the underlying symbol has a aop */
838 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
840 op->aop = OP_SYMBOL (op)->aop;
844 /* if this is a true symbol */
845 if (IS_TRUE_SYMOP (op))
847 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
851 /* this is a temporary : this has
857 e) can be a return use only */
859 sym = OP_SYMBOL (op);
862 /* if the type is a conditional */
863 if (sym->regType == REG_CND)
865 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
870 /* if it is spilt then two situations
872 b) has a spill location */
873 if (sym->isspilt || sym->nRegs == 0)
876 /* rematerialize it NOW */
879 sym->aop = op->aop = aop =
881 aop->size = getSize (sym->type);
888 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
889 aop->size = getSize (sym->type);
890 for (i = 0; i < 2; i++)
891 aop->aopu.aop_str[i] = accUse[i];
901 /* a AOP_STR uses DPTR, but DPTR is already in use;
904 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"AOP_STR with DPTR in use!");
907 aop = op->aop = sym->aop = newAsmop (AOP_STR);
908 aop->size = getSize (sym->type);
909 for (i = 0; i < (int) fReturnSizeDS390; i++)
910 aop->aopu.aop_str[i] = fReturn[i];
914 if (sym->dptr) { /* has been allocated to a DPTRn */
915 aop = op->aop = sym->aop = newAsmop (AOP_DPTRn);
916 aop->size = getSize (sym->type);
917 aop->aopu.dptr = sym->dptr;
920 /* else spill location */
921 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
922 /* force a new aop if sizes differ */
923 sym->usl.spillLoc->aop = NULL;
925 sym->aop = op->aop = aop =
926 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
927 aop->size = getSize (sym->type);
931 /* must be in a register */
932 sym->aop = op->aop = aop = newAsmop (AOP_REG);
933 aop->size = sym->nRegs;
934 for (i = 0; i < sym->nRegs; i++)
935 aop->aopu.aop_reg[i] = sym->regs[i];
938 /*-----------------------------------------------------------------*/
939 /* freeAsmop - free up the asmop given to an operand */
940 /*----------------------------------------------------------------*/
942 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
959 /* depending on the asmop type only three cases need work AOP_RO
960 , AOP_R1 && AOP_STK */
968 emitcode ("pop", "ar0");
972 bitVectUnSetBit (ic->rUsed, R0_IDX);
980 emitcode ("pop", "ar1");
984 bitVectUnSetBit (ic->rUsed, R1_IDX);
990 int stk = aop->aopu.aop_stk + aop->size;
991 bitVectUnSetBit (ic->rUsed, R0_IDX);
992 bitVectUnSetBit (ic->rUsed, R1_IDX);
994 getFreePtr (ic, &aop, FALSE);
996 if (options.stack10bit)
998 /* I'm not sure what to do here yet... */
1001 "*** Warning: probably generating bad code for "
1002 "10 bit stack mode.\n");
1007 emitcode ("mov", "a,_bp");
1008 emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
1009 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1013 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1018 emitcode ("pop", "acc");
1019 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1022 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1025 freeAsmop (op, NULL, ic, TRUE);
1028 emitcode ("pop", "ar0");
1034 emitcode ("pop", "ar1");
1039 if (_G.dptr1InUse) {
1040 emitcode ("pop","dpx1");
1041 emitcode ("pop","dph1");
1042 emitcode ("pop","dpl1");
1047 emitcode ("pop","dpx");
1048 emitcode ("pop","dph");
1049 emitcode ("pop","dpl");
1054 /* all other cases just dealloc */
1060 OP_SYMBOL (op)->aop = NULL;
1061 /* if the symbol has a spill */
1063 SPIL_LOC (op)->aop = NULL;
1068 /*------------------------------------------------------------------*/
1069 /* aopGet - for fetching value of the aop */
1071 /* Set canClobberACC if you are sure it is OK to clobber the value */
1072 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe, */
1073 /* just less efficient. */
1074 /*------------------------------------------------------------------*/
1077 aopGet (asmop * aop,
1086 /* offset is greater than
1088 if (offset > (aop->size - 1) &&
1089 aop->type != AOP_LIT)
1092 /* depending on type */
1098 /* if we need to increment it */
1099 while (offset > aop->coff)
1101 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1105 while (offset < aop->coff)
1107 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1114 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1115 return (dname ? "acc" : "a");
1117 SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1118 return Safe_strdup(buffer);
1121 assert(offset <= 3);
1122 return dptrn[aop->aopu.dptr][offset];
1127 if (aop->type == AOP_DPTR2)
1133 emitcode ("xch", "a, %s", DP2_RESULT_REG);
1139 while (offset > aop->coff)
1141 emitcode ("inc", "dptr");
1145 while (offset < aop->coff)
1147 emitcode ("lcall", "__decdptr");
1154 emitcode ("clr", "a");
1155 emitcode ("movc", "a,@a+dptr");
1159 emitcode ("movx", "a,@dptr");
1162 if (aop->type == AOP_DPTR2)
1168 emitcode ("xch", "a, %s", DP2_RESULT_REG);
1169 return DP2_RESULT_REG;
1172 return (dname ? "acc" : "a");
1175 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1177 SNPRINTF(buffer, sizeof(buffer),
1178 "%s",aop->aopu.aop_immd.aop_immd2);
1182 SNPRINTF(buffer, sizeof(buffer),
1183 "#%s", aop->aopu.aop_immd.aop_immd1);
1189 tsprintf(buffer, sizeof(buffer),
1190 "#!his",aop->aopu.aop_immd.aop_immd1);
1193 tsprintf(buffer, sizeof(buffer),
1194 "#!hihis",aop->aopu.aop_immd.aop_immd1);
1197 tsprintf(buffer, sizeof(buffer),
1198 "#!hihihis",aop->aopu.aop_immd.aop_immd1);
1200 default: /* should not need this (just in case) */
1201 SNPRINTF (buffer, sizeof(buffer),
1203 aop->aopu.aop_immd.aop_immd1,
1209 SNPRINTF (buffer, sizeof(buffer),
1210 "#%s", aop->aopu.aop_immd.aop_immd1);
1212 return Safe_strdup(buffer);
1217 SNPRINTF (buffer, sizeof(buffer),
1224 SNPRINTF(buffer, sizeof(buffer),
1225 "%s", aop->aopu.aop_dir);
1228 return Safe_strdup(buffer);
1232 return aop->aopu.aop_reg[offset]->dname;
1234 return aop->aopu.aop_reg[offset]->name;
1237 emitcode ("clr", "a");
1238 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1239 emitcode ("rlc", "a");
1240 return (dname ? "acc" : "a");
1243 if (!offset && dname)
1245 return aop->aopu.aop_str[offset];
1248 return aopLiteral (aop->aopu.aop_lit, offset);
1252 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1256 return aop->aopu.aop_str[offset];
1260 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1261 "aopget got unsupported aop->type");
1264 /*-----------------------------------------------------------------*/
1265 /* aopPut - puts a string for a aop */
1266 /*-----------------------------------------------------------------*/
1268 aopPut (asmop * aop, char *s, int offset)
1272 if (aop->size && offset > (aop->size - 1))
1274 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1275 "aopPut got offset > aop->size");
1279 /* will assign value to value */
1280 /* depending on where it is ofcourse */
1285 sprintf (d, "(%s + %d)",
1286 aop->aopu.aop_dir, offset);
1288 sprintf (d, "%s", aop->aopu.aop_dir);
1291 emitcode ("mov", "%s,%s", d, s);
1296 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1297 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1300 strcmp (s, "r0") == 0 ||
1301 strcmp (s, "r1") == 0 ||
1302 strcmp (s, "r2") == 0 ||
1303 strcmp (s, "r3") == 0 ||
1304 strcmp (s, "r4") == 0 ||
1305 strcmp (s, "r5") == 0 ||
1306 strcmp (s, "r6") == 0 ||
1307 strcmp (s, "r7") == 0)
1308 emitcode ("mov", "%s,%s",
1309 aop->aopu.aop_reg[offset]->dname, s);
1311 emitcode ("mov", "%s,%s",
1312 aop->aopu.aop_reg[offset]->name, s);
1317 emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1323 if (aop->type == AOP_DPTR2)
1331 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1332 "aopPut writting to code space");
1336 while (offset > aop->coff)
1339 emitcode ("inc", "dptr");
1342 while (offset < aop->coff)
1345 emitcode ("lcall", "__decdptr");
1350 /* if not in accumulater */
1353 emitcode ("movx", "@dptr,a");
1355 if (aop->type == AOP_DPTR2)
1363 while (offset > aop->coff)
1366 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1368 while (offset < aop->coff)
1371 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1378 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1384 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1386 else if (strcmp (s, "r0") == 0 ||
1387 strcmp (s, "r1") == 0 ||
1388 strcmp (s, "r2") == 0 ||
1389 strcmp (s, "r3") == 0 ||
1390 strcmp (s, "r4") == 0 ||
1391 strcmp (s, "r5") == 0 ||
1392 strcmp (s, "r6") == 0 ||
1393 strcmp (s, "r7") == 0)
1396 sprintf (buffer, "a%s", s);
1397 emitcode ("mov", "@%s,%s",
1398 aop->aopu.aop_ptr->name, buffer);
1401 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1406 if (strcmp (s, "a") == 0)
1407 emitcode ("push", "acc");
1411 emitcode ("push", "acc");
1413 emitcode ("push", s);
1419 /* if bit variable */
1420 if (!aop->aopu.aop_dir)
1422 emitcode ("clr", "a");
1423 emitcode ("rlc", "a");
1428 emitcode ("clr", "%s", aop->aopu.aop_dir);
1430 emitcode ("setb", "%s", aop->aopu.aop_dir);
1431 else if (!strcmp (s, "c"))
1432 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1435 if (strcmp (s, "a"))
1440 /* set C, if a >= 1 */
1441 emitcode ("add", "a,#!constbyte",0xff);
1442 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1450 if (strcmp (aop->aopu.aop_str[offset], s))
1451 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1456 if (!offset && (strcmp (s, "acc") == 0))
1459 if (strcmp (aop->aopu.aop_str[offset], s))
1460 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1464 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1465 "aopPut got unsupported aop->type");
1472 /*--------------------------------------------------------------------*/
1473 /* reAdjustPreg - points a register back to where it should (coff==0) */
1474 /*--------------------------------------------------------------------*/
1476 reAdjustPreg (asmop * aop)
1478 if ((aop->coff==0) || (aop->size <= 1)) {
1487 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1491 if (aop->type == AOP_DPTR2)
1498 emitcode ("lcall", "__decdptr");
1501 if (aop->type == AOP_DPTR2)
1511 #define AOP(op) op->aop
1512 #define AOP_TYPE(op) AOP(op)->type
1513 #define AOP_SIZE(op) AOP(op)->size
1514 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1515 AOP_TYPE(x) == AOP_R0))
1517 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1518 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1521 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1522 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1523 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1524 #define AOP_INDPTRn(x) (AOP_TYPE(x) == AOP_DPTRn)
1525 #define AOP_USESDPTR(x) (AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_STR)
1527 /* Workaround for DS80C390 bug: div ab may return bogus results
1528 * if A is accessed in instruction immediately before the div.
1530 * Will be fixed in B4 rev of processor, Dallas claims.
1533 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1534 if (!AOP_NEEDSACC(RIGHT)) \
1536 /* We can load A first, then B, since \
1537 * B (the RIGHT operand) won't clobber A, \
1538 * thus avoiding touching A right before the div. \
1540 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1541 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1543 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1547 /* Just stuff in a nop after loading A. */ \
1548 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1549 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1551 emitcode("nop", "; workaround for DS80C390 div bug."); \
1554 /*-----------------------------------------------------------------*/
1555 /* genNotFloat - generates not for float operations */
1556 /*-----------------------------------------------------------------*/
1558 genNotFloat (operand * op, operand * res)
1564 D (emitcode (";", "genNotFloat ");
1567 /* we will put 127 in the first byte of
1569 aopPut (AOP (res), "#127", 0);
1570 size = AOP_SIZE (op) - 1;
1573 _startLazyDPSEvaluation ();
1574 l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE);
1579 emitcode ("orl", "a,%s",
1581 offset++, FALSE, FALSE, FALSE));
1583 _endLazyDPSEvaluation ();
1585 tlbl = newiTempLabel (NULL);
1586 aopPut (res->aop, one, 1);
1587 emitcode ("jz", "!tlabel", (tlbl->key + 100));
1588 aopPut (res->aop, zero, 1);
1589 emitcode ("", "!tlabeldef", (tlbl->key + 100));
1591 size = res->aop->size - 2;
1593 /* put zeros in the rest */
1595 aopPut (res->aop, zero, offset++);
1598 /*-----------------------------------------------------------------*/
1599 /* opIsGptr: returns non-zero if the passed operand is */
1600 /* a generic pointer type. */
1601 /*-----------------------------------------------------------------*/
1603 opIsGptr (operand * op)
1605 sym_link *type = operandType (op);
1607 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1614 /*-----------------------------------------------------------------*/
1615 /* getDataSize - get the operand data size */
1616 /*-----------------------------------------------------------------*/
1618 getDataSize (operand * op)
1621 size = AOP_SIZE (op);
1622 if (size == GPTRSIZE)
1624 sym_link *type = operandType (op);
1625 if (IS_GENPTR (type))
1627 /* generic pointer; arithmetic operations
1628 * should ignore the high byte (pointer type).
1636 /*-----------------------------------------------------------------*/
1637 /* outAcc - output Acc */
1638 /*-----------------------------------------------------------------*/
1640 outAcc (operand * result)
1643 size = getDataSize (result);
1646 aopPut (AOP (result), "a", 0);
1649 /* unsigned or positive */
1652 aopPut (AOP (result), zero, offset++);
1657 /*-----------------------------------------------------------------*/
1658 /* outBitC - output a bit C */
1659 /*-----------------------------------------------------------------*/
1661 outBitC (operand * result)
1663 /* if the result is bit */
1664 if (AOP_TYPE (result) == AOP_CRY)
1666 aopPut (AOP (result), "c", 0);
1670 emitcode ("clr", "a");
1671 emitcode ("rlc", "a");
1676 /*-----------------------------------------------------------------*/
1677 /* toBoolean - emit code for orl a,operator(sizeop) */
1678 /*-----------------------------------------------------------------*/
1680 toBoolean (operand * oper)
1682 int size = AOP_SIZE (oper) - 1;
1686 /* The generic part of a generic pointer should
1687 * not participate in it's truth value.
1689 * i.e. 0x10000000 is zero.
1691 if (opIsGptr (oper))
1693 D (emitcode (";", "toBoolean: generic ptr special case.");
1698 _startLazyDPSEvaluation ();
1699 if (AOP_NEEDSACC (oper) && size)
1702 emitcode ("push", "b");
1703 emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1707 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1713 emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1717 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1720 _endLazyDPSEvaluation ();
1724 emitcode ("mov", "a,b");
1725 emitcode ("pop", "b");
1730 /*-----------------------------------------------------------------*/
1731 /* genNot - generate code for ! operation */
1732 /*-----------------------------------------------------------------*/
1737 sym_link *optype = operandType (IC_LEFT (ic));
1739 D (emitcode (";", "genNot ");
1742 /* assign asmOps to operand & result */
1743 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1744 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1746 /* if in bit space then a special case */
1747 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1749 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1750 emitcode ("cpl", "c");
1751 outBitC (IC_RESULT (ic));
1755 /* if type float then do float */
1756 if (IS_FLOAT (optype))
1758 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1762 toBoolean (IC_LEFT (ic));
1764 tlbl = newiTempLabel (NULL);
1765 emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1766 emitcode ("", "!tlabeldef", tlbl->key + 100);
1767 outBitC (IC_RESULT (ic));
1770 /* release the aops */
1771 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1772 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1776 /*-----------------------------------------------------------------*/
1777 /* genCpl - generate code for complement */
1778 /*-----------------------------------------------------------------*/
1786 D (emitcode (";", "genCpl ");
1790 /* assign asmOps to operand & result */
1791 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1792 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1794 /* special case if in bit space */
1795 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1796 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1797 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1798 emitcode ("cpl", "c");
1799 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1802 tlbl=newiTempLabel(NULL);
1803 emitcode ("cjne", "%s,#0x01,%05d$",
1804 aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE,TRUE), tlbl->key+100);
1805 emitcode ("", "%05d$:", tlbl->key+100);
1806 outBitC (IC_RESULT(ic));
1810 size = AOP_SIZE (IC_RESULT (ic));
1811 _startLazyDPSEvaluation ();
1814 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1816 emitcode ("cpl", "a");
1817 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1819 _endLazyDPSEvaluation ();
1823 /* release the aops */
1824 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1825 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1828 /*-----------------------------------------------------------------*/
1829 /* genUminusFloat - unary minus for floating points */
1830 /*-----------------------------------------------------------------*/
1832 genUminusFloat (operand * op, operand * result)
1834 int size, offset = 0;
1836 /* for this we just need to flip the
1837 first it then copy the rest in place */
1838 D (emitcode (";", "genUminusFloat");
1841 _startLazyDPSEvaluation ();
1842 size = AOP_SIZE (op) - 1;
1843 l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1846 emitcode ("cpl", "acc.7");
1847 aopPut (AOP (result), "a", 3);
1851 aopPut (AOP (result),
1852 aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1856 _endLazyDPSEvaluation ();
1859 /*-----------------------------------------------------------------*/
1860 /* genUminus - unary minus code generation */
1861 /*-----------------------------------------------------------------*/
1863 genUminus (iCode * ic)
1866 sym_link *optype, *rtype;
1868 D (emitcode (";", "genUminus ");
1873 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1874 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1876 /* if both in bit space then special
1878 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1879 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1882 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1883 emitcode ("cpl", "c");
1884 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1888 optype = operandType (IC_LEFT (ic));
1889 rtype = operandType (IC_RESULT (ic));
1891 /* if float then do float stuff */
1892 if (IS_FLOAT (optype))
1894 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1898 /* otherwise subtract from zero */
1899 size = AOP_SIZE (IC_LEFT (ic));
1901 _startLazyDPSEvaluation ();
1904 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1905 if (!strcmp (l, "a"))
1909 emitcode ("cpl", "a");
1910 emitcode ("addc", "a,#0");
1916 emitcode ("clr", "a");
1917 emitcode ("subb", "a,%s", l);
1919 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1921 _endLazyDPSEvaluation ();
1923 /* if any remaining bytes in the result */
1924 /* we just need to propagate the sign */
1925 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1927 emitcode ("rlc", "a");
1928 emitcode ("subb", "a,acc");
1930 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1934 /* release the aops */
1935 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1936 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1939 /*-----------------------------------------------------------------*/
1940 /* savermask - saves registers in the mask */
1941 /*-----------------------------------------------------------------*/
1942 static void savermask(bitVect *rs_mask)
1945 if (options.useXstack) {
1946 if (bitVectBitValue (rs_mask, R0_IDX))
1947 emitcode ("mov", "b,r0");
1948 emitcode ("mov", "r0,%s", spname);
1949 for (i = 0; i < ds390_nRegs; i++) {
1950 if (bitVectBitValue (rs_mask, i)) {
1952 emitcode ("mov", "a,b");
1954 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1955 emitcode ("movx", "@r0,a");
1956 emitcode ("inc", "r0");
1959 emitcode ("mov", "%s,r0", spname);
1960 if (bitVectBitValue (rs_mask, R0_IDX))
1961 emitcode ("mov", "r0,b");
1963 for (i = 0; i < ds390_nRegs; i++) {
1964 if (bitVectBitValue (rs_mask, i))
1965 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
1970 /*-----------------------------------------------------------------*/
1971 /* saveRegisters - will look for a call and save the registers */
1972 /*-----------------------------------------------------------------*/
1974 saveRegisters (iCode * lic)
1980 for (ic = lic; ic; ic = ic->next)
1981 if (ic->op == CALL || ic->op == PCALL)
1986 fprintf (stderr, "found parameter push with no function call\n");
1990 /* if the registers have been saved already then
1992 if (ic->regsSaved || IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic)))) return ;
1994 /* special case if DPTR alive across a function call then must save it
1995 even though callee saves */
1996 if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
1998 rsave = newBitVect(ic->rMask->size);
1999 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2000 if (bitVectBitValue(ic->rMask,i))
2001 rsave = bitVectSetBit(rsave,i);
2003 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2005 /* safe the registers in use at this time but skip the
2006 ones for the result */
2007 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2008 ds390_rUmaskForOp (IC_RESULT(ic)));
2014 /*-----------------------------------------------------------------*/
2015 /* usavermask - restore registers with mask */
2016 /*-----------------------------------------------------------------*/
2017 static void unsavermask(bitVect *rs_mask)
2020 if (options.useXstack) {
2021 emitcode ("mov", "r0,%s", spname);
2022 for (i = ds390_nRegs; i >= 0; i--) {
2023 if (bitVectBitValue (rs_mask, i)) {
2024 emitcode ("dec", "r0");
2025 emitcode ("movx", "a,@r0");
2027 emitcode ("mov", "b,a");
2029 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
2032 emitcode ("mov", "%s,r0", spname);
2033 if (bitVectBitValue (rs_mask, R0_IDX))
2034 emitcode ("mov", "r0,b");
2036 for (i = ds390_nRegs; i >= 0; i--) {
2037 if (bitVectBitValue (rs_mask, i))
2038 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2043 /*-----------------------------------------------------------------*/
2044 /* unsaveRegisters - pop the pushed registers */
2045 /*-----------------------------------------------------------------*/
2047 unsaveRegisters (iCode * ic)
2051 if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2053 rsave = newBitVect(ic->rMask->size);
2054 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2055 if (bitVectBitValue(ic->rMask,i))
2056 rsave = bitVectSetBit(rsave,i);
2058 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2060 /* restore the registers in use at this time but skip the
2061 ones for the result */
2062 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2063 ds390_rUmaskForOp (IC_RESULT(ic)));
2069 /*-----------------------------------------------------------------*/
2071 /*-----------------------------------------------------------------*/
2073 pushSide (operand * oper, int size)
2076 _startLazyDPSEvaluation ();
2079 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
2080 if (AOP_TYPE (oper) != AOP_REG &&
2081 AOP_TYPE (oper) != AOP_DIR &&
2084 emitcode ("mov", "a,%s", l);
2085 emitcode ("push", "acc");
2088 emitcode ("push", "%s", l);
2090 _endLazyDPSEvaluation ();
2093 /*-----------------------------------------------------------------*/
2094 /* assignResultValue - */
2095 /*-----------------------------------------------------------------*/
2097 assignResultValue (operand * oper)
2100 int size = AOP_SIZE (oper);
2102 _startLazyDPSEvaluation ();
2105 aopPut (AOP (oper), fReturn[offset], offset);
2108 _endLazyDPSEvaluation ();
2112 /*-----------------------------------------------------------------*/
2113 /* genXpush - pushes onto the external stack */
2114 /*-----------------------------------------------------------------*/
2116 genXpush (iCode * ic)
2118 asmop *aop = newAsmop (0);
2120 int size, offset = 0;
2122 D (emitcode (";", "genXpush ");
2125 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2126 r = getFreePtr (ic, &aop, FALSE);
2129 emitcode ("mov", "%s,_spx", r->name);
2131 size = AOP_SIZE (IC_LEFT (ic));
2132 _startLazyDPSEvaluation ();
2136 char *l = aopGet (AOP (IC_LEFT (ic)),
2137 offset++, FALSE, FALSE, TRUE);
2139 emitcode ("movx", "@%s,a", r->name);
2140 emitcode ("inc", "%s", r->name);
2143 _endLazyDPSEvaluation ();
2146 emitcode ("mov", "_spx,%s", r->name);
2148 freeAsmop (NULL, aop, ic, TRUE);
2149 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2152 /*-----------------------------------------------------------------*/
2153 /* genIpush - genrate code for pushing this gets a little complex */
2154 /*-----------------------------------------------------------------*/
2156 genIpush (iCode * ic)
2158 int size, offset = 0;
2161 D (emitcode (";", "genIpush ");
2164 /* if this is not a parm push : ie. it is spill push
2165 and spill push is always done on the local stack */
2169 /* and the item is spilt then do nothing */
2170 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2173 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2174 size = AOP_SIZE (IC_LEFT (ic));
2175 /* push it on the stack */
2176 _startLazyDPSEvaluation ();
2179 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
2185 emitcode ("push", "%s", l);
2187 _endLazyDPSEvaluation ();
2191 /* this is a paramter push: in this case we call
2192 the routine to find the call and save those
2193 registers that need to be saved */
2196 /* if use external stack then call the external
2197 stack pushing routine */
2198 if (options.useXstack)
2204 /* then do the push */
2205 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2207 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2208 size = AOP_SIZE (IC_LEFT (ic));
2210 _startLazyDPSEvaluation ();
2213 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
2214 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2215 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2218 emitcode ("mov", "a,%s", l);
2219 emitcode ("push", "acc");
2222 emitcode ("push", "%s", l);
2224 _endLazyDPSEvaluation ();
2226 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2229 /*-----------------------------------------------------------------*/
2230 /* genIpop - recover the registers: can happen only for spilling */
2231 /*-----------------------------------------------------------------*/
2233 genIpop (iCode * ic)
2237 D (emitcode (";", "genIpop ");
2241 /* if the temp was not pushed then */
2242 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2245 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2246 size = AOP_SIZE (IC_LEFT (ic));
2247 offset = (size - 1);
2248 _startLazyDPSEvaluation ();
2251 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2252 FALSE, TRUE, TRUE));
2254 _endLazyDPSEvaluation ();
2256 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2259 /*-----------------------------------------------------------------*/
2260 /* unsaveRBank - restores the resgister bank from stack */
2261 /*-----------------------------------------------------------------*/
2263 unsaveRBank (int bank, iCode * ic, bool popPsw)
2269 if (options.useXstack)
2273 /* Assume r0 is available for use. */
2274 r = ds390_regWithIdx (R0_IDX);;
2279 r = getFreePtr (ic, &aop, FALSE);
2281 emitcode ("mov", "%s,_spx", r->name);
2286 if (options.useXstack)
2288 emitcode ("movx", "a,@%s", r->name);
2289 emitcode ("mov", "psw,a");
2290 emitcode ("dec", "%s", r->name);
2294 emitcode ("pop", "psw");
2298 for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2300 if (options.useXstack)
2302 emitcode ("movx", "a,@%s", r->name);
2303 emitcode ("mov", "(%s+%d),a",
2304 regs390[i].base, 8 * bank + regs390[i].offset);
2305 emitcode ("dec", "%s", r->name);
2309 emitcode ("pop", "(%s+%d)",
2310 regs390[i].base, 8 * bank + regs390[i].offset);
2313 if (options.useXstack)
2315 emitcode ("mov", "_spx,%s", r->name);
2320 freeAsmop (NULL, aop, ic, TRUE);
2324 /*-----------------------------------------------------------------*/
2325 /* saveRBank - saves an entire register bank on the stack */
2326 /*-----------------------------------------------------------------*/
2328 saveRBank (int bank, iCode * ic, bool pushPsw)
2334 if (options.useXstack)
2338 /* Assume r0 is available for use. */
2339 r = ds390_regWithIdx (R0_IDX);;
2344 r = getFreePtr (ic, &aop, FALSE);
2346 emitcode ("mov", "%s,_spx", r->name);
2349 for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2351 if (options.useXstack)
2353 emitcode ("inc", "%s", r->name);
2354 emitcode ("mov", "a,(%s+%d)",
2355 regs390[i].base, 8 * bank + regs390[i].offset);
2356 emitcode ("movx", "@%s,a", r->name);
2359 emitcode ("push", "(%s+%d)",
2360 regs390[i].base, 8 * bank + regs390[i].offset);
2365 if (options.useXstack)
2367 emitcode ("mov", "a,psw");
2368 emitcode ("movx", "@%s,a", r->name);
2369 emitcode ("inc", "%s", r->name);
2370 emitcode ("mov", "_spx,%s", r->name);
2374 emitcode ("push", "psw");
2377 emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2382 freeAsmop (NULL, aop, ic, TRUE);
2391 /*-----------------------------------------------------------------*/
2392 /* genSend - gen code for SEND */
2393 /*-----------------------------------------------------------------*/
2394 static void genSend(set *sendSet)
2398 static int rb1_count = 0;
2400 for (sic = setFirstItem (sendSet); sic;
2401 sic = setNextItem (sendSet)) {
2402 int size, offset = 0;
2404 size=getSize(operandType(IC_LEFT(sic)));
2405 D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2406 if (sendCount == 0) { /* first parameter */
2407 // we know that dpl(hxb) is the result, so
2409 _startLazyDPSEvaluation ();
2411 aopOp (IC_LEFT (sic), sic, FALSE,
2412 (IS_SYMOP(IC_LEFT(sic)) && OP_SYMBOL(IC_LEFT(sic))->ruonly ? FALSE : TRUE));
2414 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2417 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2418 FALSE, FALSE, TRUE);
2419 if (strcmp (l, fReturn[offset])) {
2420 emitcode ("mov", "%s,%s",
2426 _endLazyDPSEvaluation ();
2427 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2429 } else { /* if more parameter in registers */
2430 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2432 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
2433 FALSE, FALSE, TRUE));
2435 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2441 /*-----------------------------------------------------------------*/
2442 /* genCall - generates a call statement */
2443 /*-----------------------------------------------------------------*/
2445 genCall (iCode * ic)
2448 bool restoreBank = FALSE;
2449 bool swapBanks = FALSE;
2451 D (emitcode (";", "genCall "););
2453 /* if we are calling a not _naked function that is not using
2454 the same register bank then we need to save the
2455 destination registers on the stack */
2456 dtype = operandType (IC_LEFT (ic));
2457 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2458 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2459 IFFUNC_ISISR (currFunc->type))
2463 /* This is unexpected; the bank should have been saved in
2466 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2472 /* if caller saves & we have not saved then */
2476 /* if send set is not empty the assign */
2477 /* We've saved all the registers we care about;
2478 * therefore, we may clobber any register not used
2479 * in the calling convention (i.e. anything not in
2484 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2485 genSend(reverseSet(_G.sendSet));
2487 genSend(_G.sendSet);
2494 emitcode ("mov", "psw,#!constbyte",
2495 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2499 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2500 OP_SYMBOL (IC_LEFT (ic))->rname :
2501 OP_SYMBOL (IC_LEFT (ic))->name));
2505 emitcode ("mov", "psw,#!constbyte",
2506 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2509 /* if we need assign a result value */
2510 if ((IS_ITEMP (IC_RESULT (ic)) &&
2511 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2512 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2513 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2514 IS_TRUE_SYMOP (IC_RESULT (ic)))
2516 if (isOperandInFarSpace (IC_RESULT (ic))
2517 && getSize (operandType (IC_RESULT (ic))) <= 2)
2519 int size = getSize (operandType (IC_RESULT (ic)));
2521 /* Special case for 1 or 2 byte return in far space. */
2525 emitcode ("mov", "b,%s", fReturn[1]);
2528 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2529 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2533 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2535 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2540 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2543 assignResultValue (IC_RESULT (ic));
2545 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2549 /* adjust the stack for parameters if
2551 if (ic->parmBytes) {
2553 if (options.stack10bit) {
2554 if (ic->parmBytes <= 10) {
2555 emitcode(";","stack adjustment for parms");
2556 for (i=0; i < ic->parmBytes ; i++) {
2557 emitcode("pop","acc");
2561 emitcode ("clr","c");
2562 emitcode ("mov","a,sp");
2563 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2564 emitcode ("mov","sp,a");
2565 emitcode ("mov","a,esp");
2566 emitcode ("anl","a,#3");
2567 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2568 emitcode ("mov","esp,a");
2572 if (ic->parmBytes > 3) {
2573 emitcode ("mov", "a,%s", spname);
2574 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2575 emitcode ("mov", "%s,a", spname);
2577 for (i = 0; i < ic->parmBytes; i++)
2578 emitcode ("dec", "%s", spname);
2582 /* if we hade saved some registers then unsave them */
2584 unsaveRegisters (ic);
2586 /* if register bank was saved then pop them */
2588 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2591 /*-----------------------------------------------------------------*/
2592 /* genPcall - generates a call by pointer statement */
2593 /*-----------------------------------------------------------------*/
2595 genPcall (iCode * ic)
2598 symbol *rlbl = newiTempLabel (NULL);
2599 bool restoreBank=FALSE;
2601 D (emitcode (";", "genPcall ");
2605 /* if caller saves & we have not saved then */
2609 /* if we are calling a function that is not using
2610 the same register bank then we need to save the
2611 destination registers on the stack */
2612 dtype = operandType (IC_LEFT (ic));
2613 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2614 IFFUNC_ISISR (currFunc->type) &&
2615 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2616 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2620 /* push the return address on to the stack */
2621 emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2622 emitcode ("push", "acc");
2623 emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2624 emitcode ("push", "acc");
2626 if (options.model == MODEL_FLAT24)
2628 emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2629 emitcode ("push", "acc");
2632 /* now push the calling address */
2633 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2635 pushSide (IC_LEFT (ic), FPTRSIZE);
2637 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2639 /* if send set is not empty the assign */
2642 genSend(reverseSet(_G.sendSet));
2646 emitcode ("ret", "");
2647 emitcode ("", "!tlabeldef", (rlbl->key + 100));
2650 /* if we need assign a result value */
2651 if ((IS_ITEMP (IC_RESULT (ic)) &&
2652 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2653 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2654 IS_TRUE_SYMOP (IC_RESULT (ic)))
2658 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2661 assignResultValue (IC_RESULT (ic));
2663 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2666 /* adjust the stack for parameters if
2671 if (options.stack10bit) {
2672 if (ic->parmBytes <= 10) {
2673 emitcode(";","stack adjustment for parms");
2674 for (i=0; i < ic->parmBytes ; i++) {
2675 emitcode("pop","acc");
2679 emitcode ("clr","c");
2680 emitcode ("mov","a,sp");
2681 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2682 emitcode ("mov","sp,a");
2683 emitcode ("mov","a,esp");
2684 emitcode ("anl","a,#3");
2685 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2686 emitcode ("mov","esp,a");
2690 if (ic->parmBytes > 3) {
2691 emitcode ("mov", "a,%s", spname);
2692 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2693 emitcode ("mov", "%s,a", spname);
2696 for (i = 0; i < ic->parmBytes; i++)
2697 emitcode ("dec", "%s", spname);
2701 /* if register bank was saved then unsave them */
2703 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2705 /* if we hade saved some registers then
2708 unsaveRegisters (ic);
2712 /*-----------------------------------------------------------------*/
2713 /* resultRemat - result is rematerializable */
2714 /*-----------------------------------------------------------------*/
2716 resultRemat (iCode * ic)
2718 if (SKIP_IC (ic) || ic->op == IFX)
2721 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2723 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2724 if (sym->remat && !POINTER_SET (ic))
2731 #if defined(__BORLANDC__) || defined(_MSC_VER)
2732 #define STRCASECMP stricmp
2734 #define STRCASECMP strcasecmp
2737 /*-----------------------------------------------------------------*/
2738 /* inExcludeList - return 1 if the string is in exclude Reg list */
2739 /*-----------------------------------------------------------------*/
2741 inExcludeList (char *s)
2745 if (options.excludeRegs[i] &&
2746 STRCASECMP (options.excludeRegs[i], "none") == 0)
2749 for (i = 0; options.excludeRegs[i]; i++)
2751 if (options.excludeRegs[i] &&
2752 STRCASECMP (s, options.excludeRegs[i]) == 0)
2758 /*-----------------------------------------------------------------*/
2759 /* genFunction - generated code for function entry */
2760 /*-----------------------------------------------------------------*/
2762 genFunction (iCode * ic)
2766 bool switchedPSW = FALSE;
2768 D (emitcode (";", "genFunction "););
2771 /* create the function header */
2772 emitcode (";", "-----------------------------------------");
2773 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2774 emitcode (";", "-----------------------------------------");
2776 emitcode ("", "%s:", sym->rname);
2777 ftype = operandType (IC_LEFT (ic));
2779 if (IFFUNC_ISNAKED(ftype))
2781 emitcode(";", "naked function: no prologue.");
2785 if (options.stack_probe)
2786 emitcode ("lcall","__stack_probe");
2787 /* if critical function then turn interrupts off */
2788 if (IFFUNC_ISCRITICAL (ftype))
2789 emitcode ("clr", "ea");
2791 /* here we need to generate the equates for the
2792 register bank if required */
2793 if (FUNC_REGBANK (ftype) != rbank)
2797 rbank = FUNC_REGBANK (ftype);
2798 for (i = 0; i < ds390_nRegs; i++)
2800 if (regs390[i].print) {
2801 if (strcmp (regs390[i].base, "0") == 0)
2802 emitcode ("", "%s !equ !constbyte",
2804 8 * rbank + regs390[i].offset);
2806 emitcode ("", "%s !equ %s + !constbyte",
2809 8 * rbank + regs390[i].offset);
2814 /* if this is an interrupt service routine then
2815 save acc, b, dpl, dph */
2816 if (IFFUNC_ISISR (sym->type))
2818 if (!inExcludeList ("acc"))
2819 emitcode ("push", "acc");
2820 if (!inExcludeList ("b"))
2821 emitcode ("push", "b");
2822 if (!inExcludeList ("dpl"))
2823 emitcode ("push", "dpl");
2824 if (!inExcludeList ("dph"))
2825 emitcode ("push", "dph");
2826 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2828 emitcode ("push", "dpx");
2829 /* Make sure we're using standard DPTR */
2830 emitcode ("push", "dps");
2831 emitcode ("mov", "dps,#0");
2832 if (options.stack10bit)
2834 /* This ISR could conceivably use DPTR2. Better save it. */
2835 emitcode ("push", "dpl1");
2836 emitcode ("push", "dph1");
2837 emitcode ("push", "dpx1");
2838 emitcode ("push", DP2_RESULT_REG);
2841 /* if this isr has no bank i.e. is going to
2842 run with bank 0 , then we need to save more
2844 if (!FUNC_REGBANK (sym->type))
2848 /* if this function does not call any other
2849 function then we can be economical and
2850 save only those registers that are used */
2851 if (!IFFUNC_HASFCALL(sym->type))
2854 /* if any registers used */
2857 /* save the registers used */
2858 for (i = 0; i < sym->regsUsed->size; i++)
2860 if (bitVectBitValue (sym->regsUsed, i) ||
2861 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2862 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2869 /* this function has a function call cannot
2870 determines register usage so we will have to push the
2872 saveRBank (0, ic, FALSE);
2873 if (options.parms_in_bank1) {
2874 for (i=0; i < 8 ; i++ ) {
2875 emitcode ("push","%s",rb1regs[i]);
2882 /* This ISR uses a non-zero bank.
2884 * We assume that the bank is available for our
2887 * However, if this ISR calls a function which uses some
2888 * other bank, we must save that bank entirely.
2890 unsigned long banksToSave = 0;
2892 if (IFFUNC_HASFCALL(sym->type))
2895 #define MAX_REGISTER_BANKS 4
2900 for (i = ic; i; i = i->next)
2902 if (i->op == ENDFUNCTION)
2904 /* we got to the end OK. */
2912 dtype = operandType (IC_LEFT(i));
2914 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2916 /* Mark this bank for saving. */
2917 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2919 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2923 banksToSave |= (1 << FUNC_REGBANK(dtype));
2926 /* And note that we don't need to do it in
2934 /* This is a mess; we have no idea what
2935 * register bank the called function might
2938 * The only thing I can think of to do is
2939 * throw a warning and hope.
2941 werror(W_FUNCPTR_IN_USING_ISR);
2945 if (banksToSave && options.useXstack)
2947 /* Since we aren't passing it an ic,
2948 * saveRBank will assume r0 is available to abuse.
2950 * So switch to our (trashable) bank now, so
2951 * the caller's R0 isn't trashed.
2953 emitcode ("push", "psw");
2954 emitcode ("mov", "psw,#!constbyte",
2955 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2959 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2961 if (banksToSave & (1 << ix))
2963 saveRBank(ix, NULL, FALSE);
2967 // jwk: this needs a closer look
2968 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2973 /* if callee-save to be used for this function
2974 then save the registers being used in this function */
2975 if (IFFUNC_CALLEESAVES(sym->type))
2979 /* if any registers used */
2982 /* save the registers used */
2983 for (i = 0; i < sym->regsUsed->size; i++)
2985 if (bitVectBitValue (sym->regsUsed, i) ||
2986 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2988 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2996 /* set the register bank to the desired value */
2997 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3000 emitcode ("push", "psw");
3001 emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3004 if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3005 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3006 if (options.stack10bit) {
3007 emitcode ("push","_bpx");
3008 emitcode ("push","_bpx+1");
3009 emitcode ("mov","_bpx,%s",spname);
3010 emitcode ("mov","_bpx+1,esp");
3011 emitcode ("anl","_bpx+1,#3");
3013 if (options.useXstack) {
3014 emitcode ("mov", "r0,%s", spname);
3015 emitcode ("mov", "a,_bp");
3016 emitcode ("movx", "@r0,a");
3017 emitcode ("inc", "%s", spname);
3019 /* set up the stack */
3020 emitcode ("push", "_bp"); /* save the callers stack */
3022 emitcode ("mov", "_bp,%s", spname);
3026 /* adjust the stack for the function */
3029 if (options.stack10bit) {
3030 if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
3031 assert (sym->recvSize <= 4);
3032 if (sym->stack <= 8) {
3033 while (i--) emitcode ("push","acc");
3036 emitcode ("mov","a,sp");
3037 emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3038 emitcode ("mov","sp,a");
3039 emitcode ("mov","a,esp");
3040 emitcode ("anl","a,#3");
3041 emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3042 emitcode ("mov","esp,a");
3047 werror (W_STACK_OVERFLOW, sym->name);
3049 if (i > 3 && sym->recvSize < 4) {
3051 emitcode ("mov", "a,sp");
3052 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3053 emitcode ("mov", "sp,a");
3057 emitcode ("inc", "sp");
3064 emitcode ("mov", "a,_spx");
3065 emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3066 emitcode ("mov", "_spx,a");
3071 /*-----------------------------------------------------------------*/
3072 /* genEndFunction - generates epilogue for functions */
3073 /*-----------------------------------------------------------------*/
3075 genEndFunction (iCode * ic)
3077 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3079 D (emitcode (";", "genEndFunction "););
3081 if (IFFUNC_ISNAKED(sym->type))
3083 emitcode(";", "naked function: no epilogue.");
3087 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3088 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3090 if (options.stack10bit) {
3092 emitcode ("mov", "sp,_bpx", spname);
3093 emitcode ("mov", "esp,_bpx+1", spname);
3096 emitcode ("mov", "%s,_bp", spname);
3100 /* if use external stack but some variables were
3101 added to the local stack then decrement the
3103 if (options.useXstack && sym->stack) {
3104 emitcode ("mov", "a,sp");
3105 emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3106 emitcode ("mov", "sp,a");
3110 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3111 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3113 if (options.useXstack) {
3114 emitcode ("mov", "r0,%s", spname);
3115 emitcode ("movx", "a,@r0");
3116 emitcode ("mov", "_bp,a");
3117 emitcode ("dec", "%s", spname);
3119 if (options.stack10bit) {
3120 emitcode ("pop", "_bpx+1");
3121 emitcode ("pop", "_bpx");
3123 emitcode ("pop", "_bp");
3128 /* restore the register bank */
3129 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3131 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3132 || !options.useXstack)
3134 /* Special case of ISR using non-zero bank with useXstack
3137 emitcode ("pop", "psw");
3141 if (IFFUNC_ISISR (sym->type))
3144 /* now we need to restore the registers */
3145 /* if this isr has no bank i.e. is going to
3146 run with bank 0 , then we need to save more
3148 if (!FUNC_REGBANK (sym->type))
3151 /* if this function does not call any other
3152 function then we can be economical and
3153 save only those registers that are used */
3154 if (!IFFUNC_HASFCALL(sym->type))
3157 /* if any registers used */
3160 /* save the registers used */
3161 for (i = sym->regsUsed->size; i >= 0; i--)
3163 if (bitVectBitValue (sym->regsUsed, i) ||
3164 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3165 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3172 /* this function has a function call cannot
3173 determines register usage so we will have to pop the
3175 if (options.parms_in_bank1) {
3176 for (i = 7 ; i >= 0 ; i-- ) {
3177 emitcode ("pop","%s",rb1regs[i]);
3180 unsaveRBank (0, ic, FALSE);
3185 /* This ISR uses a non-zero bank.
3187 * Restore any register banks saved by genFunction
3190 // jwk: this needs a closer look
3191 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3194 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3196 if (savedBanks & (1 << ix))
3198 unsaveRBank(ix, NULL, FALSE);
3202 if (options.useXstack)
3204 /* Restore bank AFTER calling unsaveRBank,
3205 * since it can trash r0.
3207 emitcode ("pop", "psw");
3211 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3213 if (options.stack10bit)
3215 emitcode ("pop", DP2_RESULT_REG);
3216 emitcode ("pop", "dpx1");
3217 emitcode ("pop", "dph1");
3218 emitcode ("pop", "dpl1");
3220 emitcode ("pop", "dps");
3221 emitcode ("pop", "dpx");
3223 if (!inExcludeList ("dph"))
3224 emitcode ("pop", "dph");
3225 if (!inExcludeList ("dpl"))
3226 emitcode ("pop", "dpl");
3227 if (!inExcludeList ("b"))
3228 emitcode ("pop", "b");
3229 if (!inExcludeList ("acc"))
3230 emitcode ("pop", "acc");
3232 if (IFFUNC_ISCRITICAL (sym->type))
3233 emitcode ("setb", "ea");
3235 /* if debug then send end of function */
3236 if (options.debug && currFunc) {
3238 emitcode ("", "C$%s$%d$%d$%d ==.",
3239 FileBaseName (ic->filename), currFunc->lastLine,
3240 ic->level, ic->block);
3241 if (IS_STATIC (currFunc->etype))
3242 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3244 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3248 emitcode ("reti", "");
3252 if (IFFUNC_ISCRITICAL (sym->type))
3253 emitcode ("setb", "ea");
3255 if (IFFUNC_CALLEESAVES(sym->type))
3259 /* if any registers used */
3262 /* save the registers used */
3263 for (i = sym->regsUsed->size; i >= 0; i--)
3265 if (bitVectBitValue (sym->regsUsed, i) ||
3266 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3267 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3273 /* if debug then send end of function */
3274 if (options.debug && currFunc)
3277 emitcode ("", "C$%s$%d$%d$%d ==.",
3278 FileBaseName (ic->filename), currFunc->lastLine,
3279 ic->level, ic->block);
3280 if (IS_STATIC (currFunc->etype))
3281 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3283 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3287 emitcode ("ret", "");
3292 /*-----------------------------------------------------------------*/
3293 /* genJavaNativeRet - generate code for return JavaNative */
3294 /*-----------------------------------------------------------------*/
3295 static void genJavaNativeRet(iCode *ic)
3299 aopOp (IC_LEFT (ic), ic, FALSE,
3300 (IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly ? FALSE :TRUE));
3301 size = AOP_SIZE (IC_LEFT (ic));
3305 /* it is assigned to GPR0-R3 then push them */
3306 if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3307 aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3308 for (i = 0 ; i < size ; i++ ) {
3309 emitcode ("push","%s",aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,FALSE));
3311 for (i = (size-1) ; i >= 0 ; i--) {
3312 emitcode ("pop","a%s",javaRet[i]);
3315 for (i = 0 ; i < size ; i++)
3316 emitcode ("mov","%s,%s",javaRet[i],aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,FALSE));
3318 for (i = size ; i < 4 ; i++ )
3319 emitcode ("mov","%s,#0",javaRet[i]);
3323 /*-----------------------------------------------------------------*/
3324 /* genRet - generate code for return statement */
3325 /*-----------------------------------------------------------------*/
3329 int size, offset = 0, pushed = 0;
3331 D (emitcode (";", "genRet ");
3334 /* if we have no return value then
3335 just generate the "ret" */
3339 /* if this is a JavaNative function then return
3340 value in different register */
3341 if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3342 genJavaNativeRet(ic);
3345 /* we have something to return then
3346 move the return value into place */
3347 aopOp (IC_LEFT (ic), ic, FALSE,
3348 (IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly ? FALSE :TRUE));
3349 size = AOP_SIZE (IC_LEFT (ic));
3351 _startLazyDPSEvaluation ();
3355 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3357 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3358 FALSE, TRUE, FALSE);
3359 emitcode ("push", "%s", l);
3364 /* Since A is the last element of fReturn,
3365 * is is OK to clobber it in the aopGet.
3367 l = aopGet (AOP (IC_LEFT (ic)), offset,
3368 FALSE, FALSE, TRUE);
3369 if (strcmp (fReturn[offset], l))
3370 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3373 _endLazyDPSEvaluation ();
3380 if (strcmp (fReturn[pushed], "a"))
3381 emitcode ("pop", fReturn[pushed]);
3383 emitcode ("pop", "acc");
3386 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3389 /* generate a jump to the return label
3390 if the next is not the return statement */
3391 if (!(ic->next && ic->next->op == LABEL &&
3392 IC_LABEL (ic->next) == returnLabel))
3394 emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3398 /*-----------------------------------------------------------------*/
3399 /* genLabel - generates a label */
3400 /*-----------------------------------------------------------------*/
3402 genLabel (iCode * ic)
3404 /* special case never generate */
3405 if (IC_LABEL (ic) == entryLabel)
3408 D (emitcode (";", "genLabel ");
3411 emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3414 /*-----------------------------------------------------------------*/
3415 /* genGoto - generates a ljmp */
3416 /*-----------------------------------------------------------------*/
3418 genGoto (iCode * ic)
3420 D (emitcode (";", "genGoto ");
3422 emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3425 /*-----------------------------------------------------------------*/
3426 /* findLabelBackwards: walks back through the iCode chain looking */
3427 /* for the given label. Returns number of iCode instructions */
3428 /* between that label and given ic. */
3429 /* Returns zero if label not found. */
3430 /*-----------------------------------------------------------------*/
3432 findLabelBackwards (iCode * ic, int key)
3441 /* If we have any pushes or pops, we cannot predict the distance.
3442 I don't like this at all, this should be dealt with in the
3444 if (ic->op == IPUSH || ic->op == IPOP) {
3448 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3450 /* printf("findLabelBackwards = %d\n", count); */
3458 /*-----------------------------------------------------------------*/
3459 /* genPlusIncr :- does addition with increment if possible */
3460 /*-----------------------------------------------------------------*/
3462 genPlusIncr (iCode * ic)
3464 unsigned int icount;
3465 unsigned int size = getDataSize (IC_RESULT (ic));
3467 /* will try to generate an increment */
3468 /* if the right side is not a literal
3470 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3473 /* if the literal value of the right hand side
3474 is greater than 4 then it is not worth it */
3475 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3478 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3479 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3481 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
3485 /* if increment 16 bits in register */
3487 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3488 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3489 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3497 /* If the next instruction is a goto and the goto target
3498 * is <= 5 instructions previous to this, we can generate
3499 * jumps straight to that target.
3501 if (ic->next && ic->next->op == GOTO
3502 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3505 emitcode (";", "tail increment optimized (range %d)", labelRange);
3506 tlbl = IC_LABEL (ic->next);
3511 tlbl = newiTempLabel (NULL);
3514 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3515 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3516 IS_AOP_PREG (IC_RESULT (ic)))
3517 emitcode ("cjne", "%s,#0,!tlabel"
3518 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3522 emitcode ("clr", "a");
3523 emitcode ("cjne", "a,%s,!tlabel"
3524 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3528 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3531 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3532 IS_AOP_PREG (IC_RESULT (ic)))
3533 emitcode ("cjne", "%s,#0,!tlabel"
3534 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3537 emitcode ("cjne", "a,%s,!tlabel"
3538 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3541 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3545 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3546 IS_AOP_PREG (IC_RESULT (ic)))
3547 emitcode ("cjne", "%s,#0,!tlabel"
3548 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3552 emitcode ("cjne", "a,%s,!tlabel"
3553 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3556 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3561 emitcode ("", "!tlabeldef", tlbl->key + 100);
3566 if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3567 !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 &&
3568 options.model == MODEL_FLAT24 ) {
3572 emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, FALSE));
3574 emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, FALSE));
3576 emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3579 while (icount--) emitcode ("inc","dptr");
3583 if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3584 AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3586 emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3587 while (icount--) emitcode ("inc","dptr");
3588 emitcode ("mov","dps,#0");
3592 /* if the sizes are greater than 1 then we cannot */
3593 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3594 AOP_SIZE (IC_LEFT (ic)) > 1)
3597 /* we can if the aops of the left & result match or
3598 if they are in registers and the registers are the
3601 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3602 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3603 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3608 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3609 emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3610 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3615 _startLazyDPSEvaluation ();
3618 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3620 _endLazyDPSEvaluation ();
3629 /*-----------------------------------------------------------------*/
3630 /* outBitAcc - output a bit in acc */
3631 /*-----------------------------------------------------------------*/
3633 outBitAcc (operand * result)
3635 symbol *tlbl = newiTempLabel (NULL);
3636 /* if the result is a bit */
3637 if (AOP_TYPE (result) == AOP_CRY)
3639 aopPut (AOP (result), "a", 0);
3643 emitcode ("jz", "!tlabel", tlbl->key + 100);
3644 emitcode ("mov", "a,%s", one);
3645 emitcode ("", "!tlabeldef", tlbl->key + 100);
3650 /*-----------------------------------------------------------------*/
3651 /* genPlusBits - generates code for addition of two bits */
3652 /*-----------------------------------------------------------------*/
3654 genPlusBits (iCode * ic)
3656 D (emitcode (";", "genPlusBits ");
3658 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3660 symbol *lbl = newiTempLabel (NULL);
3661 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3662 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3663 emitcode ("cpl", "c");
3664 emitcode ("", "!tlabeldef", (lbl->key + 100));
3665 outBitC (IC_RESULT (ic));
3669 emitcode ("clr", "a");
3670 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3671 emitcode ("rlc", "a");
3672 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3673 emitcode ("addc", "a,#0");
3674 outAcc (IC_RESULT (ic));
3679 adjustArithmeticResult (iCode * ic)
3681 if (opIsGptr (IC_RESULT (ic)) &&
3682 opIsGptr (IC_LEFT (ic)) &&
3683 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3685 aopPut (AOP (IC_RESULT (ic)),
3686 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3690 if (opIsGptr (IC_RESULT (ic)) &&
3691 opIsGptr (IC_RIGHT (ic)) &&
3692 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3694 aopPut (AOP (IC_RESULT (ic)),
3695 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3699 if (opIsGptr (IC_RESULT (ic)) &&
3700 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3701 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3702 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3703 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3706 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3707 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3711 #ifdef KEVIN_SCREWED_UP
3712 // Macro to aopOp all three operands of an ic. If this cannot be done,
3713 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3714 // will be set TRUE. The caller must then handle the case specially, noting
3715 // that the IC_RESULT operand is not aopOp'd.
3716 #define AOP_OP_3_NOFATAL(ic, rc) \
3717 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3718 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR) || \
3719 ((OP_SYMBOL(IC_RESULT(ic))->ruonly) && !isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)))); \
3720 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3721 (isOperandInFarSpace(IC_RESULT(ic)) || (OP_SYMBOL(IC_RESULT(ic))->ruonly && !isOperandEqual(IC_LEFT(ic),IC_RESULT(ic))))) \
3723 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3728 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3729 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3731 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3732 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3734 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3736 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3740 // aopOp the left & right operands of an ic.
3741 #define AOP_OP_2(ic) \
3742 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3743 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3745 #else // Kevin didn't screw up...
3747 #define AOP_IS_STR(x) (IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
3749 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
3750 // generates the result if possible. If result is generated, returns TRUE; otherwise
3751 // returns false and caller must deal with fact that result isn't aopOp'd.
3752 bool aopOp3(iCode * ic)
3754 bool dp1InUse, dp2InUse;
3756 // First, generate the right opcode. DPTR may be used if neither left nor result are
3759 // D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
3760 // AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
3761 // AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
3762 // AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
3765 aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)));
3767 // Now, the left opcode. This can use DPTR if the right didn't AND the result is not
3768 // AOP_STR (however, if the result is the same operand as the left, then DPTR may be used).
3769 aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)) ||
3770 (AOP_IS_STR(IC_RESULT(ic)) && !isOperandEqual(IC_LEFT(ic),IC_RESULT(ic))));
3772 // We've op'd the left. So, if left & result are the same operand, we know aopOp
3773 // will succeed, and we can just do it & bail.
3774 if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)))
3776 // D(emitcode(";", "aopOp3: left & result equal"););
3777 aopOp(IC_RESULT(ic),ic,TRUE, FALSE);
3781 // Note which dptrs are currently in use.
3782 dp1InUse = (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR) || (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) ||
3783 AOP_IS_STR(IC_RIGHT(ic)) || AOP_IS_STR(IC_LEFT(ic));
3784 dp2InUse = (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR2) || (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2);
3786 // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot generate it.
3787 if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
3792 // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck
3793 if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
3798 aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
3800 // SOme sanity checking...
3801 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 &&
3802 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2)
3805 "Ack: got unexpected DP2! (%s:%d %s:%d)\n",
3806 __FILE__, __LINE__, ic->filename, ic->lineno);
3812 // Macro to aopOp all three operands of an ic. If this cannot be done,
3813 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3814 // will be set TRUE. The caller must then handle the case specially, noting
3815 // that the IC_RESULT operand is not aopOp'd.
3817 #define AOP_OP_3_NOFATAL(ic, rc) \
3818 do { rc = !aopOp3(ic); } while (0)
3820 // aopOp the left & right operands of an ic.
3821 #define AOP_OP_2(ic) \
3822 aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
3823 aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
3827 // convienience macro.
3828 #define AOP_SET_LOCALS(ic) \
3829 left = IC_LEFT(ic); \
3830 right = IC_RIGHT(ic); \
3831 result = IC_RESULT(ic);
3834 // Given an integer value of pushedSize bytes on the stack,
3835 // adjust it to be resultSize bytes, either by discarding
3836 // the most significant bytes or by zero-padding.
3838 // On exit from this macro, pushedSize will have been adjusted to
3839 // equal resultSize, and ACC may be trashed.
3840 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3841 /* If the pushed data is bigger than the result, \
3842 * simply discard unused bytes. Icky, but works. \
3844 while (pushedSize > resultSize) \
3846 D (emitcode (";", "discarding unused result byte."););\
3847 emitcode ("pop", "acc"); \
3850 if (pushedSize < resultSize) \
3852 emitcode ("clr", "a"); \
3853 /* Conversly, we haven't pushed enough here. \
3854 * just zero-pad, and all is well. \
3856 while (pushedSize < resultSize) \
3858 emitcode("push", "acc"); \
3862 assert(pushedSize == resultSize);
3864 /*-----------------------------------------------------------------*/
3865 /* genPlus - generates code for addition */
3866 /*-----------------------------------------------------------------*/
3868 genPlus (iCode * ic)
3870 int size, offset = 0;
3871 bool pushResult = FALSE;
3874 D (emitcode (";", "genPlus "););
3876 /* special cases :- */
3877 if ( IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly &&
3878 isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
3879 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
3880 size = floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
3882 while (size--) emitcode ("inc","dptr");
3884 emitcode ("mov","a,dpl");
3885 emitcode ("add","a,#!constbyte",size & 0xff);
3886 emitcode ("mov","dpl,a");
3887 emitcode ("mov","a,dph");
3888 emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
3889 emitcode ("mov","dph,a");
3890 emitcode ("mov","a,dpx");
3891 emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
3892 emitcode ("mov","dpx,a");
3894 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
3897 if ( IS_SYMOP(IC_LEFT(ic)) &&
3898 OP_SYMBOL(IC_LEFT(ic))->remat &&
3899 isOperandInFarSpace(IC_RIGHT(ic))) {
3900 operand *op = IC_RIGHT(ic);
3901 IC_RIGHT(ic) = IC_LEFT(ic);
3905 AOP_OP_3_NOFATAL (ic, pushResult);
3908 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3913 /* if literal, literal on the right or
3914 if left requires ACC or right is already
3916 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3917 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3918 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3920 operand *t = IC_RIGHT (ic);
3921 IC_RIGHT (ic) = IC_LEFT (ic);
3923 emitcode (";", "Swapped plus args.");
3926 /* if both left & right are in bit
3928 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3929 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3935 /* if left in bit space & right literal */
3936 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3937 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3939 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3940 /* if result in bit space */
3941 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3943 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3944 emitcode ("cpl", "c");
3945 outBitC (IC_RESULT (ic));
3949 size = getDataSize (IC_RESULT (ic));
3950 _startLazyDPSEvaluation ();
3953 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3954 emitcode ("addc", "a,#0");
3955 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3957 _endLazyDPSEvaluation ();
3962 /* if I can do an increment instead
3963 of add then GOOD for ME */
3964 if (genPlusIncr (ic) == TRUE)
3966 emitcode (";", "did genPlusIncr");
3971 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3973 _startLazyDPSEvaluation ();
3976 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3978 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3980 emitcode ("add", "a,%s",
3981 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3983 emitcode ("addc", "a,%s",
3984 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3988 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3990 /* right is going to use ACC or we would have taken the
3993 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3995 D(emitcode(";", "+ AOP_ACC special case."););
3996 emitcode("xch", "a, %s", DP2_RESULT_REG);
3998 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
4001 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4004 emitcode("add", "a, %s", DP2_RESULT_REG);
4008 emitcode ("add", "a,%s",
4009 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
4014 emitcode ("addc", "a,%s",
4015 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
4020 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4024 emitcode ("push", "acc");
4028 _endLazyDPSEvaluation ();
4032 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4034 size = getDataSize (IC_LEFT (ic));
4035 rSize = getDataSize (IC_RESULT (ic));
4037 ADJUST_PUSHED_RESULT(size, rSize);
4039 _startLazyDPSEvaluation ();
4042 emitcode ("pop", "acc");
4043 aopPut (AOP (IC_RESULT (ic)), "a", size);
4045 _endLazyDPSEvaluation ();
4048 adjustArithmeticResult (ic);
4051 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4052 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4053 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4056 /*-----------------------------------------------------------------*/
4057 /* genMinusDec :- does subtraction with deccrement if possible */
4058 /*-----------------------------------------------------------------*/
4060 genMinusDec (iCode * ic)
4062 unsigned int icount;
4063 unsigned int size = getDataSize (IC_RESULT (ic));
4065 /* will try to generate an increment */
4066 /* if the right side is not a literal
4068 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4071 /* if the literal value of the right hand side
4072 is greater than 4 then it is not worth it */
4073 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4076 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4077 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4079 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
4083 /* if decrement 16 bits in register */
4084 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4085 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4086 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4094 /* If the next instruction is a goto and the goto target
4095 * is <= 5 instructions previous to this, we can generate
4096 * jumps straight to that target.
4098 if (ic->next && ic->next->op == GOTO
4099 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4102 emitcode (";", "tail decrement optimized (range %d)", labelRange);
4103 tlbl = IC_LABEL (ic->next);
4108 tlbl = newiTempLabel (NULL);
4112 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
4113 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4114 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4115 IS_AOP_PREG (IC_RESULT (ic)))
4116 emitcode ("cjne", "%s,#!constbyte,!tlabel"
4117 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE), 0xff
4121 emitcode ("mov", "a,#!constbyte",0xff);
4122 emitcode ("cjne", "a,%s,!tlabel"
4123 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
4126 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
4129 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4130 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4131 IS_AOP_PREG (IC_RESULT (ic)))
4132 emitcode ("cjne", "%s,#!constbyte,!tlabel"
4133 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE),0xff
4137 emitcode ("cjne", "a,%s,!tlabel"
4138 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
4141 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
4145 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4146 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4147 IS_AOP_PREG (IC_RESULT (ic)))
4148 emitcode ("cjne", "%s,#!constbyte,!tlabel"
4149 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE),0xff
4153 emitcode ("cjne", "a,%s,!tlabel"
4154 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
4157 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
4161 emitcode ("", "!tlabeldef", tlbl->key + 100);
4166 /* if the sizes are greater than 1 then we cannot */
4167 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4168 AOP_SIZE (IC_LEFT (ic)) > 1)
4171 /* we can if the aops of the left & result match or
4172 if they are in registers and the registers are the
4175 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4176 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4177 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4180 _startLazyDPSEvaluation ();
4183 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
4185 _endLazyDPSEvaluation ();
4193 /*-----------------------------------------------------------------*/
4194 /* addSign - complete with sign */
4195 /*-----------------------------------------------------------------*/
4197 addSign (operand * result, int offset, int sign)
4199 int size = (getDataSize (result) - offset);
4202 _startLazyDPSEvaluation();
4205 emitcode ("rlc", "a");
4206 emitcode ("subb", "a,acc");
4209 aopPut (AOP (result), "a", offset++);
4216 aopPut (AOP (result), zero, offset++);
4219 _endLazyDPSEvaluation();
4223 /*-----------------------------------------------------------------*/
4224 /* genMinusBits - generates code for subtraction of two bits */
4225 /*-----------------------------------------------------------------*/
4227 genMinusBits (iCode * ic)
4229 symbol *lbl = newiTempLabel (NULL);
4231 D (emitcode (";", "genMinusBits "););
4233 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4235 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4236 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4237 emitcode ("cpl", "c");
4238 emitcode ("", "!tlabeldef", (lbl->key + 100));
4239 outBitC (IC_RESULT (ic));
4243 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4244 emitcode ("subb", "a,acc");
4245 emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4246 emitcode ("inc", "a");
4247 emitcode ("", "!tlabeldef", (lbl->key + 100));
4248 aopPut (AOP (IC_RESULT (ic)), "a", 0);
4249 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4253 /*-----------------------------------------------------------------*/
4254 /* genMinus - generates code for subtraction */
4255 /*-----------------------------------------------------------------*/
4257 genMinus (iCode * ic)
4259 int size, offset = 0;
4261 unsigned long lit = 0L;
4262 bool pushResult = FALSE;
4264 D (emitcode (";", "genMinus "););
4266 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
4267 aopOp (IC_RIGHT (ic), ic, FALSE,
4268 (AOP_INDPTRn(IC_LEFT(ic)) ? FALSE : (AOP_USESDPTR(IC_LEFT(ic)) ? TRUE : FALSE)));
4269 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
4270 ((AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2)
4271 || OP_SYMBOL(IC_RESULT(ic))->ruonly))
4277 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
4279 /* special cases :- */
4280 /* if both left & right are in bit space */
4281 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4282 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4288 /* if I can do an decrement instead
4289 of subtract then GOOD for ME */
4290 if (genMinusDec (ic) == TRUE)
4295 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4297 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4303 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4308 /* if literal, add a,#-lit, else normal subb */
4309 _startLazyDPSEvaluation ();
4311 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
4312 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4313 if (AOP_USESDPTR(IC_RIGHT(ic))) {
4314 emitcode ("mov","b,a");
4315 MOVA(aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
4316 emitcode ("xch","a,b");
4317 emitcode ("subb","a,b");
4319 emitcode ("subb", "a,%s",
4320 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
4323 /* first add without previous c */
4325 if (!size && lit==-1) {
4326 emitcode ("dec", "a");
4328 emitcode ("add", "a,#!constbyte",
4329 (unsigned int) (lit & 0x0FFL));
4332 emitcode ("addc", "a,#!constbyte",
4333 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4338 emitcode ("push", "acc");
4340 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4344 _endLazyDPSEvaluation ();
4348 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4350 size = getDataSize (IC_LEFT (ic));
4351 rSize = getDataSize (IC_RESULT (ic));
4353 ADJUST_PUSHED_RESULT(size, rSize);
4355 _startLazyDPSEvaluation ();
4358 emitcode ("pop", "acc");
4359 aopPut (AOP (IC_RESULT (ic)), "a", size);
4361 _endLazyDPSEvaluation ();
4364 adjustArithmeticResult (ic);
4367 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4368 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4369 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4373 /*-----------------------------------------------------------------*/
4374 /* genMultbits :- multiplication of bits */
4375 /*-----------------------------------------------------------------*/
4377 genMultbits (operand * left,
4382 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4383 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4384 aopOp(result, ic, TRUE, FALSE);
4389 /*-----------------------------------------------------------------*/
4390 /* genMultOneByte : 8*8=8/16 bit multiplication */
4391 /*-----------------------------------------------------------------*/
4393 genMultOneByte (operand * left,
4398 sym_link *opetype = operandType (result);
4402 /* (if two literals: the value is computed before) */
4403 /* if one literal, literal on the right */
4404 if (AOP_TYPE (left) == AOP_LIT)
4409 emitcode (";", "swapped left and right");
4412 if (SPEC_USIGN(opetype)
4413 // ignore the sign of left and right, what else can we do?
4414 || (SPEC_USIGN(operandType(left)) &&
4415 SPEC_USIGN(operandType(right)))) {
4416 // just an unsigned 8*8=8/16 multiply
4417 //emitcode (";","unsigned");
4418 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4419 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4420 emitcode ("mul", "ab");
4422 _G.accInUse++; _G.bInUse++;
4423 aopOp(result, ic, TRUE, FALSE);
4425 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4427 // this should never happen
4428 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4429 AOP_SIZE(result), __FILE__, lineno);
4433 aopPut (AOP (result), "a", 0);
4434 _G.accInUse--; _G.bInUse--;
4435 if (AOP_SIZE(result)==2)
4437 aopPut (AOP (result), "b", 1);
4442 // we have to do a signed multiply
4444 emitcode (";", "signed");
4445 emitcode ("clr", "F0"); // reset sign flag
4446 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4448 lbl=newiTempLabel(NULL);
4449 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4450 // left side is negative, 8-bit two's complement, this fails for -128
4451 emitcode ("setb", "F0"); // set sign flag
4452 emitcode ("cpl", "a");
4453 emitcode ("inc", "a");
4455 emitcode ("", "!tlabeldef", lbl->key+100);
4458 if (AOP_TYPE(right)==AOP_LIT) {
4459 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4460 /* AND literal negative */
4461 if ((int) val < 0) {
4462 emitcode ("cpl", "F0"); // complement sign flag
4463 emitcode ("mov", "b,#!constbyte", -val);
4465 emitcode ("mov", "b,#!constbyte", val);
4468 lbl=newiTempLabel(NULL);
4469 emitcode ("mov", "b,a");
4470 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4471 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4472 // right side is negative, 8-bit two's complement
4473 emitcode ("cpl", "F0"); // complement sign flag
4474 emitcode ("cpl", "a");
4475 emitcode ("inc", "a");
4476 emitcode ("", "!tlabeldef", lbl->key+100);
4478 emitcode ("mul", "ab");
4480 _G.accInUse++;_G.bInUse++;
4481 aopOp(result, ic, TRUE, FALSE);
4483 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4485 // this should never happen
4486 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4487 AOP_SIZE(result), __FILE__, lineno);
4491 lbl=newiTempLabel(NULL);
4492 emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4493 // only ONE op was negative, we have to do a 8/16-bit two's complement
4494 emitcode ("cpl", "a"); // lsb
4495 if (AOP_SIZE(result)==1) {
4496 emitcode ("inc", "a");
4498 emitcode ("add", "a,#1");
4499 emitcode ("xch", "a,b");
4500 emitcode ("cpl", "a"); // msb
4501 emitcode ("addc", "a,#0");
4502 emitcode ("xch", "a,b");
4505 emitcode ("", "!tlabeldef", lbl->key+100);
4506 aopPut (AOP (result), "a", 0);
4507 _G.accInUse--;_G.bInUse--;
4508 if (AOP_SIZE(result)==2) {
4509 aopPut (AOP (result), "b", 1);
4513 /*-----------------------------------------------------------------*/
4514 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
4515 /*-----------------------------------------------------------------*/
4516 static void genMultTwoByte (operand *left, operand *right,
4517 operand *result, iCode *ic)
4519 sym_link *retype = getSpec(operandType(right));
4520 sym_link *letype = getSpec(operandType(left));
4521 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4524 if (AOP_TYPE (left) == AOP_LIT) {
4529 /* save EA bit in F1 */
4530 lbl = newiTempLabel(NULL);
4531 emitcode ("setb","F1");
4532 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4533 emitcode ("clr","F1");
4534 emitcode("","!tlabeldef",lbl->key+100);
4536 /* load up MB with right */
4538 emitcode("clr","F0");
4539 if (AOP_TYPE(right) == AOP_LIT) {
4540 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4542 emitcode("setb","F0");
4545 emitcode ("mov","mb,#!constbyte",val & 0xff);
4546 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4548 lbl = newiTempLabel(NULL);
4549 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4550 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4551 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4552 emitcode ("xch", "a,b");
4553 emitcode ("cpl","a");
4554 emitcode ("add", "a,#1");
4555 emitcode ("xch", "a,b");
4556 emitcode ("cpl", "a"); // msb
4557 emitcode ("addc", "a,#0");
4558 emitcode ("setb","F0");
4559 emitcode ("","!tlabeldef",lbl->key+100);
4560 emitcode ("mov","mb,b");
4561 emitcode ("mov","mb,a");
4564 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4565 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4567 /* load up MA with left */
4569 lbl = newiTempLabel(NULL);
4570 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4571 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4572 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4573 emitcode ("xch", "a,b");
4574 emitcode ("cpl","a");
4575 emitcode ("add", "a,#1");
4576 emitcode ("xch", "a,b");
4577 emitcode ("cpl", "a"); // msb
4578 emitcode ("addc","a,#0");
4579 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4580 emitcode ("setb","F0");
4581 emitcode ("","!tlabeldef",lbl->key+100);
4582 emitcode ("mov","ma,b");
4583 emitcode ("mov","ma,a");
4585 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4586 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4588 /* wait for multiplication to finish */
4589 lbl = newiTempLabel(NULL);
4590 emitcode("","!tlabeldef", lbl->key+100);
4591 emitcode("mov","a,mcnt1");
4592 emitcode("anl","a,#!constbyte",0x80);
4593 emitcode("jnz","!tlabel",lbl->key+100);
4595 freeAsmop (left, NULL, ic, TRUE);
4596 freeAsmop (right, NULL, ic,TRUE);
4597 aopOp(result, ic, TRUE, FALSE);
4599 /* if unsigned then simple */
4601 emitcode ("mov","a,ma");
4602 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4603 emitcode ("mov","a,ma");
4604 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4605 aopPut(AOP(result),"ma",1);
4606 aopPut(AOP(result),"ma",0);
4608 emitcode("push","ma");
4609 emitcode("push","ma");
4610 emitcode("push","ma");
4612 /* negate result if needed */
4613 lbl = newiTempLabel(NULL);
4614 emitcode("jnb","F0,!tlabel",lbl->key+100);
4615 emitcode("cpl","a");
4616 emitcode("add","a,#1");
4617 emitcode("","!tlabeldef", lbl->key+100);
4618 if (AOP_TYPE(result) == AOP_ACC)
4620 D(emitcode(";", "ACC special case."););
4621 /* We know result is the only live aop, and
4622 * it's obviously not a DPTR2, so AP is available.
4624 emitcode("mov", "%s,acc", DP2_RESULT_REG);
4628 aopPut(AOP(result),"a",0);
4631 emitcode("pop","acc");
4632 lbl = newiTempLabel(NULL);
4633 emitcode("jnb","F0,!tlabel",lbl->key+100);
4634 emitcode("cpl","a");
4635 emitcode("addc","a,#0");
4636 emitcode("","!tlabeldef", lbl->key+100);
4637 aopPut(AOP(result),"a",1);
4638 emitcode("pop","acc");
4639 if (AOP_SIZE(result) >= 3) {
4640 lbl = newiTempLabel(NULL);
4641 emitcode("jnb","F0,!tlabel",lbl->key+100);
4642 emitcode("cpl","a");
4643 emitcode("addc","a,#0");
4644 emitcode("","!tlabeldef", lbl->key+100);
4645 aopPut(AOP(result),"a",2);
4647 emitcode("pop","acc");
4648 if (AOP_SIZE(result) >= 4) {
4649 lbl = newiTempLabel(NULL);
4650 emitcode("jnb","F0,!tlabel",lbl->key+100);
4651 emitcode("cpl","a");
4652 emitcode("addc","a,#0");
4653 emitcode("","!tlabeldef", lbl->key+100);
4654 aopPut(AOP(result),"a",3);
4656 if (AOP_TYPE(result) == AOP_ACC)
4658 /* We stashed the result away above. */
4659 emitcode("mov", "acc,%s", DP2_RESULT_REG);
4663 freeAsmop (result, NULL, ic, TRUE);
4665 /* restore EA bit in F1 */
4666 lbl = newiTempLabel(NULL);
4667 emitcode ("jnb","F1,!tlabel",lbl->key+100);
4668 emitcode ("setb","EA");
4669 emitcode("","!tlabeldef",lbl->key+100);
4673 /*-----------------------------------------------------------------*/
4674 /* genMult - generates code for multiplication */
4675 /*-----------------------------------------------------------------*/
4677 genMult (iCode * ic)
4679 operand *left = IC_LEFT (ic);
4680 operand *right = IC_RIGHT (ic);
4681 operand *result = IC_RESULT (ic);
4683 D (emitcode (";", "genMult "););
4685 /* assign the amsops */
4688 /* special cases first */
4690 if (AOP_TYPE (left) == AOP_CRY &&
4691 AOP_TYPE (right) == AOP_CRY)
4693 genMultbits (left, right, result, ic);
4697 /* if both are of size == 1 */
4698 if (AOP_SIZE (left) == 1 &&
4699 AOP_SIZE (right) == 1)
4701 genMultOneByte (left, right, result, ic);
4705 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4706 /* use the ds390 ARITHMETIC accel UNIT */
4707 genMultTwoByte (left, right, result, ic);
4710 /* should have been converted to function call */
4714 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4715 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4716 freeAsmop (result, NULL, ic, TRUE);
4719 /*-----------------------------------------------------------------*/
4720 /* genDivbits :- division of bits */
4721 /*-----------------------------------------------------------------*/
4723 genDivbits (operand * left,
4731 /* the result must be bit */
4732 LOAD_AB_FOR_DIV (left, right, l);
4733 emitcode ("div", "ab");
4734 emitcode ("rrc", "a");
4735 aopOp(result, ic, TRUE, FALSE);
4737 aopPut (AOP (result), "c", 0);
4740 /*-----------------------------------------------------------------*/
4741 /* genDivOneByte : 8 bit division */
4742 /*-----------------------------------------------------------------*/
4744 genDivOneByte (operand * left,
4749 sym_link *opetype = operandType (result);
4755 /* signed or unsigned */
4756 if (SPEC_USIGN (opetype))
4758 /* unsigned is easy */
4759 LOAD_AB_FOR_DIV (left, right, l);
4760 emitcode ("div", "ab");
4763 aopOp(result, ic, TRUE, FALSE);
4764 aopPut (AOP (result), "a", 0);
4767 size = AOP_SIZE (result) - 1;
4771 aopPut (AOP (result), zero, offset++);
4776 /* signed is a little bit more difficult */
4778 /* save the signs of the operands */
4779 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4781 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4782 emitcode ("push", "acc"); /* save it on the stack */
4784 /* now sign adjust for both left & right */
4785 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4787 lbl = newiTempLabel (NULL);
4788 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4789 emitcode ("cpl", "a");
4790 emitcode ("inc", "a");
4791 emitcode ("", "!tlabeldef", (lbl->key + 100));
4792 emitcode ("mov", "b,a");
4794 /* sign adjust left side */
4795 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4798 lbl = newiTempLabel (NULL);
4799 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4800 emitcode ("cpl", "a");
4801 emitcode ("inc", "a");
4802 emitcode ("", "!tlabeldef", (lbl->key + 100));
4804 /* now the division */
4805 emitcode ("nop", "; workaround for DS80C390 div bug.");
4806 emitcode ("div", "ab");
4807 /* we are interested in the lower order
4809 emitcode ("mov", "b,a");
4810 lbl = newiTempLabel (NULL);
4811 emitcode ("pop", "acc");
4812 /* if there was an over flow we don't
4813 adjust the sign of the result */
4814 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4815 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4817 emitcode ("clr", "a");
4818 emitcode ("subb", "a,b");
4819 emitcode ("mov", "b,a");
4820 emitcode ("", "!tlabeldef", (lbl->key + 100));
4822 /* now we are done */
4823 _G.accInUse++; _G.bInUse++;
4824 aopOp(result, ic, TRUE, FALSE);
4826 aopPut (AOP (result), "b", 0);
4828 size = AOP_SIZE (result) - 1;
4832 emitcode ("mov", "c,b.7");
4833 emitcode ("subb", "a,acc");
4837 aopPut (AOP (result), "a", offset++);
4839 _G.accInUse--; _G.bInUse--;
4843 /*-----------------------------------------------------------------*/
4844 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
4845 /*-----------------------------------------------------------------*/
4846 static void genDivTwoByte (operand *left, operand *right,
4847 operand *result, iCode *ic)
4849 sym_link *retype = getSpec(operandType(right));
4850 sym_link *letype = getSpec(operandType(left));
4851 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4854 /* save EA bit in F1 */
4855 lbl = newiTempLabel(NULL);
4856 emitcode ("setb","F1");
4857 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4858 emitcode ("clr","F1");
4859 emitcode("","!tlabeldef",lbl->key+100);
4861 /* load up MA with left */
4863 emitcode("clr","F0");
4864 lbl = newiTempLabel(NULL);
4865 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4866 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4867 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4868 emitcode ("xch", "a,b");
4869 emitcode ("cpl","a");
4870 emitcode ("add", "a,#1");
4871 emitcode ("xch", "a,b");
4872 emitcode ("cpl", "a"); // msb
4873 emitcode ("addc","a,#0");
4874 emitcode ("setb","F0");
4875 emitcode ("","!tlabeldef",lbl->key+100);
4876 emitcode ("mov","ma,b");
4877 emitcode ("mov","ma,a");
4879 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4880 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4883 /* load up MB with right */
4885 if (AOP_TYPE(right) == AOP_LIT) {
4886 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4888 lbl = newiTempLabel(NULL);
4889 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4890 emitcode("setb","F0");
4891 emitcode ("","!tlabeldef",lbl->key+100);
4894 emitcode ("mov","mb,#!constbyte",val & 0xff);
4895 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4897 lbl = newiTempLabel(NULL);
4898 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4899 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4900 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4901 emitcode ("xch", "a,b");
4902 emitcode ("cpl","a");
4903 emitcode ("add", "a,#1");
4904 emitcode ("xch", "a,b");
4905 emitcode ("cpl", "a"); // msb
4906 emitcode ("addc", "a,#0");
4907 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4908 emitcode ("setb","F0");
4909 emitcode ("","!tlabeldef",lbl->key+100);
4910 emitcode ("mov","mb,b");
4911 emitcode ("mov","mb,a");
4914 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4915 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4918 /* wait for multiplication to finish */
4919 lbl = newiTempLabel(NULL);
4920 emitcode("","!tlabeldef", lbl->key+100);
4921 emitcode("mov","a,mcnt1");
4922 emitcode("anl","a,#!constbyte",0x80);
4923 emitcode("jnz","!tlabel",lbl->key+100);
4925 freeAsmop (left, NULL, ic, TRUE);
4926 freeAsmop (right, NULL, ic,TRUE);
4927 aopOp(result, ic, TRUE, FALSE);
4929 /* if unsigned then simple */
4931 aopPut(AOP(result),"ma",1);
4932 aopPut(AOP(result),"ma",0);
4934 emitcode("push","ma");
4936 /* negate result if needed */
4937 lbl = newiTempLabel(NULL);
4938 emitcode("jnb","F0,!tlabel",lbl->key+100);
4939 emitcode("cpl","a");
4940 emitcode("add","a,#1");
4941 emitcode("","!tlabeldef", lbl->key+100);
4942 aopPut(AOP(result),"a",0);
4943 emitcode("pop","acc");
4944 lbl = newiTempLabel(NULL);
4945 emitcode("jnb","F0,!tlabel",lbl->key+100);
4946 emitcode("cpl","a");
4947 emitcode("addc","a,#0");
4948 emitcode("","!tlabeldef", lbl->key+100);
4949 aopPut(AOP(result),"a",1);
4951 freeAsmop (result, NULL, ic, TRUE);
4952 /* restore EA bit in F1 */
4953 lbl = newiTempLabel(NULL);
4954 emitcode ("jnb","F1,!tlabel",lbl->key+100);
4955 emitcode ("setb","EA");
4956 emitcode("","!tlabeldef",lbl->key+100);
4960 /*-----------------------------------------------------------------*/
4961 /* genDiv - generates code for division */
4962 /*-----------------------------------------------------------------*/
4966 operand *left = IC_LEFT (ic);
4967 operand *right = IC_RIGHT (ic);
4968 operand *result = IC_RESULT (ic);
4970 D (emitcode (";", "genDiv "););
4972 /* assign the amsops */
4975 /* special cases first */
4977 if (AOP_TYPE (left) == AOP_CRY &&
4978 AOP_TYPE (right) == AOP_CRY)
4980 genDivbits (left, right, result, ic);
4984 /* if both are of size == 1 */
4985 if (AOP_SIZE (left) == 1 &&
4986 AOP_SIZE (right) == 1)
4988 genDivOneByte (left, right, result, ic);
4992 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4993 /* use the ds390 ARITHMETIC accel UNIT */
4994 genDivTwoByte (left, right, result, ic);
4997 /* should have been converted to function call */
5000 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5001 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5002 freeAsmop (result, NULL, ic, TRUE);
5005 /*-----------------------------------------------------------------*/
5006 /* genModbits :- modulus of bits */
5007 /*-----------------------------------------------------------------*/
5009 genModbits (operand * left,
5017 /* the result must be bit */
5018 LOAD_AB_FOR_DIV (left, right, l);
5019 emitcode ("div", "ab");
5020 emitcode ("mov", "a,b");
5021 emitcode ("rrc", "a");
5022 aopOp(result, ic, TRUE, FALSE);
5023 aopPut (AOP (result), "c", 0);
5026 /*-----------------------------------------------------------------*/
5027 /* genModOneByte : 8 bit modulus */
5028 /*-----------------------------------------------------------------*/
5030 genModOneByte (operand * left,
5035 sym_link *opetype = operandType (result);
5039 /* signed or unsigned */
5040 if (SPEC_USIGN (opetype))
5042 /* unsigned is easy */
5043 LOAD_AB_FOR_DIV (left, right, l);
5044 emitcode ("div", "ab");
5045 aopOp(result, ic, TRUE, FALSE);
5046 aopPut (AOP (result), "b", 0);
5050 /* signed is a little bit more difficult */
5052 /* save the signs of the operands */
5053 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
5056 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
5057 emitcode ("push", "acc"); /* save it on the stack */
5059 /* now sign adjust for both left & right */
5060 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
5063 lbl = newiTempLabel (NULL);
5064 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5065 emitcode ("cpl", "a");
5066 emitcode ("inc", "a");
5067 emitcode ("", "!tlabeldef", (lbl->key + 100));
5068 emitcode ("mov", "b,a");
5070 /* sign adjust left side */
5071 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
5074 lbl = newiTempLabel (NULL);
5075 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5076 emitcode ("cpl", "a");
5077 emitcode ("inc", "a");
5078 emitcode ("", "!tlabeldef", (lbl->key + 100));
5080 /* now the multiplication */
5081 emitcode ("nop", "; workaround for DS80C390 div bug.");
5082 emitcode ("div", "ab");
5083 /* we are interested in the lower order
5085 lbl = newiTempLabel (NULL);
5086 emitcode ("pop", "acc");
5087 /* if there was an over flow we don't
5088 adjust the sign of the result */
5089 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
5090 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5092 emitcode ("clr", "a");
5093 emitcode ("subb", "a,b");
5094 emitcode ("mov", "b,a");
5095 emitcode ("", "!tlabeldef", (lbl->key + 100));
5098 /* now we are done */
5099 aopOp(result, ic, TRUE, FALSE);
5100 aopPut (AOP (result), "b", 0);
5105 /*-----------------------------------------------------------------*/
5106 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
5107 /*-----------------------------------------------------------------*/
5108 static void genModTwoByte (operand *left, operand *right,
5109 operand *result, iCode *ic)
5111 sym_link *retype = getSpec(operandType(right));
5112 sym_link *letype = getSpec(operandType(left));
5113 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5116 /* load up MA with left */
5117 /* save EA bit in F1 */
5118 lbl = newiTempLabel(NULL);
5119 emitcode ("setb","F1");
5120 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5121 emitcode ("clr","F1");
5122 emitcode("","!tlabeldef",lbl->key+100);
5125 lbl = newiTempLabel(NULL);
5126 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
5127 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
5128 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5129 emitcode ("xch", "a,b");
5130 emitcode ("cpl","a");
5131 emitcode ("add", "a,#1");
5132 emitcode ("xch", "a,b");
5133 emitcode ("cpl", "a"); // msb
5134 emitcode ("addc","a,#0");
5135 emitcode ("","!tlabeldef",lbl->key+100);
5136 emitcode ("mov","ma,b");
5137 emitcode ("mov","ma,a");
5139 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
5140 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
5143 /* load up MB with right */
5145 if (AOP_TYPE(right) == AOP_LIT) {
5146 int val=floatFromVal (AOP (right)->aopu.aop_lit);
5150 emitcode ("mov","mb,#!constbyte",val & 0xff);
5151 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5153 lbl = newiTempLabel(NULL);
5154 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
5155 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
5156 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5157 emitcode ("xch", "a,b");
5158 emitcode ("cpl","a");
5159 emitcode ("add", "a,#1");
5160 emitcode ("xch", "a,b");
5161 emitcode ("cpl", "a"); // msb
5162 emitcode ("addc", "a,#0");
5163 emitcode ("","!tlabeldef",lbl->key+100);
5164 emitcode ("mov","mb,b");
5165 emitcode ("mov","mb,a");
5168 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
5169 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
5172 /* wait for multiplication to finish */
5173 lbl = newiTempLabel(NULL);
5174 emitcode("","!tlabeldef", lbl->key+100);
5175 emitcode("mov","a,mcnt1");
5176 emitcode("anl","a,#!constbyte",0x80);
5177 emitcode("jnz","!tlabel",lbl->key+100);
5179 freeAsmop (left, NULL, ic, TRUE);
5180 freeAsmop (right, NULL, ic,TRUE);
5181 aopOp(result, ic, TRUE, FALSE);
5183 aopPut(AOP(result),"mb",1);
5184 aopPut(AOP(result),"mb",0);
5185 freeAsmop (result, NULL, ic, TRUE);
5187 /* restore EA bit in F1 */
5188 lbl = newiTempLabel(NULL);
5189 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5190 emitcode ("setb","EA");
5191 emitcode("","!tlabeldef",lbl->key+100);
5195 /*-----------------------------------------------------------------*/
5196 /* genMod - generates code for division */
5197 /*-----------------------------------------------------------------*/
5201 operand *left = IC_LEFT (ic);
5202 operand *right = IC_RIGHT (ic);
5203 operand *result = IC_RESULT (ic);
5205 D (emitcode (";", "genMod "); );
5207 /* assign the amsops */
5210 /* special cases first */
5212 if (AOP_TYPE (left) == AOP_CRY &&
5213 AOP_TYPE (right) == AOP_CRY)
5215 genModbits (left, right, result, ic);
5219 /* if both are of size == 1 */
5220 if (AOP_SIZE (left) == 1 &&
5221 AOP_SIZE (right) == 1)
5223 genModOneByte (left, right, result, ic);
5227 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5228 /* use the ds390 ARITHMETIC accel UNIT */
5229 genModTwoByte (left, right, result, ic);
5233 /* should have been converted to function call */
5237 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5238 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5239 freeAsmop (result, NULL, ic, TRUE);
5242 /*-----------------------------------------------------------------*/
5243 /* genIfxJump :- will create a jump depending on the ifx */
5244 /*-----------------------------------------------------------------*/
5246 genIfxJump (iCode * ic, char *jval)
5249 symbol *tlbl = newiTempLabel (NULL);
5252 D (emitcode (";", "genIfxJump ");
5255 /* if true label then we jump if condition
5259 jlbl = IC_TRUE (ic);
5260 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5261 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5265 /* false label is present */
5266 jlbl = IC_FALSE (ic);
5267 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5268 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5270 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5271 emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5273 emitcode (inst, "!tlabel", tlbl->key + 100);
5274 emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5275 emitcode ("", "!tlabeldef", tlbl->key + 100);
5277 /* mark the icode as generated */
5281 /*-----------------------------------------------------------------*/
5282 /* genCmp :- greater or less than comparison */
5283 /*-----------------------------------------------------------------*/
5285 genCmp (operand * left, operand * right,
5286 iCode * ic, iCode * ifx, int sign)
5288 int size, offset = 0;
5289 unsigned long lit = 0L;
5292 D (emitcode (";", "genCmp");
5295 result = IC_RESULT (ic);
5297 /* if left & right are bit variables */
5298 if (AOP_TYPE (left) == AOP_CRY &&
5299 AOP_TYPE (right) == AOP_CRY)
5301 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5302 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
5306 /* subtract right from left if at the
5307 end the carry flag is set then we know that
5308 left is greater than right */
5309 size = max (AOP_SIZE (left), AOP_SIZE (right));
5311 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5312 if ((size == 1) && !sign &&
5313 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5315 symbol *lbl = newiTempLabel (NULL);
5316 emitcode ("cjne", "%s,%s,!tlabel",
5317 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5318 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5320 emitcode ("", "!tlabeldef", lbl->key + 100);
5324 if (AOP_TYPE (right) == AOP_LIT)
5326 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5327 /* optimize if(x < 0) or if(x >= 0) */
5336 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
5338 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5339 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5341 aopOp (result, ic, FALSE, FALSE);
5343 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5345 freeAsmop (result, NULL, ic, TRUE);
5346 genIfxJump (ifx, "acc.7");
5351 emitcode ("rlc", "a");
5353 goto release_freedLR;
5361 //emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5362 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5363 //emitcode (";", "genCmp #2");
5364 if (sign && (size == 0))
5366 //emitcode (";", "genCmp #3");
5367 emitcode ("xrl", "a,#!constbyte",0x80);
5368 if (AOP_TYPE (right) == AOP_LIT)
5370 unsigned long lit = (unsigned long)
5371 floatFromVal (AOP (right)->aopu.aop_lit);
5372 //emitcode (";", "genCmp #3.1");
5373 emitcode ("subb", "a,#!constbyte",
5374 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5378 //emitcode (";", "genCmp #3.2");
5379 if (AOP_NEEDSACC (right))
5381 emitcode ("push", "acc");
5383 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
5384 FALSE, FALSE, FALSE));
5385 emitcode ("xrl", "b,#!constbyte",0x80);
5386 if (AOP_NEEDSACC (right))
5388 emitcode ("pop", "acc");
5390 emitcode ("subb", "a,b");
5397 //emitcode (";", "genCmp #4");
5398 if (AOP_NEEDSACC (right))
5401 //emitcode (";", "genCmp #4.1");
5402 emitcode ("xch", "a, b");
5403 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
5404 emitcode ("xch", "a, b");
5409 //emitcode (";", "genCmp #4.2");
5410 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
5413 emitcode ("subb", "a,%s", s);
5420 /* Don't need the left & right operands any more; do need the result. */
5421 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5422 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5424 aopOp (result, ic, FALSE, FALSE);
5428 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5434 /* if the result is used in the next
5435 ifx conditional branch then generate
5436 code a little differently */
5439 genIfxJump (ifx, "c");
5445 /* leave the result in acc */
5447 freeAsmop (result, NULL, ic, TRUE);
5450 /*-----------------------------------------------------------------*/
5451 /* genCmpGt :- greater than comparison */
5452 /*-----------------------------------------------------------------*/
5454 genCmpGt (iCode * ic, iCode * ifx)
5456 operand *left, *right;
5457 sym_link *letype, *retype;
5460 D (emitcode (";", "genCmpGt ");
5463 left = IC_LEFT (ic);
5464 right = IC_RIGHT (ic);
5466 letype = getSpec (operandType (left));
5467 retype = getSpec (operandType (right));
5468 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5470 /* assign the left & right amsops */
5473 genCmp (right, left, ic, ifx, sign);
5476 /*-----------------------------------------------------------------*/
5477 /* genCmpLt - less than comparisons */
5478 /*-----------------------------------------------------------------*/
5480 genCmpLt (iCode * ic, iCode * ifx)
5482 operand *left, *right;
5483 sym_link *letype, *retype;
5486 D (emitcode (";", "genCmpLt "););
5488 left = IC_LEFT (ic);
5489 right = IC_RIGHT (ic);
5491 letype = getSpec (operandType (left));
5492 retype = getSpec (operandType (right));
5493 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5495 /* assign the left & right amsops */
5498 genCmp (left, right, ic, ifx, sign);
5501 /*-----------------------------------------------------------------*/
5502 /* gencjneshort - compare and jump if not equal */
5503 /*-----------------------------------------------------------------*/
5505 gencjneshort (operand * left, operand * right, symbol * lbl)
5507 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5509 unsigned long lit = 0L;
5511 D (emitcode (";", "gencjneshort");
5514 /* if the left side is a literal or
5515 if the right is in a pointer register and left
5517 if ((AOP_TYPE (left) == AOP_LIT) ||
5518 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5525 if (AOP_TYPE (right) == AOP_LIT)
5526 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5528 if (opIsGptr (left) || opIsGptr (right))
5530 /* We are comparing a generic pointer to something.
5531 * Exclude the generic type byte from the comparison.
5534 D (emitcode (";", "cjneshort: generic ptr special case.");
5539 /* if the right side is a literal then anything goes */
5540 if (AOP_TYPE (right) == AOP_LIT &&
5541 AOP_TYPE (left) != AOP_DIR)
5545 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5547 emitcode ("cjne", "a,%s,!tlabel",
5548 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5554 /* if the right side is in a register or in direct space or
5555 if the left is a pointer register & right is not */
5556 else if (AOP_TYPE (right) == AOP_REG ||
5557 AOP_TYPE (right) == AOP_DIR ||
5558 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5559 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5563 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5564 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5565 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5566 emitcode ("jnz", "!tlabel", lbl->key + 100);
5568 emitcode ("cjne", "a,%s,!tlabel",
5569 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
5576 /* right is a pointer reg need both a & b */
5579 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5580 if (strcmp (l, "b"))
5581 emitcode ("mov", "b,%s", l);
5582 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5583 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5589 /*-----------------------------------------------------------------*/
5590 /* gencjne - compare and jump if not equal */
5591 /*-----------------------------------------------------------------*/
5593 gencjne (operand * left, operand * right, symbol * lbl)
5595 symbol *tlbl = newiTempLabel (NULL);
5597 D (emitcode (";", "gencjne");
5600 gencjneshort (left, right, lbl);
5602 emitcode ("mov", "a,%s", one);
5603 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5604 emitcode ("", "!tlabeldef", lbl->key + 100);
5605 emitcode ("clr", "a");
5606 emitcode ("", "!tlabeldef", tlbl->key + 100);
5609 /*-----------------------------------------------------------------*/
5610 /* genCmpEq - generates code for equal to */
5611 /*-----------------------------------------------------------------*/
5613 genCmpEq (iCode * ic, iCode * ifx)
5615 operand *left, *right, *result;
5617 D (emitcode (";", "genCmpEq ");
5621 AOP_SET_LOCALS (ic);
5623 /* if literal, literal on the right or
5624 if the right is in a pointer register and left
5626 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5627 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5629 operand *t = IC_RIGHT (ic);
5630 IC_RIGHT (ic) = IC_LEFT (ic);
5634 if (ifx && /* !AOP_SIZE(result) */
5635 OP_SYMBOL (result) &&
5636 OP_SYMBOL (result)->regType == REG_CND)
5639 /* if they are both bit variables */
5640 if (AOP_TYPE (left) == AOP_CRY &&
5641 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5643 if (AOP_TYPE (right) == AOP_LIT)
5645 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5648 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5649 emitcode ("cpl", "c");
5653 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5657 emitcode ("clr", "c");
5659 /* AOP_TYPE(right) == AOP_CRY */
5663 symbol *lbl = newiTempLabel (NULL);
5664 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5665 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5666 emitcode ("cpl", "c");
5667 emitcode ("", "!tlabeldef", (lbl->key + 100));
5669 /* if true label then we jump if condition
5671 tlbl = newiTempLabel (NULL);
5674 emitcode ("jnc", "!tlabel", tlbl->key + 100);
5675 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5679 emitcode ("jc", "!tlabel", tlbl->key + 100);
5680 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5682 emitcode ("", "!tlabeldef", tlbl->key + 100);
5686 tlbl = newiTempLabel (NULL);
5687 gencjneshort (left, right, tlbl);
5690 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5691 emitcode ("", "!tlabeldef", tlbl->key + 100);
5695 symbol *lbl = newiTempLabel (NULL);
5696 emitcode ("sjmp", "!tlabel", lbl->key + 100);
5697 emitcode ("", "!tlabeldef", tlbl->key + 100);
5698 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5699 emitcode ("", "!tlabeldef", lbl->key + 100);
5702 /* mark the icode as generated */
5705 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5706 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
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));
5741 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5742 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5744 aopOp (result, ic, TRUE, FALSE);
5747 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5754 genIfxJump (ifx, "c");
5757 /* if the result is used in an arithmetic operation
5758 then put the result in place */
5763 gencjne (left, right, newiTempLabel (NULL));
5765 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5766 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5768 aopOp (result, ic, TRUE, FALSE);
5770 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5772 aopPut (AOP (result), "a", 0);
5777 genIfxJump (ifx, "a");
5780 /* if the result is used in an arithmetic operation
5781 then put the result in place */
5782 if (AOP_TYPE (result) != AOP_CRY)
5784 /* leave the result in acc */
5788 freeAsmop (result, NULL, ic, TRUE);
5791 /*-----------------------------------------------------------------*/
5792 /* ifxForOp - returns the icode containing the ifx for operand */
5793 /*-----------------------------------------------------------------*/
5795 ifxForOp (operand * op, iCode * ic)
5797 /* if true symbol then needs to be assigned */
5798 if (IS_TRUE_SYMOP (op))
5801 /* if this has register type condition and
5802 the next instruction is ifx with the same operand
5803 and live to of the operand is upto the ifx only then */
5805 ic->next->op == IFX &&
5806 IC_COND (ic->next)->key == op->key &&
5807 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5812 /*-----------------------------------------------------------------*/
5813 /* hasInc - operand is incremented before any other use */
5814 /*-----------------------------------------------------------------*/
5816 hasInc (operand *op, iCode *ic, int osize)
5818 sym_link *type = operandType(op);
5819 sym_link *retype = getSpec (type);
5820 iCode *lic = ic->next;
5823 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5824 if (!IS_SYMOP(op)) return NULL;
5826 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5827 if (IS_AGGREGATE(type->next)) return NULL;
5828 if (osize != (isize = getSize(type->next))) return NULL;
5831 /* if operand of the form op = op + <sizeof *op> */
5832 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5833 isOperandEqual(IC_RESULT(lic),op) &&
5834 isOperandLiteral(IC_RIGHT(lic)) &&
5835 operandLitValue(IC_RIGHT(lic)) == isize) {
5838 /* if the operand used or deffed */
5839 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5842 /* if GOTO or IFX */
5843 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5849 /*-----------------------------------------------------------------*/
5850 /* genAndOp - for && operation */
5851 /*-----------------------------------------------------------------*/
5853 genAndOp (iCode * ic)
5855 operand *left, *right, *result;
5858 D (emitcode (";", "genAndOp "););
5860 /* note here that && operations that are in an
5861 if statement are taken away by backPatchLabels
5862 only those used in arthmetic operations remain */
5864 AOP_SET_LOCALS (ic);
5866 /* if both are bit variables */
5867 if (AOP_TYPE (left) == AOP_CRY &&
5868 AOP_TYPE (right) == AOP_CRY)
5870 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5871 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5872 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5873 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5875 aopOp (result,ic,FALSE, FALSE);
5880 tlbl = newiTempLabel (NULL);
5882 emitcode ("jz", "!tlabel", tlbl->key + 100);
5884 emitcode ("", "!tlabeldef", tlbl->key + 100);
5885 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5886 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5888 aopOp (result,ic,FALSE, FALSE);
5891 freeAsmop (result, NULL, ic, TRUE);
5895 /*-----------------------------------------------------------------*/
5896 /* genOrOp - for || operation */
5897 /*-----------------------------------------------------------------*/
5899 genOrOp (iCode * ic)
5901 operand *left, *right, *result;
5904 D (emitcode (";", "genOrOp "););
5906 /* note here that || operations that are in an
5907 if statement are taken away by backPatchLabels
5908 only those used in arthmetic operations remain */
5910 AOP_SET_LOCALS (ic);
5912 /* if both are bit variables */
5913 if (AOP_TYPE (left) == AOP_CRY &&
5914 AOP_TYPE (right) == AOP_CRY)
5916 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5917 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5918 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5919 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5921 aopOp (result,ic,FALSE, FALSE);
5927 tlbl = newiTempLabel (NULL);
5929 emitcode ("jnz", "!tlabel", tlbl->key + 100);
5931 emitcode ("", "!tlabeldef", tlbl->key + 100);
5932 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5933 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5935 aopOp (result,ic,FALSE, FALSE);
5940 freeAsmop (result, NULL, ic, TRUE);
5943 /*-----------------------------------------------------------------*/
5944 /* isLiteralBit - test if lit == 2^n */
5945 /*-----------------------------------------------------------------*/
5947 isLiteralBit (unsigned long lit)
5949 unsigned long pw[32] =
5950 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5951 0x100L, 0x200L, 0x400L, 0x800L,
5952 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5953 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5954 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5955 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5956 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5959 for (idx = 0; idx < 32; idx++)
5965 /*-----------------------------------------------------------------*/
5966 /* continueIfTrue - */
5967 /*-----------------------------------------------------------------*/
5969 continueIfTrue (iCode * ic)
5972 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
5976 /*-----------------------------------------------------------------*/
5978 /*-----------------------------------------------------------------*/
5980 jumpIfTrue (iCode * ic)
5983 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
5987 /*-----------------------------------------------------------------*/
5988 /* jmpTrueOrFalse - */
5989 /*-----------------------------------------------------------------*/
5991 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5993 // ugly but optimized by peephole
5996 symbol *nlbl = newiTempLabel (NULL);
5997 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
5998 emitcode ("", "!tlabeldef", tlbl->key + 100);
5999 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6000 emitcode ("", "!tlabeldef", nlbl->key + 100);
6004 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6005 emitcode ("", "!tlabeldef", tlbl->key + 100);
6010 // Generate code to perform a bit-wise logic operation
6011 // on two operands in far space (assumed to already have been
6012 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6013 // in far space. This requires pushing the result on the stack
6014 // then popping it into the result.
6016 genFarFarLogicOp(iCode *ic, char *logicOp)
6018 int size, resultSize, compSize;
6022 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6023 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
6024 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6026 _startLazyDPSEvaluation();
6027 for (size = compSize; (size--); offset++)
6029 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
6030 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6031 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
6033 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6034 emitcode ("push", "acc");
6036 _endLazyDPSEvaluation();
6038 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6039 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6040 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6042 resultSize = AOP_SIZE(IC_RESULT(ic));
6044 ADJUST_PUSHED_RESULT(compSize, resultSize);
6046 _startLazyDPSEvaluation();
6049 emitcode ("pop", "acc");
6050 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6052 _endLazyDPSEvaluation();
6053 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6057 /*-----------------------------------------------------------------*/
6058 /* genAnd - code for and */
6059 /*-----------------------------------------------------------------*/
6061 genAnd (iCode * ic, iCode * ifx)
6063 operand *left, *right, *result;
6064 int size, offset = 0;
6065 unsigned long lit = 0L;
6070 D (emitcode (";", "genAnd "););
6072 AOP_OP_3_NOFATAL (ic, pushResult);
6073 AOP_SET_LOCALS (ic);
6077 genFarFarLogicOp(ic, "anl");
6082 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6084 AOP_TYPE (left), AOP_TYPE (right));
6085 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6087 AOP_SIZE (left), AOP_SIZE (right));
6090 /* if left is a literal & right is not then exchange them */
6091 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6092 #ifdef LOGIC_OPS_BROKEN
6093 || AOP_NEEDSACC (left)
6097 operand *tmp = right;
6102 /* if result = right then exchange them */
6103 if (sameRegs (AOP (result), AOP (right)))
6105 operand *tmp = right;
6110 /* if right is bit then exchange them */
6111 if (AOP_TYPE (right) == AOP_CRY &&
6112 AOP_TYPE (left) != AOP_CRY)
6114 operand *tmp = right;
6118 if (AOP_TYPE (right) == AOP_LIT)
6119 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6121 size = AOP_SIZE (result);
6124 // result = bit & yy;
6125 if (AOP_TYPE (left) == AOP_CRY)
6127 // c = bit & literal;
6128 if (AOP_TYPE (right) == AOP_LIT)
6132 if (size && sameRegs (AOP (result), AOP (left)))
6135 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6140 if (size && (AOP_TYPE (result) == AOP_CRY))
6142 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6145 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6150 emitcode ("clr", "c");
6155 if (AOP_TYPE (right) == AOP_CRY)
6158 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6159 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6164 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
6166 emitcode ("rrc", "a");
6167 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6175 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6176 genIfxJump (ifx, "c");
6180 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6181 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6182 if ((AOP_TYPE (right) == AOP_LIT) &&
6183 (AOP_TYPE (result) == AOP_CRY) &&
6184 (AOP_TYPE (left) != AOP_CRY))
6186 int posbit = isLiteralBit (lit);
6191 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
6194 emitcode ("mov", "c,acc.%d", posbit & 0x07);
6200 sprintf (buffer, "acc.%d", posbit & 0x07);
6201 genIfxJump (ifx, buffer);
6205 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6212 symbol *tlbl = newiTempLabel (NULL);
6213 int sizel = AOP_SIZE (left);
6215 emitcode ("setb", "c");
6218 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6220 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6222 if ((posbit = isLiteralBit (bytelit)) != 0)
6223 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6226 if (bytelit != 0x0FFL)
6227 emitcode ("anl", "a,%s",
6228 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
6229 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6234 // bit = left & literal
6237 emitcode ("clr", "c");
6238 emitcode ("", "!tlabeldef", tlbl->key + 100);
6240 // if(left & literal)
6244 jmpTrueOrFalse (ifx, tlbl);
6252 /* if left is same as result */
6253 if (sameRegs (AOP (result), AOP (left)))
6255 for (; size--; offset++)
6257 if (AOP_TYPE (right) == AOP_LIT)
6259 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6261 else if (bytelit == 0)
6262 aopPut (AOP (result), zero, offset);
6263 else if (IS_AOP_PREG (result))
6265 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6266 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6267 aopPut (AOP (result), "a", offset);
6270 emitcode ("anl", "%s,%s",
6271 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6272 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6276 if (AOP_TYPE (left) == AOP_ACC)
6277 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6280 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6281 if (IS_AOP_PREG (result))
6283 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6284 aopPut (AOP (result), "a", offset);
6288 emitcode ("anl", "%s,a",
6289 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6296 // left & result in different registers
6297 if (AOP_TYPE (result) == AOP_CRY)
6300 // if(size), result in bit
6301 // if(!size && ifx), conditional oper: if(left & right)
6302 symbol *tlbl = newiTempLabel (NULL);
6303 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6305 emitcode ("setb", "c");
6308 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6309 emitcode ("anl", "a,%s",
6310 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6312 if (AOP_TYPE(left)==AOP_ACC) {
6313 emitcode("mov", "b,a");
6314 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6315 emitcode("anl", "a,b");
6317 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6318 emitcode ("anl", "a,%s",
6319 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6322 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6328 emitcode ("", "!tlabeldef", tlbl->key + 100);
6332 jmpTrueOrFalse (ifx, tlbl);
6336 for (; (size--); offset++)
6339 // result = left & right
6340 if (AOP_TYPE (right) == AOP_LIT)
6342 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6344 aopPut (AOP (result),
6345 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6349 else if (bytelit == 0)
6351 aopPut (AOP (result), zero, offset);
6354 D (emitcode (";", "better literal AND."););
6355 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6356 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6357 FALSE, FALSE, FALSE));
6362 // faster than result <- left, anl result,right
6363 // and better if result is SFR
6364 if (AOP_TYPE (left) == AOP_ACC)
6366 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
6367 FALSE, FALSE, FALSE));
6371 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6372 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6374 emitcode("mov", "b,a");
6378 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6379 emitcode ("anl", "a,%s", rOp);
6382 aopPut (AOP (result), "a", offset);
6388 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6389 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6390 freeAsmop (result, NULL, ic, TRUE);
6394 /*-----------------------------------------------------------------*/
6395 /* genOr - code for or */
6396 /*-----------------------------------------------------------------*/
6398 genOr (iCode * ic, iCode * ifx)
6400 operand *left, *right, *result;
6401 int size, offset = 0;
6402 unsigned long lit = 0L;
6405 D (emitcode (";", "genOr "););
6407 AOP_OP_3_NOFATAL (ic, pushResult);
6408 AOP_SET_LOCALS (ic);
6412 genFarFarLogicOp(ic, "orl");
6418 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6420 AOP_TYPE (left), AOP_TYPE (right));
6421 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6423 AOP_SIZE (left), AOP_SIZE (right));
6426 /* if left is a literal & right is not then exchange them */
6427 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6428 #ifdef LOGIC_OPS_BROKEN
6429 || AOP_NEEDSACC (left) // I think this is a net loss now.
6433 operand *tmp = right;
6438 /* if result = right then exchange them */
6439 if (sameRegs (AOP (result), AOP (right)))
6441 operand *tmp = right;
6446 /* if right is bit then exchange them */
6447 if (AOP_TYPE (right) == AOP_CRY &&
6448 AOP_TYPE (left) != AOP_CRY)
6450 operand *tmp = right;
6454 if (AOP_TYPE (right) == AOP_LIT)
6455 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6457 size = AOP_SIZE (result);
6461 if (AOP_TYPE (left) == AOP_CRY)
6463 if (AOP_TYPE (right) == AOP_LIT)
6465 // c = bit & literal;
6468 // lit != 0 => result = 1
6469 if (AOP_TYPE (result) == AOP_CRY)
6472 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6474 continueIfTrue (ifx);
6477 emitcode ("setb", "c");
6481 // lit == 0 => result = left
6482 if (size && sameRegs (AOP (result), AOP (left)))
6484 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6489 if (AOP_TYPE (right) == AOP_CRY)
6492 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6493 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6498 symbol *tlbl = newiTempLabel (NULL);
6499 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6500 emitcode ("setb", "c");
6501 emitcode ("jb", "%s,!tlabel",
6502 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6504 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6505 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6507 jmpTrueOrFalse (ifx, tlbl);
6513 emitcode ("", "!tlabeldef", tlbl->key + 100);
6522 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6523 genIfxJump (ifx, "c");
6527 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6528 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6529 if ((AOP_TYPE (right) == AOP_LIT) &&
6530 (AOP_TYPE (result) == AOP_CRY) &&
6531 (AOP_TYPE (left) != AOP_CRY))
6537 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6539 continueIfTrue (ifx);
6544 // lit = 0, result = boolean(left)
6546 emitcode ("setb", "c");
6550 symbol *tlbl = newiTempLabel (NULL);
6551 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6553 emitcode ("", "!tlabeldef", tlbl->key + 100);
6557 genIfxJump (ifx, "a");
6565 /* if left is same as result */
6566 if (sameRegs (AOP (result), AOP (left)))
6568 for (; size--; offset++)
6570 if (AOP_TYPE (right) == AOP_LIT)
6572 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6578 if (IS_AOP_PREG (left))
6580 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6581 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6582 aopPut (AOP (result), "a", offset);
6586 emitcode ("orl", "%s,%s",
6587 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6588 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6594 if (AOP_TYPE (left) == AOP_ACC)
6596 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6600 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6601 if (IS_AOP_PREG (left))
6603 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6604 aopPut (AOP (result), "a", offset);
6608 emitcode ("orl", "%s,a",
6609 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6617 // left & result in different registers
6618 if (AOP_TYPE (result) == AOP_CRY)
6621 // if(size), result in bit
6622 // if(!size && ifx), conditional oper: if(left | right)
6623 symbol *tlbl = newiTempLabel (NULL);
6624 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6626 emitcode ("setb", "c");
6629 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6630 emitcode ("orl", "a,%s",
6631 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6633 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6634 emitcode ("orl", "a,%s",
6635 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6637 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6643 emitcode ("", "!tlabeldef", tlbl->key + 100);
6647 jmpTrueOrFalse (ifx, tlbl);
6651 _startLazyDPSEvaluation();
6652 for (; (size--); offset++)
6655 // result = left & right
6656 if (AOP_TYPE (right) == AOP_LIT)
6658 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6660 aopPut (AOP (result),
6661 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6665 D (emitcode (";", "better literal OR."););
6666 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6667 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
6668 FALSE, FALSE, FALSE));
6673 // faster than result <- left, anl result,right
6674 // and better if result is SFR
6675 if (AOP_TYPE (left) == AOP_ACC)
6677 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
6678 FALSE, FALSE, FALSE));
6682 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6684 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6686 emitcode("mov", "b,a");
6690 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6691 emitcode ("orl", "a,%s", rOp);
6694 aopPut (AOP (result), "a", offset);
6696 _endLazyDPSEvaluation();
6701 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6702 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6703 freeAsmop (result, NULL, ic, TRUE);
6706 /*-----------------------------------------------------------------*/
6707 /* genXor - code for xclusive or */
6708 /*-----------------------------------------------------------------*/
6710 genXor (iCode * ic, iCode * ifx)
6712 operand *left, *right, *result;
6713 int size, offset = 0;
6714 unsigned long lit = 0L;
6717 D (emitcode (";", "genXor "););
6719 AOP_OP_3_NOFATAL (ic, pushResult);
6720 AOP_SET_LOCALS (ic);
6724 genFarFarLogicOp(ic, "xrl");
6729 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6731 AOP_TYPE (left), AOP_TYPE (right));
6732 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6734 AOP_SIZE (left), AOP_SIZE (right));
6737 /* if left is a literal & right is not ||
6738 if left needs acc & right does not */
6739 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6740 #ifdef LOGIC_OPS_BROKEN
6741 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6745 operand *tmp = right;
6750 /* if result = right then exchange them */
6751 if (sameRegs (AOP (result), AOP (right)))
6753 operand *tmp = right;
6758 /* if right is bit then exchange them */
6759 if (AOP_TYPE (right) == AOP_CRY &&
6760 AOP_TYPE (left) != AOP_CRY)
6762 operand *tmp = right;
6766 if (AOP_TYPE (right) == AOP_LIT)
6767 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6769 size = AOP_SIZE (result);
6773 if (AOP_TYPE (left) == AOP_CRY)
6775 if (AOP_TYPE (right) == AOP_LIT)
6777 // c = bit & literal;
6780 // lit>>1 != 0 => result = 1
6781 if (AOP_TYPE (result) == AOP_CRY)
6784 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6786 continueIfTrue (ifx);
6789 emitcode ("setb", "c");
6796 // lit == 0, result = left
6797 if (size && sameRegs (AOP (result), AOP (left)))
6799 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6803 // lit == 1, result = not(left)
6804 if (size && sameRegs (AOP (result), AOP (left)))
6806 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6811 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6812 emitcode ("cpl", "c");
6821 symbol *tlbl = newiTempLabel (NULL);
6822 if (AOP_TYPE (right) == AOP_CRY)
6825 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6829 int sizer = AOP_SIZE (right);
6831 // if val>>1 != 0, result = 1
6832 emitcode ("setb", "c");
6835 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
6837 // test the msb of the lsb
6838 emitcode ("anl", "a,#!constbyte",0xfe);
6839 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6843 emitcode ("rrc", "a");
6845 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6846 emitcode ("cpl", "c");
6847 emitcode ("", "!tlabeldef", (tlbl->key + 100));
6854 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6855 genIfxJump (ifx, "c");
6859 if (sameRegs (AOP (result), AOP (left)))
6861 /* if left is same as result */
6862 for (; size--; offset++)
6864 if (AOP_TYPE (right) == AOP_LIT)
6866 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6868 else if (IS_AOP_PREG (left))
6870 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6871 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6872 aopPut (AOP (result), "a", offset);
6875 emitcode ("xrl", "%s,%s",
6876 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6877 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6881 if (AOP_TYPE (left) == AOP_ACC)
6882 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6885 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6886 if (IS_AOP_PREG (left))
6888 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6889 aopPut (AOP (result), "a", offset);
6892 emitcode ("xrl", "%s,a",
6893 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6900 // left & result in different registers
6901 if (AOP_TYPE (result) == AOP_CRY)
6904 // if(size), result in bit
6905 // if(!size && ifx), conditional oper: if(left ^ right)
6906 symbol *tlbl = newiTempLabel (NULL);
6907 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6910 emitcode ("setb", "c");
6913 if ((AOP_TYPE (right) == AOP_LIT) &&
6914 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6916 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6920 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6921 emitcode ("xrl", "a,%s",
6922 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6924 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6925 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6927 emitcode("mov", "b,a");
6931 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6932 emitcode ("xrl", "a,%s", rOp);
6935 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6941 emitcode ("", "!tlabeldef", tlbl->key + 100);
6945 jmpTrueOrFalse (ifx, tlbl);
6949 for (; (size--); offset++)
6952 // result = left & right
6953 if (AOP_TYPE (right) == AOP_LIT)
6955 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6957 aopPut (AOP (result),
6958 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6962 D (emitcode (";", "better literal XOR."););
6963 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6964 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
6965 FALSE, FALSE, FALSE));
6969 // faster than result <- left, anl result,right
6970 // and better if result is SFR
6971 if (AOP_TYPE (left) == AOP_ACC)
6973 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
6974 FALSE, FALSE, FALSE));
6978 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6979 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6981 emitcode("mov", "b,a");
6985 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6986 emitcode ("xrl", "a,%s", rOp);
6989 aopPut (AOP (result), "a", offset);
6996 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6997 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6998 freeAsmop (result, NULL, ic, TRUE);
7001 /*-----------------------------------------------------------------*/
7002 /* genInline - write the inline code out */
7003 /*-----------------------------------------------------------------*/
7005 genInline (iCode * ic)
7007 char *buffer, *bp, *bp1;
7009 D (emitcode (";", "genInline ");
7012 _G.inLine += (!options.asmpeep);
7014 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
7015 strcpy (buffer, IC_INLINE (ic));
7017 /* emit each line as a code */
7042 /* emitcode("",buffer); */
7043 _G.inLine -= (!options.asmpeep);
7046 /*-----------------------------------------------------------------*/
7047 /* genRRC - rotate right with carry */
7048 /*-----------------------------------------------------------------*/
7052 operand *left, *result;
7053 int size, offset = 0;
7056 D (emitcode (";", "genRRC ");
7059 /* rotate right with carry */
7060 left = IC_LEFT (ic);
7061 result = IC_RESULT (ic);
7062 aopOp (left, ic, FALSE, FALSE);
7063 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7065 /* move it to the result */
7066 size = AOP_SIZE (result);
7070 _startLazyDPSEvaluation ();
7073 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
7075 emitcode ("rrc", "a");
7076 if (AOP_SIZE (result) > 1)
7077 aopPut (AOP (result), "a", offset--);
7079 _endLazyDPSEvaluation ();
7081 /* now we need to put the carry into the
7082 highest order byte of the result */
7083 if (AOP_SIZE (result) > 1)
7085 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
7088 emitcode ("mov", "acc.7,c");
7089 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7090 freeAsmop (left, NULL, ic, TRUE);
7091 freeAsmop (result, NULL, ic, TRUE);
7094 /*-----------------------------------------------------------------*/
7095 /* genRLC - generate code for rotate left with carry */
7096 /*-----------------------------------------------------------------*/
7100 operand *left, *result;
7101 int size, offset = 0;
7104 D (emitcode (";", "genRLC ");
7107 /* rotate right with carry */
7108 left = IC_LEFT (ic);
7109 result = IC_RESULT (ic);
7110 aopOp (left, ic, FALSE, FALSE);
7111 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7113 /* move it to the result */
7114 size = AOP_SIZE (result);
7118 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
7120 emitcode ("add", "a,acc");
7121 if (AOP_SIZE (result) > 1)
7123 aopPut (AOP (result), "a", offset++);
7126 _startLazyDPSEvaluation ();
7129 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
7131 emitcode ("rlc", "a");
7132 if (AOP_SIZE (result) > 1)
7133 aopPut (AOP (result), "a", offset++);
7135 _endLazyDPSEvaluation ();
7137 /* now we need to put the carry into the
7138 highest order byte of the result */
7139 if (AOP_SIZE (result) > 1)
7141 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
7144 emitcode ("mov", "acc.0,c");
7145 aopPut (AOP (result), "a", 0);
7146 freeAsmop (left, NULL, ic, TRUE);
7147 freeAsmop (result, NULL, ic, TRUE);
7150 /*-----------------------------------------------------------------*/
7151 /* genGetHbit - generates code get highest order bit */
7152 /*-----------------------------------------------------------------*/
7154 genGetHbit (iCode * ic)
7156 operand *left, *result;
7157 left = IC_LEFT (ic);
7158 result = IC_RESULT (ic);
7159 aopOp (left, ic, FALSE, FALSE);
7160 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7162 D (emitcode (";", "genGetHbit ");
7165 /* get the highest order byte into a */
7166 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
7167 if (AOP_TYPE (result) == AOP_CRY)
7169 emitcode ("rlc", "a");
7174 emitcode ("rl", "a");
7175 emitcode ("anl", "a,#1");
7180 freeAsmop (left, NULL, ic, TRUE);
7181 freeAsmop (result, NULL, ic, TRUE);
7184 /*-----------------------------------------------------------------*/
7185 /* AccRol - rotate left accumulator by known count */
7186 /*-----------------------------------------------------------------*/
7188 AccRol (int shCount)
7190 shCount &= 0x0007; // shCount : 0..7
7197 emitcode ("rl", "a");
7200 emitcode ("rl", "a");
7201 emitcode ("rl", "a");
7204 emitcode ("swap", "a");
7205 emitcode ("rr", "a");
7208 emitcode ("swap", "a");
7211 emitcode ("swap", "a");
7212 emitcode ("rl", "a");
7215 emitcode ("rr", "a");
7216 emitcode ("rr", "a");
7219 emitcode ("rr", "a");
7224 /*-----------------------------------------------------------------*/
7225 /* AccLsh - left shift accumulator by known count */
7226 /*-----------------------------------------------------------------*/
7228 AccLsh (int shCount)
7233 emitcode ("add", "a,acc");
7234 else if (shCount == 2)
7236 emitcode ("add", "a,acc");
7237 emitcode ("add", "a,acc");
7241 /* rotate left accumulator */
7243 /* and kill the lower order bits */
7244 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7249 /*-----------------------------------------------------------------*/
7250 /* AccRsh - right shift accumulator by known count */
7251 /*-----------------------------------------------------------------*/
7253 AccRsh (int shCount)
7260 emitcode ("rrc", "a");
7264 /* rotate right accumulator */
7265 AccRol (8 - shCount);
7266 /* and kill the higher order bits */
7267 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7272 #ifdef BETTER_LITERAL_SHIFT
7273 /*-----------------------------------------------------------------*/
7274 /* AccSRsh - signed right shift accumulator by known count */
7275 /*-----------------------------------------------------------------*/
7277 AccSRsh (int shCount)
7284 emitcode ("mov", "c,acc.7");
7285 emitcode ("rrc", "a");
7287 else if (shCount == 2)
7289 emitcode ("mov", "c,acc.7");
7290 emitcode ("rrc", "a");
7291 emitcode ("mov", "c,acc.7");
7292 emitcode ("rrc", "a");
7296 tlbl = newiTempLabel (NULL);
7297 /* rotate right accumulator */
7298 AccRol (8 - shCount);
7299 /* and kill the higher order bits */
7300 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7301 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7302 emitcode ("orl", "a,#!constbyte",
7303 (unsigned char) ~SRMask[shCount]);
7304 emitcode ("", "!tlabeldef", tlbl->key + 100);
7310 #ifdef BETTER_LITERAL_SHIFT
7311 /*-----------------------------------------------------------------*/
7312 /* shiftR1Left2Result - shift right one byte from left to result */
7313 /*-----------------------------------------------------------------*/
7315 shiftR1Left2Result (operand * left, int offl,
7316 operand * result, int offr,
7317 int shCount, int sign)
7319 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7320 /* shift right accumulator */
7325 aopPut (AOP (result), "a", offr);
7329 #ifdef BETTER_LITERAL_SHIFT
7330 /*-----------------------------------------------------------------*/
7331 /* shiftL1Left2Result - shift left one byte from left to result */
7332 /*-----------------------------------------------------------------*/
7334 shiftL1Left2Result (operand * left, int offl,
7335 operand * result, int offr, int shCount)
7337 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7338 /* shift left accumulator */
7340 aopPut (AOP (result), "a", offr);
7344 #ifdef BETTER_LITERAL_SHIFT
7345 /*-----------------------------------------------------------------*/
7346 /* movLeft2Result - move byte from left to result */
7347 /*-----------------------------------------------------------------*/
7349 movLeft2Result (operand * left, int offl,
7350 operand * result, int offr, int sign)
7353 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7355 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
7357 if (*l == '@' && (IS_AOP_PREG (result)))
7359 emitcode ("mov", "a,%s", l);
7360 aopPut (AOP (result), "a", offr);
7366 aopPut (AOP (result), l, offr);
7370 /* MSB sign in acc.7 ! */
7371 if (getDataSize (left) == offl + 1)
7373 emitcode ("mov", "a,%s", l);
7374 aopPut (AOP (result), "a", offr);
7382 #ifdef BETTER_LITERAL_SHIFT
7383 /*-----------------------------------------------------------------*/
7384 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7385 /*-----------------------------------------------------------------*/
7389 emitcode ("rrc", "a");
7390 emitcode ("xch", "a,%s", x);
7391 emitcode ("rrc", "a");
7392 emitcode ("xch", "a,%s", x);
7396 #ifdef BETTER_LITERAL_SHIFT
7398 /*-----------------------------------------------------------------*/
7399 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7400 /*-----------------------------------------------------------------*/
7404 emitcode ("xch", "a,%s", x);
7405 emitcode ("rlc", "a");
7406 emitcode ("xch", "a,%s", x);
7407 emitcode ("rlc", "a");
7411 #ifdef BETTER_LITERAL_SHIFT
7412 /*-----------------------------------------------------------------*/
7413 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7414 /*-----------------------------------------------------------------*/
7418 emitcode ("xch", "a,%s", x);
7419 emitcode ("add", "a,acc");
7420 emitcode ("xch", "a,%s", x);
7421 emitcode ("rlc", "a");
7425 #ifdef BETTER_LITERAL_SHIFT
7426 /*-----------------------------------------------------------------*/
7427 /* AccAXLsh - left shift a:x by known count (0..7) */
7428 /*-----------------------------------------------------------------*/
7430 AccAXLsh (char *x, int shCount)
7445 case 5: // AAAAABBB:CCCCCDDD
7447 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7449 emitcode ("anl", "a,#!constbyte",
7450 SLMask[shCount]); // BBB00000:CCCCCDDD
7452 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7454 AccRol (shCount); // DDDCCCCC:BBB00000
7456 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7458 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7460 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7462 emitcode ("anl", "a,#!constbyte",
7463 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7465 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7467 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7470 case 6: // AAAAAABB:CCCCCCDD
7471 emitcode ("anl", "a,#!constbyte",
7472 SRMask[shCount]); // 000000BB:CCCCCCDD
7473 emitcode ("mov", "c,acc.0"); // c = B
7474 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7476 AccAXRrl1 (x); // BCCCCCCD:D000000B
7477 AccAXRrl1 (x); // BBCCCCCC:DD000000
7479 emitcode("rrc","a");
7480 emitcode("xch","a,%s", x);
7481 emitcode("rrc","a");
7482 emitcode("mov","c,acc.0"); //<< get correct bit
7483 emitcode("xch","a,%s", x);
7485 emitcode("rrc","a");
7486 emitcode("xch","a,%s", x);
7487 emitcode("rrc","a");
7488 emitcode("xch","a,%s", x);
7491 case 7: // a:x <<= 7
7493 emitcode ("anl", "a,#!constbyte",
7494 SRMask[shCount]); // 0000000B:CCCCCCCD
7496 emitcode ("mov", "c,acc.0"); // c = B
7498 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7500 AccAXRrl1 (x); // BCCCCCCC:D0000000
7509 #ifdef BETTER_LITERAL_SHIFT
7511 /*-----------------------------------------------------------------*/
7512 /* AccAXRsh - right shift a:x known count (0..7) */
7513 /*-----------------------------------------------------------------*/
7515 AccAXRsh (char *x, int shCount)
7523 AccAXRrl1 (x); // 0->a:x
7528 AccAXRrl1 (x); // 0->a:x
7531 AccAXRrl1 (x); // 0->a:x
7536 case 5: // AAAAABBB:CCCCCDDD = a:x
7538 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7540 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7542 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7544 emitcode ("anl", "a,#!constbyte",
7545 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7547 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7549 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7551 emitcode ("anl", "a,#!constbyte",
7552 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7554 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7556 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7558 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7561 case 6: // AABBBBBB:CCDDDDDD
7563 emitcode ("mov", "c,acc.7");
7564 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7566 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7568 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7570 emitcode ("anl", "a,#!constbyte",
7571 SRMask[shCount]); // 000000AA:BBBBBBCC
7574 case 7: // ABBBBBBB:CDDDDDDD
7576 emitcode ("mov", "c,acc.7"); // c = A
7578 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7580 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7582 emitcode ("anl", "a,#!constbyte",
7583 SRMask[shCount]); // 0000000A:BBBBBBBC
7592 #ifdef BETTER_LITERAL_SHIFT
7593 /*-----------------------------------------------------------------*/
7594 /* AccAXRshS - right shift signed a:x known count (0..7) */
7595 /*-----------------------------------------------------------------*/
7597 AccAXRshS (char *x, int shCount)
7605 emitcode ("mov", "c,acc.7");
7606 AccAXRrl1 (x); // s->a:x
7610 emitcode ("mov", "c,acc.7");
7611 AccAXRrl1 (x); // s->a:x
7613 emitcode ("mov", "c,acc.7");
7614 AccAXRrl1 (x); // s->a:x
7619 case 5: // AAAAABBB:CCCCCDDD = a:x
7621 tlbl = newiTempLabel (NULL);
7622 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7624 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7626 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7628 emitcode ("anl", "a,#!constbyte",
7629 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7631 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7633 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7635 emitcode ("anl", "a,#!constbyte",
7636 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7638 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7640 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7642 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7644 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7645 emitcode ("orl", "a,#!constbyte",
7646 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7648 emitcode ("", "!tlabeldef", tlbl->key + 100);
7649 break; // SSSSAAAA:BBBCCCCC
7651 case 6: // AABBBBBB:CCDDDDDD
7653 tlbl = newiTempLabel (NULL);
7654 emitcode ("mov", "c,acc.7");
7655 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7657 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7659 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7661 emitcode ("anl", "a,#!constbyte",
7662 SRMask[shCount]); // 000000AA:BBBBBBCC
7664 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7665 emitcode ("orl", "a,#!constbyte",
7666 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7668 emitcode ("", "!tlabeldef", tlbl->key + 100);
7670 case 7: // ABBBBBBB:CDDDDDDD
7672 tlbl = newiTempLabel (NULL);
7673 emitcode ("mov", "c,acc.7"); // c = A
7675 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7677 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7679 emitcode ("anl", "a,#!constbyte",
7680 SRMask[shCount]); // 0000000A:BBBBBBBC
7682 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7683 emitcode ("orl", "a,#!constbyte",
7684 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7686 emitcode ("", "!tlabeldef", tlbl->key + 100);
7694 #ifdef BETTER_LITERAL_SHIFT
7696 _loadLeftIntoAx(char **lsb,
7702 // Get the initial value from left into a pair of registers.
7703 // MSB must be in A, LSB can be any register.
7705 // If the result is held in registers, it is an optimization
7706 // if the LSB can be held in the register which will hold the,
7707 // result LSB since this saves us from having to copy it into
7708 // the result following AccAXLsh.
7710 // If the result is addressed indirectly, this is not a gain.
7711 if (AOP_NEEDSACC(result))
7715 _startLazyDPSEvaluation();
7716 if (AOP_TYPE(left) == AOP_DPTR2)
7719 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
7720 // get LSB in DP2_RESULT_REG.
7721 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
7722 assert(!strcmp(leftByte, DP2_RESULT_REG));
7726 // get LSB into DP2_RESULT_REG
7727 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
7728 if (strcmp(leftByte, DP2_RESULT_REG))
7731 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7734 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
7735 assert(strcmp(leftByte, DP2_RESULT_REG));
7738 _endLazyDPSEvaluation();
7739 *lsb = DP2_RESULT_REG;
7743 if (sameRegs (AOP (result), AOP (left)) &&
7744 ((offl + MSB16) == offr))
7746 /* don't crash result[offr] */
7747 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
7748 emitcode ("xch", "a,%s",
7749 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
7753 movLeft2Result (left, offl, result, offr, 0);
7754 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
7756 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
7757 assert(strcmp(*lsb,"a"));
7762 _storeAxResults(char *lsb,
7766 _startLazyDPSEvaluation();
7767 if (AOP_NEEDSACC(result))
7769 /* We have to explicitly update the result LSB.
7771 emitcode("xch","a,%s", lsb);
7772 aopPut(AOP(result), "a", offr);
7773 emitcode("mov","a,%s", lsb);
7775 if (getDataSize (result) > 1)
7777 aopPut (AOP (result), "a", offr + MSB16);
7779 _endLazyDPSEvaluation();
7782 /*-----------------------------------------------------------------*/
7783 /* shiftL2Left2Result - shift left two bytes from left to result */
7784 /*-----------------------------------------------------------------*/
7786 shiftL2Left2Result (operand * left, int offl,
7787 operand * result, int offr, int shCount)
7791 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7793 AccAXLsh (lsb, shCount);
7795 _storeAxResults(lsb, result, offr);
7799 #ifdef BETTER_LITERAL_SHIFT
7800 /*-----------------------------------------------------------------*/
7801 /* shiftR2Left2Result - shift right two bytes from left to result */
7802 /*-----------------------------------------------------------------*/
7804 shiftR2Left2Result (operand * left, int offl,
7805 operand * result, int offr,
7806 int shCount, int sign)
7810 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7812 /* a:x >> shCount (x = lsb(result)) */
7815 AccAXRshS(lsb, shCount);
7819 AccAXRsh(lsb, shCount);
7822 _storeAxResults(lsb, result, offr);
7828 /*-----------------------------------------------------------------*/
7829 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7830 /*-----------------------------------------------------------------*/
7832 shiftLLeftOrResult (operand * left, int offl,
7833 operand * result, int offr, int shCount)
7835 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7836 /* shift left accumulator */
7838 /* or with result */
7839 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7840 /* back to result */
7841 aopPut (AOP (result), "a", offr);
7847 /*-----------------------------------------------------------------*/
7848 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7849 /*-----------------------------------------------------------------*/
7851 shiftRLeftOrResult (operand * left, int offl,
7852 operand * result, int offr, int shCount)
7854 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7855 /* shift right accumulator */
7857 /* or with result */
7858 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7859 /* back to result */
7860 aopPut (AOP (result), "a", offr);
7864 #ifdef BETTER_LITERAL_SHIFT
7865 /*-----------------------------------------------------------------*/
7866 /* genlshOne - left shift a one byte quantity by known count */
7867 /*-----------------------------------------------------------------*/
7869 genlshOne (operand * result, operand * left, int shCount)
7871 D (emitcode (";", "genlshOne "););
7872 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7876 #ifdef BETTER_LITERAL_SHIFT
7877 /*-----------------------------------------------------------------*/
7878 /* genlshTwo - left shift two bytes by known amount != 0 */
7879 /*-----------------------------------------------------------------*/
7881 genlshTwo (operand * result, operand * left, int shCount)
7885 D (emitcode (";", "genlshTwo "););
7887 size = getDataSize (result);
7889 /* if shCount >= 8 */
7894 _startLazyDPSEvaluation();
7900 _endLazyDPSEvaluation();
7901 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7902 aopPut (AOP (result), zero, LSB);
7906 movLeft2Result (left, LSB, result, MSB16, 0);
7907 aopPut (AOP (result), zero, LSB);
7908 _endLazyDPSEvaluation();
7913 aopPut (AOP (result), zero, LSB);
7914 _endLazyDPSEvaluation();
7918 /* 1 <= shCount <= 7 */
7923 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7927 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7935 /*-----------------------------------------------------------------*/
7936 /* shiftLLong - shift left one long from left to result */
7937 /* offl = LSB or MSB16 */
7938 /*-----------------------------------------------------------------*/
7940 shiftLLong (operand * left, operand * result, int offr)
7943 int size = AOP_SIZE (result);
7945 if (size >= LSB + offr)
7947 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
7949 emitcode ("add", "a,acc");
7950 if (sameRegs (AOP (left), AOP (result)) &&
7951 size >= MSB16 + offr && offr != LSB)
7952 emitcode ("xch", "a,%s",
7953 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
7955 aopPut (AOP (result), "a", LSB + offr);
7958 if (size >= MSB16 + offr)
7960 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7962 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
7965 emitcode ("rlc", "a");
7966 if (sameRegs (AOP (left), AOP (result)) &&
7967 size >= MSB24 + offr && offr != LSB)
7968 emitcode ("xch", "a,%s",
7969 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
7971 aopPut (AOP (result), "a", MSB16 + offr);
7974 if (size >= MSB24 + offr)
7976 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7978 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
7981 emitcode ("rlc", "a");
7982 if (sameRegs (AOP (left), AOP (result)) &&
7983 size >= MSB32 + offr && offr != LSB)
7984 emitcode ("xch", "a,%s",
7985 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
7987 aopPut (AOP (result), "a", MSB24 + offr);
7990 if (size > MSB32 + offr)
7992 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7994 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7997 emitcode ("rlc", "a");
7998 aopPut (AOP (result), "a", MSB32 + offr);
8001 aopPut (AOP (result), zero, LSB);
8007 /*-----------------------------------------------------------------*/
8008 /* genlshFour - shift four byte by a known amount != 0 */
8009 /*-----------------------------------------------------------------*/
8011 genlshFour (operand * result, operand * left, int shCount)
8015 D (emitcode (";", "genlshFour ");
8018 size = AOP_SIZE (result);
8020 /* if shifting more that 3 bytes */
8025 /* lowest order of left goes to the highest
8026 order of the destination */
8027 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8029 movLeft2Result (left, LSB, result, MSB32, 0);
8030 aopPut (AOP (result), zero, LSB);
8031 aopPut (AOP (result), zero, MSB16);
8032 aopPut (AOP (result), zero, MSB24);
8036 /* more than two bytes */
8037 else if (shCount >= 16)
8039 /* lower order two bytes goes to higher order two bytes */
8041 /* if some more remaining */
8043 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8046 movLeft2Result (left, MSB16, result, MSB32, 0);
8047 movLeft2Result (left, LSB, result, MSB24, 0);
8049 aopPut (AOP (result), zero, MSB16);
8050 aopPut (AOP (result), zero, LSB);
8054 /* if more than 1 byte */
8055 else if (shCount >= 8)
8057 /* lower order three bytes goes to higher order three bytes */
8062 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8064 movLeft2Result (left, LSB, result, MSB16, 0);
8070 movLeft2Result (left, MSB24, result, MSB32, 0);
8071 movLeft2Result (left, MSB16, result, MSB24, 0);
8072 movLeft2Result (left, LSB, result, MSB16, 0);
8073 aopPut (AOP (result), zero, LSB);
8075 else if (shCount == 1)
8076 shiftLLong (left, result, MSB16);
8079 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8080 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8081 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8082 aopPut (AOP (result), zero, LSB);
8087 /* 1 <= shCount <= 7 */
8088 else if (shCount <= 2)
8090 shiftLLong (left, result, LSB);
8092 shiftLLong (result, result, LSB);
8094 /* 3 <= shCount <= 7, optimize */
8097 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8098 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8099 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8104 #ifdef BETTER_LITERAL_SHIFT
8105 /*-----------------------------------------------------------------*/
8106 /* genLeftShiftLiteral - left shifting by known count */
8107 /*-----------------------------------------------------------------*/
8109 genLeftShiftLiteral (operand * left,
8114 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8117 size = getSize (operandType (result));
8119 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8121 /* We only handle certain easy cases so far. */
8123 && (shCount < (size * 8))
8127 D(emitcode (";", "genLeftShiftLiteral wimping out"););
8131 freeAsmop (right, NULL, ic, TRUE);
8133 aopOp(left, ic, FALSE, FALSE);
8134 aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
8137 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8139 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8140 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8142 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8145 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8147 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8148 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8150 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8156 emitcode ("; shift left ", "result %d, left %d", size,
8160 /* I suppose that the left size >= result size */
8163 _startLazyDPSEvaluation();
8166 movLeft2Result (left, size, result, size, 0);
8168 _endLazyDPSEvaluation();
8170 else if (shCount >= (size * 8))
8172 _startLazyDPSEvaluation();
8175 aopPut (AOP (result), zero, size);
8177 _endLazyDPSEvaluation();
8184 genlshOne (result, left, shCount);
8188 genlshTwo (result, left, shCount);
8192 genlshFour (result, left, shCount);
8196 fprintf(stderr, "*** ack! mystery literal shift!\n");
8200 freeAsmop (left, NULL, ic, TRUE);
8201 freeAsmop (result, NULL, ic, TRUE);
8206 /*-----------------------------------------------------------------*/
8207 /* genLeftShift - generates code for left shifting */
8208 /*-----------------------------------------------------------------*/
8210 genLeftShift (iCode * ic)
8212 operand *left, *right, *result;
8215 symbol *tlbl, *tlbl1;
8217 D (emitcode (";", "genLeftShift "););
8219 right = IC_RIGHT (ic);
8220 left = IC_LEFT (ic);
8221 result = IC_RESULT (ic);
8223 aopOp (right, ic, FALSE, FALSE);
8226 #ifdef BETTER_LITERAL_SHIFT
8227 /* if the shift count is known then do it
8228 as efficiently as possible */
8229 if (AOP_TYPE (right) == AOP_LIT)
8231 if (genLeftShiftLiteral (left, right, result, ic))
8238 /* shift count is unknown then we have to form
8239 a loop get the loop count in B : Note: we take
8240 only the lower order byte since shifting
8241 more that 32 bits make no sense anyway, ( the
8242 largest size of an object can be only 32 bits ) */
8244 if (AOP_TYPE (right) == AOP_LIT)
8246 /* Really should be handled by genLeftShiftLiteral,
8247 * but since I'm too lazy to fix that today, at least we can make
8248 * some small improvement.
8250 emitcode("mov", "b,#!constbyte",
8251 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8255 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8256 emitcode ("inc", "b");
8258 freeAsmop (right, NULL, ic, TRUE);
8259 aopOp (left, ic, FALSE, FALSE);
8260 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8262 /* now move the left to the result if they are not the
8264 if (!sameRegs (AOP (left), AOP (result)) &&
8265 AOP_SIZE (result) > 1)
8268 size = AOP_SIZE (result);
8270 _startLazyDPSEvaluation ();
8273 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8274 if (*l == '@' && (IS_AOP_PREG (result)))
8277 emitcode ("mov", "a,%s", l);
8278 aopPut (AOP (result), "a", offset);
8281 aopPut (AOP (result), l, offset);
8284 _endLazyDPSEvaluation ();
8287 tlbl = newiTempLabel (NULL);
8288 size = AOP_SIZE (result);
8290 tlbl1 = newiTempLabel (NULL);
8292 /* if it is only one byte then */
8295 symbol *tlbl1 = newiTempLabel (NULL);
8297 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8299 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8300 emitcode ("", "!tlabeldef", tlbl->key + 100);
8301 emitcode ("add", "a,acc");
8302 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8303 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8304 aopPut (AOP (result), "a", 0);
8308 reAdjustPreg (AOP (result));
8310 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8311 emitcode ("", "!tlabeldef", tlbl->key + 100);
8312 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8314 emitcode ("add", "a,acc");
8315 aopPut (AOP (result), "a", offset++);
8316 _startLazyDPSEvaluation ();
8319 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8321 emitcode ("rlc", "a");
8322 aopPut (AOP (result), "a", offset++);
8324 _endLazyDPSEvaluation ();
8325 reAdjustPreg (AOP (result));
8327 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8328 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8330 freeAsmop (left, NULL, ic, TRUE);
8331 freeAsmop (result, NULL, ic, TRUE);
8334 #ifdef BETTER_LITERAL_SHIFT
8335 /*-----------------------------------------------------------------*/
8336 /* genrshOne - right shift a one byte quantity by known count */
8337 /*-----------------------------------------------------------------*/
8339 genrshOne (operand * result, operand * left,
8340 int shCount, int sign)
8342 D (emitcode (";", "genrshOne"););
8343 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8347 #ifdef BETTER_LITERAL_SHIFT
8348 /*-----------------------------------------------------------------*/
8349 /* genrshTwo - right shift two bytes by known amount != 0 */
8350 /*-----------------------------------------------------------------*/
8352 genrshTwo (operand * result, operand * left,
8353 int shCount, int sign)
8355 D (emitcode (";", "genrshTwo"););
8357 /* if shCount >= 8 */
8361 _startLazyDPSEvaluation();
8364 shiftR1Left2Result (left, MSB16, result, LSB,
8369 movLeft2Result (left, MSB16, result, LSB, sign);
8371 addSign (result, MSB16, sign);
8372 _endLazyDPSEvaluation();
8375 /* 1 <= shCount <= 7 */
8378 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8385 /*-----------------------------------------------------------------*/
8386 /* shiftRLong - shift right one long from left to result */
8387 /* offl = LSB or MSB16 */
8388 /*-----------------------------------------------------------------*/
8390 shiftRLong (operand * left, int offl,
8391 operand * result, int sign)
8393 int isSameRegs=sameRegs(AOP(left),AOP(result));
8395 if (isSameRegs && offl>1) {
8396 // we are in big trouble, but this shouldn't happen
8397 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8400 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
8405 emitcode ("rlc", "a");
8406 emitcode ("subb", "a,acc");
8407 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
8409 aopPut (AOP(result), zero, MSB32);
8414 emitcode ("clr", "c");
8416 emitcode ("mov", "c,acc.7");
8419 emitcode ("rrc", "a");
8421 if (isSameRegs && offl==MSB16) {
8422 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
8424 aopPut (AOP (result), "a", MSB32);
8425 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
8428 emitcode ("rrc", "a");
8429 if (isSameRegs && offl==1) {
8430 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
8432 aopPut (AOP (result), "a", MSB24);
8433 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
8435 emitcode ("rrc", "a");
8436 aopPut (AOP (result), "a", MSB16 - offl);
8440 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
8441 emitcode ("rrc", "a");
8442 aopPut (AOP (result), "a", LSB);
8449 /*-----------------------------------------------------------------*/
8450 /* genrshFour - shift four byte by a known amount != 0 */
8451 /*-----------------------------------------------------------------*/
8453 genrshFour (operand * result, operand * left,
8454 int shCount, int sign)
8456 D (emitcode (";", "genrshFour");
8459 /* if shifting more that 3 bytes */
8464 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8466 movLeft2Result (left, MSB32, result, LSB, sign);
8467 addSign (result, MSB16, sign);
8469 else if (shCount >= 16)
8473 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8476 movLeft2Result (left, MSB24, result, LSB, 0);
8477 movLeft2Result (left, MSB32, result, MSB16, sign);
8479 addSign (result, MSB24, sign);
8481 else if (shCount >= 8)
8485 shiftRLong (left, MSB16, result, sign);
8486 else if (shCount == 0)
8488 movLeft2Result (left, MSB16, result, LSB, 0);
8489 movLeft2Result (left, MSB24, result, MSB16, 0);
8490 movLeft2Result (left, MSB32, result, MSB24, sign);
8491 addSign (result, MSB32, sign);
8495 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8496 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8497 /* the last shift is signed */
8498 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8499 addSign (result, MSB32, sign);
8503 { /* 1 <= shCount <= 7 */
8506 shiftRLong (left, LSB, result, sign);
8508 shiftRLong (result, LSB, result, sign);
8512 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8513 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8514 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8520 #ifdef BETTER_LITERAL_SHIFT
8521 /*-----------------------------------------------------------------*/
8522 /* genRightShiftLiteral - right shifting by known count */
8523 /*-----------------------------------------------------------------*/
8525 genRightShiftLiteral (operand * left,
8531 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8534 size = getSize (operandType (result));
8536 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8538 /* We only handle certain easy cases so far. */
8540 && (shCount < (size * 8))
8544 D(emitcode (";", "genRightShiftLiteral wimping out"););
8548 freeAsmop (right, NULL, ic, TRUE);
8550 aopOp (left, ic, FALSE, FALSE);
8551 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8554 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8558 /* test the LEFT size !!! */
8560 /* I suppose that the left size >= result size */
8563 size = getDataSize (result);
8564 _startLazyDPSEvaluation();
8567 movLeft2Result (left, size, result, size, 0);
8569 _endLazyDPSEvaluation();
8571 else if (shCount >= (size * 8))
8575 /* get sign in acc.7 */
8576 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
8578 addSign (result, LSB, sign);
8585 genrshOne (result, left, shCount, sign);
8589 genrshTwo (result, left, shCount, sign);
8593 genrshFour (result, left, shCount, sign);
8600 freeAsmop (left, NULL, ic, TRUE);
8601 freeAsmop (result, NULL, ic, TRUE);
8607 /*-----------------------------------------------------------------*/
8608 /* genSignedRightShift - right shift of signed number */
8609 /*-----------------------------------------------------------------*/
8611 genSignedRightShift (iCode * ic)
8613 operand *right, *left, *result;
8616 symbol *tlbl, *tlbl1;
8618 D (emitcode (";", "genSignedRightShift "););
8620 /* we do it the hard way put the shift count in b
8621 and loop thru preserving the sign */
8623 right = IC_RIGHT (ic);
8624 left = IC_LEFT (ic);
8625 result = IC_RESULT (ic);
8627 aopOp (right, ic, FALSE, FALSE);
8629 #ifdef BETTER_LITERAL_SHIFT
8630 if (AOP_TYPE (right) == AOP_LIT)
8632 if (genRightShiftLiteral (left, right, result, ic, 1))
8638 /* shift count is unknown then we have to form
8639 a loop get the loop count in B : Note: we take
8640 only the lower order byte since shifting
8641 more that 32 bits make no sense anyway, ( the
8642 largest size of an object can be only 32 bits ) */
8644 if (AOP_TYPE (right) == AOP_LIT)
8646 /* Really should be handled by genRightShiftLiteral,
8647 * but since I'm too lazy to fix that today, at least we can make
8648 * some small improvement.
8650 emitcode("mov", "b,#!constbyte",
8651 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8655 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8656 emitcode ("inc", "b");
8658 freeAsmop (right, NULL, ic, TRUE);
8659 aopOp (left, ic, FALSE, FALSE);
8660 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8662 /* now move the left to the result if they are not the
8664 if (!sameRegs (AOP (left), AOP (result)) &&
8665 AOP_SIZE (result) > 1)
8668 size = AOP_SIZE (result);
8670 _startLazyDPSEvaluation ();
8673 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8674 if (*l == '@' && IS_AOP_PREG (result))
8677 emitcode ("mov", "a,%s", l);
8678 aopPut (AOP (result), "a", offset);
8681 aopPut (AOP (result), l, offset);
8684 _endLazyDPSEvaluation ();
8687 /* mov the highest order bit to OVR */
8688 tlbl = newiTempLabel (NULL);
8689 tlbl1 = newiTempLabel (NULL);
8691 size = AOP_SIZE (result);
8693 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
8694 emitcode ("rlc", "a");
8695 emitcode ("mov", "ov,c");
8696 /* if it is only one byte then */
8699 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8701 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8702 emitcode ("", "!tlabeldef", tlbl->key + 100);
8703 emitcode ("mov", "c,ov");
8704 emitcode ("rrc", "a");
8705 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8706 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8707 aopPut (AOP (result), "a", 0);
8711 reAdjustPreg (AOP (result));
8712 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8713 emitcode ("", "!tlabeldef", tlbl->key + 100);
8714 emitcode ("mov", "c,ov");
8715 _startLazyDPSEvaluation ();
8718 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8720 emitcode ("rrc", "a");
8721 aopPut (AOP (result), "a", offset--);
8723 _endLazyDPSEvaluation ();
8724 reAdjustPreg (AOP (result));
8725 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8726 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8729 freeAsmop (left, NULL, ic, TRUE);
8730 freeAsmop (result, NULL, ic, TRUE);
8733 /*-----------------------------------------------------------------*/
8734 /* genRightShift - generate code for right shifting */
8735 /*-----------------------------------------------------------------*/
8737 genRightShift (iCode * ic)
8739 operand *right, *left, *result;
8743 symbol *tlbl, *tlbl1;
8745 D (emitcode (";", "genRightShift "););
8747 /* if signed then we do it the hard way preserve the
8748 sign bit moving it inwards */
8749 retype = getSpec (operandType (IC_RESULT (ic)));
8751 if (!SPEC_USIGN (retype))
8753 genSignedRightShift (ic);
8757 /* signed & unsigned types are treated the same : i.e. the
8758 signed is NOT propagated inwards : quoting from the
8759 ANSI - standard : "for E1 >> E2, is equivalent to division
8760 by 2**E2 if unsigned or if it has a non-negative value,
8761 otherwise the result is implementation defined ", MY definition
8762 is that the sign does not get propagated */
8764 right = IC_RIGHT (ic);
8765 left = IC_LEFT (ic);
8766 result = IC_RESULT (ic);
8768 aopOp (right, ic, FALSE, FALSE);
8770 #ifdef BETTER_LITERAL_SHIFT
8771 /* if the shift count is known then do it
8772 as efficiently as possible */
8773 if (AOP_TYPE (right) == AOP_LIT)
8775 if (genRightShiftLiteral (left, right, result, ic, 0))
8782 /* shift count is unknown then we have to form
8783 a loop get the loop count in B : Note: we take
8784 only the lower order byte since shifting
8785 more that 32 bits make no sense anyway, ( the
8786 largest size of an object can be only 32 bits ) */
8788 if (AOP_TYPE (right) == AOP_LIT)
8790 /* Really should be handled by genRightShiftLiteral,
8791 * but since I'm too lazy to fix that today, at least we can make
8792 * some small improvement.
8794 emitcode("mov", "b,#!constbyte",
8795 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8799 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8800 emitcode ("inc", "b");
8802 freeAsmop (right, NULL, ic, TRUE);
8803 aopOp (left, ic, FALSE, FALSE);
8804 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8806 /* now move the left to the result if they are not the
8808 if (!sameRegs (AOP (left), AOP (result)) &&
8809 AOP_SIZE (result) > 1)
8812 size = AOP_SIZE (result);
8814 _startLazyDPSEvaluation ();
8817 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8818 if (*l == '@' && IS_AOP_PREG (result))
8821 emitcode ("mov", "a,%s", l);
8822 aopPut (AOP (result), "a", offset);
8825 aopPut (AOP (result), l, offset);
8828 _endLazyDPSEvaluation ();
8831 tlbl = newiTempLabel (NULL);
8832 tlbl1 = newiTempLabel (NULL);
8833 size = AOP_SIZE (result);
8836 /* if it is only one byte then */
8839 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8841 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8842 emitcode ("", "!tlabeldef", tlbl->key + 100);
8844 emitcode ("rrc", "a");
8845 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8846 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8847 aopPut (AOP (result), "a", 0);
8851 reAdjustPreg (AOP (result));
8852 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8853 emitcode ("", "!tlabeldef", tlbl->key + 100);
8855 _startLazyDPSEvaluation ();
8858 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8860 emitcode ("rrc", "a");
8861 aopPut (AOP (result), "a", offset--);
8863 _endLazyDPSEvaluation ();
8864 reAdjustPreg (AOP (result));
8866 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8867 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8870 freeAsmop (left, NULL, ic, TRUE);
8871 freeAsmop (result, NULL, ic, TRUE);
8874 /*-----------------------------------------------------------------*/
8875 /* genUnpackBits - generates code for unpacking bits */
8876 /*-----------------------------------------------------------------*/
8878 genUnpackBits (operand * result, char *rname, int ptype)
8885 D (emitcode (";", "genUnpackBits ");
8888 etype = getSpec (operandType (result));
8890 /* read the first byte */
8896 emitcode ("mov", "a,@%s", rname);
8900 emitcode ("movx", "a,@%s", rname);
8904 emitcode ("movx", "a,@dptr");
8908 emitcode ("clr", "a");
8909 emitcode ("movc", "a,@a+dptr");
8913 emitcode ("lcall", "__gptrget");
8917 /* if we have bitdisplacement then it fits */
8918 /* into this byte completely or if length is */
8919 /* less than a byte */
8920 if ((shCnt = SPEC_BSTR (etype)) ||
8921 (SPEC_BLEN (etype) <= 8))
8924 /* shift right acc */
8927 emitcode ("anl", "a,#!constbyte",
8928 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8929 aopPut (AOP (result), "a", offset);
8933 /* bit field did not fit in a byte */
8934 rlen = SPEC_BLEN (etype) - 8;
8935 aopPut (AOP (result), "a", offset++);
8944 emitcode ("inc", "%s", rname);
8945 emitcode ("mov", "a,@%s", rname);
8949 emitcode ("inc", "%s", rname);
8950 emitcode ("movx", "a,@%s", rname);
8954 emitcode ("inc", "dptr");
8955 emitcode ("movx", "a,@dptr");
8959 emitcode ("clr", "a");
8960 emitcode ("inc", "dptr");
8961 emitcode ("movc", "a,@a+dptr");
8965 emitcode ("inc", "dptr");
8966 emitcode ("lcall", "__gptrget");
8971 /* if we are done */
8975 aopPut (AOP (result), "a", offset++);
8981 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (rlen));
8982 aopPut (AOP (result), "a", offset);
8989 /*-----------------------------------------------------------------*/
8990 /* genDataPointerGet - generates code when ptr offset is known */
8991 /*-----------------------------------------------------------------*/
8993 genDataPointerGet (operand * left,
8999 int size, offset = 0;
9000 aopOp (result, ic, TRUE, FALSE);
9002 /* get the string representation of the name */
9003 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
9004 size = AOP_SIZE (result);
9005 _startLazyDPSEvaluation ();
9009 sprintf (buffer, "(%s + %d)", l + 1, offset);
9011 sprintf (buffer, "%s", l + 1);
9012 aopPut (AOP (result), buffer, offset++);
9014 _endLazyDPSEvaluation ();
9016 freeAsmop (left, NULL, ic, TRUE);
9017 freeAsmop (result, NULL, ic, TRUE);
9020 /*-----------------------------------------------------------------*/
9021 /* genNearPointerGet - emitcode for near pointer fetch */
9022 /*-----------------------------------------------------------------*/
9024 genNearPointerGet (operand * left,
9032 sym_link *rtype, *retype, *letype;
9033 sym_link *ltype = operandType (left);
9036 rtype = operandType (result);
9037 retype = getSpec (rtype);
9038 letype = getSpec (ltype);
9040 aopOp (left, ic, FALSE, FALSE);
9042 /* if left is rematerialisable and
9043 result is not bit variable type and
9044 the left is pointer to data space i.e
9045 lower 128 bytes of space */
9046 if (AOP_TYPE (left) == AOP_IMMD &&
9047 !IS_BITVAR (retype) &&
9048 !IS_BITVAR (letype) &&
9049 DCL_TYPE (ltype) == POINTER)
9051 genDataPointerGet (left, result, ic);
9055 /* if the value is already in a pointer register
9056 then don't need anything more */
9057 if (!AOP_INPREG (AOP (left)))
9059 /* otherwise get a free pointer register */
9061 preg = getFreePtr (ic, &aop, FALSE);
9062 emitcode ("mov", "%s,%s",
9064 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
9068 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
9070 freeAsmop (left, NULL, ic, TRUE);
9071 aopOp (result, ic, FALSE, FALSE);
9073 /* if bitfield then unpack the bits */
9074 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9075 genUnpackBits (result, rname, POINTER);
9078 /* we have can just get the values */
9079 int size = AOP_SIZE (result);
9084 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9087 emitcode ("mov", "a,@%s", rname);
9088 aopPut (AOP (result), "a", offset);
9092 sprintf (buffer, "@%s", rname);
9093 aopPut (AOP (result), buffer, offset);
9097 emitcode ("inc", "%s", rname);
9101 /* now some housekeeping stuff */
9104 /* we had to allocate for this iCode */
9105 if (pi) { /* post increment present */
9106 aopPut(AOP ( left ),rname,0);
9108 freeAsmop (NULL, aop, ic, TRUE);
9112 /* we did not allocate which means left
9113 already in a pointer register, then
9114 if size > 0 && this could be used again
9115 we have to point it back to where it
9117 if (AOP_SIZE (result) > 1 &&
9118 !OP_SYMBOL (left)->remat &&
9119 (OP_SYMBOL (left)->liveTo > ic->seq ||
9123 int size = AOP_SIZE (result) - 1;
9125 emitcode ("dec", "%s", rname);
9130 freeAsmop (result, NULL, ic, TRUE);
9131 if (pi) pi->generated = 1;
9134 /*-----------------------------------------------------------------*/
9135 /* genPagedPointerGet - emitcode for paged pointer fetch */
9136 /*-----------------------------------------------------------------*/
9138 genPagedPointerGet (operand * left,
9146 sym_link *rtype, *retype, *letype;
9148 rtype = operandType (result);
9149 retype = getSpec (rtype);
9150 letype = getSpec (operandType (left));
9151 aopOp (left, ic, FALSE, FALSE);
9153 /* if the value is already in a pointer register
9154 then don't need anything more */
9155 if (!AOP_INPREG (AOP (left)))
9157 /* otherwise get a free pointer register */
9159 preg = getFreePtr (ic, &aop, FALSE);
9160 emitcode ("mov", "%s,%s",
9162 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
9166 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
9168 freeAsmop (left, NULL, ic, TRUE);
9169 aopOp (result, ic, FALSE, FALSE);
9171 /* if bitfield then unpack the bits */
9172 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9173 genUnpackBits (result, rname, PPOINTER);
9176 /* we have can just get the values */
9177 int size = AOP_SIZE (result);
9183 emitcode ("movx", "a,@%s", rname);
9184 aopPut (AOP (result), "a", offset);
9189 emitcode ("inc", "%s", rname);
9193 /* now some housekeeping stuff */
9196 /* we had to allocate for this iCode */
9197 if (pi) aopPut ( AOP (left), rname, 0);
9198 freeAsmop (NULL, aop, ic, TRUE);
9202 /* we did not allocate which means left
9203 already in a pointer register, then
9204 if size > 0 && this could be used again
9205 we have to point it back to where it
9207 if (AOP_SIZE (result) > 1 &&
9208 !OP_SYMBOL (left)->remat &&
9209 (OP_SYMBOL (left)->liveTo > ic->seq ||
9213 int size = AOP_SIZE (result) - 1;
9215 emitcode ("dec", "%s", rname);
9220 freeAsmop (result, NULL, ic, TRUE);
9221 if (pi) pi->generated = 1;
9224 /*-----------------------------------------------------------------*/
9225 /* genFarPointerGet - gget value from far space */
9226 /*-----------------------------------------------------------------*/
9228 genFarPointerGet (operand * left,
9229 operand * result, iCode * ic, iCode *pi)
9231 int size, offset, dopi=1;
9232 sym_link *retype = getSpec (operandType (result));
9233 sym_link *letype = getSpec (operandType (left));
9234 D (emitcode (";", "genFarPointerGet");
9237 aopOp (left, ic, FALSE, FALSE);
9239 /* if the operand is already in dptr
9240 then we do nothing else we move the value to dptr */
9241 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9243 /* if this is remateriazable */
9244 if (AOP_TYPE (left) == AOP_IMMD)
9246 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9250 /* we need to get it byte by byte */
9251 _startLazyDPSEvaluation ();
9252 if (AOP_TYPE (left) != AOP_DPTR)
9254 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9255 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9256 if (options.model == MODEL_FLAT24)
9257 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9261 /* We need to generate a load to DPTR indirect through DPTR. */
9262 D (emitcode (";", "genFarPointerGet -- indirection special case.");
9264 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
9265 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
9266 if (options.model == MODEL_FLAT24)
9267 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9268 emitcode ("pop", "dph");
9269 emitcode ("pop", "dpl");
9272 _endLazyDPSEvaluation ();
9275 /* so dptr know contains the address */
9276 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9278 /* if bit then unpack */
9279 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9280 if (AOP_INDPTRn(left)) {
9281 genSetDPTR(AOP(left)->aopu.dptr);
9283 genUnpackBits (result, "dptr", FPOINTER);
9284 if (AOP_INDPTRn(left)) {
9289 size = AOP_SIZE (result);
9292 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9294 genSetDPTR(AOP(left)->aopu.dptr);
9295 emitcode ("movx", "a,@dptr");
9296 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9297 emitcode ("inc", "dptr");
9299 aopPut (AOP (result), "a", offset++);
9302 _startLazyDPSEvaluation ();
9304 if (AOP_INDPTRn(left)) {
9305 genSetDPTR(AOP(left)->aopu.dptr);
9311 emitcode ("movx", "a,@dptr");
9312 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9313 emitcode ("inc", "dptr");
9315 aopPut (AOP (result), "a", offset++);
9317 _endLazyDPSEvaluation ();
9320 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9321 if (!AOP_INDPTRn(left)) {
9322 aopPut ( AOP (left), "dpl", 0);
9323 aopPut ( AOP (left), "dph", 1);
9324 if (options.model == MODEL_FLAT24)
9325 aopPut ( AOP (left), "dpx", 2);
9328 } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
9329 AOP_SIZE(result) > 1 &&
9330 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9332 size = AOP_SIZE (result) - 1;
9333 if (AOP_INDPTRn(left)) {
9334 genSetDPTR(AOP(left)->aopu.dptr);
9336 while (size--) emitcode ("lcall","__decdptr");
9337 if (AOP_INDPTRn(left)) {
9342 freeAsmop (left, NULL, ic, TRUE);
9343 freeAsmop (result, NULL, ic, TRUE);
9346 /*-----------------------------------------------------------------*/
9347 /* genCodePointerGet - get value from code space */
9348 /*-----------------------------------------------------------------*/
9350 genCodePointerGet (operand * left,
9351 operand * result, iCode * ic, iCode *pi)
9353 int size, offset, dopi=1;
9354 sym_link *retype = getSpec (operandType (result));
9356 aopOp (left, ic, FALSE, FALSE);
9358 /* if the operand is already in dptr
9359 then we do nothing else we move the value to dptr */
9360 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
9362 /* if this is remateriazable */
9363 if (AOP_TYPE (left) == AOP_IMMD)
9365 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9368 { /* we need to get it byte by byte */
9369 _startLazyDPSEvaluation ();
9370 if (AOP_TYPE (left) != AOP_DPTR)
9372 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9373 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9374 if (options.model == MODEL_FLAT24)
9375 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9379 /* We need to generate a load to DPTR indirect through DPTR. */
9380 D (emitcode (";", "gencodePointerGet -- indirection special case.");
9382 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
9383 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
9384 if (options.model == MODEL_FLAT24)
9385 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9386 emitcode ("pop", "dph");
9387 emitcode ("pop", "dpl");
9390 _endLazyDPSEvaluation ();
9393 /* so dptr know contains the address */
9394 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9396 /* if bit then unpack */
9397 if (IS_BITVAR (retype)) {
9398 if (AOP_INDPTRn(left)) {
9399 genSetDPTR(AOP(left)->aopu.dptr);
9401 genUnpackBits (result, "dptr", CPOINTER);
9402 if (AOP_INDPTRn(left)) {
9407 size = AOP_SIZE (result);
9409 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9411 genSetDPTR(AOP(left)->aopu.dptr);
9412 emitcode ("clr", "a");
9413 emitcode ("movc", "a,@a+dptr");
9414 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9415 emitcode ("inc", "dptr");
9417 aopPut (AOP (result), "a", offset++);
9420 _startLazyDPSEvaluation ();
9423 if (AOP_INDPTRn(left)) {
9424 genSetDPTR(AOP(left)->aopu.dptr);
9430 emitcode ("clr", "a");
9431 emitcode ("movc", "a,@a+dptr");
9432 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9433 emitcode ("inc", "dptr");
9434 aopPut (AOP (result), "a", offset++);
9436 _endLazyDPSEvaluation ();
9439 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9440 if (!AOP_INDPTRn(left)) {
9441 aopPut ( AOP (left), "dpl", 0);
9442 aopPut ( AOP (left), "dph", 1);
9443 if (options.model == MODEL_FLAT24)
9444 aopPut ( AOP (left), "dpx", 2);
9447 } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
9448 AOP_SIZE(result) > 1 &&
9449 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9451 size = AOP_SIZE (result) - 1;
9452 if (AOP_INDPTRn(left)) {
9453 genSetDPTR(AOP(left)->aopu.dptr);
9455 while (size--) emitcode ("lcall","__decdptr");
9456 if (AOP_INDPTRn(left)) {
9461 freeAsmop (left, NULL, ic, TRUE);
9462 freeAsmop (result, NULL, ic, TRUE);
9465 /*-----------------------------------------------------------------*/
9466 /* genGenPointerGet - gget value from generic pointer space */
9467 /*-----------------------------------------------------------------*/
9469 genGenPointerGet (operand * left,
9470 operand * result, iCode * ic, iCode * pi)
9473 sym_link *retype = getSpec (operandType (result));
9474 sym_link *letype = getSpec (operandType (left));
9476 D (emitcode (";", "genGenPointerGet "); );
9478 aopOp (left, ic, FALSE, (OP_SYMBOL(left)->ruonly ? FALSE : TRUE));
9480 /* if the operand is already in dptr
9481 then we do nothing else we move the value to dptr */
9482 if (AOP_TYPE (left) != AOP_STR)
9484 /* if this is remateriazable */
9485 if (AOP_TYPE (left) == AOP_IMMD)
9487 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9488 if (AOP(left)->aopu.aop_immd.from_cast_remat)
9489 emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, FALSE));
9491 emitcode ("mov", "b,#%d", pointerCode (retype));
9494 { /* we need to get it byte by byte */
9495 _startLazyDPSEvaluation ();
9496 #if 0 // I see no point at all to this code.
9497 // So I yanked it. Kill at some future date if no bugs rear their heads.
9498 if (AOP(left)->type==AOP_DPTR2) {
9500 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
9503 emitcode ("mov", "dpl,%s", l);
9504 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
9507 emitcode ("mov", "dph,%s", l);
9508 if (options.model == MODEL_FLAT24) {
9509 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
9512 emitcode ("mov", "dpx,%s", l);
9513 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9515 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9521 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
9522 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
9523 if (options.model == MODEL_FLAT24) {
9524 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9525 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9527 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9530 _endLazyDPSEvaluation ();
9534 /* so dptr-b now contains the address */
9536 aopOp (result, ic, FALSE, TRUE);
9539 /* if bit then unpack */
9540 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9542 genUnpackBits (result, "dptr", GPOINTER);
9546 size = AOP_SIZE (result);
9553 // Get two bytes at a time, results in _AP & A.
9554 // dptr will be incremented ONCE by __gptrgetWord.
9556 // Note: any change here must be coordinated
9557 // with the implementation of __gptrgetWord
9558 // in device/lib/_gptrget.c
9559 emitcode ("lcall", "__gptrgetWord");
9560 aopPut (AOP (result), DP2_RESULT_REG, offset++);
9561 aopPut (AOP (result), "a", offset++);
9566 // Only one byte to get.
9567 emitcode ("lcall", "__gptrget");
9568 aopPut (AOP (result), "a", offset++);
9571 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9573 emitcode ("inc", "dptr");
9578 if (pi && AOP_TYPE (left) != AOP_IMMD) {
9579 aopPut ( AOP (left), "dpl", 0);
9580 aopPut ( AOP (left), "dph", 1);
9581 if (options.model == MODEL_FLAT24) {
9582 aopPut ( AOP (left), "dpx", 2);
9583 aopPut ( AOP (left), "b", 3);
9584 } else aopPut ( AOP (left), "b", 2);
9586 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9587 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9589 size = AOP_SIZE (result) - 1;
9590 while (size--) emitcode ("lcall","__decdptr");
9593 freeAsmop (left, NULL, ic, TRUE);
9594 freeAsmop (result, NULL, ic, TRUE);
9597 /*-----------------------------------------------------------------*/
9598 /* genPointerGet - generate code for pointer get */
9599 /*-----------------------------------------------------------------*/
9601 genPointerGet (iCode * ic, iCode *pi)
9603 operand *left, *result;
9604 sym_link *type, *etype;
9607 D (emitcode (";", "genPointerGet ");
9610 left = IC_LEFT (ic);
9611 result = IC_RESULT (ic);
9613 /* depending on the type of pointer we need to
9614 move it to the correct pointer register */
9615 type = operandType (left);
9616 etype = getSpec (type);
9617 /* if left is of type of pointer then it is simple */
9618 if (IS_PTR (type) && !IS_FUNC (type->next))
9619 p_type = DCL_TYPE (type);
9622 /* we have to go by the storage class */
9623 p_type = PTR_TYPE (SPEC_OCLS (etype));
9625 /* special case when cast remat */
9626 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9627 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9628 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9629 type = operandType (left);
9630 p_type = DCL_TYPE (type);
9632 /* now that we have the pointer type we assign
9633 the pointer values */
9639 genNearPointerGet (left, result, ic, pi);
9643 genPagedPointerGet (left, result, ic, pi);
9647 genFarPointerGet (left, result, ic, pi);
9651 genCodePointerGet (left, result, ic, pi);
9655 genGenPointerGet (left, result, ic, pi);
9661 /*-----------------------------------------------------------------*/
9662 /* genPackBits - generates code for packed bit storage */
9663 /*-----------------------------------------------------------------*/
9665 genPackBits (sym_link * etype,
9667 char *rname, int p_type)
9675 blen = SPEC_BLEN (etype);
9676 bstr = SPEC_BSTR (etype);
9678 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9681 /* if the bit lenth is less than or */
9682 /* it exactly fits a byte then */
9683 if (SPEC_BLEN (etype) <= 8)
9685 shCount = SPEC_BSTR (etype);
9687 /* shift left acc */
9690 if (SPEC_BLEN (etype) < 8)
9691 { /* if smaller than a byte */
9697 emitcode ("mov", "b,a");
9698 emitcode ("mov", "a,@%s", rname);
9702 emitcode ("mov", "b,a");
9703 emitcode ("movx", "a,@dptr");
9707 emitcode ("push", "b");
9708 emitcode ("push", "acc");
9709 emitcode ("lcall", "__gptrget");
9710 emitcode ("pop", "b");
9714 emitcode ("anl", "a,#!constbyte", (unsigned char)
9715 ((unsigned char) (0xFF << (blen + bstr)) |
9716 (unsigned char) (0xFF >> (8 - bstr))));
9717 emitcode ("orl", "a,b");
9718 if (p_type == GPOINTER)
9719 emitcode ("pop", "b");
9726 emitcode ("mov", "@%s,a", rname);
9730 emitcode ("movx", "@dptr,a");
9734 emitcode ("lcall", "__gptrput");
9739 if (SPEC_BLEN (etype) <= 8)
9742 emitcode ("inc", "%s", rname);
9743 rLen = SPEC_BLEN (etype);
9745 /* now generate for lengths greater than one byte */
9749 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
9761 emitcode ("mov", "@%s,a", rname);
9764 emitcode ("mov", "@%s,%s", rname, l);
9769 emitcode ("movx", "@dptr,a");
9774 emitcode ("lcall", "__gptrput");
9777 emitcode ("inc", "%s", rname);
9782 /* last last was not complete */
9785 /* save the byte & read byte */
9789 emitcode ("mov", "b,a");
9790 emitcode ("mov", "a,@%s", rname);
9794 emitcode ("mov", "b,a");
9795 emitcode ("movx", "a,@dptr");
9799 emitcode ("push", "b");
9800 emitcode ("push", "acc");
9801 emitcode ("lcall", "__gptrget");
9802 emitcode ("pop", "b");
9806 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1 << rLen));
9807 emitcode ("orl", "a,b");
9810 if (p_type == GPOINTER)
9811 emitcode ("pop", "b");
9817 emitcode ("mov", "@%s,a", rname);
9821 emitcode ("movx", "@dptr,a");
9825 emitcode ("lcall", "__gptrput");
9829 /*-----------------------------------------------------------------*/
9830 /* genDataPointerSet - remat pointer to data space */
9831 /*-----------------------------------------------------------------*/
9833 genDataPointerSet (operand * right,
9837 int size, offset = 0;
9838 char *l, buffer[256];
9840 aopOp (right, ic, FALSE, FALSE);
9842 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
9843 size = AOP_SIZE (right);
9847 sprintf (buffer, "(%s + %d)", l + 1, offset);
9849 sprintf (buffer, "%s", l + 1);
9850 emitcode ("mov", "%s,%s", buffer,
9851 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
9854 freeAsmop (right, NULL, ic, TRUE);
9855 freeAsmop (result, NULL, ic, TRUE);
9858 /*-----------------------------------------------------------------*/
9859 /* genNearPointerSet - emitcode for near pointer put */
9860 /*-----------------------------------------------------------------*/
9862 genNearPointerSet (operand * right,
9870 sym_link *retype, *letype;
9871 sym_link *ptype = operandType (result);
9873 retype = getSpec (operandType (right));
9874 letype = getSpec (ptype);
9876 aopOp (result, ic, FALSE, FALSE);
9878 /* if the result is rematerializable &
9879 in data space & not a bit variable */
9880 if (AOP_TYPE (result) == AOP_IMMD &&
9881 DCL_TYPE (ptype) == POINTER &&
9882 !IS_BITVAR (retype) &&
9883 !IS_BITVAR (letype))
9885 genDataPointerSet (right, result, ic);
9889 /* if the value is already in a pointer register
9890 then don't need anything more */
9891 if (!AOP_INPREG (AOP (result)))
9893 /* otherwise get a free pointer register */
9895 preg = getFreePtr (ic, &aop, FALSE);
9896 emitcode ("mov", "%s,%s",
9898 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9902 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9904 aopOp (right, ic, FALSE, FALSE);
9906 /* if bitfield then unpack the bits */
9907 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9908 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9911 /* we have can just get the values */
9912 int size = AOP_SIZE (right);
9917 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
9921 emitcode ("mov", "@%s,a", rname);
9924 emitcode ("mov", "@%s,%s", rname, l);
9926 emitcode ("inc", "%s", rname);
9931 /* now some housekeeping stuff */
9934 /* we had to allocate for this iCode */
9935 if (pi) aopPut (AOP (result),rname,0);
9936 freeAsmop (NULL, aop, ic, TRUE);
9940 /* we did not allocate which means left
9941 already in a pointer register, then
9942 if size > 0 && this could be used again
9943 we have to point it back to where it
9945 if (AOP_SIZE (right) > 1 &&
9946 !OP_SYMBOL (result)->remat &&
9947 (OP_SYMBOL (result)->liveTo > ic->seq ||
9951 int size = AOP_SIZE (right) - 1;
9953 emitcode ("dec", "%s", rname);
9958 if (pi) pi->generated = 1;
9959 freeAsmop (result, NULL, ic, TRUE);
9960 freeAsmop (right, NULL, ic, TRUE);
9965 /*-----------------------------------------------------------------*/
9966 /* genPagedPointerSet - emitcode for Paged pointer put */
9967 /*-----------------------------------------------------------------*/
9969 genPagedPointerSet (operand * right,
9977 sym_link *retype, *letype;
9979 retype = getSpec (operandType (right));
9980 letype = getSpec (operandType (result));
9982 aopOp (result, ic, FALSE, FALSE);
9984 /* if the value is already in a pointer register
9985 then don't need anything more */
9986 if (!AOP_INPREG (AOP (result)))
9988 /* otherwise get a free pointer register */
9990 preg = getFreePtr (ic, &aop, FALSE);
9991 emitcode ("mov", "%s,%s",
9993 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9997 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9999 aopOp (right, ic, FALSE, FALSE);
10001 /* if bitfield then unpack the bits */
10002 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10003 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
10006 /* we have can just get the values */
10007 int size = AOP_SIZE (right);
10012 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
10015 emitcode ("movx", "@%s,a", rname);
10018 emitcode ("inc", "%s", rname);
10024 /* now some housekeeping stuff */
10027 if (pi) aopPut (AOP (result),rname,0);
10028 /* we had to allocate for this iCode */
10029 freeAsmop (NULL, aop, ic, TRUE);
10033 /* we did not allocate which means left
10034 already in a pointer register, then
10035 if size > 0 && this could be used again
10036 we have to point it back to where it
10038 if (AOP_SIZE (right) > 1 &&
10039 !OP_SYMBOL (result)->remat &&
10040 (OP_SYMBOL (result)->liveTo > ic->seq ||
10044 int size = AOP_SIZE (right) - 1;
10046 emitcode ("dec", "%s", rname);
10051 if (pi) pi->generated = 1;
10052 freeAsmop (result, NULL, ic, TRUE);
10053 freeAsmop (right, NULL, ic, TRUE);
10058 /*-----------------------------------------------------------------*/
10059 /* genFarPointerSet - set value from far space */
10060 /*-----------------------------------------------------------------*/
10062 genFarPointerSet (operand * right,
10063 operand * result, iCode * ic, iCode *pi)
10065 int size, offset, dopi=1;
10066 sym_link *retype = getSpec (operandType (right));
10067 sym_link *letype = getSpec (operandType (result));
10069 aopOp (result, ic, FALSE, FALSE);
10071 /* if the operand is already in dptr
10072 then we do nothing else we move the value to dptr */
10073 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10075 /* if this is remateriazable */
10076 if (AOP_TYPE (result) == AOP_IMMD)
10077 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
10080 /* we need to get it byte by byte */
10081 _startLazyDPSEvaluation ();
10082 if (AOP_TYPE (result) != AOP_DPTR)
10084 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
10085 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
10086 if (options.model == MODEL_FLAT24)
10087 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
10091 /* We need to generate a load to DPTR indirect through DPTR. */
10092 D (emitcode (";", "genFarPointerSet -- indirection special case.");
10094 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
10095 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
10096 if (options.model == MODEL_FLAT24)
10097 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
10098 emitcode ("pop", "dph");
10099 emitcode ("pop", "dpl");
10102 _endLazyDPSEvaluation ();
10105 /* so dptr know contains the address */
10106 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10108 /* if bit then unpack */
10109 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
10110 if (AOP_INDPTRn(result)) {
10111 genSetDPTR(AOP(result)->aopu.dptr);
10113 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
10114 if (AOP_INDPTRn(result)) {
10118 size = AOP_SIZE (right);
10120 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10122 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
10125 genSetDPTR(AOP(result)->aopu.dptr);
10126 emitcode ("movx", "@dptr,a");
10127 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10128 emitcode ("inc", "dptr");
10132 _startLazyDPSEvaluation ();
10134 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
10137 if (AOP_INDPTRn(result)) {
10138 genSetDPTR(AOP(result)->aopu.dptr);
10144 emitcode ("movx", "@dptr,a");
10145 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10146 emitcode ("inc", "dptr");
10148 _endLazyDPSEvaluation ();
10152 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10153 if (!AOP_INDPTRn(result)) {
10154 aopPut (AOP(result),"dpl",0);
10155 aopPut (AOP(result),"dph",1);
10156 if (options.model == MODEL_FLAT24)
10157 aopPut (AOP(result),"dpx",2);
10160 } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
10161 AOP_SIZE(right) > 1 &&
10162 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10164 size = AOP_SIZE (right) - 1;
10165 if (AOP_INDPTRn(result)) {
10166 genSetDPTR(AOP(result)->aopu.dptr);
10168 while (size--) emitcode ("lcall","__decdptr");
10169 if (AOP_INDPTRn(result)) {
10173 freeAsmop (result, NULL, ic, TRUE);
10174 freeAsmop (right, NULL, ic, TRUE);
10177 /*-----------------------------------------------------------------*/
10178 /* genGenPointerSet - set value from generic pointer space */
10179 /*-----------------------------------------------------------------*/
10181 genGenPointerSet (operand * right,
10182 operand * result, iCode * ic, iCode *pi)
10185 sym_link *retype = getSpec (operandType (right));
10186 sym_link *letype = getSpec (operandType (result));
10188 aopOp (result, ic, FALSE, OP_SYMBOL(result)->ruonly ? FALSE : TRUE);
10190 /* if the operand is already in dptr
10191 then we do nothing else we move the value to dptr */
10192 if (AOP_TYPE (result) != AOP_STR)
10194 _startLazyDPSEvaluation ();
10195 /* if this is remateriazable */
10196 if (AOP_TYPE (result) == AOP_IMMD)
10198 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
10199 if (AOP(result)->aopu.aop_immd.from_cast_remat)
10200 emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, FALSE));
10202 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
10205 { /* we need to get it byte by byte */
10206 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
10207 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
10208 if (options.model == MODEL_FLAT24) {
10209 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
10210 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
10212 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
10215 _endLazyDPSEvaluation ();
10217 /* so dptr know contains the address */
10218 aopOp (right, ic, FALSE, TRUE);
10220 /* if bit then unpack */
10221 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10222 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
10225 size = AOP_SIZE (right);
10228 _startLazyDPSEvaluation ();
10231 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
10237 emitcode ("lcall", "__gptrput");
10238 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10239 emitcode ("inc", "dptr");
10241 _endLazyDPSEvaluation ();
10244 if (pi && AOP_TYPE (result) != AOP_IMMD) {
10245 aopPut (AOP(result),"dpl",0);
10246 aopPut (AOP(result),"dph",1);
10247 if (options.model == MODEL_FLAT24) {
10248 aopPut (AOP(result),"dpx",2);
10249 aopPut (AOP(result),"b",3);
10251 aopPut (AOP(result),"b",2);
10254 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10255 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10257 size = AOP_SIZE (right) - 1;
10258 while (size--) emitcode ("lcall","__decdptr");
10260 freeAsmop (result, NULL, ic, TRUE);
10261 freeAsmop (right, NULL, ic, TRUE);
10264 /*-----------------------------------------------------------------*/
10265 /* genPointerSet - stores the value into a pointer location */
10266 /*-----------------------------------------------------------------*/
10268 genPointerSet (iCode * ic, iCode *pi)
10270 operand *right, *result;
10271 sym_link *type, *etype;
10274 D (emitcode (";", "genPointerSet ");
10277 right = IC_RIGHT (ic);
10278 result = IC_RESULT (ic);
10280 /* depending on the type of pointer we need to
10281 move it to the correct pointer register */
10282 type = operandType (result);
10283 etype = getSpec (type);
10284 /* if left is of type of pointer then it is simple */
10285 if (IS_PTR (type) && !IS_FUNC (type->next))
10287 p_type = DCL_TYPE (type);
10291 /* we have to go by the storage class */
10292 p_type = PTR_TYPE (SPEC_OCLS (etype));
10294 /* special case when cast remat */
10295 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10296 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10297 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10298 type = operandType (result);
10299 p_type = DCL_TYPE (type);
10302 /* now that we have the pointer type we assign
10303 the pointer values */
10309 genNearPointerSet (right, result, ic, pi);
10313 genPagedPointerSet (right, result, ic, pi);
10317 genFarPointerSet (right, result, ic, pi);
10321 genGenPointerSet (right, result, ic, pi);
10325 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10326 "genPointerSet: illegal pointer type");
10331 /*-----------------------------------------------------------------*/
10332 /* genIfx - generate code for Ifx statement */
10333 /*-----------------------------------------------------------------*/
10335 genIfx (iCode * ic, iCode * popIc)
10337 operand *cond = IC_COND (ic);
10340 D (emitcode (";", "genIfx "););
10342 aopOp (cond, ic, FALSE, FALSE);
10344 /* get the value into acc */
10345 if (AOP_TYPE (cond) != AOP_CRY)
10349 /* the result is now in the accumulator */
10350 freeAsmop (cond, NULL, ic, TRUE);
10352 /* if there was something to be popped then do it */
10356 /* if the condition is a bit variable */
10357 if (isbit && IS_ITEMP (cond) &&
10359 genIfxJump (ic, SPIL_LOC (cond)->rname);
10360 else if (isbit && !IS_ITEMP (cond))
10361 genIfxJump (ic, OP_SYMBOL (cond)->rname);
10363 genIfxJump (ic, "a");
10368 /*-----------------------------------------------------------------*/
10369 /* genAddrOf - generates code for address of */
10370 /*-----------------------------------------------------------------*/
10372 genAddrOf (iCode * ic)
10374 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10377 D (emitcode (";", "genAddrOf ");
10380 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10382 /* if the operand is on the stack then we
10383 need to get the stack offset of this
10385 if (sym->onStack) {
10387 /* if 10 bit stack */
10388 if (options.stack10bit) {
10390 tsprintf(buff, sizeof(buff),
10391 "#!constbyte",(options.stack_loc >> 16) & 0xff);
10392 /* if it has an offset then we need to compute it */
10393 /* emitcode ("subb", "a,#!constbyte", */
10394 /* -((sym->stack < 0) ? */
10395 /* ((short) (sym->stack - _G.nRegsSaved)) : */
10396 /* ((short) sym->stack)) & 0xff); */
10397 /* emitcode ("mov","b,a"); */
10398 /* emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
10399 /* ((short) (sym->stack - _G.nRegsSaved)) : */
10400 /* ((short) sym->stack)) >> 8) & 0xff); */
10402 emitcode ("mov", "a,_bpx");
10403 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
10404 ((char) (sym->stack - _G.nRegsSaved)) :
10405 ((char) sym->stack )) & 0xff);
10406 emitcode ("mov", "b,a");
10407 emitcode ("mov", "a,_bpx+1");
10408 emitcode ("addc","a,#!constbyte", (((sym->stack < 0) ?
10409 ((short) (sym->stack - _G.nRegsSaved)) :
10410 ((short) sym->stack )) >> 8) & 0xff);
10411 aopPut (AOP (IC_RESULT (ic)), "b", 0);
10412 aopPut (AOP (IC_RESULT (ic)), "a", 1);
10413 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10415 /* we can just move _bp */
10416 aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10417 aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10418 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10421 /* if it has an offset then we need to compute it */
10423 emitcode ("mov", "a,_bp");
10424 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10425 aopPut (AOP (IC_RESULT (ic)), "a", 0);
10427 /* we can just move _bp */
10428 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10430 /* fill the result with zero */
10431 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10434 if (options.stack10bit && size < (FPTRSIZE - 1)) {
10436 "*** warning: pointer to stack var truncated.\n");
10441 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10447 /* object not on stack then we need the name */
10448 size = AOP_SIZE (IC_RESULT (ic));
10453 char s[SDCC_NAME_MAX];
10457 tsprintf(s, sizeof(s), "!his",sym->rname);
10460 tsprintf(s, sizeof(s), "!hihis",sym->rname);
10463 tsprintf(s, sizeof(s), "!hihihis",sym->rname);
10465 default: /* should not need this (just in case) */
10466 SNPRINTF (s, sizeof(s), "#(%s >> %d)",
10471 sprintf (s, "#%s", sym->rname);
10472 aopPut (AOP (IC_RESULT (ic)), s, offset++);
10476 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10480 /*-----------------------------------------------------------------*/
10481 /* genArrayInit - generates code for address of */
10482 /*-----------------------------------------------------------------*/
10484 genArrayInit (iCode * ic)
10486 literalList *iLoop;
10488 int elementSize = 0, eIndex;
10489 unsigned val, lastVal;
10491 operand *left=IC_LEFT(ic);
10493 D (emitcode (";", "genArrayInit "););
10495 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10497 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10499 // Load immediate value into DPTR.
10500 emitcode("mov", "dptr, %s",
10501 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
10503 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10506 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10507 "Unexpected operand to genArrayInit.\n");
10510 // a regression because of SDCCcse.c:1.52
10511 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
10512 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
10513 if (options.model == MODEL_FLAT24)
10514 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
10518 type = operandType(IC_LEFT(ic));
10520 if (type && type->next)
10522 elementSize = getSize(type->next);
10526 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10527 "can't determine element size in genArrayInit.\n");
10531 iLoop = IC_ARRAYILIST(ic);
10536 bool firstpass = TRUE;
10538 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
10539 iLoop->count, (int)iLoop->literalValue, elementSize);
10545 symbol *tlbl = NULL;
10547 count = ix > 256 ? 256 : ix;
10551 tlbl = newiTempLabel (NULL);
10552 if (firstpass || (count & 0xff))
10554 emitcode("mov", "b, #!constbyte", count & 0xff);
10557 emitcode ("", "!tlabeldef", tlbl->key + 100);
10562 for (eIndex = 0; eIndex < elementSize; eIndex++)
10564 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10565 if (val != lastVal)
10567 emitcode("mov", "a, #!constbyte", val);
10571 emitcode("movx", "@dptr, a");
10572 emitcode("inc", "dptr");
10577 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10583 iLoop = iLoop->next;
10586 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10589 /*-----------------------------------------------------------------*/
10590 /* genFarFarAssign - assignment when both are in far space */
10591 /*-----------------------------------------------------------------*/
10593 genFarFarAssign (operand * result, operand * right, iCode * ic)
10595 int size = AOP_SIZE (right);
10597 symbol *rSym = NULL;
10601 /* quick & easy case. */
10602 D(emitcode(";","genFarFarAssign (1 byte case)"););
10603 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
10604 freeAsmop (right, NULL, ic, FALSE);
10605 /* now assign DPTR to result */
10607 aopOp(result, ic, FALSE, FALSE);
10609 aopPut(AOP(result), "a", 0);
10610 freeAsmop(result, NULL, ic, FALSE);
10614 /* See if we've got an underlying symbol to abuse. */
10615 if (IS_SYMOP(result) && OP_SYMBOL(result))
10617 if (IS_TRUE_SYMOP(result))
10619 rSym = OP_SYMBOL(result);
10621 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10623 rSym = OP_SYMBOL(result)->usl.spillLoc;
10627 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10629 /* We can use the '390 auto-toggle feature to good effect here. */
10631 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10632 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
10633 emitcode ("mov", "dptr,#%s", rSym->rname);
10634 /* DP2 = result, DP1 = right, DP1 is current. */
10637 emitcode("movx", "a,@dptr");
10638 emitcode("movx", "@dptr,a");
10641 emitcode("inc", "dptr");
10642 emitcode("inc", "dptr");
10645 emitcode("mov", "dps,#0");
10646 freeAsmop (right, NULL, ic, FALSE);
10648 some alternative code for processors without auto-toggle
10649 no time to test now, so later well put in...kpb
10650 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10651 emitcode("mov", "dps,#1"); /* Select DPTR2. */
10652 emitcode ("mov", "dptr,#%s", rSym->rname);
10653 /* DP2 = result, DP1 = right, DP1 is current. */
10657 emitcode("movx", "a,@dptr");
10659 emitcode("inc", "dptr");
10660 emitcode("inc", "dps");
10661 emitcode("movx", "@dptr,a");
10663 emitcode("inc", "dptr");
10664 emitcode("inc", "dps");
10666 emitcode("mov", "dps,#0");
10667 freeAsmop (right, NULL, ic, FALSE);
10672 D (emitcode (";", "genFarFarAssign"););
10673 aopOp (result, ic, TRUE, TRUE);
10675 _startLazyDPSEvaluation ();
10679 aopPut (AOP (result),
10680 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
10683 _endLazyDPSEvaluation ();
10684 freeAsmop (result, NULL, ic, FALSE);
10685 freeAsmop (right, NULL, ic, FALSE);
10689 /*-----------------------------------------------------------------*/
10690 /* genAssign - generate code for assignment */
10691 /*-----------------------------------------------------------------*/
10693 genAssign (iCode * ic)
10695 operand *result, *right;
10697 unsigned long lit = 0L;
10699 D (emitcode (";", "genAssign ");
10702 result = IC_RESULT (ic);
10703 right = IC_RIGHT (ic);
10705 /* if they are the same */
10706 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10709 aopOp (right, ic, FALSE, FALSE);
10711 emitcode (";", "genAssign: resultIsFar = %s",
10712 isOperandInFarSpace (result) ?
10715 /* special case both in far space */
10716 if ((AOP_TYPE (right) == AOP_DPTR ||
10717 AOP_TYPE (right) == AOP_DPTR2) &&
10718 /* IS_TRUE_SYMOP(result) && */
10719 isOperandInFarSpace (result))
10721 genFarFarAssign (result, right, ic);
10725 aopOp (result, ic, TRUE, FALSE);
10727 /* if they are the same registers */
10728 if (sameRegs (AOP (right), AOP (result)))
10731 /* if the result is a bit */
10732 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10734 /* if the right size is a literal then
10735 we know what the value is */
10736 if (AOP_TYPE (right) == AOP_LIT)
10738 if (((int) operandLitValue (right)))
10739 aopPut (AOP (result), one, 0);
10741 aopPut (AOP (result), zero, 0);
10745 /* the right is also a bit variable */
10746 if (AOP_TYPE (right) == AOP_CRY)
10748 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10749 aopPut (AOP (result), "c", 0);
10753 /* we need to or */
10755 aopPut (AOP (result), "a", 0);
10759 /* bit variables done */
10761 size = AOP_SIZE (result);
10763 if (AOP_TYPE (right) == AOP_LIT)
10764 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10767 (AOP_TYPE (result) != AOP_REG) &&
10768 (AOP_TYPE (right) == AOP_LIT) &&
10769 !IS_FLOAT (operandType (right)))
10771 _startLazyDPSEvaluation ();
10772 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10774 aopPut (AOP (result),
10775 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
10780 /* And now fill the rest with zeros. */
10783 emitcode ("clr", "a");
10787 aopPut (AOP (result), "a", offset++);
10789 _endLazyDPSEvaluation ();
10793 _startLazyDPSEvaluation ();
10796 aopPut (AOP (result),
10797 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10801 _endLazyDPSEvaluation ();
10805 freeAsmop (right, NULL, ic, FALSE);
10806 freeAsmop (result, NULL, ic, TRUE);
10809 /*-----------------------------------------------------------------*/
10810 /* genJumpTab - generates code for jump table */
10811 /*-----------------------------------------------------------------*/
10813 genJumpTab (iCode * ic)
10818 D (emitcode (";", "genJumpTab ");
10821 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10822 /* get the condition into accumulator */
10823 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
10825 /* multiply by four! */
10826 emitcode ("add", "a,acc");
10827 emitcode ("add", "a,acc");
10828 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10830 jtab = newiTempLabel (NULL);
10831 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
10832 emitcode ("jmp", "@a+dptr");
10833 emitcode ("", "!tlabeldef", jtab->key + 100);
10834 /* now generate the jump labels */
10835 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10836 jtab = setNextItem (IC_JTLABELS (ic)))
10837 emitcode ("ljmp", "!tlabel", jtab->key + 100);
10841 /*-----------------------------------------------------------------*/
10842 /* genCast - gen code for casting */
10843 /*-----------------------------------------------------------------*/
10845 genCast (iCode * ic)
10847 operand *result = IC_RESULT (ic);
10848 sym_link *ctype = operandType (IC_LEFT (ic));
10849 sym_link *rtype = operandType (IC_RIGHT (ic));
10850 operand *right = IC_RIGHT (ic);
10853 D (emitcode (";", "genCast ");
10856 /* if they are equivalent then do nothing */
10857 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10860 aopOp (right, ic, FALSE, FALSE);
10861 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
10863 /* if the result is a bit */
10864 // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10865 if (IS_BITVAR(OP_SYMBOL(result)->type))
10867 /* if the right size is a literal then
10868 we know what the value is */
10869 if (AOP_TYPE (right) == AOP_LIT)
10871 if (((int) operandLitValue (right)))
10872 aopPut (AOP (result), one, 0);
10874 aopPut (AOP (result), zero, 0);
10879 /* the right is also a bit variable */
10880 if (AOP_TYPE (right) == AOP_CRY)
10882 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10883 aopPut (AOP (result), "c", 0);
10887 /* we need to or */
10889 aopPut (AOP (result), "a", 0);
10893 /* if they are the same size : or less */
10894 if (AOP_SIZE (result) <= AOP_SIZE (right))
10897 /* if they are in the same place */
10898 if (sameRegs (AOP (right), AOP (result)))
10901 /* if they in different places then copy */
10902 size = AOP_SIZE (result);
10904 _startLazyDPSEvaluation ();
10907 aopPut (AOP (result),
10908 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10912 _endLazyDPSEvaluation ();
10917 /* if the result is of type pointer */
10918 if (IS_PTR (ctype))
10922 sym_link *type = operandType (right);
10924 /* pointer to generic pointer */
10925 if (IS_GENPTR (ctype))
10929 p_type = DCL_TYPE (type);
10933 #if OLD_CAST_BEHAVIOR
10934 /* KV: we are converting a non-pointer type to
10935 * a generic pointer. This (ifdef'd out) code
10936 * says that the resulting generic pointer
10937 * should have the same class as the storage
10938 * location of the non-pointer variable.
10940 * For example, converting an int (which happens
10941 * to be stored in DATA space) to a pointer results
10942 * in a DATA generic pointer; if the original int
10943 * in XDATA space, so will be the resulting pointer.
10945 * I don't like that behavior, and thus this change:
10946 * all such conversions will be forced to XDATA and
10947 * throw a warning. If you want some non-XDATA
10948 * type, or you want to suppress the warning, you
10949 * must go through an intermediate cast, like so:
10951 * char _generic *gp = (char _xdata *)(intVar);
10953 sym_link *etype = getSpec (type);
10955 /* we have to go by the storage class */
10956 if (SPEC_OCLS (etype) != generic)
10958 p_type = PTR_TYPE (SPEC_OCLS (etype));
10963 /* Converting unknown class (i.e. register variable)
10964 * to generic pointer. This is not good, but
10965 * we'll make a guess (and throw a warning).
10968 werror (W_INT_TO_GEN_PTR_CAST);
10972 /* the first two bytes are known */
10973 size = GPTRSIZE - 1;
10975 _startLazyDPSEvaluation ();
10978 aopPut (AOP (result),
10979 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10983 _endLazyDPSEvaluation ();
10985 /* the last byte depending on type */
10987 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
10992 // pointerTypeToGPByte will have bitched.
10996 sprintf(gpValStr, "#0x%d", gpVal);
10997 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11002 /* just copy the pointers */
11003 size = AOP_SIZE (result);
11005 _startLazyDPSEvaluation ();
11008 aopPut (AOP (result),
11009 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
11013 _endLazyDPSEvaluation ();
11017 /* so we now know that the size of destination is greater
11018 than the size of the source */
11019 /* we move to result for the size of source */
11020 size = AOP_SIZE (right);
11022 _startLazyDPSEvaluation ();
11025 aopPut (AOP (result),
11026 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
11030 _endLazyDPSEvaluation ();
11032 /* now depending on the sign of the source && destination */
11033 size = AOP_SIZE (result) - AOP_SIZE (right);
11034 /* if unsigned or not an integral type */
11035 /* also, if the source is a bit, we don't need to sign extend, because
11036 * it can't possibly have set the sign bit.
11038 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
11042 aopPut (AOP (result), zero, offset++);
11047 /* we need to extend the sign :{ */
11048 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
11049 FALSE, FALSE, TRUE);
11051 emitcode ("rlc", "a");
11052 emitcode ("subb", "a,acc");
11054 aopPut (AOP (result), "a", offset++);
11057 /* we are done hurray !!!! */
11060 freeAsmop (right, NULL, ic, TRUE);
11061 freeAsmop (result, NULL, ic, TRUE);
11065 /*-----------------------------------------------------------------*/
11066 /* genDjnz - generate decrement & jump if not zero instrucion */
11067 /*-----------------------------------------------------------------*/
11069 genDjnz (iCode * ic, iCode * ifx)
11071 symbol *lbl, *lbl1;
11075 /* if the if condition has a false label
11076 then we cannot save */
11077 if (IC_FALSE (ifx))
11080 /* if the minus is not of the form
11082 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11083 !IS_OP_LITERAL (IC_RIGHT (ic)))
11086 if (operandLitValue (IC_RIGHT (ic)) != 1)
11089 /* if the size of this greater than one then no
11091 if (getSize (operandType (IC_RESULT (ic))) > 1)
11094 /* otherwise we can save BIG */
11095 D(emitcode(";", "genDjnz"););
11097 lbl = newiTempLabel (NULL);
11098 lbl1 = newiTempLabel (NULL);
11100 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11102 if (AOP_NEEDSACC(IC_RESULT(ic)))
11104 /* If the result is accessed indirectly via
11105 * the accumulator, we must explicitly write
11106 * it back after the decrement.
11108 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
11110 if (strcmp(rByte, "a"))
11112 /* Something is hopelessly wrong */
11113 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11114 __FILE__, __LINE__);
11115 /* We can just give up; the generated code will be inefficient,
11116 * but what the hey.
11118 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11121 emitcode ("dec", "%s", rByte);
11122 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11123 emitcode ("jnz", "!tlabel", lbl->key + 100);
11125 else if (IS_AOP_PREG (IC_RESULT (ic)))
11127 emitcode ("dec", "%s",
11128 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
11129 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
11130 emitcode ("jnz", "!tlabel", lbl->key + 100);
11134 emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
11137 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11138 emitcode ("", "!tlabeldef", lbl->key + 100);
11139 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11140 emitcode ("", "!tlabeldef", lbl1->key + 100);
11142 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11143 ifx->generated = 1;
11147 /*-----------------------------------------------------------------*/
11148 /* genReceive - generate code for a receive iCode */
11149 /*-----------------------------------------------------------------*/
11151 genReceive (iCode * ic)
11154 int size = getSize (operandType (IC_RESULT (ic)));
11158 D (emitcode (";", "genReceive ");
11161 if (ic->argreg == 1) { /* first parameter */
11162 if (isOperandInFarSpace (IC_RESULT (ic)) &&
11163 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11164 IS_TRUE_SYMOP (IC_RESULT (ic))))
11166 offset = fReturnSizeDS390 - size;
11169 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
11170 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
11173 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11174 size = AOP_SIZE (IC_RESULT (ic));
11178 emitcode ("pop", "acc");
11179 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
11184 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11186 assignResultValue (IC_RESULT (ic));
11188 } else { /* second receive onwards */
11189 /* this gets a little tricky since unused recevies will be
11190 eliminated, we have saved the reg in the type field . and
11191 we use that to figure out which register to use */
11192 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11193 rb1off = ic->argreg;
11195 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11199 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11202 /*-----------------------------------------------------------------*/
11203 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
11204 /*-----------------------------------------------------------------*/
11205 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11207 operand *from , *to , *count;
11212 /* we know it has to be 3 parameters */
11213 assert (nparms == 3);
11215 rsave = newBitVect(16);
11216 /* save DPTR if it needs to be saved */
11217 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11218 if (bitVectBitValue(ic->rMask,i))
11219 rsave = bitVectSetBit(rsave,i);
11221 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11222 ds390_rUmaskForOp (IC_RESULT(ic))));
11229 aopOp (from, ic->next, FALSE, FALSE);
11231 /* get from into DPTR1 */
11232 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
11233 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
11234 if (options.model == MODEL_FLAT24) {
11235 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
11238 freeAsmop (from, NULL, ic, FALSE);
11239 aopOp (to, ic, FALSE, FALSE);
11240 /* get "to" into DPTR */
11241 /* if the operand is already in dptr
11242 then we do nothing else we move the value to dptr */
11243 if (AOP_TYPE (to) != AOP_STR) {
11244 /* if already in DPTR then we need to push */
11245 if (AOP_TYPE(to) == AOP_DPTR) {
11246 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11247 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11248 if (options.model == MODEL_FLAT24)
11249 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11250 emitcode ("pop", "dph");
11251 emitcode ("pop", "dpl");
11253 _startLazyDPSEvaluation ();
11254 /* if this is remateriazable */
11255 if (AOP_TYPE (to) == AOP_IMMD) {
11256 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11257 } else { /* we need to get it byte by byte */
11258 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11259 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11260 if (options.model == MODEL_FLAT24) {
11261 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11264 _endLazyDPSEvaluation ();
11267 freeAsmop (to, NULL, ic, FALSE);
11268 _G.dptrInUse = _G.dptr1InUse = 1;
11269 aopOp (count, ic->next->next, FALSE,FALSE);
11270 lbl =newiTempLabel(NULL);
11272 /* now for the actual copy */
11273 if (AOP_TYPE(count) == AOP_LIT &&
11274 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11275 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11277 emitcode ("lcall","__bi_memcpyc2x_s");
11279 emitcode ("lcall","__bi_memcpyx2x_s");
11281 freeAsmop (count, NULL, ic, FALSE);
11283 symbol *lbl1 = newiTempLabel(NULL);
11285 emitcode (";"," Auto increment but no djnz");
11286 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11287 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11288 freeAsmop (count, NULL, ic, FALSE);
11289 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11290 emitcode ("","!tlabeldef",lbl->key+100);
11292 emitcode ("clr","a");
11293 emitcode ("movc", "a,@a+dptr");
11295 emitcode ("movx", "a,@dptr");
11296 emitcode ("movx", "@dptr,a");
11297 emitcode ("inc", "dptr");
11298 emitcode ("inc", "dptr");
11299 emitcode ("mov","a,b");
11300 emitcode ("orl","a,_ap");
11301 emitcode ("jz","!tlabel",lbl1->key+100);
11302 emitcode ("mov","a,_ap");
11303 emitcode ("add","a,#!constbyte",0xFF);
11304 emitcode ("mov","_ap,a");
11305 emitcode ("mov","a,b");
11306 emitcode ("addc","a,#!constbyte",0xFF);
11307 emitcode ("mov","b,a");
11308 emitcode ("sjmp","!tlabel",lbl->key+100);
11309 emitcode ("","!tlabeldef",lbl1->key+100);
11311 emitcode ("mov", "dps,#0");
11312 _G.dptrInUse = _G.dptr1InUse = 0;
11313 unsavermask(rsave);
11317 /*-----------------------------------------------------------------*/
11318 /* genMemcmpX2X - gen code for memcmp xdata to xdata */
11319 /*-----------------------------------------------------------------*/
11320 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11322 operand *from , *to , *count;
11327 /* we know it has to be 3 parameters */
11328 assert (nparms == 3);
11330 rsave = newBitVect(16);
11331 /* save DPTR if it needs to be saved */
11332 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11333 if (bitVectBitValue(ic->rMask,i))
11334 rsave = bitVectSetBit(rsave,i);
11336 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11337 ds390_rUmaskForOp (IC_RESULT(ic))));
11344 aopOp (from, ic->next, FALSE, FALSE);
11346 /* get from into DPTR1 */
11347 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
11348 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
11349 if (options.model == MODEL_FLAT24) {
11350 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
11353 freeAsmop (from, NULL, ic, FALSE);
11354 aopOp (to, ic, FALSE, FALSE);
11355 /* get "to" into DPTR */
11356 /* if the operand is already in dptr
11357 then we do nothing else we move the value to dptr */
11358 if (AOP_TYPE (to) != AOP_STR) {
11359 /* if already in DPTR then we need to push */
11360 if (AOP_TYPE(to) == AOP_DPTR) {
11361 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11362 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11363 if (options.model == MODEL_FLAT24)
11364 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11365 emitcode ("pop", "dph");
11366 emitcode ("pop", "dpl");
11368 _startLazyDPSEvaluation ();
11369 /* if this is remateriazable */
11370 if (AOP_TYPE (to) == AOP_IMMD) {
11371 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11372 } else { /* we need to get it byte by byte */
11373 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11374 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11375 if (options.model == MODEL_FLAT24) {
11376 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11379 _endLazyDPSEvaluation ();
11382 freeAsmop (to, NULL, ic, FALSE);
11383 _G.dptrInUse = _G.dptr1InUse = 1;
11384 aopOp (count, ic->next->next, FALSE,FALSE);
11385 lbl =newiTempLabel(NULL);
11386 lbl2 =newiTempLabel(NULL);
11388 /* now for the actual compare */
11389 if (AOP_TYPE(count) == AOP_LIT &&
11390 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11391 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11393 emitcode("lcall","__bi_memcmpc2x_s");
11395 emitcode("lcall","__bi_memcmpx2x_s");
11396 freeAsmop (count, NULL, ic, FALSE);
11397 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11398 aopPut(AOP(IC_RESULT(ic)),"a",0);
11399 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11401 symbol *lbl1 = newiTempLabel(NULL);
11403 emitcode("push","ar0");
11404 emitcode (";"," Auto increment but no djnz");
11405 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11406 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
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 ("mov","r0,a");
11416 emitcode ("movx", "a,@dptr");
11417 emitcode ("clr","c");
11418 emitcode ("subb","a,r0");
11419 emitcode ("jnz","!tlabel",lbl2->key+100);
11420 emitcode ("inc", "dptr");
11421 emitcode ("inc", "dptr");
11422 emitcode ("mov","a,b");
11423 emitcode ("orl","a,_ap");
11424 emitcode ("jz","!tlabel",lbl1->key+100);
11425 emitcode ("mov","a,_ap");
11426 emitcode ("add","a,#!constbyte",0xFF);
11427 emitcode ("mov","_ap,a");
11428 emitcode ("mov","a,b");
11429 emitcode ("addc","a,#!constbyte",0xFF);
11430 emitcode ("mov","b,a");
11431 emitcode ("sjmp","!tlabel",lbl->key+100);
11432 emitcode ("","!tlabeldef",lbl1->key+100);
11433 emitcode ("clr","a");
11434 emitcode ("","!tlabeldef",lbl2->key+100);
11435 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11436 aopPut(AOP(IC_RESULT(ic)),"a",0);
11437 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11438 emitcode("pop","ar0");
11439 emitcode ("mov", "dps,#0");
11441 _G.dptrInUse = _G.dptr1InUse = 0;
11442 unsavermask(rsave);
11446 /*-----------------------------------------------------------------*/
11447 /* genInp - gen code for __builtin_inp read data from a mem mapped */
11448 /* port, first parameter output area second parameter pointer to */
11449 /* port third parameter count */
11450 /*-----------------------------------------------------------------*/
11451 static void genInp( iCode *ic, int nparms, operand **parms)
11453 operand *from , *to , *count;
11458 /* we know it has to be 3 parameters */
11459 assert (nparms == 3);
11461 rsave = newBitVect(16);
11462 /* save DPTR if it needs to be saved */
11463 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11464 if (bitVectBitValue(ic->rMask,i))
11465 rsave = bitVectSetBit(rsave,i);
11467 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11468 ds390_rUmaskForOp (IC_RESULT(ic))));
11475 aopOp (from, ic->next, FALSE, FALSE);
11477 /* get from into DPTR1 */
11478 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
11479 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
11480 if (options.model == MODEL_FLAT24) {
11481 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
11484 freeAsmop (from, NULL, ic, FALSE);
11485 aopOp (to, ic, FALSE, FALSE);
11486 /* get "to" into DPTR */
11487 /* if the operand is already in dptr
11488 then we do nothing else we move the value to dptr */
11489 if (AOP_TYPE (to) != AOP_STR) {
11490 /* if already in DPTR then we need to push */
11491 if (AOP_TYPE(to) == AOP_DPTR) {
11492 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11493 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11494 if (options.model == MODEL_FLAT24)
11495 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11496 emitcode ("pop", "dph");
11497 emitcode ("pop", "dpl");
11499 _startLazyDPSEvaluation ();
11500 /* if this is remateriazable */
11501 if (AOP_TYPE (to) == AOP_IMMD) {
11502 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11503 } else { /* we need to get it byte by byte */
11504 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11505 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11506 if (options.model == MODEL_FLAT24) {
11507 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11510 _endLazyDPSEvaluation ();
11513 freeAsmop (to, NULL, ic, FALSE);
11515 _G.dptrInUse = _G.dptr1InUse = 1;
11516 aopOp (count, ic->next->next, FALSE,FALSE);
11517 lbl =newiTempLabel(NULL);
11519 /* now for the actual copy */
11520 if (AOP_TYPE(count) == AOP_LIT &&
11521 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11522 emitcode (";","OH JOY auto increment with djnz (very fast)");
11523 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11524 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11525 freeAsmop (count, NULL, ic, FALSE);
11526 emitcode ("","!tlabeldef",lbl->key+100);
11527 emitcode ("movx", "a,@dptr"); /* read data from port */
11528 emitcode ("dec","dps"); /* switch to DPTR */
11529 emitcode ("movx", "@dptr,a"); /* save into location */
11530 emitcode ("inc", "dptr"); /* point to next area */
11531 emitcode ("inc","dps"); /* switch to DPTR2 */
11532 emitcode ("djnz","b,!tlabel",lbl->key+100);
11534 symbol *lbl1 = newiTempLabel(NULL);
11536 emitcode (";"," Auto increment but no djnz");
11537 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11538 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11539 freeAsmop (count, NULL, ic, FALSE);
11540 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11541 emitcode ("","!tlabeldef",lbl->key+100);
11542 emitcode ("movx", "a,@dptr");
11543 emitcode ("dec","dps"); /* switch to DPTR */
11544 emitcode ("movx", "@dptr,a");
11545 emitcode ("inc", "dptr");
11546 emitcode ("inc","dps"); /* switch to DPTR2 */
11547 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
11548 /* emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
11549 emitcode ("mov","a,b");
11550 emitcode ("orl","a,_ap");
11551 emitcode ("jz","!tlabel",lbl1->key+100);
11552 emitcode ("mov","a,_ap");
11553 emitcode ("add","a,#!constbyte",0xFF);
11554 emitcode ("mov","_ap,a");
11555 emitcode ("mov","a,b");
11556 emitcode ("addc","a,#!constbyte",0xFF);
11557 emitcode ("mov","b,a");
11558 emitcode ("sjmp","!tlabel",lbl->key+100);
11559 emitcode ("","!tlabeldef",lbl1->key+100);
11561 emitcode ("mov", "dps,#0");
11562 _G.dptrInUse = _G.dptr1InUse = 0;
11563 unsavermask(rsave);
11567 /*-----------------------------------------------------------------*/
11568 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
11569 /* port, first parameter output area second parameter pointer to */
11570 /* port third parameter count */
11571 /*-----------------------------------------------------------------*/
11572 static void genOutp( iCode *ic, int nparms, operand **parms)
11574 operand *from , *to , *count;
11579 /* we know it has to be 3 parameters */
11580 assert (nparms == 3);
11582 rsave = newBitVect(16);
11583 /* save DPTR if it needs to be saved */
11584 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11585 if (bitVectBitValue(ic->rMask,i))
11586 rsave = bitVectSetBit(rsave,i);
11588 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11589 ds390_rUmaskForOp (IC_RESULT(ic))));
11596 aopOp (from, ic->next, FALSE, FALSE);
11598 /* get from into DPTR1 */
11599 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
11600 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
11601 if (options.model == MODEL_FLAT24) {
11602 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
11605 freeAsmop (from, NULL, ic, FALSE);
11606 aopOp (to, ic, FALSE, FALSE);
11607 /* get "to" into DPTR */
11608 /* if the operand is already in dptr
11609 then we do nothing else we move the value to dptr */
11610 if (AOP_TYPE (to) != AOP_STR) {
11611 /* if already in DPTR then we need to push */
11612 if (AOP_TYPE(to) == AOP_DPTR) {
11613 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11614 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11615 if (options.model == MODEL_FLAT24)
11616 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11617 emitcode ("pop", "dph");
11618 emitcode ("pop", "dpl");
11620 _startLazyDPSEvaluation ();
11621 /* if this is remateriazable */
11622 if (AOP_TYPE (to) == AOP_IMMD) {
11623 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11624 } else { /* we need to get it byte by byte */
11625 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11626 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11627 if (options.model == MODEL_FLAT24) {
11628 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11631 _endLazyDPSEvaluation ();
11634 freeAsmop (to, NULL, ic, FALSE);
11636 _G.dptrInUse = _G.dptr1InUse = 1;
11637 aopOp (count, ic->next->next, FALSE,FALSE);
11638 lbl =newiTempLabel(NULL);
11640 /* now for the actual copy */
11641 if (AOP_TYPE(count) == AOP_LIT &&
11642 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11643 emitcode (";","OH JOY auto increment with djnz (very fast)");
11644 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
11645 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11646 emitcode ("","!tlabeldef",lbl->key+100);
11647 emitcode ("movx", "a,@dptr"); /* read data from port */
11648 emitcode ("inc","dps"); /* switch to DPTR2 */
11649 emitcode ("movx", "@dptr,a"); /* save into location */
11650 emitcode ("inc", "dptr"); /* point to next area */
11651 emitcode ("dec","dps"); /* switch to DPTR */
11652 emitcode ("djnz","b,!tlabel",lbl->key+100);
11653 freeAsmop (count, NULL, ic, FALSE);
11655 symbol *lbl1 = newiTempLabel(NULL);
11657 emitcode (";"," Auto increment but no djnz");
11658 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11659 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11660 freeAsmop (count, NULL, ic, FALSE);
11661 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
11662 emitcode ("","!tlabeldef",lbl->key+100);
11663 emitcode ("movx", "a,@dptr");
11664 emitcode ("inc", "dptr");
11665 emitcode ("inc","dps"); /* switch to DPTR2 */
11666 emitcode ("movx", "@dptr,a");
11667 emitcode ("dec","dps"); /* switch to DPTR */
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 /* genSwapW - swap lower & high order bytes */
11688 /*-----------------------------------------------------------------*/
11689 static void genSwapW(iCode *ic, int nparms, operand **parms)
11693 assert (nparms==1);
11696 dest=IC_RESULT(ic);
11698 assert(getSize(operandType(src))==2);
11700 aopOp (src, ic, FALSE, FALSE);
11701 emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,TRUE));
11703 emitcode ("mov","b,%s",aopGet(AOP(src),1,FALSE,FALSE,FALSE));
11705 freeAsmop (src, NULL, ic, FALSE);
11707 aopOp (dest,ic, FALSE, FALSE);
11708 aopPut(AOP(dest),"b",0);
11709 aopPut(AOP(dest),"a",1);
11710 freeAsmop (dest, NULL, ic, FALSE);
11713 /*-----------------------------------------------------------------*/
11714 /* genMemsetX - gencode for memSetX data */
11715 /*-----------------------------------------------------------------*/
11716 static void genMemsetX(iCode *ic, int nparms, operand **parms)
11718 operand *to , *val , *count;
11722 bitVect *rsave = NULL;
11724 /* we know it has to be 3 parameters */
11725 assert (nparms == 3);
11731 /* save DPTR if it needs to be saved */
11732 rsave = newBitVect(16);
11733 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11734 if (bitVectBitValue(ic->rMask,i))
11735 rsave = bitVectSetBit(rsave,i);
11737 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11738 ds390_rUmaskForOp (IC_RESULT(ic))));
11741 aopOp (to, ic, FALSE, FALSE);
11742 /* get "to" into DPTR */
11743 /* if the operand is already in dptr
11744 then we do nothing else we move the value to dptr */
11745 if (AOP_TYPE (to) != AOP_STR) {
11746 /* if already in DPTR then we need to push */
11747 if (AOP_TYPE(to) == AOP_DPTR) {
11748 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11749 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11750 if (options.model == MODEL_FLAT24)
11751 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11752 emitcode ("pop", "dph");
11753 emitcode ("pop", "dpl");
11755 _startLazyDPSEvaluation ();
11756 /* if this is remateriazable */
11757 if (AOP_TYPE (to) == AOP_IMMD) {
11758 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11759 } else { /* we need to get it byte by byte */
11760 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11761 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11762 if (options.model == MODEL_FLAT24) {
11763 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11766 _endLazyDPSEvaluation ();
11769 freeAsmop (to, NULL, ic, FALSE);
11771 aopOp (val, ic->next->next, FALSE,FALSE);
11772 aopOp (count, ic->next->next, FALSE,FALSE);
11773 lbl =newiTempLabel(NULL);
11774 /* now for the actual copy */
11775 if (AOP_TYPE(count) == AOP_LIT &&
11776 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11777 l = aopGet(AOP (val), 0, FALSE, FALSE, TRUE);
11778 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11780 emitcode ("","!tlabeldef",lbl->key+100);
11781 emitcode ("movx", "@dptr,a");
11782 emitcode ("inc", "dptr");
11783 emitcode ("djnz","b,!tlabel",lbl->key+100);
11785 symbol *lbl1 = newiTempLabel(NULL);
11787 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11788 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11789 emitcode ("","!tlabeldef",lbl->key+100);
11790 l = aopGet(AOP (val), 0, FALSE, FALSE, TRUE);
11792 emitcode ("movx", "@dptr,a");
11793 emitcode ("inc", "dptr");
11794 emitcode ("mov","a,b");
11795 emitcode ("orl","a,_ap");
11796 emitcode ("jz","!tlabel",lbl1->key+100);
11797 emitcode ("mov","a,_ap");
11798 emitcode ("add","a,#!constbyte",0xFF);
11799 emitcode ("mov","_ap,a");
11800 emitcode ("mov","a,b");
11801 emitcode ("addc","a,#!constbyte",0xFF);
11802 emitcode ("mov","b,a");
11803 emitcode ("sjmp","!tlabel",lbl->key+100);
11804 emitcode ("","!tlabeldef",lbl1->key+100);
11806 freeAsmop (count, NULL, ic, FALSE);
11807 unsavermask(rsave);
11810 /*-----------------------------------------------------------------*/
11811 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
11812 /*-----------------------------------------------------------------*/
11813 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
11816 operand *pnum, *result;
11819 assert (nparms==1);
11820 /* save registers that need to be saved */
11821 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11822 ds390_rUmaskForOp (IC_RESULT(ic))));
11825 aopOp (pnum, ic, FALSE, FALSE);
11826 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,FALSE));
11827 freeAsmop (pnum, NULL, ic, FALSE);
11828 emitcode ("lcall","NatLib_LoadPrimitive");
11829 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11830 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
11831 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
11832 for (i = (size-1) ; i >= 0 ; i-- ) {
11833 emitcode ("push","a%s",javaRet[i]);
11835 for (i=0; i < size ; i++ ) {
11836 emitcode ("pop","a%s",aopGet(AOP(result),i,FALSE,FALSE,FALSE));
11839 for (i = 0 ; i < size ; i++ ) {
11840 aopPut(AOP(result),javaRet[i],i);
11843 freeAsmop (result, NULL, ic, FALSE);
11844 unsavermask(rsave);
11847 /*-----------------------------------------------------------------*/
11848 /* genNatLibLoadPointer - calls TINI api function to load pointer */
11849 /*-----------------------------------------------------------------*/
11850 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
11853 operand *pnum, *result;
11857 assert (nparms==1);
11858 /* save registers that need to be saved */
11859 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11860 ds390_rUmaskForOp (IC_RESULT(ic))));
11863 aopOp (pnum, ic, FALSE, FALSE);
11864 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,FALSE));
11865 freeAsmop (pnum, NULL, ic, FALSE);
11866 emitcode ("lcall","NatLib_LoadPointer");
11867 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11868 if (AOP_TYPE(result)!=AOP_STR) {
11869 for (i = 0 ; i < size ; i++ ) {
11870 aopPut(AOP(result),fReturn[i],i);
11873 freeAsmop (result, NULL, ic, FALSE);
11874 unsavermask(rsave);
11877 /*-----------------------------------------------------------------*/
11878 /* genNatLibInstallStateBlock - */
11879 /*-----------------------------------------------------------------*/
11880 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
11881 operand **parms, const char *name)
11884 operand *psb, *handle;
11885 assert (nparms==2);
11887 /* save registers that need to be saved */
11888 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11889 ds390_rUmaskForOp (IC_RESULT(ic))));
11893 /* put pointer to state block into DPTR1 */
11894 aopOp (psb, ic, FALSE, FALSE);
11895 if (AOP_TYPE (psb) == AOP_IMMD) {
11896 emitcode ("mov","dps,#1");
11897 emitcode ("mov", "dptr,%s", aopGet (AOP (psb), 0, TRUE, FALSE, FALSE));
11898 emitcode ("mov","dps,#0");
11900 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,FALSE));
11901 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,FALSE));
11902 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,FALSE));
11904 freeAsmop (psb, NULL, ic, FALSE);
11906 /* put libraryID into DPTR */
11907 emitcode ("mov","dptr,#LibraryID");
11909 /* put handle into r3:r2 */
11910 aopOp (handle, ic, FALSE, FALSE);
11911 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11912 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11913 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11914 emitcode ("pop","ar3");
11915 emitcode ("pop","ar2");
11917 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11918 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11920 freeAsmop (psb, NULL, ic, FALSE);
11922 /* make the call */
11923 emitcode ("lcall","NatLib_Install%sStateBlock",name);
11925 /* put return value into place*/
11927 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
11929 aopPut(AOP(IC_RESULT(ic)),"a",0);
11930 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11931 unsavermask(rsave);
11934 /*-----------------------------------------------------------------*/
11935 /* genNatLibRemoveStateBlock - */
11936 /*-----------------------------------------------------------------*/
11937 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
11943 /* save registers that need to be saved */
11944 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11945 ds390_rUmaskForOp (IC_RESULT(ic))));
11947 /* put libraryID into DPTR */
11948 emitcode ("mov","dptr,#LibraryID");
11949 /* make the call */
11950 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
11951 unsavermask(rsave);
11954 /*-----------------------------------------------------------------*/
11955 /* genNatLibGetStateBlock - */
11956 /*-----------------------------------------------------------------*/
11957 static void genNatLibGetStateBlock(iCode *ic,int nparms,
11958 operand **parms,const char *name)
11961 symbol *lbl = newiTempLabel(NULL);
11964 /* save registers that need to be saved */
11965 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11966 ds390_rUmaskForOp (IC_RESULT(ic))));
11968 /* put libraryID into DPTR */
11969 emitcode ("mov","dptr,#LibraryID");
11970 /* make the call */
11971 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
11972 emitcode ("jnz","!tlabel",lbl->key+100);
11974 /* put return value into place */
11975 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
11976 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
11977 emitcode ("push","ar3");
11978 emitcode ("push","ar2");
11979 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,FALSE));
11980 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,FALSE));
11982 aopPut(AOP(IC_RESULT(ic)),"r2",0);
11983 aopPut(AOP(IC_RESULT(ic)),"r3",1);
11985 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11986 emitcode ("","!tlabeldef",lbl->key+100);
11987 unsavermask(rsave);
11990 /*-----------------------------------------------------------------*/
11991 /* genMMMalloc - */
11992 /*-----------------------------------------------------------------*/
11993 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
11994 int size, const char *name)
11999 symbol *lbl = newiTempLabel(NULL);
12001 assert (nparms == 1);
12002 /* save registers that need to be saved */
12003 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12004 ds390_rUmaskForOp (IC_RESULT(ic))));
12007 aopOp (bsize,ic,FALSE,FALSE);
12009 /* put the size in R4-R2 */
12010 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12011 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,FALSE));
12012 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,FALSE));
12014 emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,FALSE));
12015 emitcode("pop","ar4");
12017 emitcode("pop","ar3");
12018 emitcode("pop","ar2");
12020 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,FALSE));
12021 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,FALSE));
12023 emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,FALSE));
12026 freeAsmop (bsize, NULL, ic, FALSE);
12028 /* make the call */
12029 emitcode ("lcall","MM_%s",name);
12030 emitcode ("jz","!tlabel",lbl->key+100);
12031 emitcode ("mov","r2,#!constbyte",0xff);
12032 emitcode ("mov","r3,#!constbyte",0xff);
12033 emitcode ("","!tlabeldef",lbl->key+100);
12034 /* we don't care about the pointer : we just save the handle */
12035 rsym = OP_SYMBOL(IC_RESULT(ic));
12036 if (rsym->liveFrom != rsym->liveTo) {
12037 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12038 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12039 emitcode ("push","ar3");
12040 emitcode ("push","ar2");
12041 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,FALSE));
12042 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,FALSE));
12044 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12045 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12047 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12049 unsavermask(rsave);
12052 /*-----------------------------------------------------------------*/
12054 /*-----------------------------------------------------------------*/
12055 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12060 assert (nparms == 1);
12061 /* save registers that need to be saved */
12062 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12063 ds390_rUmaskForOp (IC_RESULT(ic))));
12066 aopOp (handle,ic,FALSE,FALSE);
12068 /* put the size in R4-R2 */
12069 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12070 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
12071 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
12072 emitcode("pop","ar3");
12073 emitcode("pop","ar2");
12075 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
12076 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
12078 freeAsmop (handle, NULL, ic, FALSE);
12080 /* make the call */
12081 emitcode ("lcall","MM_Deref");
12084 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12085 if (rsym->liveFrom != rsym->liveTo) {
12086 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12087 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12088 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12089 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12090 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12094 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12095 unsavermask(rsave);
12098 /*-----------------------------------------------------------------*/
12099 /* genMMUnrestrictedPersist - */
12100 /*-----------------------------------------------------------------*/
12101 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12106 assert (nparms == 1);
12107 /* save registers that need to be saved */
12108 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12109 ds390_rUmaskForOp (IC_RESULT(ic))));
12112 aopOp (handle,ic,FALSE,FALSE);
12114 /* put the size in R3-R2 */
12115 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12116 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
12117 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
12118 emitcode("pop","ar3");
12119 emitcode("pop","ar2");
12121 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
12122 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
12124 freeAsmop (handle, NULL, ic, FALSE);
12126 /* make the call */
12127 emitcode ("lcall","MM_UnrestrictedPersist");
12130 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12131 if (rsym->liveFrom != rsym->liveTo) {
12132 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12133 aopPut(AOP(IC_RESULT(ic)),"a",0);
12134 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12137 unsavermask(rsave);
12140 /*-----------------------------------------------------------------*/
12141 /* genSystemExecJavaProcess - */
12142 /*-----------------------------------------------------------------*/
12143 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12146 operand *handle, *pp;
12148 assert (nparms==2);
12149 /* save registers that need to be saved */
12150 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12151 ds390_rUmaskForOp (IC_RESULT(ic))));
12156 /* put the handle in R3-R2 */
12157 aopOp (handle,ic,FALSE,FALSE);
12158 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12159 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
12160 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
12161 emitcode("pop","ar3");
12162 emitcode("pop","ar2");
12164 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
12165 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
12167 freeAsmop (handle, NULL, ic, FALSE);
12169 /* put pointer in DPTR */
12170 aopOp (pp,ic,FALSE,FALSE);
12171 if (AOP_TYPE(pp) == AOP_IMMD) {
12172 emitcode ("mov", "dptr,%s", aopGet (AOP (pp), 0, TRUE, FALSE, FALSE));
12173 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12174 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,FALSE));
12175 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,FALSE));
12176 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,FALSE));
12178 freeAsmop (handle, NULL, ic, FALSE);
12180 /* make the call */
12181 emitcode ("lcall","System_ExecJavaProcess");
12183 /* put result in place */
12185 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12186 if (rsym->liveFrom != rsym->liveTo) {
12187 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12188 aopPut(AOP(IC_RESULT(ic)),"a",0);
12189 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12193 unsavermask(rsave);
12196 /*-----------------------------------------------------------------*/
12197 /* genSystemRTCRegisters - */
12198 /*-----------------------------------------------------------------*/
12199 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12205 assert (nparms==1);
12206 /* save registers that need to be saved */
12207 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12208 ds390_rUmaskForOp (IC_RESULT(ic))));
12211 /* put pointer in DPTR */
12212 aopOp (pp,ic,FALSE,FALSE);
12213 if (AOP_TYPE (pp) == AOP_IMMD) {
12214 emitcode ("mov","dps,#1");
12215 emitcode ("mov", "dptr,%s", aopGet (AOP (pp), 0, TRUE, FALSE, FALSE));
12216 emitcode ("mov","dps,#0");
12218 emitcode ("mov","dpl1,%s",aopGet(AOP(pp),0,FALSE,FALSE,FALSE));
12219 emitcode ("mov","dph1,%s",aopGet(AOP(pp),1,FALSE,FALSE,FALSE));
12220 emitcode ("mov","dpx1,%s",aopGet(AOP(pp),2,FALSE,FALSE,FALSE));
12222 freeAsmop (pp, NULL, ic, FALSE);
12224 /* make the call */
12225 emitcode ("lcall","System_%sRTCRegisters",name);
12227 unsavermask(rsave);
12230 /*-----------------------------------------------------------------*/
12231 /* genSystemThreadSleep - */
12232 /*-----------------------------------------------------------------*/
12233 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12238 assert (nparms==1);
12239 /* save registers that need to be saved */
12240 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12241 ds390_rUmaskForOp (IC_RESULT(ic))));
12244 aopOp(to,ic,FALSE,FALSE);
12245 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12246 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12247 emitcode ("push","%s",aopGet(AOP(to),0,FALSE,TRUE,FALSE));
12248 emitcode ("push","%s",aopGet(AOP(to),1,FALSE,TRUE,FALSE));
12249 emitcode ("push","%s",aopGet(AOP(to),2,FALSE,TRUE,FALSE));
12250 emitcode ("push","%s",aopGet(AOP(to),3,FALSE,TRUE,FALSE));
12251 emitcode ("pop","ar3");
12252 emitcode ("pop","ar2");
12253 emitcode ("pop","ar1");
12254 emitcode ("pop","ar0");
12256 emitcode ("mov","r0,%s",aopGet(AOP(to),0,FALSE,TRUE,FALSE));
12257 emitcode ("mov","r1,%s",aopGet(AOP(to),1,FALSE,TRUE,FALSE));
12258 emitcode ("mov","r2,%s",aopGet(AOP(to),2,FALSE,TRUE,FALSE));
12259 emitcode ("mov","r3,%s",aopGet(AOP(to),3,FALSE,TRUE,FALSE));
12261 freeAsmop (to, NULL, ic, FALSE);
12263 /* suspend in acc */
12265 aopOp(s,ic,FALSE,FALSE);
12266 emitcode ("mov","a,%s",aopGet(AOP(s),0,FALSE,TRUE,FALSE));
12267 freeAsmop (s, NULL, ic, FALSE);
12269 /* make the call */
12270 emitcode ("lcall","System_%s",name);
12272 unsavermask(rsave);
12275 /*-----------------------------------------------------------------*/
12276 /* genSystemThreadResume - */
12277 /*-----------------------------------------------------------------*/
12278 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12283 assert (nparms==2);
12284 /* save registers that need to be saved */
12285 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12286 ds390_rUmaskForOp (IC_RESULT(ic))));
12292 aopOp(pid,ic,FALSE,FALSE);
12293 emitcode ("mov","r0,%s",aopGet(AOP(pid),0,FALSE,TRUE,FALSE));
12294 freeAsmop (pid, NULL, ic, FALSE);
12297 aopOp(tid,ic,FALSE,FALSE);
12298 emitcode ("mov","a,%s",aopGet(AOP(tid),0,FALSE,TRUE,FALSE));
12299 freeAsmop (tid, NULL, ic, FALSE);
12301 emitcode ("lcall","System_ThreadResume");
12303 /* put result into place */
12305 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12306 if (rsym->liveFrom != rsym->liveTo) {
12307 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12308 aopPut(AOP(IC_RESULT(ic)),"a",0);
12309 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12312 unsavermask(rsave);
12315 /*-----------------------------------------------------------------*/
12316 /* genSystemProcessResume - */
12317 /*-----------------------------------------------------------------*/
12318 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
12323 assert (nparms==1);
12324 /* save registers that need to be saved */
12325 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12326 ds390_rUmaskForOp (IC_RESULT(ic))));
12331 aopOp(pid,ic,FALSE,FALSE);
12332 emitcode ("mov","a,%s",aopGet(AOP(pid),0,FALSE,TRUE,FALSE));
12333 freeAsmop (pid, NULL, ic, FALSE);
12335 emitcode ("lcall","System_ProcessResume");
12337 unsavermask(rsave);
12340 /*-----------------------------------------------------------------*/
12342 /*-----------------------------------------------------------------*/
12343 static void genSystem (iCode *ic,int nparms,char *name)
12345 assert(nparms == 0);
12347 emitcode ("lcall","System_%s",name);
12350 /*-----------------------------------------------------------------*/
12351 /* genSystemPoll - */
12352 /*-----------------------------------------------------------------*/
12353 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
12358 assert (nparms==1);
12359 /* save registers that need to be saved */
12360 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12361 ds390_rUmaskForOp (IC_RESULT(ic))));
12364 aopOp (fp,ic,FALSE,FALSE);
12365 if (AOP_TYPE (fp) == AOP_IMMD) {
12366 emitcode ("mov", "dptr,%s", aopGet (AOP (fp), 0, TRUE, FALSE, FALSE));
12367 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
12368 emitcode ("mov","dpl,%s",aopGet(AOP(fp),0,FALSE,FALSE,FALSE));
12369 emitcode ("mov","dph,%s",aopGet(AOP(fp),1,FALSE,FALSE,FALSE));
12370 emitcode ("mov","dpx,%s",aopGet(AOP(fp),2,FALSE,FALSE,FALSE));
12372 freeAsmop (fp, NULL, ic, FALSE);
12374 emitcode ("lcall","System_%sPoll",name);
12376 /* put result into place */
12378 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12379 if (rsym->liveFrom != rsym->liveTo) {
12380 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12381 aopPut(AOP(IC_RESULT(ic)),"a",0);
12382 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12385 unsavermask(rsave);
12388 /*-----------------------------------------------------------------*/
12389 /* genSystemGetCurrentID - */
12390 /*-----------------------------------------------------------------*/
12391 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
12393 assert (nparms==0);
12395 emitcode ("lcall","System_GetCurrent%sId",name);
12396 /* put result into place */
12398 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12399 if (rsym->liveFrom != rsym->liveTo) {
12400 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12401 aopPut(AOP(IC_RESULT(ic)),"a",0);
12402 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12407 /*-----------------------------------------------------------------*/
12408 /* genBuiltIn - calls the appropriate function to generating code */
12409 /* for a built in function */
12410 /*-----------------------------------------------------------------*/
12411 static void genBuiltIn (iCode *ic)
12413 operand *bi_parms[MAX_BUILTIN_ARGS];
12418 /* get all the arguments for a built in function */
12419 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
12421 /* which function is it */
12422 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
12423 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
12424 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
12425 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
12426 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
12427 } else if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
12428 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
12429 } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
12430 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
12431 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
12432 genMemsetX(bi_iCode,nbi_parms,bi_parms);
12433 } else if (strcmp(bif->name,"__builtin_inp")==0) {
12434 genInp(bi_iCode,nbi_parms,bi_parms);
12435 } else if (strcmp(bif->name,"__builtin_outp")==0) {
12436 genOutp(bi_iCode,nbi_parms,bi_parms);
12437 } else if (strcmp(bif->name,"__builtin_swapw")==0) {
12438 genSwapW(bi_iCode,nbi_parms,bi_parms);
12439 /* JavaNative builtIns */
12440 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
12441 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
12442 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
12443 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
12444 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
12445 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
12446 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
12447 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
12448 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
12449 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12450 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
12451 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12452 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
12453 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
12454 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
12455 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
12456 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
12457 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12458 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
12459 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12460 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
12461 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
12462 } else if (strcmp(bif->name,"MM_Malloc")==0) {
12463 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
12464 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
12465 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
12466 } else if (strcmp(bif->name,"MM_Free")==0) {
12467 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
12468 } else if (strcmp(bif->name,"MM_Deref")==0) {
12469 genMMDeref(bi_iCode,nbi_parms,bi_parms);
12470 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
12471 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
12472 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
12473 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
12474 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
12475 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
12476 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
12477 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
12478 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
12479 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
12480 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
12481 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
12482 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
12483 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
12484 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
12485 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
12486 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12487 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12488 } else if (strcmp(bif->name,"System_SaveThread")==0) {
12489 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12490 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12491 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12492 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
12493 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
12494 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
12495 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
12496 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
12497 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
12498 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
12499 genSystem(bi_iCode,nbi_parms,"ProcessYield");
12500 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
12501 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
12502 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
12503 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
12504 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
12505 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
12506 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
12507 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
12508 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
12509 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
12511 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
12517 /*-----------------------------------------------------------------*/
12518 /* gen390Code - generate code for Dallas 390 based controllers */
12519 /*-----------------------------------------------------------------*/
12521 gen390Code (iCode * lic)
12526 lineHead = lineCurr = NULL;
12527 dptrn[1][0] = "dpl1";
12528 dptrn[1][1] = "dph1";
12529 dptrn[1][2] = "dpx1";
12531 if (options.model == MODEL_FLAT24) {
12532 fReturnSizeDS390 = 5;
12533 fReturn = fReturn24;
12535 fReturnSizeDS390 = 4;
12536 fReturn = fReturn16;
12537 options.stack10bit=0;
12540 /* print the allocation information */
12542 printAllocInfo (currFunc, codeOutFile);
12544 /* if debug information required */
12545 if (options.debug && currFunc)
12547 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
12549 if (IS_STATIC (currFunc->etype))
12550 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
12552 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
12555 /* stack pointer name */
12556 if (options.useXstack)
12562 for (ic = lic; ic; ic = ic->next)
12565 if (ic->lineno && cln != ic->lineno)
12570 emitcode ("", "C$%s$%d$%d$%d ==.",
12571 FileBaseName (ic->filename), ic->lineno,
12572 ic->level, ic->block);
12575 if (!options.noCcodeInAsm) {
12576 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
12577 printCLine(ic->filename, ic->lineno));
12581 if (options.iCodeInAsm) {
12582 emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
12584 /* if the result is marked as
12585 spilt and rematerializable or code for
12586 this has already been generated then
12588 if (resultRemat (ic) || ic->generated)
12591 /* depending on the operation */
12611 /* IPOP happens only when trying to restore a
12612 spilt live range, if there is an ifx statement
12613 following this pop then the if statement might
12614 be using some of the registers being popped which
12615 would destory the contents of the register so
12616 we need to check for this condition and handle it */
12618 ic->next->op == IFX &&
12619 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
12620 genIfx (ic->next, ic);
12638 genEndFunction (ic);
12658 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
12675 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
12679 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
12686 /* note these two are xlated by algebraic equivalence
12687 during parsing SDCC.y */
12688 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12689 "got '>=' or '<=' shouldn't have come here");
12693 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
12705 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
12709 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
12713 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
12737 genRightShift (ic);
12740 case GET_VALUE_AT_ADDRESS:
12741 genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
12745 if (POINTER_SET (ic))
12746 genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
12772 if (ic->builtinSEND) genBuiltIn(ic);
12773 else addSet (&_G.sendSet, ic);
12786 /* now we are ready to call the
12787 peep hole optimizer */
12788 if (!options.nopeep)
12789 peepHole (&lineHead);
12791 /* now do the actual printing */
12792 printLine (lineHead, codeOutFile);