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_strdup(sym->rname);
594 aop->size = FPTRSIZE;
598 /* only remaining is far space */
599 /* in which case DPTR gets the address */
600 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
605 emitcode ("mov", "dptr,#%s", sym->rname);
610 emitcode ("mov", "dptr,#%s", sym->rname);
612 aop->size = getSize (sym->type);
614 /* if it is in code space */
615 if (IN_CODESPACE (space))
621 /*-----------------------------------------------------------------*/
622 /* aopForRemat - rematerialzes an object */
623 /*-----------------------------------------------------------------*/
625 aopForRemat (symbol * sym)
627 iCode *ic = sym->rematiCode;
628 asmop *aop = newAsmop (AOP_IMMD);
635 val += (int) operandLitValue (IC_RIGHT (ic));
636 else if (ic->op == '-')
637 val -= (int) operandLitValue (IC_RIGHT (ic));
638 else if (IS_CAST_ICODE(ic)) {
639 sym_link *from_type = operandType(IC_RIGHT(ic));
640 aop->aopu.aop_immd.from_cast_remat = 1;
641 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
642 ptr_type = DCL_TYPE(from_type);
643 if (ptr_type == IPOINTER) {
650 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
655 SNPRINTF (buffer, sizeof(buffer),
657 OP_SYMBOL (IC_LEFT (ic))->rname,
658 val >= 0 ? '+' : '-',
663 if (IS_ASSIGN_ICODE(ic) && isOperandLiteral(IC_RIGHT(ic)))
665 SNPRINTF(buffer, sizeof(buffer),
666 "0x%x",(int) operandLitValue (IC_RIGHT (ic)));
670 strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
674 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);
675 /* set immd2 field if required */
676 if (aop->aopu.aop_immd.from_cast_remat)
678 tsprintf(buffer, sizeof(buffer), "#!constbyte",ptr_type);
679 aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
685 /*-----------------------------------------------------------------*/
686 /* aopHasRegs - returns true if aop has regs between from-to */
687 /*-----------------------------------------------------------------*/
688 static int aopHasRegs(asmop *aop, int from, int to)
692 if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
694 for (; size < aop->size ; size++) {
696 for (reg = from ; reg <= to ; reg++)
697 if (aop->aopu.aop_reg[size] == ds390_regWithIdx(reg)) return 1;
702 /*-----------------------------------------------------------------*/
703 /* regsInCommon - two operands have some registers in common */
704 /*-----------------------------------------------------------------*/
706 regsInCommon (operand * op1, operand * op2)
711 /* if they have registers in common */
712 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
715 sym1 = OP_SYMBOL (op1);
716 sym2 = OP_SYMBOL (op2);
718 if (sym1->nRegs == 0 || sym2->nRegs == 0)
721 for (i = 0; i < sym1->nRegs; i++)
727 for (j = 0; j < sym2->nRegs; j++)
732 if (sym2->regs[j] == sym1->regs[i])
740 /*-----------------------------------------------------------------*/
741 /* operandsEqu - equivalent */
742 /*-----------------------------------------------------------------*/
744 operandsEqu (operand * op1, operand * op2)
748 /* if they not symbols */
749 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
752 sym1 = OP_SYMBOL (op1);
753 sym2 = OP_SYMBOL (op2);
755 /* if both are itemps & one is spilt
756 and the other is not then false */
757 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
758 sym1->isspilt != sym2->isspilt)
761 /* if they are the same */
765 if (strcmp (sym1->rname, sym2->rname) == 0)
769 /* if left is a tmp & right is not */
770 if (IS_ITEMP (op1) &&
773 (sym1->usl.spillLoc == sym2))
776 if (IS_ITEMP (op2) &&
780 (sym2->usl.spillLoc == sym1))
786 /*-----------------------------------------------------------------*/
787 /* sameRegs - two asmops have the same registers */
788 /*-----------------------------------------------------------------*/
790 sameRegs (asmop * aop1, asmop * aop2)
796 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
803 if (aop1->type != AOP_REG ||
804 aop2->type != AOP_REG)
807 if (aop1->size != aop2->size)
810 for (i = 0; i < aop1->size; i++)
811 if (aop1->aopu.aop_reg[i] !=
812 aop2->aopu.aop_reg[i])
818 /*-----------------------------------------------------------------*/
819 /* aopOp - allocates an asmop for an operand : */
820 /*-----------------------------------------------------------------*/
822 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
831 /* if this a literal */
832 if (IS_OP_LITERAL (op))
834 op->aop = aop = newAsmop (AOP_LIT);
835 aop->aopu.aop_lit = op->operand.valOperand;
836 aop->size = getSize (operandType (op));
840 /* if already has a asmop then continue */
844 /* if the underlying symbol has a aop */
845 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
847 op->aop = OP_SYMBOL (op)->aop;
851 /* if this is a true symbol */
852 if (IS_TRUE_SYMOP (op))
854 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
858 /* this is a temporary : this has
864 e) can be a return use only */
866 sym = OP_SYMBOL (op);
869 /* if the type is a conditional */
870 if (sym->regType == REG_CND)
872 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
877 /* if it is spilt then two situations
879 b) has a spill location */
880 if (sym->isspilt || sym->nRegs == 0)
883 /* rematerialize it NOW */
886 sym->aop = op->aop = aop =
888 aop->size = getSize (sym->type);
895 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
896 aop->size = getSize (sym->type);
897 for (i = 0; i < 2; i++)
898 aop->aopu.aop_str[i] = accUse[i];
908 /* a AOP_STR uses DPTR, but DPTR is already in use;
911 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"AOP_STR with DPTR in use!");
914 aop = op->aop = sym->aop = newAsmop (AOP_STR);
915 aop->size = getSize (sym->type);
916 for (i = 0; i < (int) fReturnSizeDS390; i++)
917 aop->aopu.aop_str[i] = fReturn[i];
921 if (sym->dptr) { /* has been allocated to a DPTRn */
922 aop = op->aop = sym->aop = newAsmop (AOP_DPTRn);
923 aop->size = getSize (sym->type);
924 aop->aopu.dptr = sym->dptr;
927 /* else spill location */
928 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
929 /* force a new aop if sizes differ */
930 sym->usl.spillLoc->aop = NULL;
932 sym->aop = op->aop = aop =
933 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
934 aop->size = getSize (sym->type);
938 /* must be in a register */
939 sym->aop = op->aop = aop = newAsmop (AOP_REG);
940 aop->size = sym->nRegs;
941 for (i = 0; i < sym->nRegs; i++)
942 aop->aopu.aop_reg[i] = sym->regs[i];
945 /*-----------------------------------------------------------------*/
946 /* freeAsmop - free up the asmop given to an operand */
947 /*----------------------------------------------------------------*/
949 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
966 /* depending on the asmop type only three cases need work AOP_RO
967 , AOP_R1 && AOP_STK */
975 emitcode ("pop", "ar0");
979 bitVectUnSetBit (ic->rUsed, R0_IDX);
987 emitcode ("pop", "ar1");
991 bitVectUnSetBit (ic->rUsed, R1_IDX);
997 int stk = aop->aopu.aop_stk + aop->size;
998 bitVectUnSetBit (ic->rUsed, R0_IDX);
999 bitVectUnSetBit (ic->rUsed, R1_IDX);
1001 getFreePtr (ic, &aop, FALSE);
1003 if (options.stack10bit)
1005 /* I'm not sure what to do here yet... */
1008 "*** Warning: probably generating bad code for "
1009 "10 bit stack mode.\n");
1014 emitcode ("mov", "a,_bp");
1015 emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
1016 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1020 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1025 emitcode ("pop", "acc");
1026 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1029 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1032 freeAsmop (op, NULL, ic, TRUE);
1035 emitcode ("pop", "ar0");
1041 emitcode ("pop", "ar1");
1046 if (_G.dptr1InUse) {
1047 emitcode ("pop","dpx1");
1048 emitcode ("pop","dph1");
1049 emitcode ("pop","dpl1");
1054 emitcode ("pop","dpx");
1055 emitcode ("pop","dph");
1056 emitcode ("pop","dpl");
1061 /* all other cases just dealloc */
1067 OP_SYMBOL (op)->aop = NULL;
1068 /* if the symbol has a spill */
1070 SPIL_LOC (op)->aop = NULL;
1075 /*------------------------------------------------------------------*/
1076 /* aopGet - for fetching value of the aop */
1078 /* Set canClobberACC if you are sure it is OK to clobber the value */
1079 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe, */
1080 /* just less efficient. */
1081 /*------------------------------------------------------------------*/
1084 aopGet (asmop * aop,
1090 /* offset is greater than
1092 if (offset > (aop->size - 1) &&
1093 aop->type != AOP_LIT)
1096 /* depending on type */
1102 /* if we need to increment it */
1103 while (offset > aop->coff)
1105 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1109 while (offset < aop->coff)
1111 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1118 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1119 return (dname ? "acc" : "a");
1121 SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1122 return Safe_strdup(buffer);
1125 assert(offset <= 3);
1126 return dptrn[aop->aopu.dptr][offset];
1131 if (aop->type == AOP_DPTR2)
1137 emitcode ("xch", "a, %s", DP2_RESULT_REG);
1143 while (offset > aop->coff)
1145 emitcode ("inc", "dptr");
1149 while (offset < aop->coff)
1151 emitcode ("lcall", "__decdptr");
1158 emitcode ("clr", "a");
1159 emitcode ("movc", "a,@a+dptr");
1163 emitcode ("movx", "a,@dptr");
1166 if (aop->type == AOP_DPTR2)
1172 emitcode ("xch", "a, %s", DP2_RESULT_REG);
1173 return DP2_RESULT_REG;
1176 return (dname ? "acc" : "a");
1179 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1181 SNPRINTF(buffer, sizeof(buffer),
1182 "%s",aop->aopu.aop_immd.aop_immd2);
1186 SNPRINTF(buffer, sizeof(buffer),
1187 "#%s", aop->aopu.aop_immd.aop_immd1);
1193 tsprintf(buffer, sizeof(buffer),
1194 "#!his",aop->aopu.aop_immd.aop_immd1);
1197 tsprintf(buffer, sizeof(buffer),
1198 "#!hihis",aop->aopu.aop_immd.aop_immd1);
1201 tsprintf(buffer, sizeof(buffer),
1202 "#!hihihis",aop->aopu.aop_immd.aop_immd1);
1204 default: /* should not need this (just in case) */
1205 SNPRINTF (buffer, sizeof(buffer),
1207 aop->aopu.aop_immd.aop_immd1,
1213 SNPRINTF (buffer, sizeof(buffer),
1214 "#%s", aop->aopu.aop_immd.aop_immd1);
1216 return Safe_strdup(buffer);
1221 SNPRINTF (buffer, sizeof(buffer),
1228 SNPRINTF(buffer, sizeof(buffer),
1229 "%s", aop->aopu.aop_dir);
1232 return Safe_strdup(buffer);
1236 return aop->aopu.aop_reg[offset]->dname;
1238 return aop->aopu.aop_reg[offset]->name;
1241 emitcode ("clr", "a");
1242 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1243 emitcode ("rlc", "a");
1244 return (dname ? "acc" : "a");
1247 if (!offset && dname)
1249 return aop->aopu.aop_str[offset];
1252 return aopLiteral (aop->aopu.aop_lit, offset);
1256 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1260 return aop->aopu.aop_str[offset];
1264 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1265 "aopget got unsupported aop->type");
1268 /*-----------------------------------------------------------------*/
1269 /* aopPut - puts a string for a aop */
1270 /*-----------------------------------------------------------------*/
1272 aopPut (asmop * aop, char *s, int offset)
1274 if (aop->size && offset > (aop->size - 1))
1276 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1277 "aopPut got offset > aop->size");
1281 /* will assign value to value */
1282 /* depending on where it is ofcourse */
1288 SNPRINTF (buffer, sizeof(buffer),
1290 aop->aopu.aop_dir, offset);
1294 SNPRINTF (buffer, sizeof(buffer),
1295 "%s", aop->aopu.aop_dir);
1299 if (strcmp (buffer, s))
1301 emitcode ("mov", "%s,%s", buffer, s);
1306 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1307 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1310 strcmp (s, "r0") == 0 ||
1311 strcmp (s, "r1") == 0 ||
1312 strcmp (s, "r2") == 0 ||
1313 strcmp (s, "r3") == 0 ||
1314 strcmp (s, "r4") == 0 ||
1315 strcmp (s, "r5") == 0 ||
1316 strcmp (s, "r6") == 0 ||
1317 strcmp (s, "r7") == 0)
1319 emitcode ("mov", "%s,%s",
1320 aop->aopu.aop_reg[offset]->dname, s);
1324 emitcode ("mov", "%s,%s",
1325 aop->aopu.aop_reg[offset]->name, s);
1331 emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1337 if (aop->type == AOP_DPTR2)
1345 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1346 "aopPut writting to code space");
1350 while (offset > aop->coff)
1353 emitcode ("inc", "dptr");
1356 while (offset < aop->coff)
1359 emitcode ("lcall", "__decdptr");
1364 /* if not in accumulater */
1367 emitcode ("movx", "@dptr,a");
1369 if (aop->type == AOP_DPTR2)
1377 while (offset > aop->coff)
1380 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1382 while (offset < aop->coff)
1385 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1392 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1398 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1400 else if (strcmp (s, "r0") == 0 ||
1401 strcmp (s, "r1") == 0 ||
1402 strcmp (s, "r2") == 0 ||
1403 strcmp (s, "r3") == 0 ||
1404 strcmp (s, "r4") == 0 ||
1405 strcmp (s, "r5") == 0 ||
1406 strcmp (s, "r6") == 0 ||
1407 strcmp (s, "r7") == 0)
1410 SNPRINTF(buff, sizeof(buff),
1412 emitcode ("mov", "@%s,%s",
1413 aop->aopu.aop_ptr->name, buff);
1417 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1422 if (strcmp (s, "a") == 0)
1423 emitcode ("push", "acc");
1427 emitcode ("push", "acc");
1429 emitcode ("push", s);
1435 /* if bit variable */
1436 if (!aop->aopu.aop_dir)
1438 emitcode ("clr", "a");
1439 emitcode ("rlc", "a");
1444 emitcode ("clr", "%s", aop->aopu.aop_dir);
1446 emitcode ("setb", "%s", aop->aopu.aop_dir);
1447 else if (!strcmp (s, "c"))
1448 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1451 if (strcmp (s, "a"))
1456 /* set C, if a >= 1 */
1457 emitcode ("add", "a,#!constbyte",0xff);
1458 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1466 if (strcmp (aop->aopu.aop_str[offset], s))
1467 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1472 if (!offset && (strcmp (s, "acc") == 0))
1475 if (strcmp (aop->aopu.aop_str[offset], s))
1476 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1480 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1481 "aopPut got unsupported aop->type");
1488 /*--------------------------------------------------------------------*/
1489 /* reAdjustPreg - points a register back to where it should (coff==0) */
1490 /*--------------------------------------------------------------------*/
1492 reAdjustPreg (asmop * aop)
1494 if ((aop->coff==0) || (aop->size <= 1)) {
1503 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1507 if (aop->type == AOP_DPTR2)
1514 emitcode ("lcall", "__decdptr");
1517 if (aop->type == AOP_DPTR2)
1527 #define AOP(op) op->aop
1528 #define AOP_TYPE(op) AOP(op)->type
1529 #define AOP_SIZE(op) AOP(op)->size
1530 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1531 AOP_TYPE(x) == AOP_R0))
1533 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1534 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1537 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1538 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1539 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1540 #define AOP_INDPTRn(x) (AOP_TYPE(x) == AOP_DPTRn)
1541 #define AOP_USESDPTR(x) ((AOP_TYPE(x) == AOP_DPTR) || (AOP_TYPE(x) == AOP_STR))
1542 #define AOP_USESDPTR2(x) ((AOP_TYPE(x) == AOP_DPTR2) || (AOP_TYPE(x) == AOP_DPTRn))
1544 // The following two macros can be used even if the aop has not yet been aopOp'd.
1545 #define AOP_IS_STR(x) (IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
1546 #define AOP_IS_DPTRn(x) (IS_SYMOP(x) && OP_SYMBOL(x)->dptr)
1548 /* Workaround for DS80C390 bug: div ab may return bogus results
1549 * if A is accessed in instruction immediately before the div.
1551 * Will be fixed in B4 rev of processor, Dallas claims.
1554 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1555 if (!AOP_NEEDSACC(RIGHT)) \
1557 /* We can load A first, then B, since \
1558 * B (the RIGHT operand) won't clobber A, \
1559 * thus avoiding touching A right before the div. \
1561 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1562 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1564 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1568 /* Just stuff in a nop after loading A. */ \
1569 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1570 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1572 emitcode("nop", "; workaround for DS80C390 div bug."); \
1575 /*-----------------------------------------------------------------*/
1576 /* genNotFloat - generates not for float operations */
1577 /*-----------------------------------------------------------------*/
1579 genNotFloat (operand * op, operand * res)
1585 D (emitcode (";", "genNotFloat ");
1588 /* we will put 127 in the first byte of
1590 aopPut (AOP (res), "#127", 0);
1591 size = AOP_SIZE (op) - 1;
1594 _startLazyDPSEvaluation ();
1595 l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE);
1600 emitcode ("orl", "a,%s",
1602 offset++, FALSE, FALSE, FALSE));
1604 _endLazyDPSEvaluation ();
1606 tlbl = newiTempLabel (NULL);
1607 aopPut (res->aop, one, 1);
1608 emitcode ("jz", "!tlabel", (tlbl->key + 100));
1609 aopPut (res->aop, zero, 1);
1610 emitcode ("", "!tlabeldef", (tlbl->key + 100));
1612 size = res->aop->size - 2;
1614 /* put zeros in the rest */
1616 aopPut (res->aop, zero, offset++);
1619 /*-----------------------------------------------------------------*/
1620 /* opIsGptr: returns non-zero if the passed operand is */
1621 /* a generic pointer type. */
1622 /*-----------------------------------------------------------------*/
1624 opIsGptr (operand * op)
1626 sym_link *type = operandType (op);
1628 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1635 /*-----------------------------------------------------------------*/
1636 /* getDataSize - get the operand data size */
1637 /*-----------------------------------------------------------------*/
1639 getDataSize (operand * op)
1642 size = AOP_SIZE (op);
1643 if (size == GPTRSIZE)
1645 sym_link *type = operandType (op);
1646 if (IS_GENPTR (type))
1648 /* generic pointer; arithmetic operations
1649 * should ignore the high byte (pointer type).
1657 /*-----------------------------------------------------------------*/
1658 /* outAcc - output Acc */
1659 /*-----------------------------------------------------------------*/
1661 outAcc (operand * result)
1664 size = getDataSize (result);
1667 aopPut (AOP (result), "a", 0);
1670 /* unsigned or positive */
1673 aopPut (AOP (result), zero, offset++);
1678 /*-----------------------------------------------------------------*/
1679 /* outBitC - output a bit C */
1680 /*-----------------------------------------------------------------*/
1682 outBitC (operand * result)
1684 /* if the result is bit */
1685 if (AOP_TYPE (result) == AOP_CRY)
1687 aopPut (AOP (result), "c", 0);
1691 emitcode ("clr", "a");
1692 emitcode ("rlc", "a");
1697 /*-----------------------------------------------------------------*/
1698 /* toBoolean - emit code for orl a,operator(sizeop) */
1699 /*-----------------------------------------------------------------*/
1701 toBoolean (operand * oper)
1703 int size = AOP_SIZE (oper) - 1;
1707 /* The generic part of a generic pointer should
1708 * not participate in it's truth value.
1710 * i.e. 0x10000000 is zero.
1712 if (opIsGptr (oper))
1714 D (emitcode (";", "toBoolean: generic ptr special case."););
1718 _startLazyDPSEvaluation ();
1719 if (AOP_NEEDSACC (oper) && size)
1722 emitcode ("push", "b");
1723 emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1727 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1733 emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1737 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1740 _endLazyDPSEvaluation ();
1744 emitcode ("mov", "a,b");
1745 emitcode ("pop", "b");
1750 /*-----------------------------------------------------------------*/
1751 /* genNot - generate code for ! operation */
1752 /*-----------------------------------------------------------------*/
1757 sym_link *optype = operandType (IC_LEFT (ic));
1759 D (emitcode (";", "genNot ");
1762 /* assign asmOps to operand & result */
1763 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1764 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1766 /* if in bit space then a special case */
1767 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1769 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1770 emitcode ("cpl", "c");
1771 outBitC (IC_RESULT (ic));
1775 /* if type float then do float */
1776 if (IS_FLOAT (optype))
1778 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1782 toBoolean (IC_LEFT (ic));
1784 tlbl = newiTempLabel (NULL);
1785 emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1786 emitcode ("", "!tlabeldef", tlbl->key + 100);
1787 outBitC (IC_RESULT (ic));
1790 /* release the aops */
1791 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1792 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1796 /*-----------------------------------------------------------------*/
1797 /* genCpl - generate code for complement */
1798 /*-----------------------------------------------------------------*/
1806 D (emitcode (";", "genCpl ");
1810 /* assign asmOps to operand & result */
1811 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1812 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1814 /* special case if in bit space */
1815 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1816 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1817 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1818 emitcode ("cpl", "c");
1819 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1822 tlbl=newiTempLabel(NULL);
1823 emitcode ("cjne", "%s,#0x01,%05d$",
1824 aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE,TRUE), tlbl->key+100);
1825 emitcode ("", "%05d$:", tlbl->key+100);
1826 outBitC (IC_RESULT(ic));
1830 size = AOP_SIZE (IC_RESULT (ic));
1831 _startLazyDPSEvaluation ();
1834 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1836 emitcode ("cpl", "a");
1837 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1839 _endLazyDPSEvaluation ();
1843 /* release the aops */
1844 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1845 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1848 /*-----------------------------------------------------------------*/
1849 /* genUminusFloat - unary minus for floating points */
1850 /*-----------------------------------------------------------------*/
1852 genUminusFloat (operand * op, operand * result)
1854 int size, offset = 0;
1856 D(emitcode (";", "genUminusFloat"););
1858 /* for this we just copy and then flip the bit */
1860 _startLazyDPSEvaluation ();
1861 size = AOP_SIZE (op) - 1;
1865 aopPut (AOP (result),
1866 aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1871 MOVA(aopGet (AOP (op), offset, FALSE, FALSE, TRUE));
1873 emitcode ("cpl", "acc.7");
1874 aopPut (AOP (result), "a", offset);
1875 _endLazyDPSEvaluation ();
1878 /*-----------------------------------------------------------------*/
1879 /* genUminus - unary minus code generation */
1880 /*-----------------------------------------------------------------*/
1882 genUminus (iCode * ic)
1885 sym_link *optype, *rtype;
1887 D (emitcode (";", "genUminus ");
1892 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1893 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1895 /* if both in bit space then special
1897 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1898 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1901 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1902 emitcode ("cpl", "c");
1903 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1907 optype = operandType (IC_LEFT (ic));
1908 rtype = operandType (IC_RESULT (ic));
1910 /* if float then do float stuff */
1911 if (IS_FLOAT (optype))
1913 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1917 /* otherwise subtract from zero */
1918 size = AOP_SIZE (IC_LEFT (ic));
1920 _startLazyDPSEvaluation ();
1923 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1924 if (!strcmp (l, "a"))
1928 emitcode ("cpl", "a");
1929 emitcode ("addc", "a,#0");
1935 emitcode ("clr", "a");
1936 emitcode ("subb", "a,%s", l);
1938 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1940 _endLazyDPSEvaluation ();
1942 /* if any remaining bytes in the result */
1943 /* we just need to propagate the sign */
1944 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1946 emitcode ("rlc", "a");
1947 emitcode ("subb", "a,acc");
1949 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1953 /* release the aops */
1954 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1955 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1958 /*-----------------------------------------------------------------*/
1959 /* savermask - saves registers in the mask */
1960 /*-----------------------------------------------------------------*/
1961 static void savermask(bitVect *rs_mask)
1964 if (options.useXstack) {
1965 if (bitVectBitValue (rs_mask, R0_IDX))
1966 emitcode ("mov", "b,r0");
1967 emitcode ("mov", "r0,%s", spname);
1968 for (i = 0; i < ds390_nRegs; i++) {
1969 if (bitVectBitValue (rs_mask, i)) {
1971 emitcode ("mov", "a,b");
1973 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1974 emitcode ("movx", "@r0,a");
1975 emitcode ("inc", "r0");
1978 emitcode ("mov", "%s,r0", spname);
1979 if (bitVectBitValue (rs_mask, R0_IDX))
1980 emitcode ("mov", "r0,b");
1982 for (i = 0; i < ds390_nRegs; i++) {
1983 if (bitVectBitValue (rs_mask, i))
1984 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
1989 /*-----------------------------------------------------------------*/
1990 /* saveRegisters - will look for a call and save the registers */
1991 /*-----------------------------------------------------------------*/
1993 saveRegisters (iCode * lic)
1999 for (ic = lic; ic; ic = ic->next)
2000 if (ic->op == CALL || ic->op == PCALL)
2005 fprintf (stderr, "found parameter push with no function call\n");
2009 /* if the registers have been saved already then
2011 if (ic->regsSaved || IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic)))) return ;
2013 /* special case if DPTR alive across a function call then must save it
2014 even though callee saves */
2015 if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2017 rsave = newBitVect(ic->rMask->size);
2018 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2019 if (bitVectBitValue(ic->rMask,i))
2020 rsave = bitVectSetBit(rsave,i);
2022 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2024 /* safe the registers in use at this time but skip the
2025 ones for the result */
2026 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2027 ds390_rUmaskForOp (IC_RESULT(ic)));
2033 /*-----------------------------------------------------------------*/
2034 /* usavermask - restore registers with mask */
2035 /*-----------------------------------------------------------------*/
2036 static void unsavermask(bitVect *rs_mask)
2039 if (options.useXstack) {
2040 emitcode ("mov", "r0,%s", spname);
2041 for (i = ds390_nRegs; i >= 0; i--) {
2042 if (bitVectBitValue (rs_mask, i)) {
2043 emitcode ("dec", "r0");
2044 emitcode ("movx", "a,@r0");
2046 emitcode ("mov", "b,a");
2048 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
2051 emitcode ("mov", "%s,r0", spname);
2052 if (bitVectBitValue (rs_mask, R0_IDX))
2053 emitcode ("mov", "r0,b");
2055 for (i = ds390_nRegs; i >= 0; i--) {
2056 if (bitVectBitValue (rs_mask, i))
2057 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2062 /*-----------------------------------------------------------------*/
2063 /* unsaveRegisters - pop the pushed registers */
2064 /*-----------------------------------------------------------------*/
2066 unsaveRegisters (iCode * ic)
2070 if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2072 rsave = newBitVect(ic->rMask->size);
2073 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2074 if (bitVectBitValue(ic->rMask,i))
2075 rsave = bitVectSetBit(rsave,i);
2077 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2079 /* restore the registers in use at this time but skip the
2080 ones for the result */
2081 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2082 ds390_rUmaskForOp (IC_RESULT(ic)));
2088 /*-----------------------------------------------------------------*/
2090 /*-----------------------------------------------------------------*/
2092 pushSide (operand * oper, int size)
2095 _startLazyDPSEvaluation ();
2098 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
2099 if (AOP_TYPE (oper) != AOP_REG &&
2100 AOP_TYPE (oper) != AOP_DIR &&
2103 emitcode ("mov", "a,%s", l);
2104 emitcode ("push", "acc");
2107 emitcode ("push", "%s", l);
2109 _endLazyDPSEvaluation ();
2112 /*-----------------------------------------------------------------*/
2113 /* assignResultValue - */
2114 /*-----------------------------------------------------------------*/
2116 assignResultValue (operand * oper)
2119 int size = AOP_SIZE (oper);
2121 _startLazyDPSEvaluation ();
2124 aopPut (AOP (oper), fReturn[offset], offset);
2127 _endLazyDPSEvaluation ();
2131 /*-----------------------------------------------------------------*/
2132 /* genXpush - pushes onto the external stack */
2133 /*-----------------------------------------------------------------*/
2135 genXpush (iCode * ic)
2137 asmop *aop = newAsmop (0);
2139 int size, offset = 0;
2141 D (emitcode (";", "genXpush ");
2144 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2145 r = getFreePtr (ic, &aop, FALSE);
2148 emitcode ("mov", "%s,_spx", r->name);
2150 size = AOP_SIZE (IC_LEFT (ic));
2151 _startLazyDPSEvaluation ();
2155 char *l = aopGet (AOP (IC_LEFT (ic)),
2156 offset++, FALSE, FALSE, TRUE);
2158 emitcode ("movx", "@%s,a", r->name);
2159 emitcode ("inc", "%s", r->name);
2162 _endLazyDPSEvaluation ();
2165 emitcode ("mov", "_spx,%s", r->name);
2167 freeAsmop (NULL, aop, ic, TRUE);
2168 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2171 /*-----------------------------------------------------------------*/
2172 /* genIpush - genrate code for pushing this gets a little complex */
2173 /*-----------------------------------------------------------------*/
2175 genIpush (iCode * ic)
2177 int size, offset = 0;
2180 D (emitcode (";", "genIpush ");
2183 /* if this is not a parm push : ie. it is spill push
2184 and spill push is always done on the local stack */
2188 /* and the item is spilt then do nothing */
2189 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2192 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2193 size = AOP_SIZE (IC_LEFT (ic));
2194 /* push it on the stack */
2195 _startLazyDPSEvaluation ();
2198 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
2204 emitcode ("push", "%s", l);
2206 _endLazyDPSEvaluation ();
2210 /* this is a paramter push: in this case we call
2211 the routine to find the call and save those
2212 registers that need to be saved */
2215 /* if use external stack then call the external
2216 stack pushing routine */
2217 if (options.useXstack)
2223 /* then do the push */
2224 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2226 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2227 size = AOP_SIZE (IC_LEFT (ic));
2229 _startLazyDPSEvaluation ();
2232 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
2233 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2234 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2237 emitcode ("mov", "a,%s", l);
2238 emitcode ("push", "acc");
2241 emitcode ("push", "%s", l);
2243 _endLazyDPSEvaluation ();
2245 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2248 /*-----------------------------------------------------------------*/
2249 /* genIpop - recover the registers: can happen only for spilling */
2250 /*-----------------------------------------------------------------*/
2252 genIpop (iCode * ic)
2256 D (emitcode (";", "genIpop ");
2260 /* if the temp was not pushed then */
2261 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2264 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2265 size = AOP_SIZE (IC_LEFT (ic));
2266 offset = (size - 1);
2267 _startLazyDPSEvaluation ();
2270 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2271 FALSE, TRUE, TRUE));
2273 _endLazyDPSEvaluation ();
2275 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2278 /*-----------------------------------------------------------------*/
2279 /* unsaveRBank - restores the resgister bank from stack */
2280 /*-----------------------------------------------------------------*/
2282 unsaveRBank (int bank, iCode * ic, bool popPsw)
2288 if (options.useXstack)
2292 /* Assume r0 is available for use. */
2293 r = ds390_regWithIdx (R0_IDX);;
2298 r = getFreePtr (ic, &aop, FALSE);
2300 emitcode ("mov", "%s,_spx", r->name);
2305 if (options.useXstack)
2307 emitcode ("movx", "a,@%s", r->name);
2308 emitcode ("mov", "psw,a");
2309 emitcode ("dec", "%s", r->name);
2313 emitcode ("pop", "psw");
2317 for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2319 if (options.useXstack)
2321 emitcode ("movx", "a,@%s", r->name);
2322 emitcode ("mov", "(%s+%d),a",
2323 regs390[i].base, 8 * bank + regs390[i].offset);
2324 emitcode ("dec", "%s", r->name);
2328 emitcode ("pop", "(%s+%d)",
2329 regs390[i].base, 8 * bank + regs390[i].offset);
2332 if (options.useXstack)
2334 emitcode ("mov", "_spx,%s", r->name);
2339 freeAsmop (NULL, aop, ic, TRUE);
2343 /*-----------------------------------------------------------------*/
2344 /* saveRBank - saves an entire register bank on the stack */
2345 /*-----------------------------------------------------------------*/
2347 saveRBank (int bank, iCode * ic, bool pushPsw)
2353 if (options.useXstack)
2357 /* Assume r0 is available for use. */
2358 r = ds390_regWithIdx (R0_IDX);;
2363 r = getFreePtr (ic, &aop, FALSE);
2365 emitcode ("mov", "%s,_spx", r->name);
2368 for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2370 if (options.useXstack)
2372 emitcode ("inc", "%s", r->name);
2373 emitcode ("mov", "a,(%s+%d)",
2374 regs390[i].base, 8 * bank + regs390[i].offset);
2375 emitcode ("movx", "@%s,a", r->name);
2378 emitcode ("push", "(%s+%d)",
2379 regs390[i].base, 8 * bank + regs390[i].offset);
2384 if (options.useXstack)
2386 emitcode ("mov", "a,psw");
2387 emitcode ("movx", "@%s,a", r->name);
2388 emitcode ("inc", "%s", r->name);
2389 emitcode ("mov", "_spx,%s", r->name);
2393 emitcode ("push", "psw");
2396 emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2401 freeAsmop (NULL, aop, ic, TRUE);
2410 /*-----------------------------------------------------------------*/
2411 /* genSend - gen code for SEND */
2412 /*-----------------------------------------------------------------*/
2413 static void genSend(set *sendSet)
2417 static int rb1_count = 0;
2419 for (sic = setFirstItem (sendSet); sic;
2420 sic = setNextItem (sendSet)) {
2421 int size, offset = 0;
2423 size=getSize(operandType(IC_LEFT(sic)));
2424 D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2425 if (sendCount == 0) { /* first parameter */
2426 // we know that dpl(hxb) is the result, so
2428 _startLazyDPSEvaluation ();
2430 aopOp (IC_LEFT (sic), sic, FALSE,
2431 (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2433 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2436 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2437 FALSE, FALSE, TRUE);
2438 if (strcmp (l, fReturn[offset])) {
2439 emitcode ("mov", "%s,%s",
2445 _endLazyDPSEvaluation ();
2446 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2448 } else { /* if more parameter in registers */
2449 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2451 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
2452 FALSE, FALSE, TRUE));
2454 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2460 /*-----------------------------------------------------------------*/
2461 /* genCall - generates a call statement */
2462 /*-----------------------------------------------------------------*/
2464 genCall (iCode * ic)
2467 bool restoreBank = FALSE;
2468 bool swapBanks = FALSE;
2470 D (emitcode (";", "genCall "););
2472 /* if we are calling a not _naked function that is not using
2473 the same register bank then we need to save the
2474 destination registers on the stack */
2475 dtype = operandType (IC_LEFT (ic));
2476 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2477 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2478 IFFUNC_ISISR (currFunc->type))
2482 /* This is unexpected; the bank should have been saved in
2485 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2491 /* if caller saves & we have not saved then */
2495 /* if send set is not empty the assign */
2496 /* We've saved all the registers we care about;
2497 * therefore, we may clobber any register not used
2498 * in the calling convention (i.e. anything not in
2503 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2504 genSend(reverseSet(_G.sendSet));
2506 genSend(_G.sendSet);
2513 emitcode ("mov", "psw,#!constbyte",
2514 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2518 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2519 OP_SYMBOL (IC_LEFT (ic))->rname :
2520 OP_SYMBOL (IC_LEFT (ic))->name));
2524 emitcode ("mov", "psw,#!constbyte",
2525 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2528 /* if we need assign a result value */
2529 if ((IS_ITEMP (IC_RESULT (ic)) &&
2530 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2531 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2532 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2533 IS_TRUE_SYMOP (IC_RESULT (ic)))
2535 if (isOperandInFarSpace (IC_RESULT (ic))
2536 && getSize (operandType (IC_RESULT (ic))) <= 2)
2538 int size = getSize (operandType (IC_RESULT (ic)));
2540 /* Special case for 1 or 2 byte return in far space. */
2544 emitcode ("mov", "b,%s", fReturn[1]);
2547 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2548 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2552 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2554 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2559 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2562 assignResultValue (IC_RESULT (ic));
2564 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2568 /* adjust the stack for parameters if
2570 if (ic->parmBytes) {
2572 if (options.stack10bit) {
2573 if (ic->parmBytes <= 10) {
2574 emitcode(";","stack adjustment for parms");
2575 for (i=0; i < ic->parmBytes ; i++) {
2576 emitcode("pop","acc");
2580 emitcode ("clr","c");
2581 emitcode ("mov","a,sp");
2582 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2583 emitcode ("mov","sp,a");
2584 emitcode ("mov","a,esp");
2585 emitcode ("anl","a,#3");
2586 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2587 emitcode ("mov","esp,a");
2591 if (ic->parmBytes > 3) {
2592 emitcode ("mov", "a,%s", spname);
2593 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2594 emitcode ("mov", "%s,a", spname);
2596 for (i = 0; i < ic->parmBytes; i++)
2597 emitcode ("dec", "%s", spname);
2601 /* if we hade saved some registers then unsave them */
2603 unsaveRegisters (ic);
2605 /* if register bank was saved then pop them */
2607 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2610 /*-----------------------------------------------------------------*/
2611 /* genPcall - generates a call by pointer statement */
2612 /*-----------------------------------------------------------------*/
2614 genPcall (iCode * ic)
2617 symbol *rlbl = newiTempLabel (NULL);
2618 bool restoreBank=FALSE;
2620 D (emitcode (";", "genPcall ");
2624 /* if caller saves & we have not saved then */
2628 /* if we are calling a function that is not using
2629 the same register bank then we need to save the
2630 destination registers on the stack */
2631 dtype = operandType (IC_LEFT (ic));
2632 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2633 IFFUNC_ISISR (currFunc->type) &&
2634 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2635 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2639 /* push the return address on to the stack */
2640 emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2641 emitcode ("push", "acc");
2642 emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2643 emitcode ("push", "acc");
2645 if (options.model == MODEL_FLAT24)
2647 emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2648 emitcode ("push", "acc");
2651 /* now push the calling address */
2652 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2654 pushSide (IC_LEFT (ic), FPTRSIZE);
2656 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2658 /* if send set is not empty the assign */
2661 genSend(reverseSet(_G.sendSet));
2665 emitcode ("ret", "");
2666 emitcode ("", "!tlabeldef", (rlbl->key + 100));
2669 /* if we need assign a result value */
2670 if ((IS_ITEMP (IC_RESULT (ic)) &&
2671 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2672 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2673 IS_TRUE_SYMOP (IC_RESULT (ic)))
2677 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2680 assignResultValue (IC_RESULT (ic));
2682 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2685 /* adjust the stack for parameters if
2690 if (options.stack10bit) {
2691 if (ic->parmBytes <= 10) {
2692 emitcode(";","stack adjustment for parms");
2693 for (i=0; i < ic->parmBytes ; i++) {
2694 emitcode("pop","acc");
2698 emitcode ("clr","c");
2699 emitcode ("mov","a,sp");
2700 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2701 emitcode ("mov","sp,a");
2702 emitcode ("mov","a,esp");
2703 emitcode ("anl","a,#3");
2704 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2705 emitcode ("mov","esp,a");
2709 if (ic->parmBytes > 3) {
2710 emitcode ("mov", "a,%s", spname);
2711 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2712 emitcode ("mov", "%s,a", spname);
2715 for (i = 0; i < ic->parmBytes; i++)
2716 emitcode ("dec", "%s", spname);
2720 /* if register bank was saved then unsave them */
2722 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2724 /* if we hade saved some registers then
2727 unsaveRegisters (ic);
2731 /*-----------------------------------------------------------------*/
2732 /* resultRemat - result is rematerializable */
2733 /*-----------------------------------------------------------------*/
2735 resultRemat (iCode * ic)
2737 if (SKIP_IC (ic) || ic->op == IFX)
2740 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2742 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2743 if (sym->remat && !POINTER_SET (ic))
2750 #if defined(__BORLANDC__) || defined(_MSC_VER)
2751 #define STRCASECMP stricmp
2753 #define STRCASECMP strcasecmp
2756 /*-----------------------------------------------------------------*/
2757 /* inExcludeList - return 1 if the string is in exclude Reg list */
2758 /*-----------------------------------------------------------------*/
2760 inExcludeList (char *s)
2764 if (options.excludeRegs[i] &&
2765 STRCASECMP (options.excludeRegs[i], "none") == 0)
2768 for (i = 0; options.excludeRegs[i]; i++)
2770 if (options.excludeRegs[i] &&
2771 STRCASECMP (s, options.excludeRegs[i]) == 0)
2777 /*-----------------------------------------------------------------*/
2778 /* genFunction - generated code for function entry */
2779 /*-----------------------------------------------------------------*/
2781 genFunction (iCode * ic)
2785 bool switchedPSW = FALSE;
2787 D (emitcode (";", "genFunction "););
2790 /* create the function header */
2791 emitcode (";", "-----------------------------------------");
2792 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2793 emitcode (";", "-----------------------------------------");
2795 emitcode ("", "%s:", sym->rname);
2796 ftype = operandType (IC_LEFT (ic));
2798 if (IFFUNC_ISNAKED(ftype))
2800 emitcode(";", "naked function: no prologue.");
2804 if (options.stack_probe)
2805 emitcode ("lcall","__stack_probe");
2806 /* if critical function then turn interrupts off */
2807 if (IFFUNC_ISCRITICAL (ftype))
2808 emitcode ("clr", "ea");
2810 /* here we need to generate the equates for the
2811 register bank if required */
2812 if (FUNC_REGBANK (ftype) != rbank)
2816 rbank = FUNC_REGBANK (ftype);
2817 for (i = 0; i < ds390_nRegs; i++)
2819 if (regs390[i].print) {
2820 if (strcmp (regs390[i].base, "0") == 0)
2821 emitcode ("", "%s !equ !constbyte",
2823 8 * rbank + regs390[i].offset);
2825 emitcode ("", "%s !equ %s + !constbyte",
2828 8 * rbank + regs390[i].offset);
2833 /* if this is an interrupt service routine then
2834 save acc, b, dpl, dph */
2835 if (IFFUNC_ISISR (sym->type))
2837 if (!inExcludeList ("acc"))
2838 emitcode ("push", "acc");
2839 if (!inExcludeList ("b"))
2840 emitcode ("push", "b");
2841 if (!inExcludeList ("dpl"))
2842 emitcode ("push", "dpl");
2843 if (!inExcludeList ("dph"))
2844 emitcode ("push", "dph");
2845 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2847 emitcode ("push", "dpx");
2848 /* Make sure we're using standard DPTR */
2849 emitcode ("push", "dps");
2850 emitcode ("mov", "dps,#0");
2851 if (options.stack10bit)
2853 /* This ISR could conceivably use DPTR2. Better save it. */
2854 emitcode ("push", "dpl1");
2855 emitcode ("push", "dph1");
2856 emitcode ("push", "dpx1");
2857 emitcode ("push", DP2_RESULT_REG);
2860 /* if this isr has no bank i.e. is going to
2861 run with bank 0 , then we need to save more
2863 if (!FUNC_REGBANK (sym->type))
2867 /* if this function does not call any other
2868 function then we can be economical and
2869 save only those registers that are used */
2870 if (!IFFUNC_HASFCALL(sym->type))
2873 /* if any registers used */
2876 /* save the registers used */
2877 for (i = 0; i < sym->regsUsed->size; i++)
2879 if (bitVectBitValue (sym->regsUsed, i) ||
2880 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2881 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2888 /* this function has a function call cannot
2889 determines register usage so we will have to push the
2891 saveRBank (0, ic, FALSE);
2892 if (options.parms_in_bank1) {
2893 for (i=0; i < 8 ; i++ ) {
2894 emitcode ("push","%s",rb1regs[i]);
2901 /* This ISR uses a non-zero bank.
2903 * We assume that the bank is available for our
2906 * However, if this ISR calls a function which uses some
2907 * other bank, we must save that bank entirely.
2909 unsigned long banksToSave = 0;
2911 if (IFFUNC_HASFCALL(sym->type))
2914 #define MAX_REGISTER_BANKS 4
2919 for (i = ic; i; i = i->next)
2921 if (i->op == ENDFUNCTION)
2923 /* we got to the end OK. */
2931 dtype = operandType (IC_LEFT(i));
2933 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2935 /* Mark this bank for saving. */
2936 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2938 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2942 banksToSave |= (1 << FUNC_REGBANK(dtype));
2945 /* And note that we don't need to do it in
2953 /* This is a mess; we have no idea what
2954 * register bank the called function might
2957 * The only thing I can think of to do is
2958 * throw a warning and hope.
2960 werror(W_FUNCPTR_IN_USING_ISR);
2964 if (banksToSave && options.useXstack)
2966 /* Since we aren't passing it an ic,
2967 * saveRBank will assume r0 is available to abuse.
2969 * So switch to our (trashable) bank now, so
2970 * the caller's R0 isn't trashed.
2972 emitcode ("push", "psw");
2973 emitcode ("mov", "psw,#!constbyte",
2974 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2978 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2980 if (banksToSave & (1 << ix))
2982 saveRBank(ix, NULL, FALSE);
2986 // jwk: this needs a closer look
2987 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2992 /* if callee-save to be used for this function
2993 then save the registers being used in this function */
2994 if (IFFUNC_CALLEESAVES(sym->type))
2998 /* if any registers used */
3001 /* save the registers used */
3002 for (i = 0; i < sym->regsUsed->size; i++)
3004 if (bitVectBitValue (sym->regsUsed, i) ||
3005 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3007 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3015 /* set the register bank to the desired value */
3016 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3019 emitcode ("push", "psw");
3020 emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3023 if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3024 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3025 if (options.stack10bit) {
3026 emitcode ("push","_bpx");
3027 emitcode ("push","_bpx+1");
3028 emitcode ("mov","_bpx,%s",spname);
3029 emitcode ("mov","_bpx+1,esp");
3030 emitcode ("anl","_bpx+1,#3");
3032 if (options.useXstack) {
3033 emitcode ("mov", "r0,%s", spname);
3034 emitcode ("mov", "a,_bp");
3035 emitcode ("movx", "@r0,a");
3036 emitcode ("inc", "%s", spname);
3038 /* set up the stack */
3039 emitcode ("push", "_bp"); /* save the callers stack */
3041 emitcode ("mov", "_bp,%s", spname);
3045 /* adjust the stack for the function */
3048 if (options.stack10bit) {
3049 if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
3050 assert (sym->recvSize <= 4);
3051 if (sym->stack <= 8) {
3052 while (i--) emitcode ("push","acc");
3055 emitcode ("mov","a,sp");
3056 emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3057 emitcode ("mov","sp,a");
3058 emitcode ("mov","a,esp");
3059 emitcode ("anl","a,#3");
3060 emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3061 emitcode ("mov","esp,a");
3066 werror (W_STACK_OVERFLOW, sym->name);
3068 if (i > 3 && sym->recvSize < 4) {
3070 emitcode ("mov", "a,sp");
3071 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3072 emitcode ("mov", "sp,a");
3076 emitcode ("inc", "sp");
3083 emitcode ("mov", "a,_spx");
3084 emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3085 emitcode ("mov", "_spx,a");
3090 /*-----------------------------------------------------------------*/
3091 /* genEndFunction - generates epilogue for functions */
3092 /*-----------------------------------------------------------------*/
3094 genEndFunction (iCode * ic)
3096 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3098 D (emitcode (";", "genEndFunction "););
3100 if (IFFUNC_ISNAKED(sym->type))
3102 emitcode(";", "naked function: no epilogue.");
3106 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3107 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3109 if (options.stack10bit) {
3111 emitcode ("mov", "sp,_bpx", spname);
3112 emitcode ("mov", "esp,_bpx+1", spname);
3115 emitcode ("mov", "%s,_bp", spname);
3119 /* if use external stack but some variables were
3120 added to the local stack then decrement the
3122 if (options.useXstack && sym->stack) {
3123 emitcode ("mov", "a,sp");
3124 emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3125 emitcode ("mov", "sp,a");
3129 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3130 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3132 if (options.useXstack) {
3133 emitcode ("mov", "r0,%s", spname);
3134 emitcode ("movx", "a,@r0");
3135 emitcode ("mov", "_bp,a");
3136 emitcode ("dec", "%s", spname);
3138 if (options.stack10bit) {
3139 emitcode ("pop", "_bpx+1");
3140 emitcode ("pop", "_bpx");
3142 emitcode ("pop", "_bp");
3147 /* restore the register bank */
3148 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3150 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3151 || !options.useXstack)
3153 /* Special case of ISR using non-zero bank with useXstack
3156 emitcode ("pop", "psw");
3160 if (IFFUNC_ISISR (sym->type))
3163 /* now we need to restore the registers */
3164 /* if this isr has no bank i.e. is going to
3165 run with bank 0 , then we need to save more
3167 if (!FUNC_REGBANK (sym->type))
3170 /* if this function does not call any other
3171 function then we can be economical and
3172 save only those registers that are used */
3173 if (!IFFUNC_HASFCALL(sym->type))
3176 /* if any registers used */
3179 /* save the registers used */
3180 for (i = sym->regsUsed->size; i >= 0; i--)
3182 if (bitVectBitValue (sym->regsUsed, i) ||
3183 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3184 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3191 /* this function has a function call cannot
3192 determines register usage so we will have to pop the
3194 if (options.parms_in_bank1) {
3195 for (i = 7 ; i >= 0 ; i-- ) {
3196 emitcode ("pop","%s",rb1regs[i]);
3199 unsaveRBank (0, ic, FALSE);
3204 /* This ISR uses a non-zero bank.
3206 * Restore any register banks saved by genFunction
3209 // jwk: this needs a closer look
3210 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3213 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3215 if (savedBanks & (1 << ix))
3217 unsaveRBank(ix, NULL, FALSE);
3221 if (options.useXstack)
3223 /* Restore bank AFTER calling unsaveRBank,
3224 * since it can trash r0.
3226 emitcode ("pop", "psw");
3230 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3232 if (options.stack10bit)
3234 emitcode ("pop", DP2_RESULT_REG);
3235 emitcode ("pop", "dpx1");
3236 emitcode ("pop", "dph1");
3237 emitcode ("pop", "dpl1");
3239 emitcode ("pop", "dps");
3240 emitcode ("pop", "dpx");
3242 if (!inExcludeList ("dph"))
3243 emitcode ("pop", "dph");
3244 if (!inExcludeList ("dpl"))
3245 emitcode ("pop", "dpl");
3246 if (!inExcludeList ("b"))
3247 emitcode ("pop", "b");
3248 if (!inExcludeList ("acc"))
3249 emitcode ("pop", "acc");
3251 if (IFFUNC_ISCRITICAL (sym->type))
3252 emitcode ("setb", "ea");
3254 /* if debug then send end of function */
3255 if (options.debug && currFunc) {
3257 emitcode ("", "C$%s$%d$%d$%d ==.",
3258 FileBaseName (ic->filename), currFunc->lastLine,
3259 ic->level, ic->block);
3260 if (IS_STATIC (currFunc->etype))
3261 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3263 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3267 emitcode ("reti", "");
3271 if (IFFUNC_ISCRITICAL (sym->type))
3272 emitcode ("setb", "ea");
3274 if (IFFUNC_CALLEESAVES(sym->type))
3278 /* if any registers used */
3281 /* save the registers used */
3282 for (i = sym->regsUsed->size; i >= 0; i--)
3284 if (bitVectBitValue (sym->regsUsed, i) ||
3285 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3286 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3292 /* if debug then send end of function */
3293 if (options.debug && currFunc)
3296 emitcode ("", "C$%s$%d$%d$%d ==.",
3297 FileBaseName (ic->filename), currFunc->lastLine,
3298 ic->level, ic->block);
3299 if (IS_STATIC (currFunc->etype))
3300 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3302 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3306 emitcode ("ret", "");
3311 /*-----------------------------------------------------------------*/
3312 /* genJavaNativeRet - generate code for return JavaNative */
3313 /*-----------------------------------------------------------------*/
3314 static void genJavaNativeRet(iCode *ic)
3318 aopOp (IC_LEFT (ic), ic, FALSE,
3319 AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
3320 size = AOP_SIZE (IC_LEFT (ic));
3324 /* it is assigned to GPR0-R3 then push them */
3325 if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3326 aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3327 for (i = 0 ; i < size ; i++ ) {
3328 emitcode ("push","%s",aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,FALSE));
3330 for (i = (size-1) ; i >= 0 ; i--) {
3331 emitcode ("pop","a%s",javaRet[i]);
3334 for (i = 0 ; i < size ; i++)
3335 emitcode ("mov","%s,%s",javaRet[i],aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,FALSE));
3337 for (i = size ; i < 4 ; i++ )
3338 emitcode ("mov","%s,#0",javaRet[i]);
3342 /*-----------------------------------------------------------------*/
3343 /* genRet - generate code for return statement */
3344 /*-----------------------------------------------------------------*/
3348 int size, offset = 0, pushed = 0;
3350 D (emitcode (";", "genRet ");
3353 /* if we have no return value then
3354 just generate the "ret" */
3358 /* if this is a JavaNative function then return
3359 value in different register */
3360 if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3361 genJavaNativeRet(ic);
3364 /* we have something to return then
3365 move the return value into place */
3366 aopOp (IC_LEFT (ic), ic, FALSE,
3367 (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
3368 size = AOP_SIZE (IC_LEFT (ic));
3370 _startLazyDPSEvaluation ();
3374 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3376 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3377 FALSE, TRUE, FALSE);
3378 emitcode ("push", "%s", l);
3383 /* Since A is the last element of fReturn,
3384 * is is OK to clobber it in the aopGet.
3386 l = aopGet (AOP (IC_LEFT (ic)), offset,
3387 FALSE, FALSE, TRUE);
3388 if (strcmp (fReturn[offset], l))
3389 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3392 _endLazyDPSEvaluation ();
3399 if (strcmp (fReturn[pushed], "a"))
3400 emitcode ("pop", fReturn[pushed]);
3402 emitcode ("pop", "acc");
3405 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3408 /* generate a jump to the return label
3409 if the next is not the return statement */
3410 if (!(ic->next && ic->next->op == LABEL &&
3411 IC_LABEL (ic->next) == returnLabel))
3413 emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3417 /*-----------------------------------------------------------------*/
3418 /* genLabel - generates a label */
3419 /*-----------------------------------------------------------------*/
3421 genLabel (iCode * ic)
3423 /* special case never generate */
3424 if (IC_LABEL (ic) == entryLabel)
3427 D (emitcode (";", "genLabel ");
3430 emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3433 /*-----------------------------------------------------------------*/
3434 /* genGoto - generates a ljmp */
3435 /*-----------------------------------------------------------------*/
3437 genGoto (iCode * ic)
3439 D (emitcode (";", "genGoto ");
3441 emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3444 /*-----------------------------------------------------------------*/
3445 /* findLabelBackwards: walks back through the iCode chain looking */
3446 /* for the given label. Returns number of iCode instructions */
3447 /* between that label and given ic. */
3448 /* Returns zero if label not found. */
3449 /*-----------------------------------------------------------------*/
3451 findLabelBackwards (iCode * ic, int key)
3460 /* If we have any pushes or pops, we cannot predict the distance.
3461 I don't like this at all, this should be dealt with in the
3463 if (ic->op == IPUSH || ic->op == IPOP) {
3467 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3469 /* printf("findLabelBackwards = %d\n", count); */
3477 /*-----------------------------------------------------------------*/
3478 /* genPlusIncr :- does addition with increment if possible */
3479 /*-----------------------------------------------------------------*/
3481 genPlusIncr (iCode * ic)
3483 unsigned int icount;
3484 unsigned int size = getDataSize (IC_RESULT (ic));
3486 /* will try to generate an increment */
3487 /* if the right side is not a literal
3489 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3492 /* if the literal value of the right hand side
3493 is greater than 4 then it is not worth it */
3494 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3497 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3498 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3500 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
3504 /* if increment 16 bits in register */
3506 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3507 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3508 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3516 /* If the next instruction is a goto and the goto target
3517 * is <= 5 instructions previous to this, we can generate
3518 * jumps straight to that target.
3520 if (ic->next && ic->next->op == GOTO
3521 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3524 emitcode (";", "tail increment optimized (range %d)", labelRange);
3525 tlbl = IC_LABEL (ic->next);
3530 tlbl = newiTempLabel (NULL);
3533 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3534 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3535 IS_AOP_PREG (IC_RESULT (ic)))
3536 emitcode ("cjne", "%s,#0,!tlabel"
3537 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3541 emitcode ("clr", "a");
3542 emitcode ("cjne", "a,%s,!tlabel"
3543 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3547 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3550 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3551 IS_AOP_PREG (IC_RESULT (ic)))
3552 emitcode ("cjne", "%s,#0,!tlabel"
3553 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3556 emitcode ("cjne", "a,%s,!tlabel"
3557 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3560 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3564 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3565 IS_AOP_PREG (IC_RESULT (ic)))
3566 emitcode ("cjne", "%s,#0,!tlabel"
3567 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3571 emitcode ("cjne", "a,%s,!tlabel"
3572 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3575 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3580 emitcode ("", "!tlabeldef", tlbl->key + 100);
3585 if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3586 !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 &&
3587 options.model == MODEL_FLAT24 ) {
3591 emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, FALSE));
3593 emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, FALSE));
3595 emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3598 while (icount--) emitcode ("inc","dptr");
3602 if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3603 AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3605 emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3606 while (icount--) emitcode ("inc","dptr");
3607 emitcode ("mov","dps,#0");
3611 /* if the sizes are greater than 1 then we cannot */
3612 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3613 AOP_SIZE (IC_LEFT (ic)) > 1)
3616 /* we can if the aops of the left & result match or
3617 if they are in registers and the registers are the
3620 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3621 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3622 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3627 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3628 emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3629 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3634 _startLazyDPSEvaluation ();
3637 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3639 _endLazyDPSEvaluation ();
3648 /*-----------------------------------------------------------------*/
3649 /* outBitAcc - output a bit in acc */
3650 /*-----------------------------------------------------------------*/
3652 outBitAcc (operand * result)
3654 symbol *tlbl = newiTempLabel (NULL);
3655 /* if the result is a bit */
3656 if (AOP_TYPE (result) == AOP_CRY)
3658 aopPut (AOP (result), "a", 0);
3662 emitcode ("jz", "!tlabel", tlbl->key + 100);
3663 emitcode ("mov", "a,%s", one);
3664 emitcode ("", "!tlabeldef", tlbl->key + 100);
3669 /*-----------------------------------------------------------------*/
3670 /* genPlusBits - generates code for addition of two bits */
3671 /*-----------------------------------------------------------------*/
3673 genPlusBits (iCode * ic)
3675 D (emitcode (";", "genPlusBits ");
3677 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3679 symbol *lbl = newiTempLabel (NULL);
3680 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3681 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3682 emitcode ("cpl", "c");
3683 emitcode ("", "!tlabeldef", (lbl->key + 100));
3684 outBitC (IC_RESULT (ic));
3688 emitcode ("clr", "a");
3689 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3690 emitcode ("rlc", "a");
3691 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3692 emitcode ("addc", "a,#0");
3693 outAcc (IC_RESULT (ic));
3698 adjustArithmeticResult (iCode * ic)
3700 if (opIsGptr (IC_RESULT (ic)) &&
3701 opIsGptr (IC_LEFT (ic)) &&
3702 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3704 aopPut (AOP (IC_RESULT (ic)),
3705 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3709 if (opIsGptr (IC_RESULT (ic)) &&
3710 opIsGptr (IC_RIGHT (ic)) &&
3711 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3713 aopPut (AOP (IC_RESULT (ic)),
3714 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3718 if (opIsGptr (IC_RESULT (ic)) &&
3719 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3720 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3721 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3722 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3725 SNPRINTF (buff, sizeof(buff),
3726 "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3727 aopPut (AOP (IC_RESULT (ic)), buff, GPTRSIZE - 1);
3731 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
3732 // generates the result if possible. If result is generated, returns TRUE; otherwise
3733 // returns false and caller must deal with fact that result isn't aopOp'd.
3734 bool aopOp3(iCode * ic)
3736 bool dp1InUse, dp2InUse;
3739 // First, generate the right opcode. DPTR may be used if neither left nor result are
3742 // D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
3743 // AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
3744 // AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
3745 // AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
3747 // D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
3748 // AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
3749 // AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
3750 // AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
3754 // Right uses DPTR unless left or result is an AOP_STR.
3755 aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)));
3757 // if the right used DPTR, left MUST use DPTR2.
3758 // if the right used DPTR2, left MUST use DPTR.
3759 // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
3760 // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
3761 // enabling us to assign DPTR to result.
3763 if (AOP_USESDPTR(IC_RIGHT(ic)))
3767 else if (AOP_USESDPTR2(IC_RIGHT(ic)))
3773 if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
3783 aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
3785 // We've op'd the left & right. So, if left or right are the same operand as result,
3786 // we know aopOp will succeed, and we can just do it & bail.
3787 if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)) ||
3788 isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
3790 // D(emitcode(";", "aopOp3: (left | right) & result equal"););
3791 aopOp(IC_RESULT(ic),ic,TRUE, FALSE);
3795 // Note which dptrs are currently in use.
3796 dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
3797 dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
3799 // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot
3801 if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
3806 // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
3807 if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
3812 // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck
3813 if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
3818 aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
3820 // Some sanity checking...
3821 if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
3824 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
3825 __FILE__, __LINE__, ic->filename, ic->lineno);
3826 emitcode(";", ">>> unexpected DPTR here.");
3829 if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
3832 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
3833 __FILE__, __LINE__, ic->filename, ic->lineno);
3834 emitcode(";", ">>> unexpected DPTR2 here.");
3840 // Macro to aopOp all three operands of an ic. If this cannot be done,
3841 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3842 // will be set TRUE. The caller must then handle the case specially, noting
3843 // that the IC_RESULT operand is not aopOp'd.
3845 #define AOP_OP_3_NOFATAL(ic, rc) \
3846 do { rc = !aopOp3(ic); } while (0)
3848 // aopOp the left & right operands of an ic.
3849 #define AOP_OP_2(ic) \
3850 aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
3851 aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
3853 // convienience macro.
3854 #define AOP_SET_LOCALS(ic) \
3855 left = IC_LEFT(ic); \
3856 right = IC_RIGHT(ic); \
3857 result = IC_RESULT(ic);
3860 // Given an integer value of pushedSize bytes on the stack,
3861 // adjust it to be resultSize bytes, either by discarding
3862 // the most significant bytes or by zero-padding.
3864 // On exit from this macro, pushedSize will have been adjusted to
3865 // equal resultSize, and ACC may be trashed.
3866 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3867 /* If the pushed data is bigger than the result, \
3868 * simply discard unused bytes. Icky, but works. \
3870 while (pushedSize > resultSize) \
3872 D (emitcode (";", "discarding unused result byte."););\
3873 emitcode ("pop", "acc"); \
3876 if (pushedSize < resultSize) \
3878 emitcode ("clr", "a"); \
3879 /* Conversly, we haven't pushed enough here. \
3880 * just zero-pad, and all is well. \
3882 while (pushedSize < resultSize) \
3884 emitcode("push", "acc"); \
3888 assert(pushedSize == resultSize);
3890 /*-----------------------------------------------------------------*/
3891 /* genPlus - generates code for addition */
3892 /*-----------------------------------------------------------------*/
3894 genPlus (iCode * ic)
3896 int size, offset = 0;
3897 bool pushResult = FALSE;
3900 D (emitcode (";", "genPlus "););
3902 /* special cases :- */
3903 if ( AOP_IS_STR(IC_LEFT(ic)) &&
3904 isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
3905 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
3906 size = floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
3908 while (size--) emitcode ("inc","dptr");
3910 emitcode ("mov","a,dpl");
3911 emitcode ("add","a,#!constbyte",size & 0xff);
3912 emitcode ("mov","dpl,a");
3913 emitcode ("mov","a,dph");
3914 emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
3915 emitcode ("mov","dph,a");
3916 emitcode ("mov","a,dpx");
3917 emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
3918 emitcode ("mov","dpx,a");
3920 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
3923 if ( IS_SYMOP(IC_LEFT(ic)) &&
3924 OP_SYMBOL(IC_LEFT(ic))->remat &&
3925 isOperandInFarSpace(IC_RIGHT(ic))) {
3926 operand *op = IC_RIGHT(ic);
3927 IC_RIGHT(ic) = IC_LEFT(ic);
3931 AOP_OP_3_NOFATAL (ic, pushResult);
3935 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3940 /* if literal, literal on the right or
3941 if left requires ACC or right is already
3943 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3944 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3945 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3947 operand *t = IC_RIGHT (ic);
3948 IC_RIGHT (ic) = IC_LEFT (ic);
3950 emitcode (";", "Swapped plus args.");
3953 /* if both left & right are in bit
3955 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3956 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3962 /* if left in bit space & right literal */
3963 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3964 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3966 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3967 /* if result in bit space */
3968 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3970 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3971 emitcode ("cpl", "c");
3972 outBitC (IC_RESULT (ic));
3976 size = getDataSize (IC_RESULT (ic));
3977 _startLazyDPSEvaluation ();
3980 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3981 emitcode ("addc", "a,#0");
3982 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3984 _endLazyDPSEvaluation ();
3989 /* if I can do an increment instead
3990 of add then GOOD for ME */
3991 if (genPlusIncr (ic) == TRUE)
3993 emitcode (";", "did genPlusIncr");
3998 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4000 _startLazyDPSEvaluation ();
4003 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4005 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
4007 emitcode ("add", "a,%s",
4008 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
4010 emitcode ("addc", "a,%s",
4011 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
4015 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4017 /* right is going to use ACC or we would have taken the
4020 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4022 D(emitcode(";", "+ AOP_ACC special case."););
4023 emitcode("xch", "a, %s", DP2_RESULT_REG);
4025 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
4028 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4031 emitcode("add", "a, %s", DP2_RESULT_REG);
4035 emitcode ("add", "a,%s",
4036 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
4041 emitcode ("addc", "a,%s",
4042 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
4047 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4051 emitcode ("push", "acc");
4055 _endLazyDPSEvaluation ();
4059 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4061 size = getDataSize (IC_LEFT (ic));
4062 rSize = getDataSize (IC_RESULT (ic));
4064 ADJUST_PUSHED_RESULT(size, rSize);
4066 _startLazyDPSEvaluation ();
4069 emitcode ("pop", "acc");
4070 aopPut (AOP (IC_RESULT (ic)), "a", size);
4072 _endLazyDPSEvaluation ();
4075 adjustArithmeticResult (ic);
4078 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4079 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4080 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4083 /*-----------------------------------------------------------------*/
4084 /* genMinusDec :- does subtraction with deccrement if possible */
4085 /*-----------------------------------------------------------------*/
4087 genMinusDec (iCode * ic)
4089 unsigned int icount;
4090 unsigned int size = getDataSize (IC_RESULT (ic));
4092 /* will try to generate an increment */
4093 /* if the right side is not a literal
4095 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4098 /* if the literal value of the right hand side
4099 is greater than 4 then it is not worth it */
4100 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4103 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4104 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4106 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
4110 /* if decrement 16 bits in register */
4111 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4112 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4113 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4121 /* If the next instruction is a goto and the goto target
4122 * is <= 5 instructions previous to this, we can generate
4123 * jumps straight to that target.
4125 if (ic->next && ic->next->op == GOTO
4126 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4129 emitcode (";", "tail decrement optimized (range %d)", labelRange);
4130 tlbl = IC_LABEL (ic->next);
4135 tlbl = newiTempLabel (NULL);
4139 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
4140 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4141 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4142 IS_AOP_PREG (IC_RESULT (ic)))
4143 emitcode ("cjne", "%s,#!constbyte,!tlabel"
4144 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE), 0xff
4148 emitcode ("mov", "a,#!constbyte",0xff);
4149 emitcode ("cjne", "a,%s,!tlabel"
4150 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
4153 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
4156 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4157 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4158 IS_AOP_PREG (IC_RESULT (ic)))
4159 emitcode ("cjne", "%s,#!constbyte,!tlabel"
4160 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE),0xff
4164 emitcode ("cjne", "a,%s,!tlabel"
4165 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
4168 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
4172 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4173 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4174 IS_AOP_PREG (IC_RESULT (ic)))
4175 emitcode ("cjne", "%s,#!constbyte,!tlabel"
4176 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE),0xff
4180 emitcode ("cjne", "a,%s,!tlabel"
4181 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
4184 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
4188 emitcode ("", "!tlabeldef", tlbl->key + 100);
4193 /* if the sizes are greater than 1 then we cannot */
4194 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4195 AOP_SIZE (IC_LEFT (ic)) > 1)
4198 /* we can if the aops of the left & result match or
4199 if they are in registers and the registers are the
4202 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4203 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4204 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4207 _startLazyDPSEvaluation ();
4210 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
4212 _endLazyDPSEvaluation ();
4220 /*-----------------------------------------------------------------*/
4221 /* addSign - complete with sign */
4222 /*-----------------------------------------------------------------*/
4224 addSign (operand * result, int offset, int sign)
4226 int size = (getDataSize (result) - offset);
4229 _startLazyDPSEvaluation();
4232 emitcode ("rlc", "a");
4233 emitcode ("subb", "a,acc");
4236 aopPut (AOP (result), "a", offset++);
4243 aopPut (AOP (result), zero, offset++);
4246 _endLazyDPSEvaluation();
4250 /*-----------------------------------------------------------------*/
4251 /* genMinusBits - generates code for subtraction of two bits */
4252 /*-----------------------------------------------------------------*/
4254 genMinusBits (iCode * ic)
4256 symbol *lbl = newiTempLabel (NULL);
4258 D (emitcode (";", "genMinusBits "););
4260 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4262 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4263 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4264 emitcode ("cpl", "c");
4265 emitcode ("", "!tlabeldef", (lbl->key + 100));
4266 outBitC (IC_RESULT (ic));
4270 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4271 emitcode ("subb", "a,acc");
4272 emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4273 emitcode ("inc", "a");
4274 emitcode ("", "!tlabeldef", (lbl->key + 100));
4275 aopPut (AOP (IC_RESULT (ic)), "a", 0);
4276 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4280 /*-----------------------------------------------------------------*/
4281 /* genMinus - generates code for subtraction */
4282 /*-----------------------------------------------------------------*/
4284 genMinus (iCode * ic)
4286 int size, offset = 0;
4288 unsigned long lit = 0L;
4289 bool pushResult = FALSE;
4291 D (emitcode (";", "genMinus "););
4293 AOP_OP_3_NOFATAL(ic, pushResult);
4297 /* special cases :- */
4298 /* if both left & right are in bit space */
4299 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4300 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4306 /* if I can do an decrement instead
4307 of subtract then GOOD for ME */
4308 if (genMinusDec (ic) == TRUE)
4313 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4315 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4321 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4326 /* if literal, add a,#-lit, else normal subb */
4327 _startLazyDPSEvaluation ();
4329 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4330 if (AOP_USESDPTR(IC_RIGHT(ic))) {
4331 emitcode ("mov","b,%s",
4332 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
4333 MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
4334 emitcode ("subb","a,b");
4336 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
4337 emitcode ("subb", "a,%s",
4338 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
4341 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
4342 /* first add without previous c */
4344 if (!size && lit==-1) {
4345 emitcode ("dec", "a");
4347 emitcode ("add", "a,#!constbyte",
4348 (unsigned int) (lit & 0x0FFL));
4351 emitcode ("addc", "a,#!constbyte",
4352 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4357 emitcode ("push", "acc");
4359 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4363 _endLazyDPSEvaluation ();
4367 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4369 size = getDataSize (IC_LEFT (ic));
4370 rSize = getDataSize (IC_RESULT (ic));
4372 ADJUST_PUSHED_RESULT(size, rSize);
4374 _startLazyDPSEvaluation ();
4377 emitcode ("pop", "acc");
4378 aopPut (AOP (IC_RESULT (ic)), "a", size);
4380 _endLazyDPSEvaluation ();
4383 adjustArithmeticResult (ic);
4386 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4387 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4388 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4392 /*-----------------------------------------------------------------*/
4393 /* genMultbits :- multiplication of bits */
4394 /*-----------------------------------------------------------------*/
4396 genMultbits (operand * left,
4401 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4402 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4403 aopOp(result, ic, TRUE, FALSE);
4408 /*-----------------------------------------------------------------*/
4409 /* genMultOneByte : 8*8=8/16 bit multiplication */
4410 /*-----------------------------------------------------------------*/
4412 genMultOneByte (operand * left,
4417 sym_link *opetype = operandType (result);
4421 /* (if two literals: the value is computed before) */
4422 /* if one literal, literal on the right */
4423 if (AOP_TYPE (left) == AOP_LIT)
4428 emitcode (";", "swapped left and right");
4431 if (SPEC_USIGN(opetype)
4432 // ignore the sign of left and right, what else can we do?
4433 || (SPEC_USIGN(operandType(left)) &&
4434 SPEC_USIGN(operandType(right)))) {
4435 // just an unsigned 8*8=8/16 multiply
4436 //emitcode (";","unsigned");
4437 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4438 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4439 emitcode ("mul", "ab");
4441 _G.accInUse++; _G.bInUse++;
4442 aopOp(result, ic, TRUE, FALSE);
4444 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4446 // this should never happen
4447 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4448 AOP_SIZE(result), __FILE__, lineno);
4452 aopPut (AOP (result), "a", 0);
4453 _G.accInUse--; _G.bInUse--;
4454 if (AOP_SIZE(result)==2)
4456 aopPut (AOP (result), "b", 1);
4461 // we have to do a signed multiply
4463 emitcode (";", "signed");
4464 emitcode ("clr", "F0"); // reset sign flag
4465 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4467 lbl=newiTempLabel(NULL);
4468 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4469 // left side is negative, 8-bit two's complement, this fails for -128
4470 emitcode ("setb", "F0"); // set sign flag
4471 emitcode ("cpl", "a");
4472 emitcode ("inc", "a");
4474 emitcode ("", "!tlabeldef", lbl->key+100);
4477 if (AOP_TYPE(right)==AOP_LIT) {
4478 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4479 /* AND literal negative */
4480 if ((int) val < 0) {
4481 emitcode ("cpl", "F0"); // complement sign flag
4482 emitcode ("mov", "b,#!constbyte", -val);
4484 emitcode ("mov", "b,#!constbyte", val);
4487 lbl=newiTempLabel(NULL);
4488 emitcode ("mov", "b,a");
4489 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4490 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4491 // right side is negative, 8-bit two's complement
4492 emitcode ("cpl", "F0"); // complement sign flag
4493 emitcode ("cpl", "a");
4494 emitcode ("inc", "a");
4495 emitcode ("", "!tlabeldef", lbl->key+100);
4497 emitcode ("mul", "ab");
4499 _G.accInUse++;_G.bInUse++;
4500 aopOp(result, ic, TRUE, FALSE);
4502 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4504 // this should never happen
4505 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4506 AOP_SIZE(result), __FILE__, lineno);
4510 lbl=newiTempLabel(NULL);
4511 emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4512 // only ONE op was negative, we have to do a 8/16-bit two's complement
4513 emitcode ("cpl", "a"); // lsb
4514 if (AOP_SIZE(result)==1) {
4515 emitcode ("inc", "a");
4517 emitcode ("add", "a,#1");
4518 emitcode ("xch", "a,b");
4519 emitcode ("cpl", "a"); // msb
4520 emitcode ("addc", "a,#0");
4521 emitcode ("xch", "a,b");
4524 emitcode ("", "!tlabeldef", lbl->key+100);
4525 aopPut (AOP (result), "a", 0);
4526 _G.accInUse--;_G.bInUse--;
4527 if (AOP_SIZE(result)==2) {
4528 aopPut (AOP (result), "b", 1);
4532 /*-----------------------------------------------------------------*/
4533 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
4534 /*-----------------------------------------------------------------*/
4535 static void genMultTwoByte (operand *left, operand *right,
4536 operand *result, iCode *ic)
4538 sym_link *retype = getSpec(operandType(right));
4539 sym_link *letype = getSpec(operandType(left));
4540 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4543 if (AOP_TYPE (left) == AOP_LIT) {
4548 /* save EA bit in F1 */
4549 lbl = newiTempLabel(NULL);
4550 emitcode ("setb","F1");
4551 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4552 emitcode ("clr","F1");
4553 emitcode("","!tlabeldef",lbl->key+100);
4555 /* load up MB with right */
4557 emitcode("clr","F0");
4558 if (AOP_TYPE(right) == AOP_LIT) {
4559 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4561 emitcode("setb","F0");
4564 emitcode ("mov","mb,#!constbyte",val & 0xff);
4565 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4567 lbl = newiTempLabel(NULL);
4568 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4569 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4570 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4571 emitcode ("xch", "a,b");
4572 emitcode ("cpl","a");
4573 emitcode ("add", "a,#1");
4574 emitcode ("xch", "a,b");
4575 emitcode ("cpl", "a"); // msb
4576 emitcode ("addc", "a,#0");
4577 emitcode ("setb","F0");
4578 emitcode ("","!tlabeldef",lbl->key+100);
4579 emitcode ("mov","mb,b");
4580 emitcode ("mov","mb,a");
4583 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4584 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4586 /* load up MA with left */
4588 lbl = newiTempLabel(NULL);
4589 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4590 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4591 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4592 emitcode ("xch", "a,b");
4593 emitcode ("cpl","a");
4594 emitcode ("add", "a,#1");
4595 emitcode ("xch", "a,b");
4596 emitcode ("cpl", "a"); // msb
4597 emitcode ("addc","a,#0");
4598 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4599 emitcode ("setb","F0");
4600 emitcode ("","!tlabeldef",lbl->key+100);
4601 emitcode ("mov","ma,b");
4602 emitcode ("mov","ma,a");
4604 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4605 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4607 /* wait for multiplication to finish */
4608 lbl = newiTempLabel(NULL);
4609 emitcode("","!tlabeldef", lbl->key+100);
4610 emitcode("mov","a,mcnt1");
4611 emitcode("anl","a,#!constbyte",0x80);
4612 emitcode("jnz","!tlabel",lbl->key+100);
4614 freeAsmop (left, NULL, ic, TRUE);
4615 freeAsmop (right, NULL, ic,TRUE);
4616 aopOp(result, ic, TRUE, FALSE);
4618 /* if unsigned then simple */
4620 emitcode ("mov","a,ma");
4621 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4622 emitcode ("mov","a,ma");
4623 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4624 aopPut(AOP(result),"ma",1);
4625 aopPut(AOP(result),"ma",0);
4627 emitcode("push","ma");
4628 emitcode("push","ma");
4629 emitcode("push","ma");
4631 /* negate result if needed */
4632 lbl = newiTempLabel(NULL);
4633 emitcode("jnb","F0,!tlabel",lbl->key+100);
4634 emitcode("cpl","a");
4635 emitcode("add","a,#1");
4636 emitcode("","!tlabeldef", lbl->key+100);
4637 if (AOP_TYPE(result) == AOP_ACC)
4639 D(emitcode(";", "ACC special case."););
4640 /* We know result is the only live aop, and
4641 * it's obviously not a DPTR2, so AP is available.
4643 emitcode("mov", "%s,acc", DP2_RESULT_REG);
4647 aopPut(AOP(result),"a",0);
4650 emitcode("pop","acc");
4651 lbl = newiTempLabel(NULL);
4652 emitcode("jnb","F0,!tlabel",lbl->key+100);
4653 emitcode("cpl","a");
4654 emitcode("addc","a,#0");
4655 emitcode("","!tlabeldef", lbl->key+100);
4656 aopPut(AOP(result),"a",1);
4657 emitcode("pop","acc");
4658 if (AOP_SIZE(result) >= 3) {
4659 lbl = newiTempLabel(NULL);
4660 emitcode("jnb","F0,!tlabel",lbl->key+100);
4661 emitcode("cpl","a");
4662 emitcode("addc","a,#0");
4663 emitcode("","!tlabeldef", lbl->key+100);
4664 aopPut(AOP(result),"a",2);
4666 emitcode("pop","acc");
4667 if (AOP_SIZE(result) >= 4) {
4668 lbl = newiTempLabel(NULL);
4669 emitcode("jnb","F0,!tlabel",lbl->key+100);
4670 emitcode("cpl","a");
4671 emitcode("addc","a,#0");
4672 emitcode("","!tlabeldef", lbl->key+100);
4673 aopPut(AOP(result),"a",3);
4675 if (AOP_TYPE(result) == AOP_ACC)
4677 /* We stashed the result away above. */
4678 emitcode("mov", "acc,%s", DP2_RESULT_REG);
4682 freeAsmop (result, NULL, ic, TRUE);
4684 /* restore EA bit in F1 */
4685 lbl = newiTempLabel(NULL);
4686 emitcode ("jnb","F1,!tlabel",lbl->key+100);
4687 emitcode ("setb","EA");
4688 emitcode("","!tlabeldef",lbl->key+100);
4692 /*-----------------------------------------------------------------*/
4693 /* genMult - generates code for multiplication */
4694 /*-----------------------------------------------------------------*/
4696 genMult (iCode * ic)
4698 operand *left = IC_LEFT (ic);
4699 operand *right = IC_RIGHT (ic);
4700 operand *result = IC_RESULT (ic);
4702 D (emitcode (";", "genMult "););
4704 /* assign the amsops */
4707 /* special cases first */
4709 if (AOP_TYPE (left) == AOP_CRY &&
4710 AOP_TYPE (right) == AOP_CRY)
4712 genMultbits (left, right, result, ic);
4716 /* if both are of size == 1 */
4717 if (AOP_SIZE (left) == 1 &&
4718 AOP_SIZE (right) == 1)
4720 genMultOneByte (left, right, result, ic);
4724 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4725 /* use the ds390 ARITHMETIC accel UNIT */
4726 genMultTwoByte (left, right, result, ic);
4729 /* should have been converted to function call */
4733 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4734 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4735 freeAsmop (result, NULL, ic, TRUE);
4738 /*-----------------------------------------------------------------*/
4739 /* genDivbits :- division of bits */
4740 /*-----------------------------------------------------------------*/
4742 genDivbits (operand * left,
4750 /* the result must be bit */
4751 LOAD_AB_FOR_DIV (left, right, l);
4752 emitcode ("div", "ab");
4753 emitcode ("rrc", "a");
4754 aopOp(result, ic, TRUE, FALSE);
4756 aopPut (AOP (result), "c", 0);
4759 /*-----------------------------------------------------------------*/
4760 /* genDivOneByte : 8 bit division */
4761 /*-----------------------------------------------------------------*/
4763 genDivOneByte (operand * left,
4768 sym_link *opetype = operandType (result);
4774 /* signed or unsigned */
4775 if (SPEC_USIGN (opetype))
4777 /* unsigned is easy */
4778 LOAD_AB_FOR_DIV (left, right, l);
4779 emitcode ("div", "ab");
4782 aopOp(result, ic, TRUE, FALSE);
4783 aopPut (AOP (result), "a", 0);
4786 size = AOP_SIZE (result) - 1;
4790 aopPut (AOP (result), zero, offset++);
4795 /* signed is a little bit more difficult */
4797 /* save the signs of the operands */
4798 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4800 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4801 emitcode ("push", "acc"); /* save it on the stack */
4803 /* now sign adjust for both left & right */
4804 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4806 lbl = newiTempLabel (NULL);
4807 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4808 emitcode ("cpl", "a");
4809 emitcode ("inc", "a");
4810 emitcode ("", "!tlabeldef", (lbl->key + 100));
4811 emitcode ("mov", "b,a");
4813 /* sign adjust left side */
4814 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4817 lbl = newiTempLabel (NULL);
4818 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4819 emitcode ("cpl", "a");
4820 emitcode ("inc", "a");
4821 emitcode ("", "!tlabeldef", (lbl->key + 100));
4823 /* now the division */
4824 emitcode ("nop", "; workaround for DS80C390 div bug.");
4825 emitcode ("div", "ab");
4826 /* we are interested in the lower order
4828 emitcode ("mov", "b,a");
4829 lbl = newiTempLabel (NULL);
4830 emitcode ("pop", "acc");
4831 /* if there was an over flow we don't
4832 adjust the sign of the result */
4833 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4834 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4836 emitcode ("clr", "a");
4837 emitcode ("subb", "a,b");
4838 emitcode ("mov", "b,a");
4839 emitcode ("", "!tlabeldef", (lbl->key + 100));
4841 /* now we are done */
4842 _G.accInUse++; _G.bInUse++;
4843 aopOp(result, ic, TRUE, FALSE);
4845 aopPut (AOP (result), "b", 0);
4847 size = AOP_SIZE (result) - 1;
4851 emitcode ("mov", "c,b.7");
4852 emitcode ("subb", "a,acc");
4856 aopPut (AOP (result), "a", offset++);
4858 _G.accInUse--; _G.bInUse--;
4862 /*-----------------------------------------------------------------*/
4863 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
4864 /*-----------------------------------------------------------------*/
4865 static void genDivTwoByte (operand *left, operand *right,
4866 operand *result, iCode *ic)
4868 sym_link *retype = getSpec(operandType(right));
4869 sym_link *letype = getSpec(operandType(left));
4870 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4873 /* save EA bit in F1 */
4874 lbl = newiTempLabel(NULL);
4875 emitcode ("setb","F1");
4876 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4877 emitcode ("clr","F1");
4878 emitcode("","!tlabeldef",lbl->key+100);
4880 /* load up MA with left */
4882 emitcode("clr","F0");
4883 lbl = newiTempLabel(NULL);
4884 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4885 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4886 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4887 emitcode ("xch", "a,b");
4888 emitcode ("cpl","a");
4889 emitcode ("add", "a,#1");
4890 emitcode ("xch", "a,b");
4891 emitcode ("cpl", "a"); // msb
4892 emitcode ("addc","a,#0");
4893 emitcode ("setb","F0");
4894 emitcode ("","!tlabeldef",lbl->key+100);
4895 emitcode ("mov","ma,b");
4896 emitcode ("mov","ma,a");
4898 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4899 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4902 /* load up MB with right */
4904 if (AOP_TYPE(right) == AOP_LIT) {
4905 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4907 lbl = newiTempLabel(NULL);
4908 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4909 emitcode("setb","F0");
4910 emitcode ("","!tlabeldef",lbl->key+100);
4913 emitcode ("mov","mb,#!constbyte",val & 0xff);
4914 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4916 lbl = newiTempLabel(NULL);
4917 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4918 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4919 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4920 emitcode ("xch", "a,b");
4921 emitcode ("cpl","a");
4922 emitcode ("add", "a,#1");
4923 emitcode ("xch", "a,b");
4924 emitcode ("cpl", "a"); // msb
4925 emitcode ("addc", "a,#0");
4926 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4927 emitcode ("setb","F0");
4928 emitcode ("","!tlabeldef",lbl->key+100);
4929 emitcode ("mov","mb,b");
4930 emitcode ("mov","mb,a");
4933 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4934 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4937 /* wait for multiplication to finish */
4938 lbl = newiTempLabel(NULL);
4939 emitcode("","!tlabeldef", lbl->key+100);
4940 emitcode("mov","a,mcnt1");
4941 emitcode("anl","a,#!constbyte",0x80);
4942 emitcode("jnz","!tlabel",lbl->key+100);
4944 freeAsmop (left, NULL, ic, TRUE);
4945 freeAsmop (right, NULL, ic,TRUE);
4946 aopOp(result, ic, TRUE, FALSE);
4948 /* if unsigned then simple */
4950 aopPut(AOP(result),"ma",1);
4951 aopPut(AOP(result),"ma",0);
4953 emitcode("push","ma");
4955 /* negate result if needed */
4956 lbl = newiTempLabel(NULL);
4957 emitcode("jnb","F0,!tlabel",lbl->key+100);
4958 emitcode("cpl","a");
4959 emitcode("add","a,#1");
4960 emitcode("","!tlabeldef", lbl->key+100);
4961 aopPut(AOP(result),"a",0);
4962 emitcode("pop","acc");
4963 lbl = newiTempLabel(NULL);
4964 emitcode("jnb","F0,!tlabel",lbl->key+100);
4965 emitcode("cpl","a");
4966 emitcode("addc","a,#0");
4967 emitcode("","!tlabeldef", lbl->key+100);
4968 aopPut(AOP(result),"a",1);
4970 freeAsmop (result, NULL, ic, TRUE);
4971 /* restore EA bit in F1 */
4972 lbl = newiTempLabel(NULL);
4973 emitcode ("jnb","F1,!tlabel",lbl->key+100);
4974 emitcode ("setb","EA");
4975 emitcode("","!tlabeldef",lbl->key+100);
4979 /*-----------------------------------------------------------------*/
4980 /* genDiv - generates code for division */
4981 /*-----------------------------------------------------------------*/
4985 operand *left = IC_LEFT (ic);
4986 operand *right = IC_RIGHT (ic);
4987 operand *result = IC_RESULT (ic);
4989 D (emitcode (";", "genDiv "););
4991 /* assign the amsops */
4994 /* special cases first */
4996 if (AOP_TYPE (left) == AOP_CRY &&
4997 AOP_TYPE (right) == AOP_CRY)
4999 genDivbits (left, right, result, ic);
5003 /* if both are of size == 1 */
5004 if (AOP_SIZE (left) == 1 &&
5005 AOP_SIZE (right) == 1)
5007 genDivOneByte (left, right, result, ic);
5011 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5012 /* use the ds390 ARITHMETIC accel UNIT */
5013 genDivTwoByte (left, right, result, ic);
5016 /* should have been converted to function call */
5019 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5020 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5021 freeAsmop (result, NULL, ic, TRUE);
5024 /*-----------------------------------------------------------------*/
5025 /* genModbits :- modulus of bits */
5026 /*-----------------------------------------------------------------*/
5028 genModbits (operand * left,
5036 /* the result must be bit */
5037 LOAD_AB_FOR_DIV (left, right, l);
5038 emitcode ("div", "ab");
5039 emitcode ("mov", "a,b");
5040 emitcode ("rrc", "a");
5041 aopOp(result, ic, TRUE, FALSE);
5042 aopPut (AOP (result), "c", 0);
5045 /*-----------------------------------------------------------------*/
5046 /* genModOneByte : 8 bit modulus */
5047 /*-----------------------------------------------------------------*/
5049 genModOneByte (operand * left,
5054 sym_link *opetype = operandType (result);
5058 /* signed or unsigned */
5059 if (SPEC_USIGN (opetype))
5061 /* unsigned is easy */
5062 LOAD_AB_FOR_DIV (left, right, l);
5063 emitcode ("div", "ab");
5064 aopOp(result, ic, TRUE, FALSE);
5065 aopPut (AOP (result), "b", 0);
5069 /* signed is a little bit more difficult */
5071 /* save the signs of the operands */
5072 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
5075 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
5076 emitcode ("push", "acc"); /* save it on the stack */
5078 /* now sign adjust for both left & right */
5079 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
5082 lbl = newiTempLabel (NULL);
5083 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5084 emitcode ("cpl", "a");
5085 emitcode ("inc", "a");
5086 emitcode ("", "!tlabeldef", (lbl->key + 100));
5087 emitcode ("mov", "b,a");
5089 /* sign adjust left side */
5090 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
5093 lbl = newiTempLabel (NULL);
5094 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5095 emitcode ("cpl", "a");
5096 emitcode ("inc", "a");
5097 emitcode ("", "!tlabeldef", (lbl->key + 100));
5099 /* now the multiplication */
5100 emitcode ("nop", "; workaround for DS80C390 div bug.");
5101 emitcode ("div", "ab");
5102 /* we are interested in the lower order
5104 lbl = newiTempLabel (NULL);
5105 emitcode ("pop", "acc");
5106 /* if there was an over flow we don't
5107 adjust the sign of the result */
5108 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
5109 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5111 emitcode ("clr", "a");
5112 emitcode ("subb", "a,b");
5113 emitcode ("mov", "b,a");
5114 emitcode ("", "!tlabeldef", (lbl->key + 100));
5117 /* now we are done */
5118 aopOp(result, ic, TRUE, FALSE);
5119 aopPut (AOP (result), "b", 0);
5124 /*-----------------------------------------------------------------*/
5125 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
5126 /*-----------------------------------------------------------------*/
5127 static void genModTwoByte (operand *left, operand *right,
5128 operand *result, iCode *ic)
5130 sym_link *retype = getSpec(operandType(right));
5131 sym_link *letype = getSpec(operandType(left));
5132 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5135 /* load up MA with left */
5136 /* save EA bit in F1 */
5137 lbl = newiTempLabel(NULL);
5138 emitcode ("setb","F1");
5139 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5140 emitcode ("clr","F1");
5141 emitcode("","!tlabeldef",lbl->key+100);
5144 lbl = newiTempLabel(NULL);
5145 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
5146 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
5147 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5148 emitcode ("xch", "a,b");
5149 emitcode ("cpl","a");
5150 emitcode ("add", "a,#1");
5151 emitcode ("xch", "a,b");
5152 emitcode ("cpl", "a"); // msb
5153 emitcode ("addc","a,#0");
5154 emitcode ("","!tlabeldef",lbl->key+100);
5155 emitcode ("mov","ma,b");
5156 emitcode ("mov","ma,a");
5158 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
5159 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
5162 /* load up MB with right */
5164 if (AOP_TYPE(right) == AOP_LIT) {
5165 int val=floatFromVal (AOP (right)->aopu.aop_lit);
5169 emitcode ("mov","mb,#!constbyte",val & 0xff);
5170 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5172 lbl = newiTempLabel(NULL);
5173 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
5174 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
5175 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5176 emitcode ("xch", "a,b");
5177 emitcode ("cpl","a");
5178 emitcode ("add", "a,#1");
5179 emitcode ("xch", "a,b");
5180 emitcode ("cpl", "a"); // msb
5181 emitcode ("addc", "a,#0");
5182 emitcode ("","!tlabeldef",lbl->key+100);
5183 emitcode ("mov","mb,b");
5184 emitcode ("mov","mb,a");
5187 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
5188 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
5191 /* wait for multiplication to finish */
5192 lbl = newiTempLabel(NULL);
5193 emitcode("","!tlabeldef", lbl->key+100);
5194 emitcode("mov","a,mcnt1");
5195 emitcode("anl","a,#!constbyte",0x80);
5196 emitcode("jnz","!tlabel",lbl->key+100);
5198 freeAsmop (left, NULL, ic, TRUE);
5199 freeAsmop (right, NULL, ic,TRUE);
5200 aopOp(result, ic, TRUE, FALSE);
5202 aopPut(AOP(result),"mb",1);
5203 aopPut(AOP(result),"mb",0);
5204 freeAsmop (result, NULL, ic, TRUE);
5206 /* restore EA bit in F1 */
5207 lbl = newiTempLabel(NULL);
5208 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5209 emitcode ("setb","EA");
5210 emitcode("","!tlabeldef",lbl->key+100);
5214 /*-----------------------------------------------------------------*/
5215 /* genMod - generates code for division */
5216 /*-----------------------------------------------------------------*/
5220 operand *left = IC_LEFT (ic);
5221 operand *right = IC_RIGHT (ic);
5222 operand *result = IC_RESULT (ic);
5224 D (emitcode (";", "genMod "); );
5226 /* assign the amsops */
5229 /* special cases first */
5231 if (AOP_TYPE (left) == AOP_CRY &&
5232 AOP_TYPE (right) == AOP_CRY)
5234 genModbits (left, right, result, ic);
5238 /* if both are of size == 1 */
5239 if (AOP_SIZE (left) == 1 &&
5240 AOP_SIZE (right) == 1)
5242 genModOneByte (left, right, result, ic);
5246 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5247 /* use the ds390 ARITHMETIC accel UNIT */
5248 genModTwoByte (left, right, result, ic);
5252 /* should have been converted to function call */
5256 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5257 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5258 freeAsmop (result, NULL, ic, TRUE);
5261 /*-----------------------------------------------------------------*/
5262 /* genIfxJump :- will create a jump depending on the ifx */
5263 /*-----------------------------------------------------------------*/
5265 genIfxJump (iCode * ic, char *jval)
5268 symbol *tlbl = newiTempLabel (NULL);
5271 D (emitcode (";", "genIfxJump"););
5273 /* if true label then we jump if condition
5277 jlbl = IC_TRUE (ic);
5278 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5279 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5283 /* false label is present */
5284 jlbl = IC_FALSE (ic);
5285 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5286 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5288 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5289 emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5291 emitcode (inst, "!tlabel", tlbl->key + 100);
5292 emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5293 emitcode ("", "!tlabeldef", tlbl->key + 100);
5295 /* mark the icode as generated */
5299 /*-----------------------------------------------------------------*/
5300 /* genCmp :- greater or less than comparison */
5301 /*-----------------------------------------------------------------*/
5303 genCmp (operand * left, operand * right,
5304 iCode * ic, iCode * ifx, int sign)
5306 int size, offset = 0;
5307 unsigned long lit = 0L;
5310 D (emitcode (";", "genCmp");
5313 result = IC_RESULT (ic);
5315 /* if left & right are bit variables */
5316 if (AOP_TYPE (left) == AOP_CRY &&
5317 AOP_TYPE (right) == AOP_CRY)
5319 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5320 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
5324 /* subtract right from left if at the
5325 end the carry flag is set then we know that
5326 left is greater than right */
5327 size = max (AOP_SIZE (left), AOP_SIZE (right));
5329 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5330 if ((size == 1) && !sign &&
5331 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5333 symbol *lbl = newiTempLabel (NULL);
5334 emitcode ("cjne", "%s,%s,!tlabel",
5335 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5336 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5338 emitcode ("", "!tlabeldef", lbl->key + 100);
5342 if (AOP_TYPE (right) == AOP_LIT)
5344 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5345 /* optimize if(x < 0) or if(x >= 0) */
5354 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
5356 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5357 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5359 aopOp (result, ic, FALSE, FALSE);
5361 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5363 freeAsmop (result, NULL, ic, TRUE);
5364 genIfxJump (ifx, "acc.7");
5369 emitcode ("rlc", "a");
5371 goto release_freedLR;
5379 //emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5380 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5381 //emitcode (";", "genCmp #2");
5382 if (sign && (size == 0))
5384 //emitcode (";", "genCmp #3");
5385 emitcode ("xrl", "a,#!constbyte",0x80);
5386 if (AOP_TYPE (right) == AOP_LIT)
5388 unsigned long lit = (unsigned long)
5389 floatFromVal (AOP (right)->aopu.aop_lit);
5390 //emitcode (";", "genCmp #3.1");
5391 emitcode ("subb", "a,#!constbyte",
5392 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5396 //emitcode (";", "genCmp #3.2");
5397 if (AOP_NEEDSACC (right))
5399 emitcode ("push", "acc");
5401 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
5402 FALSE, FALSE, FALSE));
5403 emitcode ("xrl", "b,#!constbyte",0x80);
5404 if (AOP_NEEDSACC (right))
5406 emitcode ("pop", "acc");
5408 emitcode ("subb", "a,b");
5415 //emitcode (";", "genCmp #4");
5416 if (AOP_NEEDSACC (right))
5419 //emitcode (";", "genCmp #4.1");
5420 emitcode ("xch", "a, b");
5421 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
5422 emitcode ("xch", "a, b");
5427 //emitcode (";", "genCmp #4.2");
5428 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
5431 emitcode ("subb", "a,%s", s);
5438 /* Don't need the left & right operands any more; do need the result. */
5439 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5440 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5442 aopOp (result, ic, FALSE, FALSE);
5446 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5452 /* if the result is used in the next
5453 ifx conditional branch then generate
5454 code a little differently */
5457 genIfxJump (ifx, "c");
5463 /* leave the result in acc */
5465 freeAsmop (result, NULL, ic, TRUE);
5468 /*-----------------------------------------------------------------*/
5469 /* genCmpGt :- greater than comparison */
5470 /*-----------------------------------------------------------------*/
5472 genCmpGt (iCode * ic, iCode * ifx)
5474 operand *left, *right;
5475 sym_link *letype, *retype;
5478 D (emitcode (";", "genCmpGt ");
5481 left = IC_LEFT (ic);
5482 right = IC_RIGHT (ic);
5484 letype = getSpec (operandType (left));
5485 retype = getSpec (operandType (right));
5486 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5488 /* assign the left & right amsops */
5491 genCmp (right, left, ic, ifx, sign);
5494 /*-----------------------------------------------------------------*/
5495 /* genCmpLt - less than comparisons */
5496 /*-----------------------------------------------------------------*/
5498 genCmpLt (iCode * ic, iCode * ifx)
5500 operand *left, *right;
5501 sym_link *letype, *retype;
5504 D (emitcode (";", "genCmpLt "););
5506 left = IC_LEFT (ic);
5507 right = IC_RIGHT (ic);
5509 letype = getSpec (operandType (left));
5510 retype = getSpec (operandType (right));
5511 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5513 /* assign the left & right amsops */
5516 genCmp (left, right, ic, ifx, sign);
5519 /*-----------------------------------------------------------------*/
5520 /* gencjneshort - compare and jump if not equal */
5521 /*-----------------------------------------------------------------*/
5523 gencjneshort (operand * left, operand * right, symbol * lbl)
5525 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5527 unsigned long lit = 0L;
5529 D (emitcode (";", "gencjneshort");
5532 /* if the left side is a literal or
5533 if the right is in a pointer register and left
5535 if ((AOP_TYPE (left) == AOP_LIT) ||
5536 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5543 if (AOP_TYPE (right) == AOP_LIT)
5544 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5546 if (opIsGptr (left) || opIsGptr (right))
5548 /* We are comparing a generic pointer to something.
5549 * Exclude the generic type byte from the comparison.
5552 D (emitcode (";", "cjneshort: generic ptr special case.");
5557 /* if the right side is a literal then anything goes */
5558 if (AOP_TYPE (right) == AOP_LIT &&
5559 AOP_TYPE (left) != AOP_DIR)
5563 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5565 emitcode ("cjne", "a,%s,!tlabel",
5566 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5572 /* if the right side is in a register or in direct space or
5573 if the left is a pointer register & right is not */
5574 else if (AOP_TYPE (right) == AOP_REG ||
5575 AOP_TYPE (right) == AOP_DIR ||
5576 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5577 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5581 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5582 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5583 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5584 emitcode ("jnz", "!tlabel", lbl->key + 100);
5586 emitcode ("cjne", "a,%s,!tlabel",
5587 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
5594 /* right is a pointer reg need both a & b */
5597 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5598 if (strcmp (l, "b"))
5599 emitcode ("mov", "b,%s", l);
5600 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5601 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5607 /*-----------------------------------------------------------------*/
5608 /* gencjne - compare and jump if not equal */
5609 /*-----------------------------------------------------------------*/
5611 gencjne (operand * left, operand * right, symbol * lbl)
5613 symbol *tlbl = newiTempLabel (NULL);
5615 D (emitcode (";", "gencjne");
5618 gencjneshort (left, right, lbl);
5620 emitcode ("mov", "a,%s", one);
5621 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5622 emitcode ("", "!tlabeldef", lbl->key + 100);
5623 emitcode ("clr", "a");
5624 emitcode ("", "!tlabeldef", tlbl->key + 100);
5627 /*-----------------------------------------------------------------*/
5628 /* genCmpEq - generates code for equal to */
5629 /*-----------------------------------------------------------------*/
5631 genCmpEq (iCode * ic, iCode * ifx)
5633 operand *left, *right, *result;
5635 D (emitcode (";", "genCmpEq ");
5639 AOP_SET_LOCALS (ic);
5641 /* if literal, literal on the right or
5642 if the right is in a pointer register and left
5644 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5645 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5647 operand *t = IC_RIGHT (ic);
5648 IC_RIGHT (ic) = IC_LEFT (ic);
5652 if (ifx && /* !AOP_SIZE(result) */
5653 OP_SYMBOL (result) &&
5654 OP_SYMBOL (result)->regType == REG_CND)
5657 /* if they are both bit variables */
5658 if (AOP_TYPE (left) == AOP_CRY &&
5659 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5661 if (AOP_TYPE (right) == AOP_LIT)
5663 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5666 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5667 emitcode ("cpl", "c");
5671 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5675 emitcode ("clr", "c");
5677 /* AOP_TYPE(right) == AOP_CRY */
5681 symbol *lbl = newiTempLabel (NULL);
5682 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5683 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5684 emitcode ("cpl", "c");
5685 emitcode ("", "!tlabeldef", (lbl->key + 100));
5687 /* if true label then we jump if condition
5689 tlbl = newiTempLabel (NULL);
5692 emitcode ("jnc", "!tlabel", tlbl->key + 100);
5693 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5697 emitcode ("jc", "!tlabel", tlbl->key + 100);
5698 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5700 emitcode ("", "!tlabeldef", tlbl->key + 100);
5704 tlbl = newiTempLabel (NULL);
5705 gencjneshort (left, right, tlbl);
5708 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5709 emitcode ("", "!tlabeldef", tlbl->key + 100);
5713 symbol *lbl = newiTempLabel (NULL);
5714 emitcode ("sjmp", "!tlabel", lbl->key + 100);
5715 emitcode ("", "!tlabeldef", tlbl->key + 100);
5716 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5717 emitcode ("", "!tlabeldef", lbl->key + 100);
5720 /* mark the icode as generated */
5723 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5724 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5728 /* if they are both bit variables */
5729 if (AOP_TYPE (left) == AOP_CRY &&
5730 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5732 if (AOP_TYPE (right) == AOP_LIT)
5734 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5737 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5738 emitcode ("cpl", "c");
5742 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5746 emitcode ("clr", "c");
5748 /* AOP_TYPE(right) == AOP_CRY */
5752 symbol *lbl = newiTempLabel (NULL);
5753 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5754 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5755 emitcode ("cpl", "c");
5756 emitcode ("", "!tlabeldef", (lbl->key + 100));
5759 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5760 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5762 aopOp (result, ic, TRUE, FALSE);
5765 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5772 genIfxJump (ifx, "c");
5775 /* if the result is used in an arithmetic operation
5776 then put the result in place */
5781 gencjne (left, right, newiTempLabel (NULL));
5783 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5784 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5786 aopOp (result, ic, TRUE, FALSE);
5788 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5790 aopPut (AOP (result), "a", 0);
5795 genIfxJump (ifx, "a");
5798 /* if the result is used in an arithmetic operation
5799 then put the result in place */
5800 if (AOP_TYPE (result) != AOP_CRY)
5802 /* leave the result in acc */
5806 freeAsmop (result, NULL, ic, TRUE);
5809 /*-----------------------------------------------------------------*/
5810 /* ifxForOp - returns the icode containing the ifx for operand */
5811 /*-----------------------------------------------------------------*/
5813 ifxForOp (operand * op, iCode * ic)
5815 /* if true symbol then needs to be assigned */
5816 if (IS_TRUE_SYMOP (op))
5819 /* if this has register type condition and
5820 the next instruction is ifx with the same operand
5821 and live to of the operand is upto the ifx only then */
5823 ic->next->op == IFX &&
5824 IC_COND (ic->next)->key == op->key &&
5825 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5830 /*-----------------------------------------------------------------*/
5831 /* hasInc - operand is incremented before any other use */
5832 /*-----------------------------------------------------------------*/
5834 hasInc (operand *op, iCode *ic, int osize)
5836 sym_link *type = operandType(op);
5837 sym_link *retype = getSpec (type);
5838 iCode *lic = ic->next;
5841 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5842 if (!IS_SYMOP(op)) return NULL;
5844 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5845 if (IS_AGGREGATE(type->next)) return NULL;
5846 if (osize != (isize = getSize(type->next))) return NULL;
5849 /* if operand of the form op = op + <sizeof *op> */
5850 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5851 isOperandEqual(IC_RESULT(lic),op) &&
5852 isOperandLiteral(IC_RIGHT(lic)) &&
5853 operandLitValue(IC_RIGHT(lic)) == isize) {
5856 /* if the operand used or deffed */
5857 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5860 /* if GOTO or IFX */
5861 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5867 /*-----------------------------------------------------------------*/
5868 /* genAndOp - for && operation */
5869 /*-----------------------------------------------------------------*/
5871 genAndOp (iCode * ic)
5873 operand *left, *right, *result;
5876 D (emitcode (";", "genAndOp "););
5878 /* note here that && operations that are in an
5879 if statement are taken away by backPatchLabels
5880 only those used in arthmetic operations remain */
5882 AOP_SET_LOCALS (ic);
5884 /* if both are bit variables */
5885 if (AOP_TYPE (left) == AOP_CRY &&
5886 AOP_TYPE (right) == AOP_CRY)
5888 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5889 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5890 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5891 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5893 aopOp (result,ic,FALSE, FALSE);
5898 tlbl = newiTempLabel (NULL);
5900 emitcode ("jz", "!tlabel", tlbl->key + 100);
5902 emitcode ("", "!tlabeldef", tlbl->key + 100);
5903 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5904 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5906 aopOp (result,ic,FALSE, FALSE);
5909 freeAsmop (result, NULL, ic, TRUE);
5913 /*-----------------------------------------------------------------*/
5914 /* genOrOp - for || operation */
5915 /*-----------------------------------------------------------------*/
5917 genOrOp (iCode * ic)
5919 operand *left, *right, *result;
5922 D (emitcode (";", "genOrOp "););
5924 /* note here that || operations that are in an
5925 if statement are taken away by backPatchLabels
5926 only those used in arthmetic operations remain */
5928 AOP_SET_LOCALS (ic);
5930 /* if both are bit variables */
5931 if (AOP_TYPE (left) == AOP_CRY &&
5932 AOP_TYPE (right) == AOP_CRY)
5934 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5935 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5936 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5937 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5939 aopOp (result,ic,FALSE, FALSE);
5945 tlbl = newiTempLabel (NULL);
5947 emitcode ("jnz", "!tlabel", tlbl->key + 100);
5949 emitcode ("", "!tlabeldef", tlbl->key + 100);
5950 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5951 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5953 aopOp (result,ic,FALSE, FALSE);
5958 freeAsmop (result, NULL, ic, TRUE);
5961 /*-----------------------------------------------------------------*/
5962 /* isLiteralBit - test if lit == 2^n */
5963 /*-----------------------------------------------------------------*/
5965 isLiteralBit (unsigned long lit)
5967 unsigned long pw[32] =
5968 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5969 0x100L, 0x200L, 0x400L, 0x800L,
5970 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5971 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5972 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5973 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5974 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5977 for (idx = 0; idx < 32; idx++)
5983 /*-----------------------------------------------------------------*/
5984 /* continueIfTrue - */
5985 /*-----------------------------------------------------------------*/
5987 continueIfTrue (iCode * ic)
5990 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
5994 /*-----------------------------------------------------------------*/
5996 /*-----------------------------------------------------------------*/
5998 jumpIfTrue (iCode * ic)
6001 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6005 /*-----------------------------------------------------------------*/
6006 /* jmpTrueOrFalse - */
6007 /*-----------------------------------------------------------------*/
6009 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6011 // ugly but optimized by peephole
6014 symbol *nlbl = newiTempLabel (NULL);
6015 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6016 emitcode ("", "!tlabeldef", tlbl->key + 100);
6017 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6018 emitcode ("", "!tlabeldef", nlbl->key + 100);
6022 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6023 emitcode ("", "!tlabeldef", tlbl->key + 100);
6028 // Generate code to perform a bit-wise logic operation
6029 // on two operands in far space (assumed to already have been
6030 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6031 // in far space. This requires pushing the result on the stack
6032 // then popping it into the result.
6034 genFarFarLogicOp(iCode *ic, char *logicOp)
6036 int size, resultSize, compSize;
6040 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6041 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
6042 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6044 _startLazyDPSEvaluation();
6045 for (size = compSize; (size--); offset++)
6047 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
6048 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6049 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
6051 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6052 emitcode ("push", "acc");
6054 _endLazyDPSEvaluation();
6056 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6057 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6058 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6060 resultSize = AOP_SIZE(IC_RESULT(ic));
6062 ADJUST_PUSHED_RESULT(compSize, resultSize);
6064 _startLazyDPSEvaluation();
6067 emitcode ("pop", "acc");
6068 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6070 _endLazyDPSEvaluation();
6071 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6075 /*-----------------------------------------------------------------*/
6076 /* genAnd - code for and */
6077 /*-----------------------------------------------------------------*/
6079 genAnd (iCode * ic, iCode * ifx)
6081 operand *left, *right, *result;
6082 int size, offset = 0;
6083 unsigned long lit = 0L;
6088 D (emitcode (";", "genAnd "););
6090 AOP_OP_3_NOFATAL (ic, pushResult);
6091 AOP_SET_LOCALS (ic);
6095 genFarFarLogicOp(ic, "anl");
6100 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6102 AOP_TYPE (left), AOP_TYPE (right));
6103 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6105 AOP_SIZE (left), AOP_SIZE (right));
6108 /* if left is a literal & right is not then exchange them */
6109 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6110 #ifdef LOGIC_OPS_BROKEN
6111 || AOP_NEEDSACC (left)
6115 operand *tmp = right;
6120 /* if result = right then exchange them */
6121 if (sameRegs (AOP (result), AOP (right)))
6123 operand *tmp = right;
6128 /* if right is bit then exchange them */
6129 if (AOP_TYPE (right) == AOP_CRY &&
6130 AOP_TYPE (left) != AOP_CRY)
6132 operand *tmp = right;
6136 if (AOP_TYPE (right) == AOP_LIT)
6137 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6139 size = AOP_SIZE (result);
6142 // result = bit & yy;
6143 if (AOP_TYPE (left) == AOP_CRY)
6145 // c = bit & literal;
6146 if (AOP_TYPE (right) == AOP_LIT)
6150 if (size && sameRegs (AOP (result), AOP (left)))
6153 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6158 if (size && (AOP_TYPE (result) == AOP_CRY))
6160 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6163 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6168 emitcode ("clr", "c");
6173 if (AOP_TYPE (right) == AOP_CRY)
6176 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6177 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6182 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
6184 emitcode ("rrc", "a");
6185 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6193 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6194 genIfxJump (ifx, "c");
6198 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6199 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6200 if ((AOP_TYPE (right) == AOP_LIT) &&
6201 (AOP_TYPE (result) == AOP_CRY) &&
6202 (AOP_TYPE (left) != AOP_CRY))
6204 int posbit = isLiteralBit (lit);
6209 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
6212 emitcode ("mov", "c,acc.%d", posbit & 0x07);
6218 SNPRINTF (buff, sizeof(buff),
6219 "acc.%d", posbit & 0x07);
6220 genIfxJump (ifx, buff);
6224 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6231 symbol *tlbl = newiTempLabel (NULL);
6232 int sizel = AOP_SIZE (left);
6234 emitcode ("setb", "c");
6237 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6239 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6241 if ((posbit = isLiteralBit (bytelit)) != 0)
6242 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6245 if (bytelit != 0x0FFL)
6246 emitcode ("anl", "a,%s",
6247 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
6248 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6253 // bit = left & literal
6256 emitcode ("clr", "c");
6257 emitcode ("", "!tlabeldef", tlbl->key + 100);
6259 // if(left & literal)
6263 jmpTrueOrFalse (ifx, tlbl);
6271 /* if left is same as result */
6272 if (sameRegs (AOP (result), AOP (left)))
6274 for (; size--; offset++)
6276 if (AOP_TYPE (right) == AOP_LIT)
6278 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6280 else if (bytelit == 0)
6281 aopPut (AOP (result), zero, offset);
6282 else if (IS_AOP_PREG (result))
6284 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6285 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6286 aopPut (AOP (result), "a", offset);
6289 emitcode ("anl", "%s,%s",
6290 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6291 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6295 if (AOP_TYPE (left) == AOP_ACC)
6296 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6299 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6300 if (IS_AOP_PREG (result))
6302 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6303 aopPut (AOP (result), "a", offset);
6307 emitcode ("anl", "%s,a",
6308 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6315 // left & result in different registers
6316 if (AOP_TYPE (result) == AOP_CRY)
6319 // if(size), result in bit
6320 // if(!size && ifx), conditional oper: if(left & right)
6321 symbol *tlbl = newiTempLabel (NULL);
6322 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6324 emitcode ("setb", "c");
6327 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6328 emitcode ("anl", "a,%s",
6329 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6331 if (AOP_TYPE(left)==AOP_ACC) {
6332 emitcode("mov", "b,a");
6333 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6334 emitcode("anl", "a,b");
6336 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6337 emitcode ("anl", "a,%s",
6338 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6341 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6347 emitcode ("", "!tlabeldef", tlbl->key + 100);
6351 jmpTrueOrFalse (ifx, tlbl);
6355 for (; (size--); offset++)
6358 // result = left & right
6359 if (AOP_TYPE (right) == AOP_LIT)
6361 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6363 aopPut (AOP (result),
6364 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6368 else if (bytelit == 0)
6370 aopPut (AOP (result), zero, offset);
6373 D (emitcode (";", "better literal AND."););
6374 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6375 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6376 FALSE, FALSE, FALSE));
6381 // faster than result <- left, anl result,right
6382 // and better if result is SFR
6383 if (AOP_TYPE (left) == AOP_ACC)
6385 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
6386 FALSE, FALSE, FALSE));
6390 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6391 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6393 emitcode("mov", "b,a");
6397 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6398 emitcode ("anl", "a,%s", rOp);
6401 aopPut (AOP (result), "a", offset);
6407 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6408 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6409 freeAsmop (result, NULL, ic, TRUE);
6413 /*-----------------------------------------------------------------*/
6414 /* genOr - code for or */
6415 /*-----------------------------------------------------------------*/
6417 genOr (iCode * ic, iCode * ifx)
6419 operand *left, *right, *result;
6420 int size, offset = 0;
6421 unsigned long lit = 0L;
6424 D (emitcode (";", "genOr "););
6426 AOP_OP_3_NOFATAL (ic, pushResult);
6427 AOP_SET_LOCALS (ic);
6431 genFarFarLogicOp(ic, "orl");
6437 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6439 AOP_TYPE (left), AOP_TYPE (right));
6440 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6442 AOP_SIZE (left), AOP_SIZE (right));
6445 /* if left is a literal & right is not then exchange them */
6446 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6447 #ifdef LOGIC_OPS_BROKEN
6448 || AOP_NEEDSACC (left) // I think this is a net loss now.
6452 operand *tmp = right;
6457 /* if result = right then exchange them */
6458 if (sameRegs (AOP (result), AOP (right)))
6460 operand *tmp = right;
6465 /* if right is bit then exchange them */
6466 if (AOP_TYPE (right) == AOP_CRY &&
6467 AOP_TYPE (left) != AOP_CRY)
6469 operand *tmp = right;
6473 if (AOP_TYPE (right) == AOP_LIT)
6474 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6476 size = AOP_SIZE (result);
6480 if (AOP_TYPE (left) == AOP_CRY)
6482 if (AOP_TYPE (right) == AOP_LIT)
6484 // c = bit & literal;
6487 // lit != 0 => result = 1
6488 if (AOP_TYPE (result) == AOP_CRY)
6491 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6493 continueIfTrue (ifx);
6496 emitcode ("setb", "c");
6500 // lit == 0 => result = left
6501 if (size && sameRegs (AOP (result), AOP (left)))
6503 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6508 if (AOP_TYPE (right) == AOP_CRY)
6511 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6512 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6517 symbol *tlbl = newiTempLabel (NULL);
6518 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6519 emitcode ("setb", "c");
6520 emitcode ("jb", "%s,!tlabel",
6521 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6523 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6524 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6526 jmpTrueOrFalse (ifx, tlbl);
6532 emitcode ("", "!tlabeldef", tlbl->key + 100);
6541 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6542 genIfxJump (ifx, "c");
6546 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6547 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6548 if ((AOP_TYPE (right) == AOP_LIT) &&
6549 (AOP_TYPE (result) == AOP_CRY) &&
6550 (AOP_TYPE (left) != AOP_CRY))
6556 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6558 continueIfTrue (ifx);
6563 // lit = 0, result = boolean(left)
6565 emitcode ("setb", "c");
6569 symbol *tlbl = newiTempLabel (NULL);
6570 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6572 emitcode ("", "!tlabeldef", tlbl->key + 100);
6576 genIfxJump (ifx, "a");
6584 /* if left is same as result */
6585 if (sameRegs (AOP (result), AOP (left)))
6587 for (; size--; offset++)
6589 if (AOP_TYPE (right) == AOP_LIT)
6591 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6597 if (IS_AOP_PREG (left))
6599 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6600 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6601 aopPut (AOP (result), "a", offset);
6605 emitcode ("orl", "%s,%s",
6606 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6607 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6613 if (AOP_TYPE (left) == AOP_ACC)
6615 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6619 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6620 if (IS_AOP_PREG (left))
6622 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6623 aopPut (AOP (result), "a", offset);
6627 emitcode ("orl", "%s,a",
6628 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6636 // left & result in different registers
6637 if (AOP_TYPE (result) == AOP_CRY)
6640 // if(size), result in bit
6641 // if(!size && ifx), conditional oper: if(left | right)
6642 symbol *tlbl = newiTempLabel (NULL);
6643 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6645 emitcode ("setb", "c");
6648 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6649 emitcode ("orl", "a,%s",
6650 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6652 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6653 emitcode ("orl", "a,%s",
6654 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6656 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6662 emitcode ("", "!tlabeldef", tlbl->key + 100);
6666 jmpTrueOrFalse (ifx, tlbl);
6670 _startLazyDPSEvaluation();
6671 for (; (size--); offset++)
6674 // result = left & right
6675 if (AOP_TYPE (right) == AOP_LIT)
6677 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6679 aopPut (AOP (result),
6680 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6684 D (emitcode (";", "better literal OR."););
6685 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6686 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
6687 FALSE, FALSE, FALSE));
6692 // faster than result <- left, anl result,right
6693 // and better if result is SFR
6694 if (AOP_TYPE (left) == AOP_ACC)
6696 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
6697 FALSE, FALSE, FALSE));
6701 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6703 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6705 emitcode("mov", "b,a");
6709 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6710 emitcode ("orl", "a,%s", rOp);
6713 aopPut (AOP (result), "a", offset);
6715 _endLazyDPSEvaluation();
6720 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6721 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6722 freeAsmop (result, NULL, ic, TRUE);
6725 /*-----------------------------------------------------------------*/
6726 /* genXor - code for xclusive or */
6727 /*-----------------------------------------------------------------*/
6729 genXor (iCode * ic, iCode * ifx)
6731 operand *left, *right, *result;
6732 int size, offset = 0;
6733 unsigned long lit = 0L;
6736 D (emitcode (";", "genXor "););
6738 AOP_OP_3_NOFATAL (ic, pushResult);
6739 AOP_SET_LOCALS (ic);
6743 genFarFarLogicOp(ic, "xrl");
6748 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6750 AOP_TYPE (left), AOP_TYPE (right));
6751 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6753 AOP_SIZE (left), AOP_SIZE (right));
6756 /* if left is a literal & right is not ||
6757 if left needs acc & right does not */
6758 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6759 #ifdef LOGIC_OPS_BROKEN
6760 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6764 operand *tmp = right;
6769 /* if result = right then exchange them */
6770 if (sameRegs (AOP (result), AOP (right)))
6772 operand *tmp = right;
6777 /* if right is bit then exchange them */
6778 if (AOP_TYPE (right) == AOP_CRY &&
6779 AOP_TYPE (left) != AOP_CRY)
6781 operand *tmp = right;
6785 if (AOP_TYPE (right) == AOP_LIT)
6786 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6788 size = AOP_SIZE (result);
6792 if (AOP_TYPE (left) == AOP_CRY)
6794 if (AOP_TYPE (right) == AOP_LIT)
6796 // c = bit & literal;
6799 // lit>>1 != 0 => result = 1
6800 if (AOP_TYPE (result) == AOP_CRY)
6803 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6805 continueIfTrue (ifx);
6808 emitcode ("setb", "c");
6815 // lit == 0, result = left
6816 if (size && sameRegs (AOP (result), AOP (left)))
6818 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6822 // lit == 1, result = not(left)
6823 if (size && sameRegs (AOP (result), AOP (left)))
6825 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6830 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6831 emitcode ("cpl", "c");
6840 symbol *tlbl = newiTempLabel (NULL);
6841 if (AOP_TYPE (right) == AOP_CRY)
6844 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6848 int sizer = AOP_SIZE (right);
6850 // if val>>1 != 0, result = 1
6851 emitcode ("setb", "c");
6854 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
6856 // test the msb of the lsb
6857 emitcode ("anl", "a,#!constbyte",0xfe);
6858 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6862 emitcode ("rrc", "a");
6864 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6865 emitcode ("cpl", "c");
6866 emitcode ("", "!tlabeldef", (tlbl->key + 100));
6873 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6874 genIfxJump (ifx, "c");
6878 if (sameRegs (AOP (result), AOP (left)))
6880 /* if left is same as result */
6881 for (; size--; offset++)
6883 if (AOP_TYPE (right) == AOP_LIT)
6885 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6887 else if (IS_AOP_PREG (left))
6889 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6890 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6891 aopPut (AOP (result), "a", offset);
6894 emitcode ("xrl", "%s,%s",
6895 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6896 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6900 if (AOP_TYPE (left) == AOP_ACC)
6901 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6904 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6905 if (IS_AOP_PREG (left))
6907 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6908 aopPut (AOP (result), "a", offset);
6911 emitcode ("xrl", "%s,a",
6912 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6919 // left & result in different registers
6920 if (AOP_TYPE (result) == AOP_CRY)
6923 // if(size), result in bit
6924 // if(!size && ifx), conditional oper: if(left ^ right)
6925 symbol *tlbl = newiTempLabel (NULL);
6926 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6929 emitcode ("setb", "c");
6932 if ((AOP_TYPE (right) == AOP_LIT) &&
6933 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6935 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6939 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6940 emitcode ("xrl", "a,%s",
6941 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6943 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6944 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6946 emitcode("mov", "b,a");
6950 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6951 emitcode ("xrl", "a,%s", rOp);
6954 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6960 emitcode ("", "!tlabeldef", tlbl->key + 100);
6964 jmpTrueOrFalse (ifx, tlbl);
6968 for (; (size--); offset++)
6971 // result = left & right
6972 if (AOP_TYPE (right) == AOP_LIT)
6974 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6976 aopPut (AOP (result),
6977 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6981 D (emitcode (";", "better literal XOR."););
6982 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6983 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
6984 FALSE, FALSE, FALSE));
6988 // faster than result <- left, anl result,right
6989 // and better if result is SFR
6990 if (AOP_TYPE (left) == AOP_ACC)
6992 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
6993 FALSE, FALSE, FALSE));
6997 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6998 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7000 emitcode("mov", "b,a");
7004 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
7005 emitcode ("xrl", "a,%s", rOp);
7008 aopPut (AOP (result), "a", offset);
7015 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7016 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7017 freeAsmop (result, NULL, ic, TRUE);
7020 /*-----------------------------------------------------------------*/
7021 /* genInline - write the inline code out */
7022 /*-----------------------------------------------------------------*/
7024 genInline (iCode * ic)
7026 char *buffer, *bp, *bp1;
7028 D (emitcode (";", "genInline "); );
7030 _G.inLine += (!options.asmpeep);
7032 buffer = Safe_strdup(IC_INLINE(ic));
7036 /* emit each line as a code */
7061 /* emitcode("",buffer); */
7062 _G.inLine -= (!options.asmpeep);
7065 /*-----------------------------------------------------------------*/
7066 /* genRRC - rotate right with carry */
7067 /*-----------------------------------------------------------------*/
7071 operand *left, *result;
7072 int size, offset = 0;
7075 D (emitcode (";", "genRRC ");
7078 /* rotate right with carry */
7079 left = IC_LEFT (ic);
7080 result = IC_RESULT (ic);
7081 aopOp (left, ic, FALSE, FALSE);
7082 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7084 /* move it to the result */
7085 size = AOP_SIZE (result);
7089 _startLazyDPSEvaluation ();
7092 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
7094 emitcode ("rrc", "a");
7095 if (AOP_SIZE (result) > 1)
7096 aopPut (AOP (result), "a", offset--);
7098 _endLazyDPSEvaluation ();
7100 /* now we need to put the carry into the
7101 highest order byte of the result */
7102 if (AOP_SIZE (result) > 1)
7104 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
7107 emitcode ("mov", "acc.7,c");
7108 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7109 freeAsmop (left, NULL, ic, TRUE);
7110 freeAsmop (result, NULL, ic, TRUE);
7113 /*-----------------------------------------------------------------*/
7114 /* genRLC - generate code for rotate left with carry */
7115 /*-----------------------------------------------------------------*/
7119 operand *left, *result;
7120 int size, offset = 0;
7123 D (emitcode (";", "genRLC ");
7126 /* rotate right with carry */
7127 left = IC_LEFT (ic);
7128 result = IC_RESULT (ic);
7129 aopOp (left, ic, FALSE, FALSE);
7130 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7132 /* move it to the result */
7133 size = AOP_SIZE (result);
7137 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
7139 emitcode ("add", "a,acc");
7140 if (AOP_SIZE (result) > 1)
7142 aopPut (AOP (result), "a", offset++);
7145 _startLazyDPSEvaluation ();
7148 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
7150 emitcode ("rlc", "a");
7151 if (AOP_SIZE (result) > 1)
7152 aopPut (AOP (result), "a", offset++);
7154 _endLazyDPSEvaluation ();
7156 /* now we need to put the carry into the
7157 highest order byte of the result */
7158 if (AOP_SIZE (result) > 1)
7160 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
7163 emitcode ("mov", "acc.0,c");
7164 aopPut (AOP (result), "a", 0);
7165 freeAsmop (left, NULL, ic, TRUE);
7166 freeAsmop (result, NULL, ic, TRUE);
7169 /*-----------------------------------------------------------------*/
7170 /* genGetHbit - generates code get highest order bit */
7171 /*-----------------------------------------------------------------*/
7173 genGetHbit (iCode * ic)
7175 operand *left, *result;
7176 left = IC_LEFT (ic);
7177 result = IC_RESULT (ic);
7178 aopOp (left, ic, FALSE, FALSE);
7179 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7181 D (emitcode (";", "genGetHbit ");
7184 /* get the highest order byte into a */
7185 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
7186 if (AOP_TYPE (result) == AOP_CRY)
7188 emitcode ("rlc", "a");
7193 emitcode ("rl", "a");
7194 emitcode ("anl", "a,#1");
7199 freeAsmop (left, NULL, ic, TRUE);
7200 freeAsmop (result, NULL, ic, TRUE);
7203 /*-----------------------------------------------------------------*/
7204 /* AccRol - rotate left accumulator by known count */
7205 /*-----------------------------------------------------------------*/
7207 AccRol (int shCount)
7209 shCount &= 0x0007; // shCount : 0..7
7216 emitcode ("rl", "a");
7219 emitcode ("rl", "a");
7220 emitcode ("rl", "a");
7223 emitcode ("swap", "a");
7224 emitcode ("rr", "a");
7227 emitcode ("swap", "a");
7230 emitcode ("swap", "a");
7231 emitcode ("rl", "a");
7234 emitcode ("rr", "a");
7235 emitcode ("rr", "a");
7238 emitcode ("rr", "a");
7243 /*-----------------------------------------------------------------*/
7244 /* AccLsh - left shift accumulator by known count */
7245 /*-----------------------------------------------------------------*/
7247 AccLsh (int shCount)
7252 emitcode ("add", "a,acc");
7253 else if (shCount == 2)
7255 emitcode ("add", "a,acc");
7256 emitcode ("add", "a,acc");
7260 /* rotate left accumulator */
7262 /* and kill the lower order bits */
7263 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7268 /*-----------------------------------------------------------------*/
7269 /* AccRsh - right shift accumulator by known count */
7270 /*-----------------------------------------------------------------*/
7272 AccRsh (int shCount)
7279 emitcode ("rrc", "a");
7283 /* rotate right accumulator */
7284 AccRol (8 - shCount);
7285 /* and kill the higher order bits */
7286 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7291 #ifdef BETTER_LITERAL_SHIFT
7292 /*-----------------------------------------------------------------*/
7293 /* AccSRsh - signed right shift accumulator by known count */
7294 /*-----------------------------------------------------------------*/
7296 AccSRsh (int shCount)
7303 emitcode ("mov", "c,acc.7");
7304 emitcode ("rrc", "a");
7306 else if (shCount == 2)
7308 emitcode ("mov", "c,acc.7");
7309 emitcode ("rrc", "a");
7310 emitcode ("mov", "c,acc.7");
7311 emitcode ("rrc", "a");
7315 tlbl = newiTempLabel (NULL);
7316 /* rotate right accumulator */
7317 AccRol (8 - shCount);
7318 /* and kill the higher order bits */
7319 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7320 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7321 emitcode ("orl", "a,#!constbyte",
7322 (unsigned char) ~SRMask[shCount]);
7323 emitcode ("", "!tlabeldef", tlbl->key + 100);
7329 #ifdef BETTER_LITERAL_SHIFT
7330 /*-----------------------------------------------------------------*/
7331 /* shiftR1Left2Result - shift right one byte from left to result */
7332 /*-----------------------------------------------------------------*/
7334 shiftR1Left2Result (operand * left, int offl,
7335 operand * result, int offr,
7336 int shCount, int sign)
7338 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7339 /* shift right accumulator */
7344 aopPut (AOP (result), "a", offr);
7348 #ifdef BETTER_LITERAL_SHIFT
7349 /*-----------------------------------------------------------------*/
7350 /* shiftL1Left2Result - shift left one byte from left to result */
7351 /*-----------------------------------------------------------------*/
7353 shiftL1Left2Result (operand * left, int offl,
7354 operand * result, int offr, int shCount)
7356 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7357 /* shift left accumulator */
7359 aopPut (AOP (result), "a", offr);
7363 #ifdef BETTER_LITERAL_SHIFT
7364 /*-----------------------------------------------------------------*/
7365 /* movLeft2Result - move byte from left to result */
7366 /*-----------------------------------------------------------------*/
7368 movLeft2Result (operand * left, int offl,
7369 operand * result, int offr, int sign)
7372 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7374 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
7376 if (*l == '@' && (IS_AOP_PREG (result)))
7378 emitcode ("mov", "a,%s", l);
7379 aopPut (AOP (result), "a", offr);
7385 aopPut (AOP (result), l, offr);
7389 /* MSB sign in acc.7 ! */
7390 if (getDataSize (left) == offl + 1)
7392 emitcode ("mov", "a,%s", l);
7393 aopPut (AOP (result), "a", offr);
7401 #ifdef BETTER_LITERAL_SHIFT
7402 /*-----------------------------------------------------------------*/
7403 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7404 /*-----------------------------------------------------------------*/
7408 emitcode ("rrc", "a");
7409 emitcode ("xch", "a,%s", x);
7410 emitcode ("rrc", "a");
7411 emitcode ("xch", "a,%s", x);
7415 #ifdef BETTER_LITERAL_SHIFT
7417 /*-----------------------------------------------------------------*/
7418 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7419 /*-----------------------------------------------------------------*/
7423 emitcode ("xch", "a,%s", x);
7424 emitcode ("rlc", "a");
7425 emitcode ("xch", "a,%s", x);
7426 emitcode ("rlc", "a");
7430 #ifdef BETTER_LITERAL_SHIFT
7431 /*-----------------------------------------------------------------*/
7432 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7433 /*-----------------------------------------------------------------*/
7437 emitcode ("xch", "a,%s", x);
7438 emitcode ("add", "a,acc");
7439 emitcode ("xch", "a,%s", x);
7440 emitcode ("rlc", "a");
7444 #ifdef BETTER_LITERAL_SHIFT
7445 /*-----------------------------------------------------------------*/
7446 /* AccAXLsh - left shift a:x by known count (0..7) */
7447 /*-----------------------------------------------------------------*/
7449 AccAXLsh (char *x, int shCount)
7464 case 5: // AAAAABBB:CCCCCDDD
7466 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7468 emitcode ("anl", "a,#!constbyte",
7469 SLMask[shCount]); // BBB00000:CCCCCDDD
7471 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7473 AccRol (shCount); // DDDCCCCC:BBB00000
7475 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7477 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7479 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7481 emitcode ("anl", "a,#!constbyte",
7482 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7484 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7486 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7489 case 6: // AAAAAABB:CCCCCCDD
7490 emitcode ("anl", "a,#!constbyte",
7491 SRMask[shCount]); // 000000BB:CCCCCCDD
7492 emitcode ("mov", "c,acc.0"); // c = B
7493 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7495 AccAXRrl1 (x); // BCCCCCCD:D000000B
7496 AccAXRrl1 (x); // BBCCCCCC:DD000000
7498 emitcode("rrc","a");
7499 emitcode("xch","a,%s", x);
7500 emitcode("rrc","a");
7501 emitcode("mov","c,acc.0"); //<< get correct bit
7502 emitcode("xch","a,%s", x);
7504 emitcode("rrc","a");
7505 emitcode("xch","a,%s", x);
7506 emitcode("rrc","a");
7507 emitcode("xch","a,%s", x);
7510 case 7: // a:x <<= 7
7512 emitcode ("anl", "a,#!constbyte",
7513 SRMask[shCount]); // 0000000B:CCCCCCCD
7515 emitcode ("mov", "c,acc.0"); // c = B
7517 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7519 AccAXRrl1 (x); // BCCCCCCC:D0000000
7528 #ifdef BETTER_LITERAL_SHIFT
7530 /*-----------------------------------------------------------------*/
7531 /* AccAXRsh - right shift a:x known count (0..7) */
7532 /*-----------------------------------------------------------------*/
7534 AccAXRsh (char *x, int shCount)
7542 AccAXRrl1 (x); // 0->a:x
7547 AccAXRrl1 (x); // 0->a:x
7550 AccAXRrl1 (x); // 0->a:x
7555 case 5: // AAAAABBB:CCCCCDDD = a:x
7557 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7559 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7561 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7563 emitcode ("anl", "a,#!constbyte",
7564 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7566 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7568 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7570 emitcode ("anl", "a,#!constbyte",
7571 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7573 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7575 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7577 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7580 case 6: // AABBBBBB:CCDDDDDD
7582 emitcode ("mov", "c,acc.7");
7583 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7585 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7587 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7589 emitcode ("anl", "a,#!constbyte",
7590 SRMask[shCount]); // 000000AA:BBBBBBCC
7593 case 7: // ABBBBBBB:CDDDDDDD
7595 emitcode ("mov", "c,acc.7"); // c = A
7597 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7599 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7601 emitcode ("anl", "a,#!constbyte",
7602 SRMask[shCount]); // 0000000A:BBBBBBBC
7611 #ifdef BETTER_LITERAL_SHIFT
7612 /*-----------------------------------------------------------------*/
7613 /* AccAXRshS - right shift signed a:x known count (0..7) */
7614 /*-----------------------------------------------------------------*/
7616 AccAXRshS (char *x, int shCount)
7624 emitcode ("mov", "c,acc.7");
7625 AccAXRrl1 (x); // s->a:x
7629 emitcode ("mov", "c,acc.7");
7630 AccAXRrl1 (x); // s->a:x
7632 emitcode ("mov", "c,acc.7");
7633 AccAXRrl1 (x); // s->a:x
7638 case 5: // AAAAABBB:CCCCCDDD = a:x
7640 tlbl = newiTempLabel (NULL);
7641 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7643 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7645 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7647 emitcode ("anl", "a,#!constbyte",
7648 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7650 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7652 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7654 emitcode ("anl", "a,#!constbyte",
7655 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7657 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7659 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7661 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7663 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7664 emitcode ("orl", "a,#!constbyte",
7665 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7667 emitcode ("", "!tlabeldef", tlbl->key + 100);
7668 break; // SSSSAAAA:BBBCCCCC
7670 case 6: // AABBBBBB:CCDDDDDD
7672 tlbl = newiTempLabel (NULL);
7673 emitcode ("mov", "c,acc.7");
7674 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7676 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7678 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7680 emitcode ("anl", "a,#!constbyte",
7681 SRMask[shCount]); // 000000AA:BBBBBBCC
7683 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7684 emitcode ("orl", "a,#!constbyte",
7685 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7687 emitcode ("", "!tlabeldef", tlbl->key + 100);
7689 case 7: // ABBBBBBB:CDDDDDDD
7691 tlbl = newiTempLabel (NULL);
7692 emitcode ("mov", "c,acc.7"); // c = A
7694 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7696 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7698 emitcode ("anl", "a,#!constbyte",
7699 SRMask[shCount]); // 0000000A:BBBBBBBC
7701 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7702 emitcode ("orl", "a,#!constbyte",
7703 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7705 emitcode ("", "!tlabeldef", tlbl->key + 100);
7713 #ifdef BETTER_LITERAL_SHIFT
7715 _loadLeftIntoAx(char **lsb,
7721 // Get the initial value from left into a pair of registers.
7722 // MSB must be in A, LSB can be any register.
7724 // If the result is held in registers, it is an optimization
7725 // if the LSB can be held in the register which will hold the,
7726 // result LSB since this saves us from having to copy it into
7727 // the result following AccAXLsh.
7729 // If the result is addressed indirectly, this is not a gain.
7730 if (AOP_NEEDSACC(result))
7734 _startLazyDPSEvaluation();
7735 if (AOP_TYPE(left) == AOP_DPTR2)
7738 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
7739 // get LSB in DP2_RESULT_REG.
7740 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
7741 assert(!strcmp(leftByte, DP2_RESULT_REG));
7745 // get LSB into DP2_RESULT_REG
7746 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
7747 if (strcmp(leftByte, DP2_RESULT_REG))
7750 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7753 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
7754 assert(strcmp(leftByte, DP2_RESULT_REG));
7757 _endLazyDPSEvaluation();
7758 *lsb = DP2_RESULT_REG;
7762 if (sameRegs (AOP (result), AOP (left)) &&
7763 ((offl + MSB16) == offr))
7765 /* don't crash result[offr] */
7766 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
7767 emitcode ("xch", "a,%s",
7768 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
7772 movLeft2Result (left, offl, result, offr, 0);
7773 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
7775 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
7776 assert(strcmp(*lsb,"a"));
7781 _storeAxResults(char *lsb,
7785 _startLazyDPSEvaluation();
7786 if (AOP_NEEDSACC(result))
7788 /* We have to explicitly update the result LSB.
7790 emitcode("xch","a,%s", lsb);
7791 aopPut(AOP(result), "a", offr);
7792 emitcode("mov","a,%s", lsb);
7794 if (getDataSize (result) > 1)
7796 aopPut (AOP (result), "a", offr + MSB16);
7798 _endLazyDPSEvaluation();
7801 /*-----------------------------------------------------------------*/
7802 /* shiftL2Left2Result - shift left two bytes from left to result */
7803 /*-----------------------------------------------------------------*/
7805 shiftL2Left2Result (operand * left, int offl,
7806 operand * result, int offr, int shCount)
7810 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7812 AccAXLsh (lsb, shCount);
7814 _storeAxResults(lsb, result, offr);
7818 #ifdef BETTER_LITERAL_SHIFT
7819 /*-----------------------------------------------------------------*/
7820 /* shiftR2Left2Result - shift right two bytes from left to result */
7821 /*-----------------------------------------------------------------*/
7823 shiftR2Left2Result (operand * left, int offl,
7824 operand * result, int offr,
7825 int shCount, int sign)
7829 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7831 /* a:x >> shCount (x = lsb(result)) */
7834 AccAXRshS(lsb, shCount);
7838 AccAXRsh(lsb, shCount);
7841 _storeAxResults(lsb, result, offr);
7847 /*-----------------------------------------------------------------*/
7848 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7849 /*-----------------------------------------------------------------*/
7851 shiftLLeftOrResult (operand * left, int offl,
7852 operand * result, int offr, int shCount)
7854 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7855 /* shift left 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);
7866 /*-----------------------------------------------------------------*/
7867 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7868 /*-----------------------------------------------------------------*/
7870 shiftRLeftOrResult (operand * left, int offl,
7871 operand * result, int offr, int shCount)
7873 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7874 /* shift right accumulator */
7876 /* or with result */
7877 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7878 /* back to result */
7879 aopPut (AOP (result), "a", offr);
7883 #ifdef BETTER_LITERAL_SHIFT
7884 /*-----------------------------------------------------------------*/
7885 /* genlshOne - left shift a one byte quantity by known count */
7886 /*-----------------------------------------------------------------*/
7888 genlshOne (operand * result, operand * left, int shCount)
7890 D (emitcode (";", "genlshOne "););
7891 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7895 #ifdef BETTER_LITERAL_SHIFT
7896 /*-----------------------------------------------------------------*/
7897 /* genlshTwo - left shift two bytes by known amount != 0 */
7898 /*-----------------------------------------------------------------*/
7900 genlshTwo (operand * result, operand * left, int shCount)
7904 D (emitcode (";", "genlshTwo "););
7906 size = getDataSize (result);
7908 /* if shCount >= 8 */
7913 _startLazyDPSEvaluation();
7919 _endLazyDPSEvaluation();
7920 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7921 aopPut (AOP (result), zero, LSB);
7925 movLeft2Result (left, LSB, result, MSB16, 0);
7926 aopPut (AOP (result), zero, LSB);
7927 _endLazyDPSEvaluation();
7932 aopPut (AOP (result), zero, LSB);
7933 _endLazyDPSEvaluation();
7937 /* 1 <= shCount <= 7 */
7942 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7946 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7954 /*-----------------------------------------------------------------*/
7955 /* shiftLLong - shift left one long from left to result */
7956 /* offl = LSB or MSB16 */
7957 /*-----------------------------------------------------------------*/
7959 shiftLLong (operand * left, operand * result, int offr)
7962 int size = AOP_SIZE (result);
7964 if (size >= LSB + offr)
7966 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
7968 emitcode ("add", "a,acc");
7969 if (sameRegs (AOP (left), AOP (result)) &&
7970 size >= MSB16 + offr && offr != LSB)
7971 emitcode ("xch", "a,%s",
7972 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
7974 aopPut (AOP (result), "a", LSB + offr);
7977 if (size >= MSB16 + offr)
7979 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7981 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
7984 emitcode ("rlc", "a");
7985 if (sameRegs (AOP (left), AOP (result)) &&
7986 size >= MSB24 + offr && offr != LSB)
7987 emitcode ("xch", "a,%s",
7988 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
7990 aopPut (AOP (result), "a", MSB16 + offr);
7993 if (size >= MSB24 + offr)
7995 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7997 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
8000 emitcode ("rlc", "a");
8001 if (sameRegs (AOP (left), AOP (result)) &&
8002 size >= MSB32 + offr && offr != LSB)
8003 emitcode ("xch", "a,%s",
8004 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
8006 aopPut (AOP (result), "a", MSB24 + offr);
8009 if (size > MSB32 + offr)
8011 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8013 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
8016 emitcode ("rlc", "a");
8017 aopPut (AOP (result), "a", MSB32 + offr);
8020 aopPut (AOP (result), zero, LSB);
8026 /*-----------------------------------------------------------------*/
8027 /* genlshFour - shift four byte by a known amount != 0 */
8028 /*-----------------------------------------------------------------*/
8030 genlshFour (operand * result, operand * left, int shCount)
8034 D (emitcode (";", "genlshFour ");
8037 size = AOP_SIZE (result);
8039 /* if shifting more that 3 bytes */
8044 /* lowest order of left goes to the highest
8045 order of the destination */
8046 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8048 movLeft2Result (left, LSB, result, MSB32, 0);
8049 aopPut (AOP (result), zero, LSB);
8050 aopPut (AOP (result), zero, MSB16);
8051 aopPut (AOP (result), zero, MSB24);
8055 /* more than two bytes */
8056 else if (shCount >= 16)
8058 /* lower order two bytes goes to higher order two bytes */
8060 /* if some more remaining */
8062 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8065 movLeft2Result (left, MSB16, result, MSB32, 0);
8066 movLeft2Result (left, LSB, result, MSB24, 0);
8068 aopPut (AOP (result), zero, MSB16);
8069 aopPut (AOP (result), zero, LSB);
8073 /* if more than 1 byte */
8074 else if (shCount >= 8)
8076 /* lower order three bytes goes to higher order three bytes */
8081 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8083 movLeft2Result (left, LSB, result, MSB16, 0);
8089 movLeft2Result (left, MSB24, result, MSB32, 0);
8090 movLeft2Result (left, MSB16, result, MSB24, 0);
8091 movLeft2Result (left, LSB, result, MSB16, 0);
8092 aopPut (AOP (result), zero, LSB);
8094 else if (shCount == 1)
8095 shiftLLong (left, result, MSB16);
8098 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8099 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8100 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8101 aopPut (AOP (result), zero, LSB);
8106 /* 1 <= shCount <= 7 */
8107 else if (shCount <= 2)
8109 shiftLLong (left, result, LSB);
8111 shiftLLong (result, result, LSB);
8113 /* 3 <= shCount <= 7, optimize */
8116 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8117 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8118 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8123 #ifdef BETTER_LITERAL_SHIFT
8124 /*-----------------------------------------------------------------*/
8125 /* genLeftShiftLiteral - left shifting by known count */
8126 /*-----------------------------------------------------------------*/
8128 genLeftShiftLiteral (operand * left,
8133 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8136 size = getSize (operandType (result));
8138 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8140 /* We only handle certain easy cases so far. */
8142 && (shCount < (size * 8))
8146 D(emitcode (";", "genLeftShiftLiteral wimping out"););
8150 freeAsmop (right, NULL, ic, TRUE);
8152 aopOp(left, ic, FALSE, FALSE);
8153 aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
8156 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8158 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8159 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8161 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8164 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8166 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8167 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8169 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8175 emitcode ("; shift left ", "result %d, left %d", size,
8179 /* I suppose that the left size >= result size */
8182 _startLazyDPSEvaluation();
8185 movLeft2Result (left, size, result, size, 0);
8187 _endLazyDPSEvaluation();
8189 else if (shCount >= (size * 8))
8191 _startLazyDPSEvaluation();
8194 aopPut (AOP (result), zero, size);
8196 _endLazyDPSEvaluation();
8203 genlshOne (result, left, shCount);
8207 genlshTwo (result, left, shCount);
8211 genlshFour (result, left, shCount);
8215 fprintf(stderr, "*** ack! mystery literal shift!\n");
8219 freeAsmop (left, NULL, ic, TRUE);
8220 freeAsmop (result, NULL, ic, TRUE);
8225 /*-----------------------------------------------------------------*/
8226 /* genLeftShift - generates code for left shifting */
8227 /*-----------------------------------------------------------------*/
8229 genLeftShift (iCode * ic)
8231 operand *left, *right, *result;
8234 symbol *tlbl, *tlbl1;
8236 D (emitcode (";", "genLeftShift "););
8238 right = IC_RIGHT (ic);
8239 left = IC_LEFT (ic);
8240 result = IC_RESULT (ic);
8242 aopOp (right, ic, FALSE, FALSE);
8245 #ifdef BETTER_LITERAL_SHIFT
8246 /* if the shift count is known then do it
8247 as efficiently as possible */
8248 if (AOP_TYPE (right) == AOP_LIT)
8250 if (genLeftShiftLiteral (left, right, result, ic))
8257 /* shift count is unknown then we have to form
8258 a loop get the loop count in B : Note: we take
8259 only the lower order byte since shifting
8260 more that 32 bits make no sense anyway, ( the
8261 largest size of an object can be only 32 bits ) */
8263 if (AOP_TYPE (right) == AOP_LIT)
8265 /* Really should be handled by genLeftShiftLiteral,
8266 * but since I'm too lazy to fix that today, at least we can make
8267 * some small improvement.
8269 emitcode("mov", "b,#!constbyte",
8270 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8274 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8275 emitcode ("inc", "b");
8277 freeAsmop (right, NULL, ic, TRUE);
8278 aopOp (left, ic, FALSE, FALSE);
8279 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8281 /* now move the left to the result if they are not the
8283 if (!sameRegs (AOP (left), AOP (result)) &&
8284 AOP_SIZE (result) > 1)
8287 size = AOP_SIZE (result);
8289 _startLazyDPSEvaluation ();
8292 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8293 if (*l == '@' && (IS_AOP_PREG (result)))
8296 emitcode ("mov", "a,%s", l);
8297 aopPut (AOP (result), "a", offset);
8300 aopPut (AOP (result), l, offset);
8303 _endLazyDPSEvaluation ();
8306 tlbl = newiTempLabel (NULL);
8307 size = AOP_SIZE (result);
8309 tlbl1 = newiTempLabel (NULL);
8311 /* if it is only one byte then */
8314 symbol *tlbl1 = newiTempLabel (NULL);
8316 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8318 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8319 emitcode ("", "!tlabeldef", tlbl->key + 100);
8320 emitcode ("add", "a,acc");
8321 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8322 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8323 aopPut (AOP (result), "a", 0);
8327 reAdjustPreg (AOP (result));
8329 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8330 emitcode ("", "!tlabeldef", tlbl->key + 100);
8331 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8333 emitcode ("add", "a,acc");
8334 aopPut (AOP (result), "a", offset++);
8335 _startLazyDPSEvaluation ();
8338 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8340 emitcode ("rlc", "a");
8341 aopPut (AOP (result), "a", offset++);
8343 _endLazyDPSEvaluation ();
8344 reAdjustPreg (AOP (result));
8346 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8347 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8349 freeAsmop (left, NULL, ic, TRUE);
8350 freeAsmop (result, NULL, ic, TRUE);
8353 #ifdef BETTER_LITERAL_SHIFT
8354 /*-----------------------------------------------------------------*/
8355 /* genrshOne - right shift a one byte quantity by known count */
8356 /*-----------------------------------------------------------------*/
8358 genrshOne (operand * result, operand * left,
8359 int shCount, int sign)
8361 D (emitcode (";", "genrshOne"););
8362 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8366 #ifdef BETTER_LITERAL_SHIFT
8367 /*-----------------------------------------------------------------*/
8368 /* genrshTwo - right shift two bytes by known amount != 0 */
8369 /*-----------------------------------------------------------------*/
8371 genrshTwo (operand * result, operand * left,
8372 int shCount, int sign)
8374 D (emitcode (";", "genrshTwo"););
8376 /* if shCount >= 8 */
8380 _startLazyDPSEvaluation();
8383 shiftR1Left2Result (left, MSB16, result, LSB,
8388 movLeft2Result (left, MSB16, result, LSB, sign);
8390 addSign (result, MSB16, sign);
8391 _endLazyDPSEvaluation();
8394 /* 1 <= shCount <= 7 */
8397 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8404 /*-----------------------------------------------------------------*/
8405 /* shiftRLong - shift right one long from left to result */
8406 /* offl = LSB or MSB16 */
8407 /*-----------------------------------------------------------------*/
8409 shiftRLong (operand * left, int offl,
8410 operand * result, int sign)
8412 int isSameRegs=sameRegs(AOP(left),AOP(result));
8414 if (isSameRegs && offl>1) {
8415 // we are in big trouble, but this shouldn't happen
8416 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8419 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
8424 emitcode ("rlc", "a");
8425 emitcode ("subb", "a,acc");
8426 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
8428 aopPut (AOP(result), zero, MSB32);
8433 emitcode ("clr", "c");
8435 emitcode ("mov", "c,acc.7");
8438 emitcode ("rrc", "a");
8440 if (isSameRegs && offl==MSB16) {
8441 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
8443 aopPut (AOP (result), "a", MSB32);
8444 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
8447 emitcode ("rrc", "a");
8448 if (isSameRegs && offl==1) {
8449 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
8451 aopPut (AOP (result), "a", MSB24);
8452 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
8454 emitcode ("rrc", "a");
8455 aopPut (AOP (result), "a", MSB16 - offl);
8459 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
8460 emitcode ("rrc", "a");
8461 aopPut (AOP (result), "a", LSB);
8468 /*-----------------------------------------------------------------*/
8469 /* genrshFour - shift four byte by a known amount != 0 */
8470 /*-----------------------------------------------------------------*/
8472 genrshFour (operand * result, operand * left,
8473 int shCount, int sign)
8475 D (emitcode (";", "genrshFour");
8478 /* if shifting more that 3 bytes */
8483 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8485 movLeft2Result (left, MSB32, result, LSB, sign);
8486 addSign (result, MSB16, sign);
8488 else if (shCount >= 16)
8492 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8495 movLeft2Result (left, MSB24, result, LSB, 0);
8496 movLeft2Result (left, MSB32, result, MSB16, sign);
8498 addSign (result, MSB24, sign);
8500 else if (shCount >= 8)
8504 shiftRLong (left, MSB16, result, sign);
8505 else if (shCount == 0)
8507 movLeft2Result (left, MSB16, result, LSB, 0);
8508 movLeft2Result (left, MSB24, result, MSB16, 0);
8509 movLeft2Result (left, MSB32, result, MSB24, sign);
8510 addSign (result, MSB32, sign);
8514 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8515 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8516 /* the last shift is signed */
8517 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8518 addSign (result, MSB32, sign);
8522 { /* 1 <= shCount <= 7 */
8525 shiftRLong (left, LSB, result, sign);
8527 shiftRLong (result, LSB, result, sign);
8531 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8532 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8533 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8539 #ifdef BETTER_LITERAL_SHIFT
8540 /*-----------------------------------------------------------------*/
8541 /* genRightShiftLiteral - right shifting by known count */
8542 /*-----------------------------------------------------------------*/
8544 genRightShiftLiteral (operand * left,
8550 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8553 size = getSize (operandType (result));
8555 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8557 /* We only handle certain easy cases so far. */
8559 && (shCount < (size * 8))
8563 D(emitcode (";", "genRightShiftLiteral wimping out"););
8567 freeAsmop (right, NULL, ic, TRUE);
8569 aopOp (left, ic, FALSE, FALSE);
8570 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8573 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8577 /* test the LEFT size !!! */
8579 /* I suppose that the left size >= result size */
8582 size = getDataSize (result);
8583 _startLazyDPSEvaluation();
8586 movLeft2Result (left, size, result, size, 0);
8588 _endLazyDPSEvaluation();
8590 else if (shCount >= (size * 8))
8594 /* get sign in acc.7 */
8595 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
8597 addSign (result, LSB, sign);
8604 genrshOne (result, left, shCount, sign);
8608 genrshTwo (result, left, shCount, sign);
8612 genrshFour (result, left, shCount, sign);
8619 freeAsmop (left, NULL, ic, TRUE);
8620 freeAsmop (result, NULL, ic, TRUE);
8626 /*-----------------------------------------------------------------*/
8627 /* genSignedRightShift - right shift of signed number */
8628 /*-----------------------------------------------------------------*/
8630 genSignedRightShift (iCode * ic)
8632 operand *right, *left, *result;
8635 symbol *tlbl, *tlbl1;
8637 D (emitcode (";", "genSignedRightShift "););
8639 /* we do it the hard way put the shift count in b
8640 and loop thru preserving the sign */
8642 right = IC_RIGHT (ic);
8643 left = IC_LEFT (ic);
8644 result = IC_RESULT (ic);
8646 aopOp (right, ic, FALSE, FALSE);
8648 #ifdef BETTER_LITERAL_SHIFT
8649 if (AOP_TYPE (right) == AOP_LIT)
8651 if (genRightShiftLiteral (left, right, result, ic, 1))
8657 /* shift count is unknown then we have to form
8658 a loop get the loop count in B : Note: we take
8659 only the lower order byte since shifting
8660 more that 32 bits make no sense anyway, ( the
8661 largest size of an object can be only 32 bits ) */
8663 if (AOP_TYPE (right) == AOP_LIT)
8665 /* Really should be handled by genRightShiftLiteral,
8666 * but since I'm too lazy to fix that today, at least we can make
8667 * some small improvement.
8669 emitcode("mov", "b,#!constbyte",
8670 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8674 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8675 emitcode ("inc", "b");
8677 freeAsmop (right, NULL, ic, TRUE);
8678 aopOp (left, ic, FALSE, FALSE);
8679 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8681 /* now move the left to the result if they are not the
8683 if (!sameRegs (AOP (left), AOP (result)) &&
8684 AOP_SIZE (result) > 1)
8687 size = AOP_SIZE (result);
8689 _startLazyDPSEvaluation ();
8692 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8693 if (*l == '@' && IS_AOP_PREG (result))
8696 emitcode ("mov", "a,%s", l);
8697 aopPut (AOP (result), "a", offset);
8700 aopPut (AOP (result), l, offset);
8703 _endLazyDPSEvaluation ();
8706 /* mov the highest order bit to OVR */
8707 tlbl = newiTempLabel (NULL);
8708 tlbl1 = newiTempLabel (NULL);
8710 size = AOP_SIZE (result);
8712 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
8713 emitcode ("rlc", "a");
8714 emitcode ("mov", "ov,c");
8715 /* if it is only one byte then */
8718 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8720 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8721 emitcode ("", "!tlabeldef", tlbl->key + 100);
8722 emitcode ("mov", "c,ov");
8723 emitcode ("rrc", "a");
8724 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8725 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8726 aopPut (AOP (result), "a", 0);
8730 reAdjustPreg (AOP (result));
8731 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8732 emitcode ("", "!tlabeldef", tlbl->key + 100);
8733 emitcode ("mov", "c,ov");
8734 _startLazyDPSEvaluation ();
8737 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8739 emitcode ("rrc", "a");
8740 aopPut (AOP (result), "a", offset--);
8742 _endLazyDPSEvaluation ();
8743 reAdjustPreg (AOP (result));
8744 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8745 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8748 freeAsmop (left, NULL, ic, TRUE);
8749 freeAsmop (result, NULL, ic, TRUE);
8752 /*-----------------------------------------------------------------*/
8753 /* genRightShift - generate code for right shifting */
8754 /*-----------------------------------------------------------------*/
8756 genRightShift (iCode * ic)
8758 operand *right, *left, *result;
8762 symbol *tlbl, *tlbl1;
8764 D (emitcode (";", "genRightShift "););
8766 /* if signed then we do it the hard way preserve the
8767 sign bit moving it inwards */
8768 retype = getSpec (operandType (IC_RESULT (ic)));
8770 if (!SPEC_USIGN (retype))
8772 genSignedRightShift (ic);
8776 /* signed & unsigned types are treated the same : i.e. the
8777 signed is NOT propagated inwards : quoting from the
8778 ANSI - standard : "for E1 >> E2, is equivalent to division
8779 by 2**E2 if unsigned or if it has a non-negative value,
8780 otherwise the result is implementation defined ", MY definition
8781 is that the sign does not get propagated */
8783 right = IC_RIGHT (ic);
8784 left = IC_LEFT (ic);
8785 result = IC_RESULT (ic);
8787 aopOp (right, ic, FALSE, FALSE);
8789 #ifdef BETTER_LITERAL_SHIFT
8790 /* if the shift count is known then do it
8791 as efficiently as possible */
8792 if (AOP_TYPE (right) == AOP_LIT)
8794 if (genRightShiftLiteral (left, right, result, ic, 0))
8801 /* shift count is unknown then we have to form
8802 a loop get the loop count in B : Note: we take
8803 only the lower order byte since shifting
8804 more that 32 bits make no sense anyway, ( the
8805 largest size of an object can be only 32 bits ) */
8807 if (AOP_TYPE (right) == AOP_LIT)
8809 /* Really should be handled by genRightShiftLiteral,
8810 * but since I'm too lazy to fix that today, at least we can make
8811 * some small improvement.
8813 emitcode("mov", "b,#!constbyte",
8814 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8818 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8819 emitcode ("inc", "b");
8821 freeAsmop (right, NULL, ic, TRUE);
8822 aopOp (left, ic, FALSE, FALSE);
8823 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8825 /* now move the left to the result if they are not the
8827 if (!sameRegs (AOP (left), AOP (result)) &&
8828 AOP_SIZE (result) > 1)
8831 size = AOP_SIZE (result);
8833 _startLazyDPSEvaluation ();
8836 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8837 if (*l == '@' && IS_AOP_PREG (result))
8840 emitcode ("mov", "a,%s", l);
8841 aopPut (AOP (result), "a", offset);
8844 aopPut (AOP (result), l, offset);
8847 _endLazyDPSEvaluation ();
8850 tlbl = newiTempLabel (NULL);
8851 tlbl1 = newiTempLabel (NULL);
8852 size = AOP_SIZE (result);
8855 /* if it is only one byte then */
8858 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8860 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8861 emitcode ("", "!tlabeldef", tlbl->key + 100);
8863 emitcode ("rrc", "a");
8864 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8865 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8866 aopPut (AOP (result), "a", 0);
8870 reAdjustPreg (AOP (result));
8871 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8872 emitcode ("", "!tlabeldef", tlbl->key + 100);
8874 _startLazyDPSEvaluation ();
8877 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8879 emitcode ("rrc", "a");
8880 aopPut (AOP (result), "a", offset--);
8882 _endLazyDPSEvaluation ();
8883 reAdjustPreg (AOP (result));
8885 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8886 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8889 freeAsmop (left, NULL, ic, TRUE);
8890 freeAsmop (result, NULL, ic, TRUE);
8893 /*-----------------------------------------------------------------*/
8894 /* genUnpackBits - generates code for unpacking bits */
8895 /*-----------------------------------------------------------------*/
8897 genUnpackBits (operand * result, char *rname, int ptype)
8904 D (emitcode (";", "genUnpackBits ");
8907 etype = getSpec (operandType (result));
8909 /* read the first byte */
8915 emitcode ("mov", "a,@%s", rname);
8919 emitcode ("movx", "a,@%s", rname);
8923 emitcode ("movx", "a,@dptr");
8927 emitcode ("clr", "a");
8928 emitcode ("movc", "a,@a+dptr");
8932 emitcode ("lcall", "__gptrget");
8936 /* if we have bitdisplacement then it fits */
8937 /* into this byte completely or if length is */
8938 /* less than a byte */
8939 if ((shCnt = SPEC_BSTR (etype)) ||
8940 (SPEC_BLEN (etype) <= 8))
8943 /* shift right acc */
8946 emitcode ("anl", "a,#!constbyte",
8947 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8948 aopPut (AOP (result), "a", offset);
8952 /* bit field did not fit in a byte */
8953 rlen = SPEC_BLEN (etype) - 8;
8954 aopPut (AOP (result), "a", offset++);
8963 emitcode ("inc", "%s", rname);
8964 emitcode ("mov", "a,@%s", rname);
8968 emitcode ("inc", "%s", rname);
8969 emitcode ("movx", "a,@%s", rname);
8973 emitcode ("inc", "dptr");
8974 emitcode ("movx", "a,@dptr");
8978 emitcode ("clr", "a");
8979 emitcode ("inc", "dptr");
8980 emitcode ("movc", "a,@a+dptr");
8984 emitcode ("inc", "dptr");
8985 emitcode ("lcall", "__gptrget");
8990 /* if we are done */
8994 aopPut (AOP (result), "a", offset++);
9000 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (rlen));
9001 aopPut (AOP (result), "a", offset);
9008 /*-----------------------------------------------------------------*/
9009 /* genDataPointerGet - generates code when ptr offset is known */
9010 /*-----------------------------------------------------------------*/
9012 genDataPointerGet (operand * left,
9018 int size, offset = 0;
9019 aopOp (result, ic, TRUE, FALSE);
9021 /* get the string representation of the name */
9022 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
9023 size = AOP_SIZE (result);
9024 _startLazyDPSEvaluation ();
9029 SNPRINTF (buff, sizeof(buff),
9030 "(%s + %d)", l + 1, offset);
9034 SNPRINTF (buff, sizeof(buff),
9037 aopPut (AOP (result), buff, offset++);
9039 _endLazyDPSEvaluation ();
9041 freeAsmop (left, NULL, ic, TRUE);
9042 freeAsmop (result, NULL, ic, TRUE);
9045 /*-----------------------------------------------------------------*/
9046 /* genNearPointerGet - emitcode for near pointer fetch */
9047 /*-----------------------------------------------------------------*/
9049 genNearPointerGet (operand * left,
9057 sym_link *rtype, *retype, *letype;
9058 sym_link *ltype = operandType (left);
9061 rtype = operandType (result);
9062 retype = getSpec (rtype);
9063 letype = getSpec (ltype);
9065 aopOp (left, ic, FALSE, FALSE);
9067 /* if left is rematerialisable and
9068 result is not bit variable type and
9069 the left is pointer to data space i.e
9070 lower 128 bytes of space */
9071 if (AOP_TYPE (left) == AOP_IMMD &&
9072 !IS_BITVAR (retype) &&
9073 !IS_BITVAR (letype) &&
9074 DCL_TYPE (ltype) == POINTER)
9076 genDataPointerGet (left, result, ic);
9080 /* if the value is already in a pointer register
9081 then don't need anything more */
9082 if (!AOP_INPREG (AOP (left)))
9084 /* otherwise get a free pointer register */
9086 preg = getFreePtr (ic, &aop, FALSE);
9087 emitcode ("mov", "%s,%s",
9089 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
9093 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
9095 freeAsmop (left, NULL, ic, TRUE);
9096 aopOp (result, ic, FALSE, FALSE);
9098 /* if bitfield then unpack the bits */
9099 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9100 genUnpackBits (result, rname, POINTER);
9103 /* we have can just get the values */
9104 int size = AOP_SIZE (result);
9109 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9112 emitcode ("mov", "a,@%s", rname);
9113 aopPut (AOP (result), "a", offset);
9117 SNPRINTF (buff, sizeof(buff), "@%s", rname);
9118 aopPut (AOP (result), buff, offset);
9123 emitcode ("inc", "%s", rname);
9128 /* now some housekeeping stuff */
9131 /* we had to allocate for this iCode */
9132 if (pi) { /* post increment present */
9133 aopPut(AOP ( left ),rname,0);
9135 freeAsmop (NULL, aop, ic, TRUE);
9139 /* we did not allocate which means left
9140 already in a pointer register, then
9141 if size > 0 && this could be used again
9142 we have to point it back to where it
9144 if (AOP_SIZE (result) > 1 &&
9145 !OP_SYMBOL (left)->remat &&
9146 (OP_SYMBOL (left)->liveTo > ic->seq ||
9150 int size = AOP_SIZE (result) - 1;
9152 emitcode ("dec", "%s", rname);
9157 freeAsmop (result, NULL, ic, TRUE);
9158 if (pi) pi->generated = 1;
9161 /*-----------------------------------------------------------------*/
9162 /* genPagedPointerGet - emitcode for paged pointer fetch */
9163 /*-----------------------------------------------------------------*/
9165 genPagedPointerGet (operand * left,
9173 sym_link *rtype, *retype, *letype;
9175 rtype = operandType (result);
9176 retype = getSpec (rtype);
9177 letype = getSpec (operandType (left));
9178 aopOp (left, ic, FALSE, FALSE);
9180 /* if the value is already in a pointer register
9181 then don't need anything more */
9182 if (!AOP_INPREG (AOP (left)))
9184 /* otherwise get a free pointer register */
9186 preg = getFreePtr (ic, &aop, FALSE);
9187 emitcode ("mov", "%s,%s",
9189 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
9193 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
9195 freeAsmop (left, NULL, ic, TRUE);
9196 aopOp (result, ic, FALSE, FALSE);
9198 /* if bitfield then unpack the bits */
9199 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9200 genUnpackBits (result, rname, PPOINTER);
9203 /* we have can just get the values */
9204 int size = AOP_SIZE (result);
9210 emitcode ("movx", "a,@%s", rname);
9211 aopPut (AOP (result), "a", offset);
9216 emitcode ("inc", "%s", rname);
9220 /* now some housekeeping stuff */
9223 /* we had to allocate for this iCode */
9224 if (pi) aopPut ( AOP (left), rname, 0);
9225 freeAsmop (NULL, aop, ic, TRUE);
9229 /* we did not allocate which means left
9230 already in a pointer register, then
9231 if size > 0 && this could be used again
9232 we have to point it back to where it
9234 if (AOP_SIZE (result) > 1 &&
9235 !OP_SYMBOL (left)->remat &&
9236 (OP_SYMBOL (left)->liveTo > ic->seq ||
9240 int size = AOP_SIZE (result) - 1;
9242 emitcode ("dec", "%s", rname);
9247 freeAsmop (result, NULL, ic, TRUE);
9248 if (pi) pi->generated = 1;
9251 /*-----------------------------------------------------------------*/
9252 /* genFarPointerGet - gget value from far space */
9253 /*-----------------------------------------------------------------*/
9255 genFarPointerGet (operand * left,
9256 operand * result, iCode * ic, iCode *pi)
9258 int size, offset, dopi=1;
9259 sym_link *retype = getSpec (operandType (result));
9260 sym_link *letype = getSpec (operandType (left));
9261 D (emitcode (";", "genFarPointerGet");
9264 aopOp (left, ic, FALSE, FALSE);
9266 /* if the operand is already in dptr
9267 then we do nothing else we move the value to dptr */
9268 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9270 /* if this is remateriazable */
9271 if (AOP_TYPE (left) == AOP_IMMD)
9273 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9277 /* we need to get it byte by byte */
9278 _startLazyDPSEvaluation ();
9279 if (AOP_TYPE (left) != AOP_DPTR)
9281 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9282 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9283 if (options.model == MODEL_FLAT24)
9284 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9288 /* We need to generate a load to DPTR indirect through DPTR. */
9289 D (emitcode (";", "genFarPointerGet -- indirection special case.");
9291 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
9292 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
9293 if (options.model == MODEL_FLAT24)
9294 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9295 emitcode ("pop", "dph");
9296 emitcode ("pop", "dpl");
9299 _endLazyDPSEvaluation ();
9302 /* so dptr know contains the address */
9303 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9305 /* if bit then unpack */
9306 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9307 if (AOP_INDPTRn(left)) {
9308 genSetDPTR(AOP(left)->aopu.dptr);
9310 genUnpackBits (result, "dptr", FPOINTER);
9311 if (AOP_INDPTRn(left)) {
9316 size = AOP_SIZE (result);
9319 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9321 genSetDPTR(AOP(left)->aopu.dptr);
9322 emitcode ("movx", "a,@dptr");
9323 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9324 emitcode ("inc", "dptr");
9326 aopPut (AOP (result), "a", offset++);
9329 _startLazyDPSEvaluation ();
9331 if (AOP_INDPTRn(left)) {
9332 genSetDPTR(AOP(left)->aopu.dptr);
9338 emitcode ("movx", "a,@dptr");
9339 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9340 emitcode ("inc", "dptr");
9342 aopPut (AOP (result), "a", offset++);
9344 _endLazyDPSEvaluation ();
9347 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9348 if (!AOP_INDPTRn(left)) {
9349 aopPut ( AOP (left), "dpl", 0);
9350 aopPut ( AOP (left), "dph", 1);
9351 if (options.model == MODEL_FLAT24)
9352 aopPut ( AOP (left), "dpx", 2);
9355 } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
9356 AOP_SIZE(result) > 1 &&
9357 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9359 size = AOP_SIZE (result) - 1;
9360 if (AOP_INDPTRn(left)) {
9361 genSetDPTR(AOP(left)->aopu.dptr);
9363 while (size--) emitcode ("lcall","__decdptr");
9364 if (AOP_INDPTRn(left)) {
9369 freeAsmop (left, NULL, ic, TRUE);
9370 freeAsmop (result, NULL, ic, TRUE);
9373 /*-----------------------------------------------------------------*/
9374 /* genCodePointerGet - get value from code space */
9375 /*-----------------------------------------------------------------*/
9377 genCodePointerGet (operand * left,
9378 operand * result, iCode * ic, iCode *pi)
9380 int size, offset, dopi=1;
9381 sym_link *retype = getSpec (operandType (result));
9383 aopOp (left, ic, FALSE, FALSE);
9385 /* if the operand is already in dptr
9386 then we do nothing else we move the value to dptr */
9387 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
9389 /* if this is remateriazable */
9390 if (AOP_TYPE (left) == AOP_IMMD)
9392 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9395 { /* we need to get it byte by byte */
9396 _startLazyDPSEvaluation ();
9397 if (AOP_TYPE (left) != AOP_DPTR)
9399 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9400 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9401 if (options.model == MODEL_FLAT24)
9402 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9406 /* We need to generate a load to DPTR indirect through DPTR. */
9407 D (emitcode (";", "gencodePointerGet -- indirection special case.");
9409 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
9410 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
9411 if (options.model == MODEL_FLAT24)
9412 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9413 emitcode ("pop", "dph");
9414 emitcode ("pop", "dpl");
9417 _endLazyDPSEvaluation ();
9420 /* so dptr know contains the address */
9421 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9423 /* if bit then unpack */
9424 if (IS_BITVAR (retype)) {
9425 if (AOP_INDPTRn(left)) {
9426 genSetDPTR(AOP(left)->aopu.dptr);
9428 genUnpackBits (result, "dptr", CPOINTER);
9429 if (AOP_INDPTRn(left)) {
9434 size = AOP_SIZE (result);
9436 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9438 genSetDPTR(AOP(left)->aopu.dptr);
9439 emitcode ("clr", "a");
9440 emitcode ("movc", "a,@a+dptr");
9441 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9442 emitcode ("inc", "dptr");
9444 aopPut (AOP (result), "a", offset++);
9447 _startLazyDPSEvaluation ();
9450 if (AOP_INDPTRn(left)) {
9451 genSetDPTR(AOP(left)->aopu.dptr);
9457 emitcode ("clr", "a");
9458 emitcode ("movc", "a,@a+dptr");
9459 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9460 emitcode ("inc", "dptr");
9461 aopPut (AOP (result), "a", offset++);
9463 _endLazyDPSEvaluation ();
9466 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9467 if (!AOP_INDPTRn(left)) {
9468 aopPut ( AOP (left), "dpl", 0);
9469 aopPut ( AOP (left), "dph", 1);
9470 if (options.model == MODEL_FLAT24)
9471 aopPut ( AOP (left), "dpx", 2);
9474 } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
9475 AOP_SIZE(result) > 1 &&
9476 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9478 size = AOP_SIZE (result) - 1;
9479 if (AOP_INDPTRn(left)) {
9480 genSetDPTR(AOP(left)->aopu.dptr);
9482 while (size--) emitcode ("lcall","__decdptr");
9483 if (AOP_INDPTRn(left)) {
9488 freeAsmop (left, NULL, ic, TRUE);
9489 freeAsmop (result, NULL, ic, TRUE);
9492 /*-----------------------------------------------------------------*/
9493 /* genGenPointerGet - gget value from generic pointer space */
9494 /*-----------------------------------------------------------------*/
9496 genGenPointerGet (operand * left,
9497 operand * result, iCode * ic, iCode * pi)
9500 sym_link *retype = getSpec (operandType (result));
9501 sym_link *letype = getSpec (operandType (left));
9503 D (emitcode (";", "genGenPointerGet "); );
9505 aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
9507 /* if the operand is already in dptr
9508 then we do nothing else we move the value to dptr */
9509 if (AOP_TYPE (left) != AOP_STR)
9511 /* if this is remateriazable */
9512 if (AOP_TYPE (left) == AOP_IMMD)
9514 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9515 if (AOP(left)->aopu.aop_immd.from_cast_remat)
9516 emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, FALSE));
9518 emitcode ("mov", "b,#%d", pointerCode (retype));
9521 { /* we need to get it byte by byte */
9522 _startLazyDPSEvaluation ();
9523 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
9524 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
9525 if (options.model == MODEL_FLAT24) {
9526 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9527 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9529 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9531 _endLazyDPSEvaluation ();
9535 /* so dptr-b now contains the address */
9537 aopOp (result, ic, FALSE, TRUE);
9540 /* if bit then unpack */
9541 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9543 genUnpackBits (result, "dptr", GPOINTER);
9547 size = AOP_SIZE (result);
9554 // Get two bytes at a time, results in _AP & A.
9555 // dptr will be incremented ONCE by __gptrgetWord.
9557 // Note: any change here must be coordinated
9558 // with the implementation of __gptrgetWord
9559 // in device/lib/_gptrget.c
9560 emitcode ("lcall", "__gptrgetWord");
9561 aopPut (AOP (result), DP2_RESULT_REG, offset++);
9562 aopPut (AOP (result), "a", offset++);
9567 // Only one byte to get.
9568 emitcode ("lcall", "__gptrget");
9569 aopPut (AOP (result), "a", offset++);
9572 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9574 emitcode ("inc", "dptr");
9579 if (pi && AOP_TYPE (left) != AOP_IMMD) {
9580 aopPut ( AOP (left), "dpl", 0);
9581 aopPut ( AOP (left), "dph", 1);
9582 if (options.model == MODEL_FLAT24) {
9583 aopPut ( AOP (left), "dpx", 2);
9584 aopPut ( AOP (left), "b", 3);
9585 } else aopPut ( AOP (left), "b", 2);
9587 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9588 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9590 size = AOP_SIZE (result) - 1;
9591 while (size--) emitcode ("lcall","__decdptr");
9594 freeAsmop (left, NULL, ic, TRUE);
9595 freeAsmop (result, NULL, ic, TRUE);
9598 /*-----------------------------------------------------------------*/
9599 /* genPointerGet - generate code for pointer get */
9600 /*-----------------------------------------------------------------*/
9602 genPointerGet (iCode * ic, iCode *pi)
9604 operand *left, *result;
9605 sym_link *type, *etype;
9608 D (emitcode (";", "genPointerGet ");
9611 left = IC_LEFT (ic);
9612 result = IC_RESULT (ic);
9614 /* depending on the type of pointer we need to
9615 move it to the correct pointer register */
9616 type = operandType (left);
9617 etype = getSpec (type);
9618 /* if left is of type of pointer then it is simple */
9619 if (IS_PTR (type) && !IS_FUNC (type->next))
9620 p_type = DCL_TYPE (type);
9623 /* we have to go by the storage class */
9624 p_type = PTR_TYPE (SPEC_OCLS (etype));
9626 /* special case when cast remat */
9627 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9628 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9629 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9630 type = operandType (left);
9631 p_type = DCL_TYPE (type);
9633 /* now that we have the pointer type we assign
9634 the pointer values */
9640 genNearPointerGet (left, result, ic, pi);
9644 genPagedPointerGet (left, result, ic, pi);
9648 genFarPointerGet (left, result, ic, pi);
9652 genCodePointerGet (left, result, ic, pi);
9656 genGenPointerGet (left, result, ic, pi);
9662 /*-----------------------------------------------------------------*/
9663 /* genPackBits - generates code for packed bit storage */
9664 /*-----------------------------------------------------------------*/
9666 genPackBits (sym_link * etype,
9668 char *rname, int p_type)
9676 blen = SPEC_BLEN (etype);
9677 bstr = SPEC_BSTR (etype);
9679 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9682 /* if the bit lenth is less than or */
9683 /* it exactly fits a byte then */
9684 if (SPEC_BLEN (etype) <= 8)
9686 shCount = SPEC_BSTR (etype);
9688 /* shift left acc */
9691 if (SPEC_BLEN (etype) < 8)
9692 { /* if smaller than a byte */
9698 emitcode ("mov", "b,a");
9699 emitcode ("mov", "a,@%s", rname);
9703 emitcode ("mov", "b,a");
9704 emitcode ("movx", "a,@dptr");
9708 emitcode ("push", "b");
9709 emitcode ("push", "acc");
9710 emitcode ("lcall", "__gptrget");
9711 emitcode ("pop", "b");
9715 emitcode ("anl", "a,#!constbyte", (unsigned char)
9716 ((unsigned char) (0xFF << (blen + bstr)) |
9717 (unsigned char) (0xFF >> (8 - bstr))));
9718 emitcode ("orl", "a,b");
9719 if (p_type == GPOINTER)
9720 emitcode ("pop", "b");
9727 emitcode ("mov", "@%s,a", rname);
9731 emitcode ("movx", "@dptr,a");
9735 emitcode ("lcall", "__gptrput");
9740 if (SPEC_BLEN (etype) <= 8)
9743 emitcode ("inc", "%s", rname);
9744 rLen = SPEC_BLEN (etype);
9746 /* now generate for lengths greater than one byte */
9750 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
9762 emitcode ("mov", "@%s,a", rname);
9765 emitcode ("mov", "@%s,%s", rname, l);
9770 emitcode ("movx", "@dptr,a");
9775 emitcode ("lcall", "__gptrput");
9778 emitcode ("inc", "%s", rname);
9783 /* last last was not complete */
9786 /* save the byte & read byte */
9790 emitcode ("mov", "b,a");
9791 emitcode ("mov", "a,@%s", rname);
9795 emitcode ("mov", "b,a");
9796 emitcode ("movx", "a,@dptr");
9800 emitcode ("push", "b");
9801 emitcode ("push", "acc");
9802 emitcode ("lcall", "__gptrget");
9803 emitcode ("pop", "b");
9807 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1 << rLen));
9808 emitcode ("orl", "a,b");
9811 if (p_type == GPOINTER)
9812 emitcode ("pop", "b");
9818 emitcode ("mov", "@%s,a", rname);
9822 emitcode ("movx", "@dptr,a");
9826 emitcode ("lcall", "__gptrput");
9830 /*-----------------------------------------------------------------*/
9831 /* genDataPointerSet - remat pointer to data space */
9832 /*-----------------------------------------------------------------*/
9834 genDataPointerSet (operand * right,
9838 int size, offset = 0;
9841 aopOp (right, ic, FALSE, FALSE);
9843 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
9844 size = AOP_SIZE (right);
9849 SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
9853 SNPRINTF (buff, sizeof(buff), "%s", l + 1);
9856 emitcode ("mov", "%s,%s", buff,
9857 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
9860 freeAsmop (right, NULL, ic, TRUE);
9861 freeAsmop (result, NULL, ic, TRUE);
9864 /*-----------------------------------------------------------------*/
9865 /* genNearPointerSet - emitcode for near pointer put */
9866 /*-----------------------------------------------------------------*/
9868 genNearPointerSet (operand * right,
9876 sym_link *retype, *letype;
9877 sym_link *ptype = operandType (result);
9879 retype = getSpec (operandType (right));
9880 letype = getSpec (ptype);
9882 aopOp (result, ic, FALSE, FALSE);
9884 /* if the result is rematerializable &
9885 in data space & not a bit variable */
9886 if (AOP_TYPE (result) == AOP_IMMD &&
9887 DCL_TYPE (ptype) == POINTER &&
9888 !IS_BITVAR (retype) &&
9889 !IS_BITVAR (letype))
9891 genDataPointerSet (right, result, ic);
9895 /* if the value is already in a pointer register
9896 then don't need anything more */
9897 if (!AOP_INPREG (AOP (result)))
9899 /* otherwise get a free pointer register */
9901 preg = getFreePtr (ic, &aop, FALSE);
9902 emitcode ("mov", "%s,%s",
9904 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9908 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9910 aopOp (right, ic, FALSE, FALSE);
9912 /* if bitfield then unpack the bits */
9913 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9914 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9917 /* we have can just get the values */
9918 int size = AOP_SIZE (right);
9923 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
9927 emitcode ("mov", "@%s,a", rname);
9930 emitcode ("mov", "@%s,%s", rname, l);
9932 emitcode ("inc", "%s", rname);
9937 /* now some housekeeping stuff */
9940 /* we had to allocate for this iCode */
9941 if (pi) aopPut (AOP (result),rname,0);
9942 freeAsmop (NULL, aop, ic, TRUE);
9946 /* we did not allocate which means left
9947 already in a pointer register, then
9948 if size > 0 && this could be used again
9949 we have to point it back to where it
9951 if (AOP_SIZE (right) > 1 &&
9952 !OP_SYMBOL (result)->remat &&
9953 (OP_SYMBOL (result)->liveTo > ic->seq ||
9957 int size = AOP_SIZE (right) - 1;
9959 emitcode ("dec", "%s", rname);
9964 if (pi) pi->generated = 1;
9965 freeAsmop (result, NULL, ic, TRUE);
9966 freeAsmop (right, NULL, ic, TRUE);
9971 /*-----------------------------------------------------------------*/
9972 /* genPagedPointerSet - emitcode for Paged pointer put */
9973 /*-----------------------------------------------------------------*/
9975 genPagedPointerSet (operand * right,
9983 sym_link *retype, *letype;
9985 retype = getSpec (operandType (right));
9986 letype = getSpec (operandType (result));
9988 aopOp (result, ic, FALSE, FALSE);
9990 /* if the value is already in a pointer register
9991 then don't need anything more */
9992 if (!AOP_INPREG (AOP (result)))
9994 /* otherwise get a free pointer register */
9996 preg = getFreePtr (ic, &aop, FALSE);
9997 emitcode ("mov", "%s,%s",
9999 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
10000 rname = preg->name;
10003 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
10005 aopOp (right, ic, FALSE, FALSE);
10007 /* if bitfield then unpack the bits */
10008 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10009 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
10012 /* we have can just get the values */
10013 int size = AOP_SIZE (right);
10018 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
10021 emitcode ("movx", "@%s,a", rname);
10024 emitcode ("inc", "%s", rname);
10030 /* now some housekeeping stuff */
10033 if (pi) aopPut (AOP (result),rname,0);
10034 /* we had to allocate for this iCode */
10035 freeAsmop (NULL, aop, ic, TRUE);
10039 /* we did not allocate which means left
10040 already in a pointer register, then
10041 if size > 0 && this could be used again
10042 we have to point it back to where it
10044 if (AOP_SIZE (right) > 1 &&
10045 !OP_SYMBOL (result)->remat &&
10046 (OP_SYMBOL (result)->liveTo > ic->seq ||
10050 int size = AOP_SIZE (right) - 1;
10052 emitcode ("dec", "%s", rname);
10057 if (pi) pi->generated = 1;
10058 freeAsmop (result, NULL, ic, TRUE);
10059 freeAsmop (right, NULL, ic, TRUE);
10064 /*-----------------------------------------------------------------*/
10065 /* genFarPointerSet - set value from far space */
10066 /*-----------------------------------------------------------------*/
10068 genFarPointerSet (operand * right,
10069 operand * result, iCode * ic, iCode *pi)
10071 int size, offset, dopi=1;
10072 sym_link *retype = getSpec (operandType (right));
10073 sym_link *letype = getSpec (operandType (result));
10075 aopOp (result, ic, FALSE, FALSE);
10077 /* if the operand is already in dptr
10078 then we do nothing else we move the value to dptr */
10079 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10081 /* if this is remateriazable */
10082 if (AOP_TYPE (result) == AOP_IMMD)
10083 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
10086 /* we need to get it byte by byte */
10087 _startLazyDPSEvaluation ();
10088 if (AOP_TYPE (result) != AOP_DPTR)
10090 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
10091 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
10092 if (options.model == MODEL_FLAT24)
10093 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
10097 /* We need to generate a load to DPTR indirect through DPTR. */
10098 D (emitcode (";", "genFarPointerSet -- indirection special case.");
10100 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
10101 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
10102 if (options.model == MODEL_FLAT24)
10103 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
10104 emitcode ("pop", "dph");
10105 emitcode ("pop", "dpl");
10108 _endLazyDPSEvaluation ();
10111 /* so dptr know contains the address */
10112 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10114 /* if bit then unpack */
10115 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
10116 if (AOP_INDPTRn(result)) {
10117 genSetDPTR(AOP(result)->aopu.dptr);
10119 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
10120 if (AOP_INDPTRn(result)) {
10124 size = AOP_SIZE (right);
10126 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10128 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
10131 genSetDPTR(AOP(result)->aopu.dptr);
10132 emitcode ("movx", "@dptr,a");
10133 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10134 emitcode ("inc", "dptr");
10138 _startLazyDPSEvaluation ();
10140 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
10143 if (AOP_INDPTRn(result)) {
10144 genSetDPTR(AOP(result)->aopu.dptr);
10150 emitcode ("movx", "@dptr,a");
10151 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10152 emitcode ("inc", "dptr");
10154 _endLazyDPSEvaluation ();
10158 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10159 if (!AOP_INDPTRn(result)) {
10160 aopPut (AOP(result),"dpl",0);
10161 aopPut (AOP(result),"dph",1);
10162 if (options.model == MODEL_FLAT24)
10163 aopPut (AOP(result),"dpx",2);
10166 } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
10167 AOP_SIZE(right) > 1 &&
10168 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10170 size = AOP_SIZE (right) - 1;
10171 if (AOP_INDPTRn(result)) {
10172 genSetDPTR(AOP(result)->aopu.dptr);
10174 while (size--) emitcode ("lcall","__decdptr");
10175 if (AOP_INDPTRn(result)) {
10179 freeAsmop (result, NULL, ic, TRUE);
10180 freeAsmop (right, NULL, ic, TRUE);
10183 /*-----------------------------------------------------------------*/
10184 /* genGenPointerSet - set value from generic pointer space */
10185 /*-----------------------------------------------------------------*/
10187 genGenPointerSet (operand * right,
10188 operand * result, iCode * ic, iCode *pi)
10191 sym_link *retype = getSpec (operandType (right));
10192 sym_link *letype = getSpec (operandType (result));
10194 aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10196 /* if the operand is already in dptr
10197 then we do nothing else we move the value to dptr */
10198 if (AOP_TYPE (result) != AOP_STR)
10200 _startLazyDPSEvaluation ();
10201 /* if this is remateriazable */
10202 if (AOP_TYPE (result) == AOP_IMMD)
10204 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
10205 if (AOP(result)->aopu.aop_immd.from_cast_remat)
10206 emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, FALSE));
10208 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
10211 { /* we need to get it byte by byte */
10212 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
10213 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
10214 if (options.model == MODEL_FLAT24) {
10215 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
10216 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
10218 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
10221 _endLazyDPSEvaluation ();
10223 /* so dptr know contains the address */
10224 aopOp (right, ic, FALSE, TRUE);
10226 /* if bit then unpack */
10227 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10228 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
10231 size = AOP_SIZE (right);
10234 _startLazyDPSEvaluation ();
10237 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
10243 emitcode ("lcall", "__gptrput");
10244 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10245 emitcode ("inc", "dptr");
10247 _endLazyDPSEvaluation ();
10250 if (pi && AOP_TYPE (result) != AOP_IMMD) {
10251 aopPut (AOP(result),"dpl",0);
10252 aopPut (AOP(result),"dph",1);
10253 if (options.model == MODEL_FLAT24) {
10254 aopPut (AOP(result),"dpx",2);
10255 aopPut (AOP(result),"b",3);
10257 aopPut (AOP(result),"b",2);
10260 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10261 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10263 size = AOP_SIZE (right) - 1;
10264 while (size--) emitcode ("lcall","__decdptr");
10266 freeAsmop (result, NULL, ic, TRUE);
10267 freeAsmop (right, NULL, ic, TRUE);
10270 /*-----------------------------------------------------------------*/
10271 /* genPointerSet - stores the value into a pointer location */
10272 /*-----------------------------------------------------------------*/
10274 genPointerSet (iCode * ic, iCode *pi)
10276 operand *right, *result;
10277 sym_link *type, *etype;
10280 D (emitcode (";", "genPointerSet ");
10283 right = IC_RIGHT (ic);
10284 result = IC_RESULT (ic);
10286 /* depending on the type of pointer we need to
10287 move it to the correct pointer register */
10288 type = operandType (result);
10289 etype = getSpec (type);
10290 /* if left is of type of pointer then it is simple */
10291 if (IS_PTR (type) && !IS_FUNC (type->next))
10293 p_type = DCL_TYPE (type);
10297 /* we have to go by the storage class */
10298 p_type = PTR_TYPE (SPEC_OCLS (etype));
10300 /* special case when cast remat */
10301 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10302 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10303 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10304 type = operandType (result);
10305 p_type = DCL_TYPE (type);
10308 /* now that we have the pointer type we assign
10309 the pointer values */
10315 genNearPointerSet (right, result, ic, pi);
10319 genPagedPointerSet (right, result, ic, pi);
10323 genFarPointerSet (right, result, ic, pi);
10327 genGenPointerSet (right, result, ic, pi);
10331 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10332 "genPointerSet: illegal pointer type");
10337 /*-----------------------------------------------------------------*/
10338 /* genIfx - generate code for Ifx statement */
10339 /*-----------------------------------------------------------------*/
10341 genIfx (iCode * ic, iCode * popIc)
10343 operand *cond = IC_COND (ic);
10346 D (emitcode (";", "genIfx "););
10348 aopOp (cond, ic, FALSE, FALSE);
10350 /* get the value into acc */
10351 if (AOP_TYPE (cond) != AOP_CRY)
10360 /* the result is now in the accumulator */
10361 freeAsmop (cond, NULL, ic, TRUE);
10363 /* if there was something to be popped then do it */
10367 /* if the condition is a bit variable */
10368 if (isbit && IS_ITEMP (cond) &&
10371 genIfxJump (ic, SPIL_LOC (cond)->rname);
10373 else if (isbit && !IS_ITEMP (cond))
10375 genIfxJump (ic, OP_SYMBOL (cond)->rname);
10379 genIfxJump (ic, "a");
10385 /*-----------------------------------------------------------------*/
10386 /* genAddrOf - generates code for address of */
10387 /*-----------------------------------------------------------------*/
10389 genAddrOf (iCode * ic)
10391 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10394 D (emitcode (";", "genAddrOf ");
10397 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10399 /* if the operand is on the stack then we
10400 need to get the stack offset of this
10402 if (sym->onStack) {
10404 /* if 10 bit stack */
10405 if (options.stack10bit) {
10407 tsprintf(buff, sizeof(buff),
10408 "#!constbyte",(options.stack_loc >> 16) & 0xff);
10409 /* if it has an offset then we need to compute it */
10410 /* emitcode ("subb", "a,#!constbyte", */
10411 /* -((sym->stack < 0) ? */
10412 /* ((short) (sym->stack - _G.nRegsSaved)) : */
10413 /* ((short) sym->stack)) & 0xff); */
10414 /* emitcode ("mov","b,a"); */
10415 /* emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
10416 /* ((short) (sym->stack - _G.nRegsSaved)) : */
10417 /* ((short) sym->stack)) >> 8) & 0xff); */
10419 emitcode ("mov", "a,_bpx");
10420 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
10421 ((char) (sym->stack - _G.nRegsSaved)) :
10422 ((char) sym->stack )) & 0xff);
10423 emitcode ("mov", "b,a");
10424 emitcode ("mov", "a,_bpx+1");
10425 emitcode ("addc","a,#!constbyte", (((sym->stack < 0) ?
10426 ((short) (sym->stack - _G.nRegsSaved)) :
10427 ((short) sym->stack )) >> 8) & 0xff);
10428 aopPut (AOP (IC_RESULT (ic)), "b", 0);
10429 aopPut (AOP (IC_RESULT (ic)), "a", 1);
10430 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10432 /* we can just move _bp */
10433 aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10434 aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10435 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10438 /* if it has an offset then we need to compute it */
10440 emitcode ("mov", "a,_bp");
10441 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10442 aopPut (AOP (IC_RESULT (ic)), "a", 0);
10444 /* we can just move _bp */
10445 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10447 /* fill the result with zero */
10448 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10451 if (options.stack10bit && size < (FPTRSIZE - 1)) {
10453 "*** warning: pointer to stack var truncated.\n");
10458 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10464 /* object not on stack then we need the name */
10465 size = AOP_SIZE (IC_RESULT (ic));
10470 char s[SDCC_NAME_MAX];
10474 tsprintf(s, sizeof(s), "!his",sym->rname);
10477 tsprintf(s, sizeof(s), "!hihis",sym->rname);
10480 tsprintf(s, sizeof(s), "!hihihis",sym->rname);
10482 default: /* should not need this (just in case) */
10483 SNPRINTF (s, sizeof(s), "#(%s >> %d)",
10490 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10493 aopPut (AOP (IC_RESULT (ic)), s, offset++);
10497 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10501 /*-----------------------------------------------------------------*/
10502 /* genArrayInit - generates code for address of */
10503 /*-----------------------------------------------------------------*/
10505 genArrayInit (iCode * ic)
10507 literalList *iLoop;
10509 int elementSize = 0, eIndex;
10510 unsigned val, lastVal;
10512 operand *left=IC_LEFT(ic);
10514 D (emitcode (";", "genArrayInit "););
10516 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10518 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10520 // Load immediate value into DPTR.
10521 emitcode("mov", "dptr, %s",
10522 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
10524 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10527 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10528 "Unexpected operand to genArrayInit.\n");
10531 // a regression because of SDCCcse.c:1.52
10532 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
10533 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
10534 if (options.model == MODEL_FLAT24)
10535 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
10539 type = operandType(IC_LEFT(ic));
10541 if (type && type->next)
10543 elementSize = getSize(type->next);
10547 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10548 "can't determine element size in genArrayInit.\n");
10552 iLoop = IC_ARRAYILIST(ic);
10557 bool firstpass = TRUE;
10559 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
10560 iLoop->count, (int)iLoop->literalValue, elementSize);
10566 symbol *tlbl = NULL;
10568 count = ix > 256 ? 256 : ix;
10572 tlbl = newiTempLabel (NULL);
10573 if (firstpass || (count & 0xff))
10575 emitcode("mov", "b, #!constbyte", count & 0xff);
10578 emitcode ("", "!tlabeldef", tlbl->key + 100);
10583 for (eIndex = 0; eIndex < elementSize; eIndex++)
10585 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10586 if (val != lastVal)
10588 emitcode("mov", "a, #!constbyte", val);
10592 emitcode("movx", "@dptr, a");
10593 emitcode("inc", "dptr");
10598 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10604 iLoop = iLoop->next;
10607 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10610 /*-----------------------------------------------------------------*/
10611 /* genFarFarAssign - assignment when both are in far space */
10612 /*-----------------------------------------------------------------*/
10614 genFarFarAssign (operand * result, operand * right, iCode * ic)
10616 int size = AOP_SIZE (right);
10618 symbol *rSym = NULL;
10622 /* quick & easy case. */
10623 D(emitcode(";","genFarFarAssign (1 byte case)"););
10624 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
10625 freeAsmop (right, NULL, ic, FALSE);
10626 /* now assign DPTR to result */
10628 aopOp(result, ic, FALSE, FALSE);
10630 aopPut(AOP(result), "a", 0);
10631 freeAsmop(result, NULL, ic, FALSE);
10635 /* See if we've got an underlying symbol to abuse. */
10636 if (IS_SYMOP(result) && OP_SYMBOL(result))
10638 if (IS_TRUE_SYMOP(result))
10640 rSym = OP_SYMBOL(result);
10642 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10644 rSym = OP_SYMBOL(result)->usl.spillLoc;
10648 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10650 /* We can use the '390 auto-toggle feature to good effect here. */
10652 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10653 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
10654 emitcode ("mov", "dptr,#%s", rSym->rname);
10655 /* DP2 = result, DP1 = right, DP1 is current. */
10658 emitcode("movx", "a,@dptr");
10659 emitcode("movx", "@dptr,a");
10662 emitcode("inc", "dptr");
10663 emitcode("inc", "dptr");
10666 emitcode("mov", "dps,#0");
10667 freeAsmop (right, NULL, ic, FALSE);
10669 some alternative code for processors without auto-toggle
10670 no time to test now, so later well put in...kpb
10671 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10672 emitcode("mov", "dps,#1"); /* Select DPTR2. */
10673 emitcode ("mov", "dptr,#%s", rSym->rname);
10674 /* DP2 = result, DP1 = right, DP1 is current. */
10678 emitcode("movx", "a,@dptr");
10680 emitcode("inc", "dptr");
10681 emitcode("inc", "dps");
10682 emitcode("movx", "@dptr,a");
10684 emitcode("inc", "dptr");
10685 emitcode("inc", "dps");
10687 emitcode("mov", "dps,#0");
10688 freeAsmop (right, NULL, ic, FALSE);
10693 D (emitcode (";", "genFarFarAssign"););
10694 aopOp (result, ic, TRUE, TRUE);
10696 _startLazyDPSEvaluation ();
10700 aopPut (AOP (result),
10701 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
10704 _endLazyDPSEvaluation ();
10705 freeAsmop (result, NULL, ic, FALSE);
10706 freeAsmop (right, NULL, ic, FALSE);
10710 /*-----------------------------------------------------------------*/
10711 /* genAssign - generate code for assignment */
10712 /*-----------------------------------------------------------------*/
10714 genAssign (iCode * ic)
10716 operand *result, *right;
10718 unsigned long lit = 0L;
10720 D (emitcode (";", "genAssign ");
10723 result = IC_RESULT (ic);
10724 right = IC_RIGHT (ic);
10726 /* if they are the same */
10727 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10730 aopOp (right, ic, FALSE, FALSE);
10732 emitcode (";", "genAssign: resultIsFar = %s",
10733 isOperandInFarSpace (result) ?
10736 /* special case both in far space */
10737 if ((AOP_TYPE (right) == AOP_DPTR ||
10738 AOP_TYPE (right) == AOP_DPTR2) &&
10739 /* IS_TRUE_SYMOP(result) && */
10740 isOperandInFarSpace (result))
10742 genFarFarAssign (result, right, ic);
10746 aopOp (result, ic, TRUE, FALSE);
10748 /* if they are the same registers */
10749 if (sameRegs (AOP (right), AOP (result)))
10752 /* if the result is a bit */
10753 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10755 /* if the right size is a literal then
10756 we know what the value is */
10757 if (AOP_TYPE (right) == AOP_LIT)
10759 if (((int) operandLitValue (right)))
10760 aopPut (AOP (result), one, 0);
10762 aopPut (AOP (result), zero, 0);
10766 /* the right is also a bit variable */
10767 if (AOP_TYPE (right) == AOP_CRY)
10769 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10770 aopPut (AOP (result), "c", 0);
10774 /* we need to or */
10776 aopPut (AOP (result), "a", 0);
10780 /* bit variables done */
10782 size = AOP_SIZE (result);
10784 if (AOP_TYPE (right) == AOP_LIT)
10785 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10788 (AOP_TYPE (result) != AOP_REG) &&
10789 (AOP_TYPE (right) == AOP_LIT) &&
10790 !IS_FLOAT (operandType (right)))
10792 _startLazyDPSEvaluation ();
10793 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10795 aopPut (AOP (result),
10796 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
10801 /* And now fill the rest with zeros. */
10804 emitcode ("clr", "a");
10808 aopPut (AOP (result), "a", offset++);
10810 _endLazyDPSEvaluation ();
10814 _startLazyDPSEvaluation ();
10817 aopPut (AOP (result),
10818 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10822 _endLazyDPSEvaluation ();
10826 freeAsmop (right, NULL, ic, FALSE);
10827 freeAsmop (result, NULL, ic, TRUE);
10830 /*-----------------------------------------------------------------*/
10831 /* genJumpTab - generates code for jump table */
10832 /*-----------------------------------------------------------------*/
10834 genJumpTab (iCode * ic)
10839 D (emitcode (";", "genJumpTab ");
10842 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10843 /* get the condition into accumulator */
10844 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
10846 /* multiply by four! */
10847 emitcode ("add", "a,acc");
10848 emitcode ("add", "a,acc");
10849 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10851 jtab = newiTempLabel (NULL);
10852 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
10853 emitcode ("jmp", "@a+dptr");
10854 emitcode ("", "!tlabeldef", jtab->key + 100);
10855 /* now generate the jump labels */
10856 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10857 jtab = setNextItem (IC_JTLABELS (ic)))
10858 emitcode ("ljmp", "!tlabel", jtab->key + 100);
10862 /*-----------------------------------------------------------------*/
10863 /* genCast - gen code for casting */
10864 /*-----------------------------------------------------------------*/
10866 genCast (iCode * ic)
10868 operand *result = IC_RESULT (ic);
10869 sym_link *ctype = operandType (IC_LEFT (ic));
10870 sym_link *rtype = operandType (IC_RIGHT (ic));
10871 operand *right = IC_RIGHT (ic);
10874 D (emitcode (";", "genCast ");
10877 /* if they are equivalent then do nothing */
10878 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10881 aopOp (right, ic, FALSE, FALSE);
10882 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
10884 /* if the result is a bit */
10885 // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10886 if (IS_BITVAR(OP_SYMBOL(result)->type))
10888 /* if the right size is a literal then
10889 we know what the value is */
10890 if (AOP_TYPE (right) == AOP_LIT)
10892 if (((int) operandLitValue (right)))
10893 aopPut (AOP (result), one, 0);
10895 aopPut (AOP (result), zero, 0);
10900 /* the right is also a bit variable */
10901 if (AOP_TYPE (right) == AOP_CRY)
10903 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10904 aopPut (AOP (result), "c", 0);
10908 /* we need to or */
10910 aopPut (AOP (result), "a", 0);
10914 /* if they are the same size : or less */
10915 if (AOP_SIZE (result) <= AOP_SIZE (right))
10918 /* if they are in the same place */
10919 if (sameRegs (AOP (right), AOP (result)))
10922 /* if they in different places then copy */
10923 size = AOP_SIZE (result);
10925 _startLazyDPSEvaluation ();
10928 aopPut (AOP (result),
10929 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10933 _endLazyDPSEvaluation ();
10938 /* if the result is of type pointer */
10939 if (IS_PTR (ctype))
10943 sym_link *type = operandType (right);
10945 /* pointer to generic pointer */
10946 if (IS_GENPTR (ctype))
10950 p_type = DCL_TYPE (type);
10954 #if OLD_CAST_BEHAVIOR
10955 /* KV: we are converting a non-pointer type to
10956 * a generic pointer. This (ifdef'd out) code
10957 * says that the resulting generic pointer
10958 * should have the same class as the storage
10959 * location of the non-pointer variable.
10961 * For example, converting an int (which happens
10962 * to be stored in DATA space) to a pointer results
10963 * in a DATA generic pointer; if the original int
10964 * in XDATA space, so will be the resulting pointer.
10966 * I don't like that behavior, and thus this change:
10967 * all such conversions will be forced to XDATA and
10968 * throw a warning. If you want some non-XDATA
10969 * type, or you want to suppress the warning, you
10970 * must go through an intermediate cast, like so:
10972 * char _generic *gp = (char _xdata *)(intVar);
10974 sym_link *etype = getSpec (type);
10976 /* we have to go by the storage class */
10977 if (SPEC_OCLS (etype) != generic)
10979 p_type = PTR_TYPE (SPEC_OCLS (etype));
10984 /* Converting unknown class (i.e. register variable)
10985 * to generic pointer. This is not good, but
10986 * we'll make a guess (and throw a warning).
10989 werror (W_INT_TO_GEN_PTR_CAST);
10993 /* the first two bytes are known */
10994 size = GPTRSIZE - 1;
10996 _startLazyDPSEvaluation ();
10999 aopPut (AOP (result),
11000 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
11004 _endLazyDPSEvaluation ();
11006 /* the last byte depending on type */
11008 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11013 // pointerTypeToGPByte will have bitched.
11017 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11018 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11023 /* just copy the pointers */
11024 size = AOP_SIZE (result);
11026 _startLazyDPSEvaluation ();
11029 aopPut (AOP (result),
11030 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
11034 _endLazyDPSEvaluation ();
11038 /* so we now know that the size of destination is greater
11039 than the size of the source */
11040 /* we move to result for the size of source */
11041 size = AOP_SIZE (right);
11043 _startLazyDPSEvaluation ();
11046 aopPut (AOP (result),
11047 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
11051 _endLazyDPSEvaluation ();
11053 /* now depending on the sign of the source && destination */
11054 size = AOP_SIZE (result) - AOP_SIZE (right);
11055 /* if unsigned or not an integral type */
11056 /* also, if the source is a bit, we don't need to sign extend, because
11057 * it can't possibly have set the sign bit.
11059 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
11063 aopPut (AOP (result), zero, offset++);
11068 /* we need to extend the sign :{ */
11069 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
11070 FALSE, FALSE, TRUE);
11072 emitcode ("rlc", "a");
11073 emitcode ("subb", "a,acc");
11075 aopPut (AOP (result), "a", offset++);
11078 /* we are done hurray !!!! */
11081 freeAsmop (right, NULL, ic, TRUE);
11082 freeAsmop (result, NULL, ic, TRUE);
11086 /*-----------------------------------------------------------------*/
11087 /* genDjnz - generate decrement & jump if not zero instrucion */
11088 /*-----------------------------------------------------------------*/
11090 genDjnz (iCode * ic, iCode * ifx)
11092 symbol *lbl, *lbl1;
11096 /* if the if condition has a false label
11097 then we cannot save */
11098 if (IC_FALSE (ifx))
11101 /* if the minus is not of the form
11103 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11104 !IS_OP_LITERAL (IC_RIGHT (ic)))
11107 if (operandLitValue (IC_RIGHT (ic)) != 1)
11110 /* if the size of this greater than one then no
11112 if (getSize (operandType (IC_RESULT (ic))) > 1)
11115 /* otherwise we can save BIG */
11116 D(emitcode(";", "genDjnz"););
11118 lbl = newiTempLabel (NULL);
11119 lbl1 = newiTempLabel (NULL);
11121 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11123 if (AOP_NEEDSACC(IC_RESULT(ic)))
11125 /* If the result is accessed indirectly via
11126 * the accumulator, we must explicitly write
11127 * it back after the decrement.
11129 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
11131 if (strcmp(rByte, "a"))
11133 /* Something is hopelessly wrong */
11134 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11135 __FILE__, __LINE__);
11136 /* We can just give up; the generated code will be inefficient,
11137 * but what the hey.
11139 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11142 emitcode ("dec", "%s", rByte);
11143 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11144 emitcode ("jnz", "!tlabel", lbl->key + 100);
11146 else if (IS_AOP_PREG (IC_RESULT (ic)))
11148 emitcode ("dec", "%s",
11149 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
11150 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
11151 emitcode ("jnz", "!tlabel", lbl->key + 100);
11155 emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
11158 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11159 emitcode ("", "!tlabeldef", lbl->key + 100);
11160 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11161 emitcode ("", "!tlabeldef", lbl1->key + 100);
11163 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11164 ifx->generated = 1;
11168 /*-----------------------------------------------------------------*/
11169 /* genReceive - generate code for a receive iCode */
11170 /*-----------------------------------------------------------------*/
11172 genReceive (iCode * ic)
11175 int size = getSize (operandType (IC_RESULT (ic)));
11179 D (emitcode (";", "genReceive ");
11182 if (ic->argreg == 1) { /* first parameter */
11183 if (isOperandInFarSpace (IC_RESULT (ic)) &&
11184 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11185 IS_TRUE_SYMOP (IC_RESULT (ic))))
11187 offset = fReturnSizeDS390 - size;
11190 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
11191 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
11194 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11195 size = AOP_SIZE (IC_RESULT (ic));
11199 emitcode ("pop", "acc");
11200 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
11205 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11207 assignResultValue (IC_RESULT (ic));
11209 } else { /* second receive onwards */
11210 /* this gets a little tricky since unused recevies will be
11211 eliminated, we have saved the reg in the type field . and
11212 we use that to figure out which register to use */
11213 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11214 rb1off = ic->argreg;
11216 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11220 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11223 /*-----------------------------------------------------------------*/
11224 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
11225 /*-----------------------------------------------------------------*/
11226 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11228 operand *from , *to , *count;
11233 /* we know it has to be 3 parameters */
11234 assert (nparms == 3);
11236 rsave = newBitVect(16);
11237 /* save DPTR if it needs to be saved */
11238 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11239 if (bitVectBitValue(ic->rMask,i))
11240 rsave = bitVectSetBit(rsave,i);
11242 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11243 ds390_rUmaskForOp (IC_RESULT(ic))));
11250 aopOp (from, ic->next, FALSE, FALSE);
11252 /* get from into DPTR1 */
11253 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
11254 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
11255 if (options.model == MODEL_FLAT24) {
11256 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
11259 freeAsmop (from, NULL, ic, FALSE);
11260 aopOp (to, ic, FALSE, FALSE);
11261 /* get "to" into DPTR */
11262 /* if the operand is already in dptr
11263 then we do nothing else we move the value to dptr */
11264 if (AOP_TYPE (to) != AOP_STR) {
11265 /* if already in DPTR then we need to push */
11266 if (AOP_TYPE(to) == AOP_DPTR) {
11267 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11268 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11269 if (options.model == MODEL_FLAT24)
11270 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11271 emitcode ("pop", "dph");
11272 emitcode ("pop", "dpl");
11274 _startLazyDPSEvaluation ();
11275 /* if this is remateriazable */
11276 if (AOP_TYPE (to) == AOP_IMMD) {
11277 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11278 } else { /* we need to get it byte by byte */
11279 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11280 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11281 if (options.model == MODEL_FLAT24) {
11282 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11285 _endLazyDPSEvaluation ();
11288 freeAsmop (to, NULL, ic, FALSE);
11289 _G.dptrInUse = _G.dptr1InUse = 1;
11290 aopOp (count, ic->next->next, FALSE,FALSE);
11291 lbl =newiTempLabel(NULL);
11293 /* now for the actual copy */
11294 if (AOP_TYPE(count) == AOP_LIT &&
11295 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11296 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11298 emitcode ("lcall","__bi_memcpyc2x_s");
11300 emitcode ("lcall","__bi_memcpyx2x_s");
11302 freeAsmop (count, NULL, ic, FALSE);
11304 symbol *lbl1 = newiTempLabel(NULL);
11306 emitcode (";"," Auto increment but no djnz");
11307 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11308 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11309 freeAsmop (count, NULL, ic, FALSE);
11310 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11311 emitcode ("","!tlabeldef",lbl->key+100);
11313 emitcode ("clr","a");
11314 emitcode ("movc", "a,@a+dptr");
11316 emitcode ("movx", "a,@dptr");
11317 emitcode ("movx", "@dptr,a");
11318 emitcode ("inc", "dptr");
11319 emitcode ("inc", "dptr");
11320 emitcode ("mov","a,b");
11321 emitcode ("orl","a,_ap");
11322 emitcode ("jz","!tlabel",lbl1->key+100);
11323 emitcode ("mov","a,_ap");
11324 emitcode ("add","a,#!constbyte",0xFF);
11325 emitcode ("mov","_ap,a");
11326 emitcode ("mov","a,b");
11327 emitcode ("addc","a,#!constbyte",0xFF);
11328 emitcode ("mov","b,a");
11329 emitcode ("sjmp","!tlabel",lbl->key+100);
11330 emitcode ("","!tlabeldef",lbl1->key+100);
11332 emitcode ("mov", "dps,#0");
11333 _G.dptrInUse = _G.dptr1InUse = 0;
11334 unsavermask(rsave);
11338 /*-----------------------------------------------------------------*/
11339 /* genMemcmpX2X - gen code for memcmp xdata to xdata */
11340 /*-----------------------------------------------------------------*/
11341 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11343 operand *from , *to , *count;
11348 /* we know it has to be 3 parameters */
11349 assert (nparms == 3);
11351 rsave = newBitVect(16);
11352 /* save DPTR if it needs to be saved */
11353 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11354 if (bitVectBitValue(ic->rMask,i))
11355 rsave = bitVectSetBit(rsave,i);
11357 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11358 ds390_rUmaskForOp (IC_RESULT(ic))));
11365 aopOp (from, ic->next, FALSE, FALSE);
11367 /* get from into DPTR1 */
11368 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
11369 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
11370 if (options.model == MODEL_FLAT24) {
11371 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
11374 freeAsmop (from, NULL, ic, FALSE);
11375 aopOp (to, ic, FALSE, FALSE);
11376 /* get "to" into DPTR */
11377 /* if the operand is already in dptr
11378 then we do nothing else we move the value to dptr */
11379 if (AOP_TYPE (to) != AOP_STR) {
11380 /* if already in DPTR then we need to push */
11381 if (AOP_TYPE(to) == AOP_DPTR) {
11382 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11383 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11384 if (options.model == MODEL_FLAT24)
11385 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11386 emitcode ("pop", "dph");
11387 emitcode ("pop", "dpl");
11389 _startLazyDPSEvaluation ();
11390 /* if this is remateriazable */
11391 if (AOP_TYPE (to) == AOP_IMMD) {
11392 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11393 } else { /* we need to get it byte by byte */
11394 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11395 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11396 if (options.model == MODEL_FLAT24) {
11397 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11400 _endLazyDPSEvaluation ();
11403 freeAsmop (to, NULL, ic, FALSE);
11404 _G.dptrInUse = _G.dptr1InUse = 1;
11405 aopOp (count, ic->next->next, FALSE,FALSE);
11406 lbl =newiTempLabel(NULL);
11407 lbl2 =newiTempLabel(NULL);
11409 /* now for the actual compare */
11410 if (AOP_TYPE(count) == AOP_LIT &&
11411 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11412 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11414 emitcode("lcall","__bi_memcmpc2x_s");
11416 emitcode("lcall","__bi_memcmpx2x_s");
11417 freeAsmop (count, NULL, ic, FALSE);
11418 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11419 aopPut(AOP(IC_RESULT(ic)),"a",0);
11420 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11422 symbol *lbl1 = newiTempLabel(NULL);
11424 emitcode("push","ar0");
11425 emitcode (";"," Auto increment but no djnz");
11426 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11427 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11428 freeAsmop (count, NULL, ic, FALSE);
11429 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11430 emitcode ("","!tlabeldef",lbl->key+100);
11432 emitcode ("clr","a");
11433 emitcode ("movc", "a,@a+dptr");
11435 emitcode ("movx", "a,@dptr");
11436 emitcode ("mov","r0,a");
11437 emitcode ("movx", "a,@dptr");
11438 emitcode ("clr","c");
11439 emitcode ("subb","a,r0");
11440 emitcode ("jnz","!tlabel",lbl2->key+100);
11441 emitcode ("inc", "dptr");
11442 emitcode ("inc", "dptr");
11443 emitcode ("mov","a,b");
11444 emitcode ("orl","a,_ap");
11445 emitcode ("jz","!tlabel",lbl1->key+100);
11446 emitcode ("mov","a,_ap");
11447 emitcode ("add","a,#!constbyte",0xFF);
11448 emitcode ("mov","_ap,a");
11449 emitcode ("mov","a,b");
11450 emitcode ("addc","a,#!constbyte",0xFF);
11451 emitcode ("mov","b,a");
11452 emitcode ("sjmp","!tlabel",lbl->key+100);
11453 emitcode ("","!tlabeldef",lbl1->key+100);
11454 emitcode ("clr","a");
11455 emitcode ("","!tlabeldef",lbl2->key+100);
11456 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11457 aopPut(AOP(IC_RESULT(ic)),"a",0);
11458 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11459 emitcode("pop","ar0");
11460 emitcode ("mov", "dps,#0");
11462 _G.dptrInUse = _G.dptr1InUse = 0;
11463 unsavermask(rsave);
11467 /*-----------------------------------------------------------------*/
11468 /* genInp - gen code for __builtin_inp read data from a mem mapped */
11469 /* port, first parameter output area second parameter pointer to */
11470 /* port third parameter count */
11471 /*-----------------------------------------------------------------*/
11472 static void genInp( iCode *ic, int nparms, operand **parms)
11474 operand *from , *to , *count;
11479 /* we know it has to be 3 parameters */
11480 assert (nparms == 3);
11482 rsave = newBitVect(16);
11483 /* save DPTR if it needs to be saved */
11484 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11485 if (bitVectBitValue(ic->rMask,i))
11486 rsave = bitVectSetBit(rsave,i);
11488 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11489 ds390_rUmaskForOp (IC_RESULT(ic))));
11496 aopOp (from, ic->next, FALSE, FALSE);
11498 /* get from into DPTR1 */
11499 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
11500 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
11501 if (options.model == MODEL_FLAT24) {
11502 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
11505 freeAsmop (from, NULL, ic, FALSE);
11506 aopOp (to, ic, FALSE, FALSE);
11507 /* get "to" into DPTR */
11508 /* if the operand is already in dptr
11509 then we do nothing else we move the value to dptr */
11510 if (AOP_TYPE (to) != AOP_STR) {
11511 /* if already in DPTR then we need to push */
11512 if (AOP_TYPE(to) == AOP_DPTR) {
11513 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11514 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11515 if (options.model == MODEL_FLAT24)
11516 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11517 emitcode ("pop", "dph");
11518 emitcode ("pop", "dpl");
11520 _startLazyDPSEvaluation ();
11521 /* if this is remateriazable */
11522 if (AOP_TYPE (to) == AOP_IMMD) {
11523 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11524 } else { /* we need to get it byte by byte */
11525 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11526 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11527 if (options.model == MODEL_FLAT24) {
11528 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11531 _endLazyDPSEvaluation ();
11534 freeAsmop (to, NULL, ic, FALSE);
11536 _G.dptrInUse = _G.dptr1InUse = 1;
11537 aopOp (count, ic->next->next, FALSE,FALSE);
11538 lbl =newiTempLabel(NULL);
11540 /* now for the actual copy */
11541 if (AOP_TYPE(count) == AOP_LIT &&
11542 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11543 emitcode (";","OH JOY auto increment with djnz (very fast)");
11544 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11545 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11546 freeAsmop (count, NULL, ic, FALSE);
11547 emitcode ("","!tlabeldef",lbl->key+100);
11548 emitcode ("movx", "a,@dptr"); /* read data from port */
11549 emitcode ("dec","dps"); /* switch to DPTR */
11550 emitcode ("movx", "@dptr,a"); /* save into location */
11551 emitcode ("inc", "dptr"); /* point to next area */
11552 emitcode ("inc","dps"); /* switch to DPTR2 */
11553 emitcode ("djnz","b,!tlabel",lbl->key+100);
11555 symbol *lbl1 = newiTempLabel(NULL);
11557 emitcode (";"," Auto increment but no djnz");
11558 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11559 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11560 freeAsmop (count, NULL, ic, FALSE);
11561 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11562 emitcode ("","!tlabeldef",lbl->key+100);
11563 emitcode ("movx", "a,@dptr");
11564 emitcode ("dec","dps"); /* switch to DPTR */
11565 emitcode ("movx", "@dptr,a");
11566 emitcode ("inc", "dptr");
11567 emitcode ("inc","dps"); /* switch to DPTR2 */
11568 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
11569 /* emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
11570 emitcode ("mov","a,b");
11571 emitcode ("orl","a,_ap");
11572 emitcode ("jz","!tlabel",lbl1->key+100);
11573 emitcode ("mov","a,_ap");
11574 emitcode ("add","a,#!constbyte",0xFF);
11575 emitcode ("mov","_ap,a");
11576 emitcode ("mov","a,b");
11577 emitcode ("addc","a,#!constbyte",0xFF);
11578 emitcode ("mov","b,a");
11579 emitcode ("sjmp","!tlabel",lbl->key+100);
11580 emitcode ("","!tlabeldef",lbl1->key+100);
11582 emitcode ("mov", "dps,#0");
11583 _G.dptrInUse = _G.dptr1InUse = 0;
11584 unsavermask(rsave);
11588 /*-----------------------------------------------------------------*/
11589 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
11590 /* port, first parameter output area second parameter pointer to */
11591 /* port third parameter count */
11592 /*-----------------------------------------------------------------*/
11593 static void genOutp( iCode *ic, int nparms, operand **parms)
11595 operand *from , *to , *count;
11600 /* we know it has to be 3 parameters */
11601 assert (nparms == 3);
11603 rsave = newBitVect(16);
11604 /* save DPTR if it needs to be saved */
11605 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11606 if (bitVectBitValue(ic->rMask,i))
11607 rsave = bitVectSetBit(rsave,i);
11609 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11610 ds390_rUmaskForOp (IC_RESULT(ic))));
11617 aopOp (from, ic->next, FALSE, FALSE);
11619 /* get from into DPTR1 */
11620 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
11621 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
11622 if (options.model == MODEL_FLAT24) {
11623 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
11626 freeAsmop (from, NULL, ic, FALSE);
11627 aopOp (to, ic, FALSE, FALSE);
11628 /* get "to" into DPTR */
11629 /* if the operand is already in dptr
11630 then we do nothing else we move the value to dptr */
11631 if (AOP_TYPE (to) != AOP_STR) {
11632 /* if already in DPTR then we need to push */
11633 if (AOP_TYPE(to) == AOP_DPTR) {
11634 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11635 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11636 if (options.model == MODEL_FLAT24)
11637 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11638 emitcode ("pop", "dph");
11639 emitcode ("pop", "dpl");
11641 _startLazyDPSEvaluation ();
11642 /* if this is remateriazable */
11643 if (AOP_TYPE (to) == AOP_IMMD) {
11644 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11645 } else { /* we need to get it byte by byte */
11646 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11647 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11648 if (options.model == MODEL_FLAT24) {
11649 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11652 _endLazyDPSEvaluation ();
11655 freeAsmop (to, NULL, ic, FALSE);
11657 _G.dptrInUse = _G.dptr1InUse = 1;
11658 aopOp (count, ic->next->next, FALSE,FALSE);
11659 lbl =newiTempLabel(NULL);
11661 /* now for the actual copy */
11662 if (AOP_TYPE(count) == AOP_LIT &&
11663 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11664 emitcode (";","OH JOY auto increment with djnz (very fast)");
11665 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
11666 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11667 emitcode ("","!tlabeldef",lbl->key+100);
11668 emitcode ("movx", "a,@dptr"); /* read data from port */
11669 emitcode ("inc","dps"); /* switch to DPTR2 */
11670 emitcode ("movx", "@dptr,a"); /* save into location */
11671 emitcode ("inc", "dptr"); /* point to next area */
11672 emitcode ("dec","dps"); /* switch to DPTR */
11673 emitcode ("djnz","b,!tlabel",lbl->key+100);
11674 freeAsmop (count, NULL, ic, FALSE);
11676 symbol *lbl1 = newiTempLabel(NULL);
11678 emitcode (";"," Auto increment but no djnz");
11679 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11680 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11681 freeAsmop (count, NULL, ic, FALSE);
11682 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
11683 emitcode ("","!tlabeldef",lbl->key+100);
11684 emitcode ("movx", "a,@dptr");
11685 emitcode ("inc", "dptr");
11686 emitcode ("inc","dps"); /* switch to DPTR2 */
11687 emitcode ("movx", "@dptr,a");
11688 emitcode ("dec","dps"); /* switch to DPTR */
11689 emitcode ("mov","a,b");
11690 emitcode ("orl","a,_ap");
11691 emitcode ("jz","!tlabel",lbl1->key+100);
11692 emitcode ("mov","a,_ap");
11693 emitcode ("add","a,#!constbyte",0xFF);
11694 emitcode ("mov","_ap,a");
11695 emitcode ("mov","a,b");
11696 emitcode ("addc","a,#!constbyte",0xFF);
11697 emitcode ("mov","b,a");
11698 emitcode ("sjmp","!tlabel",lbl->key+100);
11699 emitcode ("","!tlabeldef",lbl1->key+100);
11701 emitcode ("mov", "dps,#0");
11702 _G.dptrInUse = _G.dptr1InUse = 0;
11703 unsavermask(rsave);
11707 /*-----------------------------------------------------------------*/
11708 /* genSwapW - swap lower & high order bytes */
11709 /*-----------------------------------------------------------------*/
11710 static void genSwapW(iCode *ic, int nparms, operand **parms)
11714 assert (nparms==1);
11717 dest=IC_RESULT(ic);
11719 assert(getSize(operandType(src))==2);
11721 aopOp (src, ic, FALSE, FALSE);
11722 emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,TRUE));
11724 emitcode ("mov","b,%s",aopGet(AOP(src),1,FALSE,FALSE,FALSE));
11726 freeAsmop (src, NULL, ic, FALSE);
11728 aopOp (dest,ic, FALSE, FALSE);
11729 aopPut(AOP(dest),"b",0);
11730 aopPut(AOP(dest),"a",1);
11731 freeAsmop (dest, NULL, ic, FALSE);
11734 /*-----------------------------------------------------------------*/
11735 /* genMemsetX - gencode for memSetX data */
11736 /*-----------------------------------------------------------------*/
11737 static void genMemsetX(iCode *ic, int nparms, operand **parms)
11739 operand *to , *val , *count;
11743 bitVect *rsave = NULL;
11745 /* we know it has to be 3 parameters */
11746 assert (nparms == 3);
11752 /* save DPTR if it needs to be saved */
11753 rsave = newBitVect(16);
11754 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11755 if (bitVectBitValue(ic->rMask,i))
11756 rsave = bitVectSetBit(rsave,i);
11758 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11759 ds390_rUmaskForOp (IC_RESULT(ic))));
11762 aopOp (to, ic, FALSE, FALSE);
11763 /* get "to" into DPTR */
11764 /* if the operand is already in dptr
11765 then we do nothing else we move the value to dptr */
11766 if (AOP_TYPE (to) != AOP_STR) {
11767 /* if already in DPTR then we need to push */
11768 if (AOP_TYPE(to) == AOP_DPTR) {
11769 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11770 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11771 if (options.model == MODEL_FLAT24)
11772 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11773 emitcode ("pop", "dph");
11774 emitcode ("pop", "dpl");
11776 _startLazyDPSEvaluation ();
11777 /* if this is remateriazable */
11778 if (AOP_TYPE (to) == AOP_IMMD) {
11779 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11780 } else { /* we need to get it byte by byte */
11781 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11782 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11783 if (options.model == MODEL_FLAT24) {
11784 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11787 _endLazyDPSEvaluation ();
11790 freeAsmop (to, NULL, ic, FALSE);
11792 aopOp (val, ic->next->next, FALSE,FALSE);
11793 aopOp (count, ic->next->next, FALSE,FALSE);
11794 lbl =newiTempLabel(NULL);
11795 /* now for the actual copy */
11796 if (AOP_TYPE(count) == AOP_LIT &&
11797 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11798 l = aopGet(AOP (val), 0, FALSE, FALSE, TRUE);
11799 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11801 emitcode ("","!tlabeldef",lbl->key+100);
11802 emitcode ("movx", "@dptr,a");
11803 emitcode ("inc", "dptr");
11804 emitcode ("djnz","b,!tlabel",lbl->key+100);
11806 symbol *lbl1 = newiTempLabel(NULL);
11808 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11809 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11810 emitcode ("","!tlabeldef",lbl->key+100);
11811 l = aopGet(AOP (val), 0, FALSE, FALSE, TRUE);
11813 emitcode ("movx", "@dptr,a");
11814 emitcode ("inc", "dptr");
11815 emitcode ("mov","a,b");
11816 emitcode ("orl","a,_ap");
11817 emitcode ("jz","!tlabel",lbl1->key+100);
11818 emitcode ("mov","a,_ap");
11819 emitcode ("add","a,#!constbyte",0xFF);
11820 emitcode ("mov","_ap,a");
11821 emitcode ("mov","a,b");
11822 emitcode ("addc","a,#!constbyte",0xFF);
11823 emitcode ("mov","b,a");
11824 emitcode ("sjmp","!tlabel",lbl->key+100);
11825 emitcode ("","!tlabeldef",lbl1->key+100);
11827 freeAsmop (count, NULL, ic, FALSE);
11828 unsavermask(rsave);
11831 /*-----------------------------------------------------------------*/
11832 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
11833 /*-----------------------------------------------------------------*/
11834 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
11837 operand *pnum, *result;
11840 assert (nparms==1);
11841 /* save registers that need to be saved */
11842 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11843 ds390_rUmaskForOp (IC_RESULT(ic))));
11846 aopOp (pnum, ic, FALSE, FALSE);
11847 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,FALSE));
11848 freeAsmop (pnum, NULL, ic, FALSE);
11849 emitcode ("lcall","NatLib_LoadPrimitive");
11850 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11851 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
11852 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
11853 for (i = (size-1) ; i >= 0 ; i-- ) {
11854 emitcode ("push","a%s",javaRet[i]);
11856 for (i=0; i < size ; i++ ) {
11857 emitcode ("pop","a%s",aopGet(AOP(result),i,FALSE,FALSE,FALSE));
11860 for (i = 0 ; i < size ; i++ ) {
11861 aopPut(AOP(result),javaRet[i],i);
11864 freeAsmop (result, NULL, ic, FALSE);
11865 unsavermask(rsave);
11868 /*-----------------------------------------------------------------*/
11869 /* genNatLibLoadPointer - calls TINI api function to load pointer */
11870 /*-----------------------------------------------------------------*/
11871 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
11874 operand *pnum, *result;
11878 assert (nparms==1);
11879 /* save registers that need to be saved */
11880 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11881 ds390_rUmaskForOp (IC_RESULT(ic))));
11884 aopOp (pnum, ic, FALSE, FALSE);
11885 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,FALSE));
11886 freeAsmop (pnum, NULL, ic, FALSE);
11887 emitcode ("lcall","NatLib_LoadPointer");
11888 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11889 if (AOP_TYPE(result)!=AOP_STR) {
11890 for (i = 0 ; i < size ; i++ ) {
11891 aopPut(AOP(result),fReturn[i],i);
11894 freeAsmop (result, NULL, ic, FALSE);
11895 unsavermask(rsave);
11898 /*-----------------------------------------------------------------*/
11899 /* genNatLibInstallStateBlock - */
11900 /*-----------------------------------------------------------------*/
11901 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
11902 operand **parms, const char *name)
11905 operand *psb, *handle;
11906 assert (nparms==2);
11908 /* save registers that need to be saved */
11909 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11910 ds390_rUmaskForOp (IC_RESULT(ic))));
11914 /* put pointer to state block into DPTR1 */
11915 aopOp (psb, ic, FALSE, FALSE);
11916 if (AOP_TYPE (psb) == AOP_IMMD) {
11917 emitcode ("mov","dps,#1");
11918 emitcode ("mov", "dptr,%s", aopGet (AOP (psb), 0, TRUE, FALSE, FALSE));
11919 emitcode ("mov","dps,#0");
11921 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,FALSE));
11922 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,FALSE));
11923 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,FALSE));
11925 freeAsmop (psb, NULL, ic, FALSE);
11927 /* put libraryID into DPTR */
11928 emitcode ("mov","dptr,#LibraryID");
11930 /* put handle into r3:r2 */
11931 aopOp (handle, ic, FALSE, FALSE);
11932 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11933 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11934 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11935 emitcode ("pop","ar3");
11936 emitcode ("pop","ar2");
11938 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11939 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11941 freeAsmop (psb, NULL, ic, FALSE);
11943 /* make the call */
11944 emitcode ("lcall","NatLib_Install%sStateBlock",name);
11946 /* put return value into place*/
11948 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
11950 aopPut(AOP(IC_RESULT(ic)),"a",0);
11951 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11952 unsavermask(rsave);
11955 /*-----------------------------------------------------------------*/
11956 /* genNatLibRemoveStateBlock - */
11957 /*-----------------------------------------------------------------*/
11958 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
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 unsavermask(rsave);
11975 /*-----------------------------------------------------------------*/
11976 /* genNatLibGetStateBlock - */
11977 /*-----------------------------------------------------------------*/
11978 static void genNatLibGetStateBlock(iCode *ic,int nparms,
11979 operand **parms,const char *name)
11982 symbol *lbl = newiTempLabel(NULL);
11985 /* save registers that need to be saved */
11986 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11987 ds390_rUmaskForOp (IC_RESULT(ic))));
11989 /* put libraryID into DPTR */
11990 emitcode ("mov","dptr,#LibraryID");
11991 /* make the call */
11992 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
11993 emitcode ("jnz","!tlabel",lbl->key+100);
11995 /* put return value into place */
11996 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
11997 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
11998 emitcode ("push","ar3");
11999 emitcode ("push","ar2");
12000 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,FALSE));
12001 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,FALSE));
12003 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12004 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12006 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12007 emitcode ("","!tlabeldef",lbl->key+100);
12008 unsavermask(rsave);
12011 /*-----------------------------------------------------------------*/
12012 /* genMMMalloc - */
12013 /*-----------------------------------------------------------------*/
12014 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12015 int size, const char *name)
12020 symbol *lbl = newiTempLabel(NULL);
12022 assert (nparms == 1);
12023 /* save registers that need to be saved */
12024 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12025 ds390_rUmaskForOp (IC_RESULT(ic))));
12028 aopOp (bsize,ic,FALSE,FALSE);
12030 /* put the size in R4-R2 */
12031 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12032 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,FALSE));
12033 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,FALSE));
12035 emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,FALSE));
12036 emitcode("pop","ar4");
12038 emitcode("pop","ar3");
12039 emitcode("pop","ar2");
12041 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,FALSE));
12042 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,FALSE));
12044 emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,FALSE));
12047 freeAsmop (bsize, NULL, ic, FALSE);
12049 /* make the call */
12050 emitcode ("lcall","MM_%s",name);
12051 emitcode ("jz","!tlabel",lbl->key+100);
12052 emitcode ("mov","r2,#!constbyte",0xff);
12053 emitcode ("mov","r3,#!constbyte",0xff);
12054 emitcode ("","!tlabeldef",lbl->key+100);
12055 /* we don't care about the pointer : we just save the handle */
12056 rsym = OP_SYMBOL(IC_RESULT(ic));
12057 if (rsym->liveFrom != rsym->liveTo) {
12058 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12059 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12060 emitcode ("push","ar3");
12061 emitcode ("push","ar2");
12062 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,FALSE));
12063 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,FALSE));
12065 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12066 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12068 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12070 unsavermask(rsave);
12073 /*-----------------------------------------------------------------*/
12075 /*-----------------------------------------------------------------*/
12076 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12081 assert (nparms == 1);
12082 /* save registers that need to be saved */
12083 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12084 ds390_rUmaskForOp (IC_RESULT(ic))));
12087 aopOp (handle,ic,FALSE,FALSE);
12089 /* put the size in R4-R2 */
12090 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12091 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
12092 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
12093 emitcode("pop","ar3");
12094 emitcode("pop","ar2");
12096 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
12097 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
12099 freeAsmop (handle, NULL, ic, FALSE);
12101 /* make the call */
12102 emitcode ("lcall","MM_Deref");
12105 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12106 if (rsym->liveFrom != rsym->liveTo) {
12107 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12108 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12109 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12110 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12111 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12115 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12116 unsavermask(rsave);
12119 /*-----------------------------------------------------------------*/
12120 /* genMMUnrestrictedPersist - */
12121 /*-----------------------------------------------------------------*/
12122 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12127 assert (nparms == 1);
12128 /* save registers that need to be saved */
12129 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12130 ds390_rUmaskForOp (IC_RESULT(ic))));
12133 aopOp (handle,ic,FALSE,FALSE);
12135 /* put the size in R3-R2 */
12136 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12137 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
12138 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
12139 emitcode("pop","ar3");
12140 emitcode("pop","ar2");
12142 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
12143 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
12145 freeAsmop (handle, NULL, ic, FALSE);
12147 /* make the call */
12148 emitcode ("lcall","MM_UnrestrictedPersist");
12151 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12152 if (rsym->liveFrom != rsym->liveTo) {
12153 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12154 aopPut(AOP(IC_RESULT(ic)),"a",0);
12155 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12158 unsavermask(rsave);
12161 /*-----------------------------------------------------------------*/
12162 /* genSystemExecJavaProcess - */
12163 /*-----------------------------------------------------------------*/
12164 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12167 operand *handle, *pp;
12169 assert (nparms==2);
12170 /* save registers that need to be saved */
12171 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12172 ds390_rUmaskForOp (IC_RESULT(ic))));
12177 /* put the handle in R3-R2 */
12178 aopOp (handle,ic,FALSE,FALSE);
12179 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12180 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
12181 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
12182 emitcode("pop","ar3");
12183 emitcode("pop","ar2");
12185 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
12186 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
12188 freeAsmop (handle, NULL, ic, FALSE);
12190 /* put pointer in DPTR */
12191 aopOp (pp,ic,FALSE,FALSE);
12192 if (AOP_TYPE(pp) == AOP_IMMD) {
12193 emitcode ("mov", "dptr,%s", aopGet (AOP (pp), 0, TRUE, FALSE, FALSE));
12194 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12195 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,FALSE));
12196 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,FALSE));
12197 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,FALSE));
12199 freeAsmop (handle, NULL, ic, FALSE);
12201 /* make the call */
12202 emitcode ("lcall","System_ExecJavaProcess");
12204 /* put result in place */
12206 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12207 if (rsym->liveFrom != rsym->liveTo) {
12208 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12209 aopPut(AOP(IC_RESULT(ic)),"a",0);
12210 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12214 unsavermask(rsave);
12217 /*-----------------------------------------------------------------*/
12218 /* genSystemRTCRegisters - */
12219 /*-----------------------------------------------------------------*/
12220 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12226 assert (nparms==1);
12227 /* save registers that need to be saved */
12228 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12229 ds390_rUmaskForOp (IC_RESULT(ic))));
12232 /* put pointer in DPTR */
12233 aopOp (pp,ic,FALSE,FALSE);
12234 if (AOP_TYPE (pp) == AOP_IMMD) {
12235 emitcode ("mov","dps,#1");
12236 emitcode ("mov", "dptr,%s", aopGet (AOP (pp), 0, TRUE, FALSE, FALSE));
12237 emitcode ("mov","dps,#0");
12239 emitcode ("mov","dpl1,%s",aopGet(AOP(pp),0,FALSE,FALSE,FALSE));
12240 emitcode ("mov","dph1,%s",aopGet(AOP(pp),1,FALSE,FALSE,FALSE));
12241 emitcode ("mov","dpx1,%s",aopGet(AOP(pp),2,FALSE,FALSE,FALSE));
12243 freeAsmop (pp, NULL, ic, FALSE);
12245 /* make the call */
12246 emitcode ("lcall","System_%sRTCRegisters",name);
12248 unsavermask(rsave);
12251 /*-----------------------------------------------------------------*/
12252 /* genSystemThreadSleep - */
12253 /*-----------------------------------------------------------------*/
12254 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12259 assert (nparms==1);
12260 /* save registers that need to be saved */
12261 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12262 ds390_rUmaskForOp (IC_RESULT(ic))));
12265 aopOp(to,ic,FALSE,FALSE);
12266 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12267 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12268 emitcode ("push","%s",aopGet(AOP(to),0,FALSE,TRUE,FALSE));
12269 emitcode ("push","%s",aopGet(AOP(to),1,FALSE,TRUE,FALSE));
12270 emitcode ("push","%s",aopGet(AOP(to),2,FALSE,TRUE,FALSE));
12271 emitcode ("push","%s",aopGet(AOP(to),3,FALSE,TRUE,FALSE));
12272 emitcode ("pop","ar3");
12273 emitcode ("pop","ar2");
12274 emitcode ("pop","ar1");
12275 emitcode ("pop","ar0");
12277 emitcode ("mov","r0,%s",aopGet(AOP(to),0,FALSE,TRUE,FALSE));
12278 emitcode ("mov","r1,%s",aopGet(AOP(to),1,FALSE,TRUE,FALSE));
12279 emitcode ("mov","r2,%s",aopGet(AOP(to),2,FALSE,TRUE,FALSE));
12280 emitcode ("mov","r3,%s",aopGet(AOP(to),3,FALSE,TRUE,FALSE));
12282 freeAsmop (to, NULL, ic, FALSE);
12284 /* suspend in acc */
12286 aopOp(s,ic,FALSE,FALSE);
12287 emitcode ("mov","a,%s",aopGet(AOP(s),0,FALSE,TRUE,FALSE));
12288 freeAsmop (s, NULL, ic, FALSE);
12290 /* make the call */
12291 emitcode ("lcall","System_%s",name);
12293 unsavermask(rsave);
12296 /*-----------------------------------------------------------------*/
12297 /* genSystemThreadResume - */
12298 /*-----------------------------------------------------------------*/
12299 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12304 assert (nparms==2);
12305 /* save registers that need to be saved */
12306 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12307 ds390_rUmaskForOp (IC_RESULT(ic))));
12313 aopOp(pid,ic,FALSE,FALSE);
12314 emitcode ("mov","r0,%s",aopGet(AOP(pid),0,FALSE,TRUE,FALSE));
12315 freeAsmop (pid, NULL, ic, FALSE);
12318 aopOp(tid,ic,FALSE,FALSE);
12319 emitcode ("mov","a,%s",aopGet(AOP(tid),0,FALSE,TRUE,FALSE));
12320 freeAsmop (tid, NULL, ic, FALSE);
12322 emitcode ("lcall","System_ThreadResume");
12324 /* put result into place */
12326 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12327 if (rsym->liveFrom != rsym->liveTo) {
12328 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12329 aopPut(AOP(IC_RESULT(ic)),"a",0);
12330 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12333 unsavermask(rsave);
12336 /*-----------------------------------------------------------------*/
12337 /* genSystemProcessResume - */
12338 /*-----------------------------------------------------------------*/
12339 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
12344 assert (nparms==1);
12345 /* save registers that need to be saved */
12346 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12347 ds390_rUmaskForOp (IC_RESULT(ic))));
12352 aopOp(pid,ic,FALSE,FALSE);
12353 emitcode ("mov","a,%s",aopGet(AOP(pid),0,FALSE,TRUE,FALSE));
12354 freeAsmop (pid, NULL, ic, FALSE);
12356 emitcode ("lcall","System_ProcessResume");
12358 unsavermask(rsave);
12361 /*-----------------------------------------------------------------*/
12363 /*-----------------------------------------------------------------*/
12364 static void genSystem (iCode *ic,int nparms,char *name)
12366 assert(nparms == 0);
12368 emitcode ("lcall","System_%s",name);
12371 /*-----------------------------------------------------------------*/
12372 /* genSystemPoll - */
12373 /*-----------------------------------------------------------------*/
12374 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
12379 assert (nparms==1);
12380 /* save registers that need to be saved */
12381 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12382 ds390_rUmaskForOp (IC_RESULT(ic))));
12385 aopOp (fp,ic,FALSE,FALSE);
12386 if (AOP_TYPE (fp) == AOP_IMMD) {
12387 emitcode ("mov", "dptr,%s", aopGet (AOP (fp), 0, TRUE, FALSE, FALSE));
12388 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
12389 emitcode ("mov","dpl,%s",aopGet(AOP(fp),0,FALSE,FALSE,FALSE));
12390 emitcode ("mov","dph,%s",aopGet(AOP(fp),1,FALSE,FALSE,FALSE));
12391 emitcode ("mov","dpx,%s",aopGet(AOP(fp),2,FALSE,FALSE,FALSE));
12393 freeAsmop (fp, NULL, ic, FALSE);
12395 emitcode ("lcall","System_%sPoll",name);
12397 /* put result into place */
12399 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12400 if (rsym->liveFrom != rsym->liveTo) {
12401 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12402 aopPut(AOP(IC_RESULT(ic)),"a",0);
12403 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12406 unsavermask(rsave);
12409 /*-----------------------------------------------------------------*/
12410 /* genSystemGetCurrentID - */
12411 /*-----------------------------------------------------------------*/
12412 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
12414 assert (nparms==0);
12416 emitcode ("lcall","System_GetCurrent%sId",name);
12417 /* put result into place */
12419 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12420 if (rsym->liveFrom != rsym->liveTo) {
12421 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12422 aopPut(AOP(IC_RESULT(ic)),"a",0);
12423 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12428 /*-----------------------------------------------------------------*/
12429 /* genBuiltIn - calls the appropriate function to generating code */
12430 /* for a built in function */
12431 /*-----------------------------------------------------------------*/
12432 static void genBuiltIn (iCode *ic)
12434 operand *bi_parms[MAX_BUILTIN_ARGS];
12439 /* get all the arguments for a built in function */
12440 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
12442 /* which function is it */
12443 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
12444 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
12445 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
12446 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
12447 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
12448 } else if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
12449 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
12450 } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
12451 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
12452 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
12453 genMemsetX(bi_iCode,nbi_parms,bi_parms);
12454 } else if (strcmp(bif->name,"__builtin_inp")==0) {
12455 genInp(bi_iCode,nbi_parms,bi_parms);
12456 } else if (strcmp(bif->name,"__builtin_outp")==0) {
12457 genOutp(bi_iCode,nbi_parms,bi_parms);
12458 } else if (strcmp(bif->name,"__builtin_swapw")==0) {
12459 genSwapW(bi_iCode,nbi_parms,bi_parms);
12460 /* JavaNative builtIns */
12461 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
12462 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
12463 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
12464 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
12465 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
12466 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
12467 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
12468 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
12469 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
12470 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12471 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
12472 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12473 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
12474 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
12475 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
12476 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
12477 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
12478 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12479 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
12480 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12481 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
12482 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
12483 } else if (strcmp(bif->name,"MM_Malloc")==0) {
12484 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
12485 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
12486 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
12487 } else if (strcmp(bif->name,"MM_Free")==0) {
12488 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
12489 } else if (strcmp(bif->name,"MM_Deref")==0) {
12490 genMMDeref(bi_iCode,nbi_parms,bi_parms);
12491 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
12492 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
12493 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
12494 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
12495 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
12496 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
12497 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
12498 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
12499 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
12500 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
12501 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
12502 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
12503 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
12504 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
12505 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
12506 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
12507 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12508 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12509 } else if (strcmp(bif->name,"System_SaveThread")==0) {
12510 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12511 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12512 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12513 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
12514 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
12515 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
12516 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
12517 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
12518 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
12519 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
12520 genSystem(bi_iCode,nbi_parms,"ProcessYield");
12521 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
12522 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
12523 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
12524 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
12525 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
12526 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
12527 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
12528 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
12529 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
12530 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
12532 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
12538 /*-----------------------------------------------------------------*/
12539 /* gen390Code - generate code for Dallas 390 based controllers */
12540 /*-----------------------------------------------------------------*/
12542 gen390Code (iCode * lic)
12547 lineHead = lineCurr = NULL;
12548 dptrn[1][0] = "dpl1";
12549 dptrn[1][1] = "dph1";
12550 dptrn[1][2] = "dpx1";
12552 if (options.model == MODEL_FLAT24) {
12553 fReturnSizeDS390 = 5;
12554 fReturn = fReturn24;
12556 fReturnSizeDS390 = 4;
12557 fReturn = fReturn16;
12558 options.stack10bit=0;
12561 /* print the allocation information */
12563 printAllocInfo (currFunc, codeOutFile);
12565 /* if debug information required */
12566 if (options.debug && currFunc)
12568 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
12570 if (IS_STATIC (currFunc->etype))
12571 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
12573 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
12576 /* stack pointer name */
12577 if (options.useXstack)
12583 for (ic = lic; ic; ic = ic->next)
12586 if (ic->lineno && cln != ic->lineno)
12591 emitcode ("", "C$%s$%d$%d$%d ==.",
12592 FileBaseName (ic->filename), ic->lineno,
12593 ic->level, ic->block);
12596 if (!options.noCcodeInAsm) {
12597 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
12598 printCLine(ic->filename, ic->lineno));
12602 if (options.iCodeInAsm) {
12603 emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
12605 /* if the result is marked as
12606 spilt and rematerializable or code for
12607 this has already been generated then
12609 if (resultRemat (ic) || ic->generated)
12612 /* depending on the operation */
12632 /* IPOP happens only when trying to restore a
12633 spilt live range, if there is an ifx statement
12634 following this pop then the if statement might
12635 be using some of the registers being popped which
12636 would destory the contents of the register so
12637 we need to check for this condition and handle it */
12639 ic->next->op == IFX &&
12640 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
12641 genIfx (ic->next, ic);
12659 genEndFunction (ic);
12679 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
12696 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
12700 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
12707 /* note these two are xlated by algebraic equivalence
12708 during parsing SDCC.y */
12709 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12710 "got '>=' or '<=' shouldn't have come here");
12714 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
12726 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
12730 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
12734 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
12758 genRightShift (ic);
12761 case GET_VALUE_AT_ADDRESS:
12762 genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
12766 if (POINTER_SET (ic))
12767 genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
12793 if (ic->builtinSEND) genBuiltIn(ic);
12794 else addSet (&_G.sendSet, ic);
12807 /* now we are ready to call the
12808 peep hole optimizer */
12809 if (!options.nopeep)
12810 peepHole (&lineHead);
12812 /* now do the actual printing */
12813 printLine (lineHead, codeOutFile);