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) _movA(x)
113 #define MOVB(x) _movB(x)
115 #define CLRC emitcode("clr","c")
116 #define SETC emitcode("setb","c")
118 // A scratch register which will be used to hold
119 // result bytes from operands in far space via DPTR2.
120 #define DP2_RESULT_REG "_ap"
122 static lineNode *lineHead = NULL;
123 static lineNode *lineCurr = NULL;
125 static unsigned char SLMask[] =
126 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
127 0xE0, 0xC0, 0x80, 0x00};
128 static unsigned char SRMask[] =
129 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
130 0x07, 0x03, 0x01, 0x00};
136 #define PROTECT_SP {if (options.protect_sp_update) { \
137 symbol *lbl = newiTempLabel(NULL); \
138 emitcode ("setb","F1"); \
139 emitcode ("jbc","EA,!tlabel",lbl->key+100); \
140 emitcode ("clr","F1"); \
141 emitcode ("","!tlabeldef",lbl->key+100); \
143 #define UNPROTECT_SP { if (options.protect_sp_update) { \
144 symbol *lbl = newiTempLabel(NULL); \
145 emitcode ("jnb","F1,!tlabel",lbl->key+100); \
146 emitcode ("setb","EA"); \
147 emitcode ("","!tlabeldef",lbl->key+100); \
151 /*-----------------------------------------------------------------*/
152 /* emitcode - writes the code into a file : for now it is simple */
153 /*-----------------------------------------------------------------*/
155 emitcode (char *inst, char *fmt,...)
158 char lb[INITIAL_INLINEASM];
167 SNPRINTF (lb, sizeof(lb), "%s\t", inst);
171 SNPRINTF (lb, sizeof(lb), "%s", inst);
174 tvsprintf (lb + strlen(lb), sizeof(lb) - strlen(lb),
179 tvsprintf (lb, sizeof(lb), fmt, ap);
183 while (isspace (*lbp))
190 lineCurr = (lineCurr ?
191 connectLine (lineCurr, newLineNode (lb)) :
192 (lineHead = newLineNode (lb)));
195 lineCurr->isInline = _G.inLine;
196 lineCurr->isDebug = _G.debugLine;
201 // Move the passed value into A unless it is already there.
206 if (strcmp(s,"a") && strcmp(s,"acc"))
208 emitcode("mov","a,%s",s);
213 // Move the passed value into B unless it is already there.
220 emitcode("mov","b,%s",s);
224 /*-----------------------------------------------------------------*/
225 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
226 /*-----------------------------------------------------------------*/
228 getFreePtr (iCode * ic, asmop ** aopp, bool result)
233 /* the logic: if r0 & r1 used in the instruction
234 then we are in trouble otherwise */
236 /* first check if r0 & r1 are used by this
237 instruction, in which case we are in trouble */
238 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
239 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
244 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
245 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
247 /* if no usage of r0 then return it */
250 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
251 (*aopp)->type = AOP_R0;
253 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
256 /* if no usage of r1 then return it */
259 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
260 (*aopp)->type = AOP_R1;
262 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
265 /* now we know they both have usage */
266 /* if r0 not used in this instruction */
269 /* push it if not already pushed */
272 emitcode ("push", "%s",
273 ds390_regWithIdx (R0_IDX)->dname);
277 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
278 (*aopp)->type = AOP_R0;
280 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
283 /* if r1 not used then */
287 /* push it if not already pushed */
290 emitcode ("push", "%s",
291 ds390_regWithIdx (R1_IDX)->dname);
295 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
296 (*aopp)->type = AOP_R1;
297 return ds390_regWithIdx (R1_IDX);
301 /* I said end of world but not quite end of world yet */
302 /* if this is a result then we can push it on the stack */
305 (*aopp)->type = AOP_STK;
309 /* other wise this is true end of the world */
310 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
311 "getFreePtr should never reach here");
314 return NULL; // notreached, but makes compiler happy.
317 /*-----------------------------------------------------------------*/
318 /* newAsmop - creates a new asmOp */
319 /*-----------------------------------------------------------------*/
321 newAsmop (short type)
325 aop = Safe_calloc (1, sizeof (asmop));
330 static int _currentDPS; /* Current processor DPS. */
331 static int _desiredDPS; /* DPS value compiler thinks we should be using. */
332 static int _lazyDPS = 0; /* if non-zero, we are doing lazy evaluation of DPS changes. */
334 /*-----------------------------------------------------------------*/
335 /* genSetDPTR: generate code to select which DPTR is in use (zero */
336 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390 */
337 /* alternate DPTR (DPL1/DPH1/DPX1). */
338 /*-----------------------------------------------------------------*/
343 /* If we are doing lazy evaluation, simply note the desired
344 * change, but don't emit any code yet.
354 emitcode ("mov", "dps,#0");
359 emitcode ("mov", "dps,#1");
363 /*-----------------------------------------------------------------*/
364 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
366 /* Any code that operates on DPTR (NB: not on the individual */
367 /* components, like DPH) *must* call _flushLazyDPS() before using */
368 /* DPTR within a lazy DPS evaluation block. */
370 /* Note that aopPut and aopGet already contain the proper calls to */
371 /* _flushLazyDPS, so it is safe to use these calls within a lazy */
372 /* DPS evaluation block. */
374 /* Also, _flushLazyDPS must be called before any flow control */
375 /* operations that could potentially branch out of the block. */
377 /* Lazy DPS evaluation is simply an optimization (though an */
378 /* important one), so if in doubt, leave it out. */
379 /*-----------------------------------------------------------------*/
381 _startLazyDPSEvaluation (void)
385 #ifdef BETTER_LITERAL_SHIFT
392 /*-----------------------------------------------------------------*/
393 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
394 /* desired one. Call before using DPTR within a lazy DPS evaluation */
396 /*-----------------------------------------------------------------*/
406 if (_desiredDPS != _currentDPS)
410 emitcode ("inc", "dps");
414 emitcode ("dec", "dps");
416 _currentDPS = _desiredDPS;
420 /*-----------------------------------------------------------------*/
421 /* _endLazyDPSEvaluation: end lazy DPS evaluation block. */
423 /* Forces us back to the safe state (standard DPTR selected). */
424 /*-----------------------------------------------------------------*/
426 _endLazyDPSEvaluation (void)
428 #ifdef BETTER_LITERAL_SHIFT
447 /*-----------------------------------------------------------------*/
448 /* pointerCode - returns the code for a pointer type */
449 /*-----------------------------------------------------------------*/
451 pointerCode (sym_link * etype)
454 return PTR_TYPE (SPEC_OCLS (etype));
458 /*-----------------------------------------------------------------*/
459 /* aopForSym - for a true symbol */
460 /*-----------------------------------------------------------------*/
462 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
465 memmap *space = SPEC_OCLS (sym->etype);
467 /* if already has one */
471 /* assign depending on the storage class */
472 /* if it is on the stack or indirectly addressable */
473 /* space we need to assign either r0 or r1 to it */
474 if ((sym->onStack && !options.stack10bit) || sym->iaccess)
476 sym->aop = aop = newAsmop (0);
477 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
478 aop->size = getSize (sym->type);
480 /* now assign the address of the variable to
481 the pointer register */
482 if (aop->type != AOP_STK)
488 emitcode ("push", "acc");
491 emitcode ("push", "b");
493 emitcode ("mov", "a,_bp");
494 emitcode ("add", "a,#!constbyte",
496 ((char) (sym->stack - _G.nRegsSaved)) :
497 ((char) sym->stack)) & 0xff);
498 emitcode ("mov", "%s,a",
499 aop->aopu.aop_ptr->name);
502 emitcode ("pop", "b");
505 emitcode ("pop", "acc");
508 emitcode ("mov", "%s,#%s",
509 aop->aopu.aop_ptr->name,
511 aop->paged = space->paged;
514 aop->aopu.aop_stk = sym->stack;
518 if (sym->onStack && options.stack10bit)
520 short stack_val = -((sym->stack < 0) ?
521 ((short) (sym->stack - _G.nRegsSaved)) :
522 ((short) sym->stack)) ;
523 if (useDP2 && _G.dptr1InUse) {
524 emitcode ("push","dpl1");
525 emitcode ("push","dph1");
526 emitcode ("push","dpx1");
527 } else if (_G.dptrInUse ) {
528 emitcode ("push","dpl");
529 emitcode ("push","dph");
530 emitcode ("push","dpx");
532 /* It's on the 10 bit stack, which is located in
535 if (stack_val < 0 && stack_val > -5) { /* between -5 & -1 */
537 if (options.model == MODEL_FLAT24)
538 emitcode ("mov", "dpx1,#!constbyte", (options.stack_loc >> 16) & 0xff);
540 emitcode ("mov", "dph1,_bpx+1");
541 emitcode ("mov", "dpl1,_bpx");
542 emitcode ("mov","dps,#1");
544 if (options.model == MODEL_FLAT24)
545 emitcode ("mov", "dpx,#!constbyte", (options.stack_loc >> 16) & 0xff);
546 emitcode ("mov", "dph,_bpx+1");
547 emitcode ("mov", "dpl,_bpx");
549 stack_val = -stack_val;
550 while (stack_val--) {
551 emitcode ("inc","dptr");
554 emitcode("mov","dps,#0");
558 emitcode ("push", "acc");
561 emitcode ("push", "b");
563 emitcode ("mov", "a,_bpx");
564 emitcode ("clr","c");
565 emitcode ("subb", "a,#!constbyte", stack_val & 0xff);
566 emitcode ("mov","b,a");
567 emitcode ("mov","a,_bpx+1");
568 emitcode ("subb","a,#!constbyte",(stack_val >> 8) & 0xff);
570 if (options.model == MODEL_FLAT24)
571 emitcode ("mov", "dpx1,#!constbyte", (options.stack_loc >> 16) & 0xff);
573 emitcode ("mov", "dph1,a");
574 emitcode ("mov", "dpl1,b");
576 if (options.model == MODEL_FLAT24)
577 emitcode ("mov", "dpx,#!constbyte", (options.stack_loc >> 16) & 0xff);
578 emitcode ("mov", "dph,a");
579 emitcode ("mov", "dpl,b");
583 emitcode ("pop", "b");
586 emitcode ("pop", "acc");
588 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
589 aop->size = getSize (sym->type);
593 /* if in bit space */
594 if (IN_BITSPACE (space))
596 sym->aop = aop = newAsmop (AOP_CRY);
597 aop->aopu.aop_dir = sym->rname;
598 aop->size = getSize (sym->type);
601 /* if it is in direct space */
602 if (IN_DIRSPACE (space))
604 sym->aop = aop = newAsmop (AOP_DIR);
605 aop->aopu.aop_dir = sym->rname;
606 aop->size = getSize (sym->type);
610 /* special case for a function */
611 if (IS_FUNC (sym->type))
613 sym->aop = aop = newAsmop (AOP_IMMD);
614 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
615 aop->size = FPTRSIZE;
619 /* only remaining is far space */
620 /* in which case DPTR gets the address */
621 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
626 emitcode ("mov", "dptr,#%s", sym->rname);
631 emitcode ("mov", "dptr,#%s", sym->rname);
633 aop->size = getSize (sym->type);
635 /* if it is in code space */
636 if (IN_CODESPACE (space))
642 /*-----------------------------------------------------------------*/
643 /* aopForRemat - rematerialzes an object */
644 /*-----------------------------------------------------------------*/
646 aopForRemat (symbol * sym)
648 iCode *ic = sym->rematiCode;
649 asmop *aop = newAsmop (AOP_IMMD);
656 val += (int) operandLitValue (IC_RIGHT (ic));
657 else if (ic->op == '-')
658 val -= (int) operandLitValue (IC_RIGHT (ic));
659 else if (IS_CAST_ICODE(ic)) {
660 sym_link *from_type = operandType(IC_RIGHT(ic));
661 aop->aopu.aop_immd.from_cast_remat = 1;
662 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
663 ptr_type = DCL_TYPE(from_type);
664 if (ptr_type == IPOINTER) {
671 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
676 SNPRINTF (buffer, sizeof(buffer),
678 OP_SYMBOL (IC_LEFT (ic))->rname,
679 val >= 0 ? '+' : '-',
684 if (IS_ASSIGN_ICODE(ic) && isOperandLiteral(IC_RIGHT(ic)))
686 SNPRINTF(buffer, sizeof(buffer),
687 "0x%x",(int) operandLitValue (IC_RIGHT (ic)));
691 strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
695 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);
696 /* set immd2 field if required */
697 if (aop->aopu.aop_immd.from_cast_remat)
699 tsprintf(buffer, sizeof(buffer), "#!constbyte",ptr_type);
700 aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
706 /*-----------------------------------------------------------------*/
707 /* aopHasRegs - returns true if aop has regs between from-to */
708 /*-----------------------------------------------------------------*/
709 static int aopHasRegs(asmop *aop, int from, int to)
713 if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
715 for (; size < aop->size ; size++) {
717 for (reg = from ; reg <= to ; reg++)
718 if (aop->aopu.aop_reg[size] == ds390_regWithIdx(reg)) return 1;
723 /*-----------------------------------------------------------------*/
724 /* regsInCommon - two operands have some registers in common */
725 /*-----------------------------------------------------------------*/
727 regsInCommon (operand * op1, operand * op2)
732 /* if they have registers in common */
733 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
736 sym1 = OP_SYMBOL (op1);
737 sym2 = OP_SYMBOL (op2);
739 if (sym1->nRegs == 0 || sym2->nRegs == 0)
742 for (i = 0; i < sym1->nRegs; i++)
748 for (j = 0; j < sym2->nRegs; j++)
753 if (sym2->regs[j] == sym1->regs[i])
761 /*-----------------------------------------------------------------*/
762 /* operandsEqu - equivalent */
763 /*-----------------------------------------------------------------*/
765 operandsEqu (operand * op1, operand * op2)
769 /* if they not symbols */
770 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
773 sym1 = OP_SYMBOL (op1);
774 sym2 = OP_SYMBOL (op2);
776 /* if both are itemps & one is spilt
777 and the other is not then false */
778 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
779 sym1->isspilt != sym2->isspilt)
782 /* if they are the same */
786 if (strcmp (sym1->rname, sym2->rname) == 0)
790 /* if left is a tmp & right is not */
791 if (IS_ITEMP (op1) &&
794 (sym1->usl.spillLoc == sym2))
797 if (IS_ITEMP (op2) &&
801 (sym2->usl.spillLoc == sym1))
807 /*-----------------------------------------------------------------*/
808 /* sameRegs - two asmops have the same registers */
809 /*-----------------------------------------------------------------*/
811 sameRegs (asmop * aop1, asmop * aop2)
817 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
824 if (aop1->type != AOP_REG ||
825 aop2->type != AOP_REG)
828 if (aop1->size != aop2->size)
831 for (i = 0; i < aop1->size; i++)
832 if (aop1->aopu.aop_reg[i] !=
833 aop2->aopu.aop_reg[i])
839 /*-----------------------------------------------------------------*/
840 /* aopOp - allocates an asmop for an operand : */
841 /*-----------------------------------------------------------------*/
843 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
852 /* if this a literal */
853 if (IS_OP_LITERAL (op))
855 op->aop = aop = newAsmop (AOP_LIT);
856 aop->aopu.aop_lit = op->operand.valOperand;
857 aop->size = getSize (operandType (op));
861 /* if already has a asmop then continue */
865 /* if the underlying symbol has a aop */
866 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
868 op->aop = OP_SYMBOL (op)->aop;
872 /* if this is a true symbol */
873 if (IS_TRUE_SYMOP (op))
875 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
879 /* this is a temporary : this has
885 e) can be a return use only */
887 sym = OP_SYMBOL (op);
890 /* if the type is a conditional */
891 if (sym->regType == REG_CND)
893 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
898 /* if it is spilt then two situations
900 b) has a spill location */
901 if (sym->isspilt || sym->nRegs == 0)
904 /* rematerialize it NOW */
907 sym->aop = op->aop = aop =
909 aop->size = getSize (sym->type);
916 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
917 aop->size = getSize (sym->type);
918 for (i = 0; i < 2; i++)
919 aop->aopu.aop_str[i] = accUse[i];
929 /* a AOP_STR uses DPTR, but DPTR is already in use;
932 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"AOP_STR with DPTR in use!");
935 aop = op->aop = sym->aop = newAsmop (AOP_STR);
936 aop->size = getSize (sym->type);
937 for (i = 0; i < (int) fReturnSizeDS390; i++)
938 aop->aopu.aop_str[i] = fReturn[i];
942 if (sym->dptr) { /* has been allocated to a DPTRn */
943 aop = op->aop = sym->aop = newAsmop (AOP_DPTRn);
944 aop->size = getSize (sym->type);
945 aop->aopu.dptr = sym->dptr;
948 /* else spill location */
949 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
950 /* force a new aop if sizes differ */
951 sym->usl.spillLoc->aop = NULL;
953 sym->aop = op->aop = aop =
954 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
955 aop->size = getSize (sym->type);
959 /* must be in a register */
960 sym->aop = op->aop = aop = newAsmop (AOP_REG);
961 aop->size = sym->nRegs;
962 for (i = 0; i < sym->nRegs; i++)
963 aop->aopu.aop_reg[i] = sym->regs[i];
966 /*-----------------------------------------------------------------*/
967 /* freeAsmop - free up the asmop given to an operand */
968 /*----------------------------------------------------------------*/
970 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
987 /* depending on the asmop type only three cases need work AOP_RO
988 , AOP_R1 && AOP_STK */
996 emitcode ("pop", "ar0");
1000 bitVectUnSetBit (ic->rUsed, R0_IDX);
1008 emitcode ("pop", "ar1");
1012 bitVectUnSetBit (ic->rUsed, R1_IDX);
1018 int stk = aop->aopu.aop_stk + aop->size;
1019 bitVectUnSetBit (ic->rUsed, R0_IDX);
1020 bitVectUnSetBit (ic->rUsed, R1_IDX);
1022 getFreePtr (ic, &aop, FALSE);
1024 if (options.stack10bit)
1026 /* I'm not sure what to do here yet... */
1029 "*** Warning: probably generating bad code for "
1030 "10 bit stack mode.\n");
1035 emitcode ("mov", "a,_bp");
1036 emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
1037 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1041 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1046 emitcode ("pop", "acc");
1047 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1050 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1053 freeAsmop (op, NULL, ic, TRUE);
1056 emitcode ("pop", "ar0");
1062 emitcode ("pop", "ar1");
1067 if (_G.dptr1InUse) {
1068 emitcode ("pop","dpx1");
1069 emitcode ("pop","dph1");
1070 emitcode ("pop","dpl1");
1075 emitcode ("pop","dpx");
1076 emitcode ("pop","dph");
1077 emitcode ("pop","dpl");
1082 /* all other cases just dealloc */
1088 OP_SYMBOL (op)->aop = NULL;
1089 /* if the symbol has a spill */
1091 SPIL_LOC (op)->aop = NULL;
1096 #define DEFAULT_ACC_WARNING 0
1097 static int saveAccWarn = DEFAULT_ACC_WARNING;
1099 /*-------------------------------------------------------------------*/
1100 /* aopGet - for fetching value of the aop */
1102 /* Set saveAcc to NULL if you are sure it is OK to clobber the value */
1103 /* in the accumulator. Set it to the name of a free register */
1104 /* if acc must be preserved; the register will be used to preserve */
1105 /* acc temporarily and to return the result byte. */
1106 /*-------------------------------------------------------------------*/
1115 /* offset is greater than
1117 if (offset > (aop->size - 1) &&
1118 aop->type != AOP_LIT)
1121 /* depending on type */
1127 /* if we need to increment it */
1128 while (offset > aop->coff)
1130 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1134 while (offset < aop->coff)
1136 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1143 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1144 return (dname ? "acc" : "a");
1146 SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1147 return Safe_strdup(buffer);
1150 assert(offset <= 3);
1151 return dptrn[aop->aopu.dptr][offset];
1156 if (aop->type == AOP_DPTR2)
1164 // if (aop->type != AOP_DPTR2)
1166 // if (saveAccWarn) { fprintf(stderr, "saveAcc for DPTR...\n"); }
1167 // emitcode(";", "spanky: saveAcc for DPTR");
1170 emitcode ("xch", "a, %s", saveAcc);
1175 while (offset > aop->coff)
1177 emitcode ("inc", "dptr");
1181 while (offset < aop->coff)
1183 emitcode ("lcall", "__decdptr");
1190 emitcode ("clr", "a");
1191 emitcode ("movc", "a,@a+dptr");
1195 emitcode ("movx", "a,@dptr");
1198 if (aop->type == AOP_DPTR2)
1206 emitcode ("xch", "a, %s", saveAcc);
1207 // if (strcmp(saveAcc, "_ap"))
1209 // emitcode(";", "spiffy: non _ap return from aopGet.");
1214 return (dname ? "acc" : "a");
1217 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1219 SNPRINTF(buffer, sizeof(buffer),
1220 "%s",aop->aopu.aop_immd.aop_immd2);
1224 SNPRINTF(buffer, sizeof(buffer),
1225 "#%s", aop->aopu.aop_immd.aop_immd1);
1231 tsprintf(buffer, sizeof(buffer),
1232 "#!his",aop->aopu.aop_immd.aop_immd1);
1235 tsprintf(buffer, sizeof(buffer),
1236 "#!hihis",aop->aopu.aop_immd.aop_immd1);
1239 tsprintf(buffer, sizeof(buffer),
1240 "#!hihihis",aop->aopu.aop_immd.aop_immd1);
1242 default: /* should not need this (just in case) */
1243 SNPRINTF (buffer, sizeof(buffer),
1245 aop->aopu.aop_immd.aop_immd1,
1251 SNPRINTF (buffer, sizeof(buffer),
1252 "#%s", aop->aopu.aop_immd.aop_immd1);
1254 return Safe_strdup(buffer);
1259 SNPRINTF (buffer, sizeof(buffer),
1266 SNPRINTF(buffer, sizeof(buffer),
1267 "%s", aop->aopu.aop_dir);
1270 return Safe_strdup(buffer);
1274 return aop->aopu.aop_reg[offset]->dname;
1276 return aop->aopu.aop_reg[offset]->name;
1279 emitcode ("clr", "a");
1280 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1281 emitcode ("rlc", "a");
1282 return (dname ? "acc" : "a");
1285 if (!offset && dname)
1287 return aop->aopu.aop_str[offset];
1290 return aopLiteral (aop->aopu.aop_lit, offset);
1294 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1298 return aop->aopu.aop_str[offset];
1302 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1303 "aopget got unsupported aop->type");
1306 return NULL; // not reached, but makes compiler happy.
1308 /*-----------------------------------------------------------------*/
1309 /* aopPut - puts a string for a aop */
1310 /*-----------------------------------------------------------------*/
1312 aopPut (asmop * aop, char *s, int offset)
1314 if (aop->size && offset > (aop->size - 1))
1316 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1317 "aopPut got offset > aop->size");
1321 /* will assign value to value */
1322 /* depending on where it is ofcourse */
1328 SNPRINTF (buffer, sizeof(buffer),
1330 aop->aopu.aop_dir, offset);
1334 SNPRINTF (buffer, sizeof(buffer),
1335 "%s", aop->aopu.aop_dir);
1339 if (strcmp (buffer, s))
1341 emitcode ("mov", "%s,%s", buffer, s);
1346 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1347 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1350 strcmp (s, "r0") == 0 ||
1351 strcmp (s, "r1") == 0 ||
1352 strcmp (s, "r2") == 0 ||
1353 strcmp (s, "r3") == 0 ||
1354 strcmp (s, "r4") == 0 ||
1355 strcmp (s, "r5") == 0 ||
1356 strcmp (s, "r6") == 0 ||
1357 strcmp (s, "r7") == 0)
1359 emitcode ("mov", "%s,%s",
1360 aop->aopu.aop_reg[offset]->dname, s);
1364 emitcode ("mov", "%s,%s",
1365 aop->aopu.aop_reg[offset]->name, s);
1371 emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1377 if (aop->type == AOP_DPTR2)
1385 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1386 "aopPut writting to code space");
1390 while (offset > aop->coff)
1393 emitcode ("inc", "dptr");
1396 while (offset < aop->coff)
1399 emitcode ("lcall", "__decdptr");
1404 /* if not in accumulater */
1407 emitcode ("movx", "@dptr,a");
1409 if (aop->type == AOP_DPTR2)
1417 while (offset > aop->coff)
1420 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1422 while (offset < aop->coff)
1425 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1432 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1438 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1440 else if (strcmp (s, "r0") == 0 ||
1441 strcmp (s, "r1") == 0 ||
1442 strcmp (s, "r2") == 0 ||
1443 strcmp (s, "r3") == 0 ||
1444 strcmp (s, "r4") == 0 ||
1445 strcmp (s, "r5") == 0 ||
1446 strcmp (s, "r6") == 0 ||
1447 strcmp (s, "r7") == 0)
1450 SNPRINTF(buff, sizeof(buff),
1452 emitcode ("mov", "@%s,%s",
1453 aop->aopu.aop_ptr->name, buff);
1457 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1462 if (strcmp (s, "a") == 0)
1463 emitcode ("push", "acc");
1467 emitcode ("push", "acc");
1469 emitcode ("push", s);
1475 /* if bit variable */
1476 if (!aop->aopu.aop_dir)
1478 emitcode ("clr", "a");
1479 emitcode ("rlc", "a");
1484 emitcode ("clr", "%s", aop->aopu.aop_dir);
1486 emitcode ("setb", "%s", aop->aopu.aop_dir);
1487 else if (!strcmp (s, "c"))
1488 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1491 if (strcmp (s, "a"))
1496 /* set C, if a >= 1 */
1497 emitcode ("add", "a,#!constbyte",0xff);
1498 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1506 if (strcmp (aop->aopu.aop_str[offset], s))
1507 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1512 if (!offset && (strcmp (s, "acc") == 0))
1515 if (strcmp (aop->aopu.aop_str[offset], s))
1516 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1520 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1521 "aopPut got unsupported aop->type");
1528 /*--------------------------------------------------------------------*/
1529 /* reAdjustPreg - points a register back to where it should (coff==0) */
1530 /*--------------------------------------------------------------------*/
1532 reAdjustPreg (asmop * aop)
1534 if ((aop->coff==0) || (aop->size <= 1)) {
1543 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1547 if (aop->type == AOP_DPTR2)
1554 emitcode ("lcall", "__decdptr");
1557 if (aop->type == AOP_DPTR2)
1567 #define AOP(op) op->aop
1568 #define AOP_TYPE(op) AOP(op)->type
1569 #define AOP_SIZE(op) AOP(op)->size
1570 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1571 AOP_TYPE(x) == AOP_R0))
1573 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1574 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1577 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1578 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1579 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1580 #define AOP_INDPTRn(x) (AOP_TYPE(x) == AOP_DPTRn)
1581 #define AOP_USESDPTR(x) ((AOP_TYPE(x) == AOP_DPTR) || (AOP_TYPE(x) == AOP_STR))
1582 #define AOP_USESDPTR2(x) ((AOP_TYPE(x) == AOP_DPTR2) || (AOP_TYPE(x) == AOP_DPTRn))
1584 // The following two macros can be used even if the aop has not yet been aopOp'd.
1585 #define AOP_IS_STR(x) (IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
1586 #define AOP_IS_DPTRn(x) (IS_SYMOP(x) && OP_SYMBOL(x)->dptr)
1588 /* Workaround for DS80C390 bug: div ab may return bogus results
1589 * if A is accessed in instruction immediately before the div.
1591 * Will be fixed in B4 rev of processor, Dallas claims.
1594 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1595 if (!AOP_NEEDSACC(RIGHT)) \
1597 /* We can load A first, then B, since \
1598 * B (the RIGHT operand) won't clobber A, \
1599 * thus avoiding touching A right before the div. \
1601 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1602 L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL); \
1604 L = aopGet(AOP(RIGHT),0,FALSE,FALSE,"b"); \
1609 /* Just stuff in a nop after loading A. */ \
1610 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,NULL));\
1611 L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL); \
1613 emitcode("nop", "; workaround for DS80C390 div bug."); \
1616 /*-----------------------------------------------------------------*/
1617 /* genNotFloat - generates not for float operations */
1618 /*-----------------------------------------------------------------*/
1620 genNotFloat (operand * op, operand * res)
1625 D (emitcode (";", "genNotFloat "););
1627 /* we will put 127 in the first byte of
1629 aopPut (AOP (res), "#127", 0);
1630 size = AOP_SIZE (op) - 1;
1633 _startLazyDPSEvaluation ();
1634 MOVA(aopGet(op->aop, offset++, FALSE, FALSE, NULL));
1638 emitcode ("orl", "a,%s",
1640 offset++, FALSE, FALSE,
1643 _endLazyDPSEvaluation ();
1645 tlbl = newiTempLabel (NULL);
1646 aopPut (res->aop, one, 1);
1647 emitcode ("jz", "!tlabel", (tlbl->key + 100));
1648 aopPut (res->aop, zero, 1);
1649 emitcode ("", "!tlabeldef", (tlbl->key + 100));
1651 size = res->aop->size - 2;
1653 /* put zeros in the rest */
1655 aopPut (res->aop, zero, offset++);
1658 /*-----------------------------------------------------------------*/
1659 /* opIsGptr: returns non-zero if the passed operand is */
1660 /* a generic pointer type. */
1661 /*-----------------------------------------------------------------*/
1663 opIsGptr (operand * op)
1665 sym_link *type = operandType (op);
1667 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1674 /*-----------------------------------------------------------------*/
1675 /* getDataSize - get the operand data size */
1676 /*-----------------------------------------------------------------*/
1678 getDataSize (operand * op)
1681 size = AOP_SIZE (op);
1682 if (size == GPTRSIZE)
1684 sym_link *type = operandType (op);
1685 if (IS_GENPTR (type))
1687 /* generic pointer; arithmetic operations
1688 * should ignore the high byte (pointer type).
1696 /*-----------------------------------------------------------------*/
1697 /* outAcc - output Acc */
1698 /*-----------------------------------------------------------------*/
1700 outAcc (operand * result)
1703 size = getDataSize (result);
1706 aopPut (AOP (result), "a", 0);
1709 /* unsigned or positive */
1712 aopPut (AOP (result), zero, offset++);
1717 /*-----------------------------------------------------------------*/
1718 /* outBitC - output a bit C */
1719 /*-----------------------------------------------------------------*/
1721 outBitC (operand * result)
1723 /* if the result is bit */
1724 if (AOP_TYPE (result) == AOP_CRY)
1726 aopPut (AOP (result), "c", 0);
1730 emitcode ("clr", "a");
1731 emitcode ("rlc", "a");
1736 /*-----------------------------------------------------------------*/
1737 /* toBoolean - emit code for orl a,operator(sizeop) */
1738 /*-----------------------------------------------------------------*/
1740 toBoolean (operand * oper)
1742 int size = AOP_SIZE (oper) - 1;
1746 /* The generic part of a generic pointer should
1747 * not participate in it's truth value.
1749 * i.e. 0x10000000 is zero.
1751 if (opIsGptr (oper))
1753 D (emitcode (";", "toBoolean: generic ptr special case."););
1757 _startLazyDPSEvaluation ();
1758 if (AOP_NEEDSACC (oper) && size)
1763 emitcode ("push", "b");
1765 MOVB (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1769 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1776 emitcode ("orl", "b,%s",
1777 aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1781 emitcode ("orl", "a,%s",
1782 aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1785 _endLazyDPSEvaluation ();
1789 emitcode ("mov", "a,b");
1792 emitcode ("pop", "b");
1799 /*-----------------------------------------------------------------*/
1800 /* genNot - generate code for ! operation */
1801 /*-----------------------------------------------------------------*/
1806 sym_link *optype = operandType (IC_LEFT (ic));
1808 D (emitcode (";", "genNot "););
1810 /* assign asmOps to operand & result */
1811 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1812 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1814 /* if in bit space then a special case */
1815 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 outBitC (IC_RESULT (ic));
1823 /* if type float then do float */
1824 if (IS_FLOAT (optype))
1826 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1830 toBoolean (IC_LEFT (ic));
1832 tlbl = newiTempLabel (NULL);
1833 emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1834 emitcode ("", "!tlabeldef", tlbl->key + 100);
1835 outBitC (IC_RESULT (ic));
1838 /* release the aops */
1839 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1840 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1844 /*-----------------------------------------------------------------*/
1845 /* genCpl - generate code for complement */
1846 /*-----------------------------------------------------------------*/
1854 D (emitcode (";", "genCpl "););
1857 /* assign asmOps to operand & result */
1858 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1859 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1861 /* special case if in bit space */
1862 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1863 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1864 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1865 emitcode ("cpl", "c");
1866 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1869 tlbl=newiTempLabel(NULL);
1870 emitcode ("cjne", "%s,#0x01,%05d$",
1871 aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE,NULL), tlbl->key+100);
1872 emitcode ("", "%05d$:", tlbl->key+100);
1873 outBitC (IC_RESULT(ic));
1877 size = AOP_SIZE (IC_RESULT (ic));
1878 _startLazyDPSEvaluation ();
1881 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
1882 emitcode ("cpl", "a");
1883 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1885 _endLazyDPSEvaluation ();
1889 /* release the aops */
1890 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1891 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1894 /*-----------------------------------------------------------------*/
1895 /* genUminusFloat - unary minus for floating points */
1896 /*-----------------------------------------------------------------*/
1898 genUminusFloat (operand * op, operand * result)
1900 int size, offset = 0;
1902 D(emitcode (";", "genUminusFloat"););
1904 /* for this we just copy and then flip the bit */
1906 _startLazyDPSEvaluation ();
1907 size = AOP_SIZE (op) - 1;
1911 aopPut (AOP (result),
1912 aopGet (AOP (op), offset, FALSE, FALSE, NULL),
1917 MOVA(aopGet (AOP (op), offset, FALSE, FALSE, NULL));
1919 emitcode ("cpl", "acc.7");
1920 aopPut (AOP (result), "a", offset);
1921 _endLazyDPSEvaluation ();
1924 /*-----------------------------------------------------------------*/
1925 /* genUminus - unary minus code generation */
1926 /*-----------------------------------------------------------------*/
1928 genUminus (iCode * ic)
1933 D (emitcode (";", "genUminus "););
1936 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1937 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1939 /* if both in bit space then special
1941 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1942 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1945 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1946 emitcode ("cpl", "c");
1947 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1951 optype = operandType (IC_LEFT (ic));
1953 /* if float then do float stuff */
1954 if (IS_FLOAT (optype))
1956 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1960 /* otherwise subtract from zero */
1961 size = AOP_SIZE (IC_LEFT (ic));
1963 _startLazyDPSEvaluation ();
1966 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL);
1967 if (!strcmp (l, "a"))
1971 emitcode ("cpl", "a");
1972 emitcode ("addc", "a,#0");
1978 emitcode ("clr", "a");
1979 emitcode ("subb", "a,%s", l);
1981 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1983 _endLazyDPSEvaluation ();
1985 /* if any remaining bytes in the result */
1986 /* we just need to propagate the sign */
1987 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic)))) != 0)
1989 emitcode ("rlc", "a");
1990 emitcode ("subb", "a,acc");
1992 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1996 /* release the aops */
1997 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1998 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2001 /*-----------------------------------------------------------------*/
2002 /* savermask - saves registers in the mask */
2003 /*-----------------------------------------------------------------*/
2004 static void savermask(bitVect *rs_mask)
2007 if (options.useXstack) {
2008 if (bitVectBitValue (rs_mask, R0_IDX))
2009 emitcode ("mov", "b,r0");
2010 emitcode ("mov", "r0,%s", spname);
2011 for (i = 0; i < ds390_nRegs; i++) {
2012 if (bitVectBitValue (rs_mask, i)) {
2014 emitcode ("mov", "a,b");
2016 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
2017 emitcode ("movx", "@r0,a");
2018 emitcode ("inc", "r0");
2021 emitcode ("mov", "%s,r0", spname);
2022 if (bitVectBitValue (rs_mask, R0_IDX))
2023 emitcode ("mov", "r0,b");
2025 for (i = 0; i < ds390_nRegs; i++) {
2026 if (bitVectBitValue (rs_mask, i))
2027 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2032 /*-----------------------------------------------------------------*/
2033 /* saveRegisters - will look for a call and save the registers */
2034 /*-----------------------------------------------------------------*/
2036 saveRegisters (iCode * lic)
2042 for (ic = lic; ic; ic = ic->next)
2043 if (ic->op == CALL || ic->op == PCALL)
2048 fprintf (stderr, "found parameter push with no function call\n");
2052 /* if the registers have been saved already then
2054 if (ic->regsSaved || IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic)))) return ;
2056 /* special case if DPTR alive across a function call then must save it
2057 even though callee saves */
2058 if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2060 rsave = newBitVect(ic->rMask->size);
2061 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2062 if (bitVectBitValue(ic->rMask,i))
2063 rsave = bitVectSetBit(rsave,i);
2065 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2067 /* safe the registers in use at this time but skip the
2068 ones for the result */
2069 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2070 ds390_rUmaskForOp (IC_RESULT(ic)));
2076 /*-----------------------------------------------------------------*/
2077 /* usavermask - restore registers with mask */
2078 /*-----------------------------------------------------------------*/
2079 static void unsavermask(bitVect *rs_mask)
2082 if (options.useXstack) {
2083 emitcode ("mov", "r0,%s", spname);
2084 for (i = ds390_nRegs; i >= 0; i--) {
2085 if (bitVectBitValue (rs_mask, i)) {
2086 emitcode ("dec", "r0");
2087 emitcode ("movx", "a,@r0");
2089 emitcode ("mov", "b,a");
2091 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
2094 emitcode ("mov", "%s,r0", spname);
2095 if (bitVectBitValue (rs_mask, R0_IDX))
2096 emitcode ("mov", "r0,b");
2098 for (i = ds390_nRegs; i >= 0; i--) {
2099 if (bitVectBitValue (rs_mask, i))
2100 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2105 /*-----------------------------------------------------------------*/
2106 /* unsaveRegisters - pop the pushed registers */
2107 /*-----------------------------------------------------------------*/
2109 unsaveRegisters (iCode * ic)
2113 if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2115 rsave = newBitVect(ic->rMask->size);
2116 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2117 if (bitVectBitValue(ic->rMask,i))
2118 rsave = bitVectSetBit(rsave,i);
2120 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2122 /* restore the registers in use at this time but skip the
2123 ones for the result */
2124 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2125 ds390_rUmaskForOp (IC_RESULT(ic)));
2131 /*-----------------------------------------------------------------*/
2133 /*-----------------------------------------------------------------*/
2135 pushSide (operand * oper, int size)
2138 _startLazyDPSEvaluation ();
2141 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, NULL);
2142 if (AOP_TYPE (oper) != AOP_REG &&
2143 AOP_TYPE (oper) != AOP_DIR &&
2146 emitcode ("mov", "a,%s", l);
2147 emitcode ("push", "acc");
2150 emitcode ("push", "%s", l);
2152 _endLazyDPSEvaluation ();
2155 /*-----------------------------------------------------------------*/
2156 /* assignResultValue - */
2157 /*-----------------------------------------------------------------*/
2159 assignResultValue (operand * oper)
2162 int size = AOP_SIZE (oper);
2163 bool pushedAcc = FALSE;
2165 if (size == fReturnSizeDS390)
2167 /* I don't think this case can ever happen... */
2168 /* ACC is the last part of this. If writing the result
2169 * uses AC, we must preserve it.
2171 if (AOP_NEEDSACC(oper))
2173 emitcode(";", "assignResultValue special case for ACC.");
2174 emitcode("push", "acc");
2181 _startLazyDPSEvaluation ();
2184 aopPut (AOP (oper), fReturn[offset], offset);
2187 _endLazyDPSEvaluation ();
2191 emitcode("pop", "acc");
2192 aopPut(AOP(oper), "a", offset);
2197 /*-----------------------------------------------------------------*/
2198 /* genXpush - pushes onto the external stack */
2199 /*-----------------------------------------------------------------*/
2201 genXpush (iCode * ic)
2203 asmop *aop = newAsmop (0);
2205 int size, offset = 0;
2207 D (emitcode (";", "genXpush ");
2210 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2211 r = getFreePtr (ic, &aop, FALSE);
2214 emitcode ("mov", "%s,_spx", r->name);
2216 size = AOP_SIZE (IC_LEFT (ic));
2217 _startLazyDPSEvaluation ();
2221 MOVA (aopGet (AOP (IC_LEFT (ic)),
2222 offset++, FALSE, FALSE, NULL));
2223 emitcode ("movx", "@%s,a", r->name);
2224 emitcode ("inc", "%s", r->name);
2227 _endLazyDPSEvaluation ();
2230 emitcode ("mov", "_spx,%s", r->name);
2232 freeAsmop (NULL, aop, ic, TRUE);
2233 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2236 /*-----------------------------------------------------------------*/
2237 /* genIpush - generate code for pushing this gets a little complex */
2238 /*-----------------------------------------------------------------*/
2240 genIpush (iCode * ic)
2242 int size, offset = 0;
2245 D (emitcode (";", "genIpush ");
2248 /* if this is not a parm push : ie. it is spill push
2249 and spill push is always done on the local stack */
2253 /* and the item is spilt then do nothing */
2254 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2257 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2258 size = AOP_SIZE (IC_LEFT (ic));
2259 /* push it on the stack */
2260 _startLazyDPSEvaluation ();
2263 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2269 emitcode ("push", "%s", l);
2271 _endLazyDPSEvaluation ();
2275 /* this is a paramter push: in this case we call
2276 the routine to find the call and save those
2277 registers that need to be saved */
2280 /* if use external stack then call the external
2281 stack pushing routine */
2282 if (options.useXstack)
2288 /* then do the push */
2289 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2291 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2292 size = AOP_SIZE (IC_LEFT (ic));
2294 _startLazyDPSEvaluation ();
2297 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2298 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2299 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2302 emitcode ("mov", "a,%s", l);
2303 emitcode ("push", "acc");
2307 emitcode ("push", "%s", l);
2310 _endLazyDPSEvaluation ();
2312 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2315 /*-----------------------------------------------------------------*/
2316 /* genIpop - recover the registers: can happen only for spilling */
2317 /*-----------------------------------------------------------------*/
2319 genIpop (iCode * ic)
2323 D (emitcode (";", "genIpop ");
2327 /* if the temp was not pushed then */
2328 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2331 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2332 size = AOP_SIZE (IC_LEFT (ic));
2333 offset = (size - 1);
2334 _startLazyDPSEvaluation ();
2337 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2338 FALSE, TRUE, NULL));
2340 _endLazyDPSEvaluation ();
2342 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2345 /*-----------------------------------------------------------------*/
2346 /* unsaveRBank - restores the resgister bank from stack */
2347 /*-----------------------------------------------------------------*/
2349 unsaveRBank (int bank, iCode * ic, bool popPsw)
2355 if (options.useXstack)
2359 /* Assume r0 is available for use. */
2360 r = ds390_regWithIdx (R0_IDX);;
2365 r = getFreePtr (ic, &aop, FALSE);
2367 emitcode ("mov", "%s,_spx", r->name);
2372 if (options.useXstack)
2374 emitcode ("movx", "a,@%s", r->name);
2375 emitcode ("mov", "psw,a");
2376 emitcode ("dec", "%s", r->name);
2380 emitcode ("pop", "psw");
2384 for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2386 if (options.useXstack)
2388 emitcode ("movx", "a,@%s", r->name);
2389 emitcode ("mov", "(%s+%d),a",
2390 regs390[i].base, 8 * bank + regs390[i].offset);
2391 emitcode ("dec", "%s", r->name);
2395 emitcode ("pop", "(%s+%d)",
2396 regs390[i].base, 8 * bank + regs390[i].offset);
2399 if (options.useXstack)
2401 emitcode ("mov", "_spx,%s", r->name);
2406 freeAsmop (NULL, aop, ic, TRUE);
2410 /*-----------------------------------------------------------------*/
2411 /* saveRBank - saves an entire register bank on the stack */
2412 /*-----------------------------------------------------------------*/
2414 saveRBank (int bank, iCode * ic, bool pushPsw)
2420 if (options.useXstack)
2424 /* Assume r0 is available for use. */
2425 r = ds390_regWithIdx (R0_IDX);;
2430 r = getFreePtr (ic, &aop, FALSE);
2432 emitcode ("mov", "%s,_spx", r->name);
2435 for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2437 if (options.useXstack)
2439 emitcode ("inc", "%s", r->name);
2440 emitcode ("mov", "a,(%s+%d)",
2441 regs390[i].base, 8 * bank + regs390[i].offset);
2442 emitcode ("movx", "@%s,a", r->name);
2445 emitcode ("push", "(%s+%d)",
2446 regs390[i].base, 8 * bank + regs390[i].offset);
2451 if (options.useXstack)
2453 emitcode ("mov", "a,psw");
2454 emitcode ("movx", "@%s,a", r->name);
2455 emitcode ("inc", "%s", r->name);
2456 emitcode ("mov", "_spx,%s", r->name);
2460 emitcode ("push", "psw");
2463 emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2468 freeAsmop (NULL, aop, ic, TRUE);
2477 /*-----------------------------------------------------------------*/
2478 /* genSend - gen code for SEND */
2479 /*-----------------------------------------------------------------*/
2480 static void genSend(set *sendSet)
2484 static int rb1_count = 0;
2486 for (sic = setFirstItem (sendSet); sic;
2487 sic = setNextItem (sendSet)) {
2488 int size, offset = 0;
2490 size=getSize(operandType(IC_LEFT(sic)));
2491 D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2492 if (sendCount == 0) { /* first parameter */
2493 // we know that dpl(hxb) is the result, so
2495 _startLazyDPSEvaluation ();
2497 aopOp (IC_LEFT (sic), sic, FALSE,
2498 (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2500 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2503 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2504 FALSE, FALSE, NULL);
2505 if (strcmp (l, fReturn[offset])) {
2506 emitcode ("mov", "%s,%s",
2512 _endLazyDPSEvaluation ();
2513 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2515 } else { /* if more parameter in registers */
2516 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2518 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
2519 FALSE, FALSE, NULL));
2521 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2527 /*-----------------------------------------------------------------*/
2528 /* genCall - generates a call statement */
2529 /*-----------------------------------------------------------------*/
2531 genCall (iCode * ic)
2534 bool restoreBank = FALSE;
2535 bool swapBanks = FALSE;
2537 D (emitcode (";", "genCall "););
2539 /* if we are calling a not _naked function that is not using
2540 the same register bank then we need to save the
2541 destination registers on the stack */
2542 dtype = operandType (IC_LEFT (ic));
2543 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2544 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2545 IFFUNC_ISISR (currFunc->type))
2549 /* This is unexpected; the bank should have been saved in
2552 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2558 /* if caller saves & we have not saved then */
2562 /* if send set is not empty the assign */
2563 /* We've saved all the registers we care about;
2564 * therefore, we may clobber any register not used
2565 * in the calling convention (i.e. anything not in
2570 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2571 genSend(reverseSet(_G.sendSet));
2573 genSend(_G.sendSet);
2580 emitcode ("mov", "psw,#!constbyte",
2581 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2585 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2586 OP_SYMBOL (IC_LEFT (ic))->rname :
2587 OP_SYMBOL (IC_LEFT (ic))->name));
2591 emitcode ("mov", "psw,#!constbyte",
2592 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2595 /* if we need assign a result value */
2596 if ((IS_ITEMP (IC_RESULT (ic)) &&
2597 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2598 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2599 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2600 IS_TRUE_SYMOP (IC_RESULT (ic)))
2602 if (isOperandInFarSpace (IC_RESULT (ic))
2603 && getSize (operandType (IC_RESULT (ic))) <= 2)
2605 int size = getSize (operandType (IC_RESULT (ic)));
2607 /* Special case for 1 or 2 byte return in far space. */
2611 emitcode ("mov", "b,%s", fReturn[1]);
2614 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2615 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2619 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2621 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2626 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2629 assignResultValue (IC_RESULT (ic));
2631 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2635 /* adjust the stack for parameters if
2637 if (ic->parmBytes) {
2639 if (options.stack10bit) {
2640 if (ic->parmBytes <= 10) {
2641 emitcode(";","stack adjustment for parms");
2642 for (i=0; i < ic->parmBytes ; i++) {
2643 emitcode("pop","acc");
2647 emitcode ("clr","c");
2648 emitcode ("mov","a,sp");
2649 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2650 emitcode ("mov","sp,a");
2651 emitcode ("mov","a,esp");
2652 emitcode ("anl","a,#3");
2653 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2654 emitcode ("mov","esp,a");
2658 if (ic->parmBytes > 3) {
2659 emitcode ("mov", "a,%s", spname);
2660 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2661 emitcode ("mov", "%s,a", spname);
2663 for (i = 0; i < ic->parmBytes; i++)
2664 emitcode ("dec", "%s", spname);
2668 /* if we hade saved some registers then unsave them */
2670 unsaveRegisters (ic);
2672 /* if register bank was saved then pop them */
2674 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2677 /*-----------------------------------------------------------------*/
2678 /* genPcall - generates a call by pointer statement */
2679 /*-----------------------------------------------------------------*/
2681 genPcall (iCode * ic)
2684 symbol *rlbl = newiTempLabel (NULL);
2685 bool restoreBank=FALSE;
2687 D (emitcode (";", "genPcall ");
2691 /* if caller saves & we have not saved then */
2695 /* if we are calling a function that is not using
2696 the same register bank then we need to save the
2697 destination registers on the stack */
2698 dtype = operandType (IC_LEFT (ic));
2699 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2700 IFFUNC_ISISR (currFunc->type) &&
2701 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2702 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2706 /* push the return address on to the stack */
2707 emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2708 emitcode ("push", "acc");
2709 emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2710 emitcode ("push", "acc");
2712 if (options.model == MODEL_FLAT24)
2714 emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2715 emitcode ("push", "acc");
2718 /* now push the calling address */
2719 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2721 pushSide (IC_LEFT (ic), FPTRSIZE);
2723 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2725 /* if send set is not empty the assign */
2728 genSend(reverseSet(_G.sendSet));
2732 emitcode ("ret", "");
2733 emitcode ("", "!tlabeldef", (rlbl->key + 100));
2736 /* if we need assign a result value */
2737 if ((IS_ITEMP (IC_RESULT (ic)) &&
2738 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2739 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2740 IS_TRUE_SYMOP (IC_RESULT (ic)))
2744 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2747 assignResultValue (IC_RESULT (ic));
2749 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2752 /* adjust the stack for parameters if
2757 if (options.stack10bit) {
2758 if (ic->parmBytes <= 10) {
2759 emitcode(";","stack adjustment for parms");
2760 for (i=0; i < ic->parmBytes ; i++) {
2761 emitcode("pop","acc");
2765 emitcode ("clr","c");
2766 emitcode ("mov","a,sp");
2767 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2768 emitcode ("mov","sp,a");
2769 emitcode ("mov","a,esp");
2770 emitcode ("anl","a,#3");
2771 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2772 emitcode ("mov","esp,a");
2776 if (ic->parmBytes > 3) {
2777 emitcode ("mov", "a,%s", spname);
2778 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2779 emitcode ("mov", "%s,a", spname);
2782 for (i = 0; i < ic->parmBytes; i++)
2783 emitcode ("dec", "%s", spname);
2787 /* if register bank was saved then unsave them */
2789 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2791 /* if we hade saved some registers then
2794 unsaveRegisters (ic);
2798 /*-----------------------------------------------------------------*/
2799 /* resultRemat - result is rematerializable */
2800 /*-----------------------------------------------------------------*/
2802 resultRemat (iCode * ic)
2804 if (SKIP_IC (ic) || ic->op == IFX)
2807 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2809 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2810 if (sym->remat && !POINTER_SET (ic))
2817 #if defined(__BORLANDC__) || defined(_MSC_VER)
2818 #define STRCASECMP stricmp
2820 #define STRCASECMP strcasecmp
2823 /*-----------------------------------------------------------------*/
2824 /* inExcludeList - return 1 if the string is in exclude Reg list */
2825 /*-----------------------------------------------------------------*/
2827 inExcludeList (char *s)
2831 if (options.excludeRegs[i] &&
2832 STRCASECMP (options.excludeRegs[i], "none") == 0)
2835 for (i = 0; options.excludeRegs[i]; i++)
2837 if (options.excludeRegs[i] &&
2838 STRCASECMP (s, options.excludeRegs[i]) == 0)
2844 /*-----------------------------------------------------------------*/
2845 /* genFunction - generated code for function entry */
2846 /*-----------------------------------------------------------------*/
2848 genFunction (iCode * ic)
2852 bool switchedPSW = FALSE;
2854 D (emitcode (";", "genFunction "););
2857 /* create the function header */
2858 emitcode (";", "-----------------------------------------");
2859 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2860 emitcode (";", "-----------------------------------------");
2862 emitcode ("", "%s:", sym->rname);
2863 ftype = operandType (IC_LEFT (ic));
2865 if (IFFUNC_ISNAKED(ftype))
2867 emitcode(";", "naked function: no prologue.");
2871 if (options.stack_probe)
2872 emitcode ("lcall","__stack_probe");
2873 /* if critical function then turn interrupts off */
2874 if (IFFUNC_ISCRITICAL (ftype))
2875 emitcode ("clr", "ea");
2877 /* here we need to generate the equates for the
2878 register bank if required */
2879 if (FUNC_REGBANK (ftype) != rbank)
2883 rbank = FUNC_REGBANK (ftype);
2884 for (i = 0; i < ds390_nRegs; i++)
2886 if (regs390[i].print) {
2887 if (strcmp (regs390[i].base, "0") == 0)
2888 emitcode ("", "%s !equ !constbyte",
2890 8 * rbank + regs390[i].offset);
2892 emitcode ("", "%s !equ %s + !constbyte",
2895 8 * rbank + regs390[i].offset);
2900 /* if this is an interrupt service routine then
2901 save acc, b, dpl, dph */
2902 if (IFFUNC_ISISR (sym->type))
2904 if (!inExcludeList ("acc"))
2905 emitcode ("push", "acc");
2906 if (!inExcludeList ("b"))
2907 emitcode ("push", "b");
2908 if (!inExcludeList ("dpl"))
2909 emitcode ("push", "dpl");
2910 if (!inExcludeList ("dph"))
2911 emitcode ("push", "dph");
2912 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2914 emitcode ("push", "dpx");
2915 /* Make sure we're using standard DPTR */
2916 emitcode ("push", "dps");
2917 emitcode ("mov", "dps,#0");
2918 if (options.stack10bit)
2920 /* This ISR could conceivably use DPTR2. Better save it. */
2921 emitcode ("push", "dpl1");
2922 emitcode ("push", "dph1");
2923 emitcode ("push", "dpx1");
2924 emitcode ("push", DP2_RESULT_REG);
2927 /* if this isr has no bank i.e. is going to
2928 run with bank 0 , then we need to save more
2930 if (!FUNC_REGBANK (sym->type))
2934 /* if this function does not call any other
2935 function then we can be economical and
2936 save only those registers that are used */
2937 if (!IFFUNC_HASFCALL(sym->type))
2940 /* if any registers used */
2943 /* save the registers used */
2944 for (i = 0; i < sym->regsUsed->size; i++)
2946 if (bitVectBitValue (sym->regsUsed, i) ||
2947 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2948 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2955 /* this function has a function call cannot
2956 determines register usage so we will have to push the
2958 saveRBank (0, ic, FALSE);
2959 if (options.parms_in_bank1) {
2960 for (i=0; i < 8 ; i++ ) {
2961 emitcode ("push","%s",rb1regs[i]);
2968 /* This ISR uses a non-zero bank.
2970 * We assume that the bank is available for our
2973 * However, if this ISR calls a function which uses some
2974 * other bank, we must save that bank entirely.
2976 unsigned long banksToSave = 0;
2978 if (IFFUNC_HASFCALL(sym->type))
2981 #define MAX_REGISTER_BANKS 4
2986 for (i = ic; i; i = i->next)
2988 if (i->op == ENDFUNCTION)
2990 /* we got to the end OK. */
2998 dtype = operandType (IC_LEFT(i));
3000 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3002 /* Mark this bank for saving. */
3003 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3005 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3009 banksToSave |= (1 << FUNC_REGBANK(dtype));
3012 /* And note that we don't need to do it in
3020 /* This is a mess; we have no idea what
3021 * register bank the called function might
3024 * The only thing I can think of to do is
3025 * throw a warning and hope.
3027 werror(W_FUNCPTR_IN_USING_ISR);
3031 if (banksToSave && options.useXstack)
3033 /* Since we aren't passing it an ic,
3034 * saveRBank will assume r0 is available to abuse.
3036 * So switch to our (trashable) bank now, so
3037 * the caller's R0 isn't trashed.
3039 emitcode ("push", "psw");
3040 emitcode ("mov", "psw,#!constbyte",
3041 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3045 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3047 if (banksToSave & (1 << ix))
3049 saveRBank(ix, NULL, FALSE);
3053 // jwk: this needs a closer look
3054 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3059 /* if callee-save to be used for this function
3060 then save the registers being used in this function */
3061 if (IFFUNC_CALLEESAVES(sym->type))
3065 /* if any registers used */
3068 /* save the registers used */
3069 for (i = 0; i < sym->regsUsed->size; i++)
3071 if (bitVectBitValue (sym->regsUsed, i) ||
3072 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3074 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3082 /* set the register bank to the desired value */
3083 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3086 emitcode ("push", "psw");
3087 emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3090 if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3091 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3092 if (options.stack10bit) {
3093 emitcode ("push","_bpx");
3094 emitcode ("push","_bpx+1");
3095 emitcode ("mov","_bpx,%s",spname);
3096 emitcode ("mov","_bpx+1,esp");
3097 emitcode ("anl","_bpx+1,#3");
3099 if (options.useXstack) {
3100 emitcode ("mov", "r0,%s", spname);
3101 emitcode ("mov", "a,_bp");
3102 emitcode ("movx", "@r0,a");
3103 emitcode ("inc", "%s", spname);
3105 /* set up the stack */
3106 emitcode ("push", "_bp"); /* save the callers stack */
3108 emitcode ("mov", "_bp,%s", spname);
3112 /* adjust the stack for the function */
3115 if (options.stack10bit) {
3116 if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
3117 assert (sym->recvSize <= 4);
3118 if (sym->stack <= 8) {
3119 while (i--) emitcode ("push","acc");
3122 emitcode ("mov","a,sp");
3123 emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3124 emitcode ("mov","sp,a");
3125 emitcode ("mov","a,esp");
3126 emitcode ("anl","a,#3");
3127 emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3128 emitcode ("mov","esp,a");
3133 werror (W_STACK_OVERFLOW, sym->name);
3135 if (i > 3 && sym->recvSize < 4) {
3137 emitcode ("mov", "a,sp");
3138 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3139 emitcode ("mov", "sp,a");
3143 emitcode ("inc", "sp");
3150 emitcode ("mov", "a,_spx");
3151 emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3152 emitcode ("mov", "_spx,a");
3157 /*-----------------------------------------------------------------*/
3158 /* genEndFunction - generates epilogue for functions */
3159 /*-----------------------------------------------------------------*/
3161 genEndFunction (iCode * ic)
3163 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3165 D (emitcode (";", "genEndFunction "););
3167 if (IFFUNC_ISNAKED(sym->type))
3169 emitcode(";", "naked function: no epilogue.");
3173 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3174 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3176 if (options.stack10bit) {
3178 emitcode ("mov", "sp,_bpx", spname);
3179 emitcode ("mov", "esp,_bpx+1", spname);
3182 emitcode ("mov", "%s,_bp", spname);
3186 /* if use external stack but some variables were
3187 added to the local stack then decrement the
3189 if (options.useXstack && sym->stack) {
3190 emitcode ("mov", "a,sp");
3191 emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3192 emitcode ("mov", "sp,a");
3196 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3197 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3199 if (options.useXstack) {
3200 emitcode ("mov", "r0,%s", spname);
3201 emitcode ("movx", "a,@r0");
3202 emitcode ("mov", "_bp,a");
3203 emitcode ("dec", "%s", spname);
3205 if (options.stack10bit) {
3206 emitcode ("pop", "_bpx+1");
3207 emitcode ("pop", "_bpx");
3209 emitcode ("pop", "_bp");
3214 /* restore the register bank */
3215 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3217 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3218 || !options.useXstack)
3220 /* Special case of ISR using non-zero bank with useXstack
3223 emitcode ("pop", "psw");
3227 if (IFFUNC_ISISR (sym->type))
3230 /* now we need to restore the registers */
3231 /* if this isr has no bank i.e. is going to
3232 run with bank 0 , then we need to save more
3234 if (!FUNC_REGBANK (sym->type))
3237 /* if this function does not call any other
3238 function then we can be economical and
3239 save only those registers that are used */
3240 if (!IFFUNC_HASFCALL(sym->type))
3243 /* if any registers used */
3246 /* save the registers used */
3247 for (i = sym->regsUsed->size; i >= 0; i--)
3249 if (bitVectBitValue (sym->regsUsed, i) ||
3250 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3251 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3258 /* this function has a function call cannot
3259 determines register usage so we will have to pop the
3261 if (options.parms_in_bank1) {
3262 for (i = 7 ; i >= 0 ; i-- ) {
3263 emitcode ("pop","%s",rb1regs[i]);
3266 unsaveRBank (0, ic, FALSE);
3271 /* This ISR uses a non-zero bank.
3273 * Restore any register banks saved by genFunction
3276 // jwk: this needs a closer look
3277 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3280 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3282 if (savedBanks & (1 << ix))
3284 unsaveRBank(ix, NULL, FALSE);
3288 if (options.useXstack)
3290 /* Restore bank AFTER calling unsaveRBank,
3291 * since it can trash r0.
3293 emitcode ("pop", "psw");
3297 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3299 if (options.stack10bit)
3301 emitcode ("pop", DP2_RESULT_REG);
3302 emitcode ("pop", "dpx1");
3303 emitcode ("pop", "dph1");
3304 emitcode ("pop", "dpl1");
3306 emitcode ("pop", "dps");
3307 emitcode ("pop", "dpx");
3309 if (!inExcludeList ("dph"))
3310 emitcode ("pop", "dph");
3311 if (!inExcludeList ("dpl"))
3312 emitcode ("pop", "dpl");
3313 if (!inExcludeList ("b"))
3314 emitcode ("pop", "b");
3315 if (!inExcludeList ("acc"))
3316 emitcode ("pop", "acc");
3318 if (IFFUNC_ISCRITICAL (sym->type))
3319 emitcode ("setb", "ea");
3321 /* if debug then send end of function */
3322 if (options.debug && currFunc) {
3324 emitcode ("", "C$%s$%d$%d$%d ==.",
3325 FileBaseName (ic->filename), currFunc->lastLine,
3326 ic->level, ic->block);
3327 if (IS_STATIC (currFunc->etype))
3328 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3330 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3334 emitcode ("reti", "");
3338 if (IFFUNC_ISCRITICAL (sym->type))
3339 emitcode ("setb", "ea");
3341 if (IFFUNC_CALLEESAVES(sym->type))
3345 /* if any registers used */
3348 /* save the registers used */
3349 for (i = sym->regsUsed->size; i >= 0; i--)
3351 if (bitVectBitValue (sym->regsUsed, i) ||
3352 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3353 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3359 /* if debug then send end of function */
3360 if (options.debug && currFunc)
3363 emitcode ("", "C$%s$%d$%d$%d ==.",
3364 FileBaseName (ic->filename), currFunc->lastLine,
3365 ic->level, ic->block);
3366 if (IS_STATIC (currFunc->etype))
3367 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3369 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3373 emitcode ("ret", "");
3378 /*-----------------------------------------------------------------*/
3379 /* genJavaNativeRet - generate code for return JavaNative */
3380 /*-----------------------------------------------------------------*/
3381 static void genJavaNativeRet(iCode *ic)
3385 aopOp (IC_LEFT (ic), ic, FALSE,
3386 AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
3387 size = AOP_SIZE (IC_LEFT (ic));
3391 /* it is assigned to GPR0-R3 then push them */
3392 if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3393 aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3394 for (i = 0 ; i < size ; i++ ) {
3395 emitcode ("push","%s",
3396 aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3398 for (i = (size-1) ; i >= 0 ; i--) {
3399 emitcode ("pop","a%s",javaRet[i]);
3402 for (i = 0 ; i < size ; i++)
3403 emitcode ("mov","%s,%s",javaRet[i],
3404 aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3406 for (i = size ; i < 4 ; i++ )
3407 emitcode ("mov","%s,#0",javaRet[i]);
3411 /*-----------------------------------------------------------------*/
3412 /* genRet - generate code for return statement */
3413 /*-----------------------------------------------------------------*/
3417 int size, offset = 0, pushed = 0;
3419 D (emitcode (";", "genRet "););
3421 /* if we have no return value then
3422 just generate the "ret" */
3426 /* if this is a JavaNative function then return
3427 value in different register */
3428 if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3429 genJavaNativeRet(ic);
3432 /* we have something to return then
3433 move the return value into place */
3434 aopOp (IC_LEFT (ic), ic, FALSE,
3435 (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
3436 size = AOP_SIZE (IC_LEFT (ic));
3438 _startLazyDPSEvaluation ();
3442 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3444 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3446 emitcode ("push", "%s", l);
3451 /* Since A is the last element of fReturn,
3452 * is is OK to clobber it in the aopGet.
3454 l = aopGet (AOP (IC_LEFT (ic)), offset,
3455 FALSE, FALSE, NULL);
3456 if (strcmp (fReturn[offset], l))
3457 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3460 _endLazyDPSEvaluation ();
3467 if (strcmp (fReturn[pushed], "a"))
3468 emitcode ("pop", fReturn[pushed]);
3470 emitcode ("pop", "acc");
3473 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3476 /* generate a jump to the return label
3477 if the next is not the return statement */
3478 if (!(ic->next && ic->next->op == LABEL &&
3479 IC_LABEL (ic->next) == returnLabel))
3481 emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3485 /*-----------------------------------------------------------------*/
3486 /* genLabel - generates a label */
3487 /*-----------------------------------------------------------------*/
3489 genLabel (iCode * ic)
3491 /* special case never generate */
3492 if (IC_LABEL (ic) == entryLabel)
3495 D (emitcode (";", "genLabel ");
3498 emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3501 /*-----------------------------------------------------------------*/
3502 /* genGoto - generates a ljmp */
3503 /*-----------------------------------------------------------------*/
3505 genGoto (iCode * ic)
3507 D (emitcode (";", "genGoto ");
3509 emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3512 /*-----------------------------------------------------------------*/
3513 /* findLabelBackwards: walks back through the iCode chain looking */
3514 /* for the given label. Returns number of iCode instructions */
3515 /* between that label and given ic. */
3516 /* Returns zero if label not found. */
3517 /*-----------------------------------------------------------------*/
3519 findLabelBackwards (iCode * ic, int key)
3528 /* If we have any pushes or pops, we cannot predict the distance.
3529 I don't like this at all, this should be dealt with in the
3531 if (ic->op == IPUSH || ic->op == IPOP) {
3535 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3537 /* printf("findLabelBackwards = %d\n", count); */
3545 /*-----------------------------------------------------------------*/
3546 /* genPlusIncr :- does addition with increment if possible */
3547 /*-----------------------------------------------------------------*/
3549 genPlusIncr (iCode * ic)
3551 unsigned int icount;
3552 unsigned int size = getDataSize (IC_RESULT (ic));
3554 /* will try to generate an increment */
3555 /* if the right side is not a literal
3557 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3560 /* if the literal value of the right hand side
3561 is greater than 4 then it is not worth it */
3562 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3565 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3566 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3568 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
3572 /* if increment 16 bits in register */
3574 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3575 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3576 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3585 /* If the next instruction is a goto and the goto target
3586 * is <= 5 instructions previous to this, we can generate
3587 * jumps straight to that target.
3589 if (ic->next && ic->next->op == GOTO
3590 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3593 D(emitcode (";", "tail increment optimized (range %d)", labelRange););
3594 tlbl = IC_LABEL (ic->next);
3599 tlbl = newiTempLabel (NULL);
3603 l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
3604 emitcode ("inc", "%s", l);
3606 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3607 IS_AOP_PREG (IC_RESULT (ic)))
3609 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3613 emitcode ("clr", "a");
3614 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3617 l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
3618 emitcode ("inc", "%s", l);
3621 if (!strcmp(l, "acc"))
3623 emitcode("jnz", "!tlabel", tlbl->key + 100);
3625 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3626 IS_AOP_PREG (IC_RESULT (ic)))
3628 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3632 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3635 l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
3636 emitcode ("inc", "%s", l);
3640 if (!strcmp(l, "acc"))
3642 emitcode("jnz", "!tlabel", tlbl->key + 100);
3644 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3645 IS_AOP_PREG (IC_RESULT (ic)))
3647 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3651 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3654 l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
3655 emitcode ("inc", "%s", l); }
3659 emitcode ("", "!tlabeldef", tlbl->key + 100);
3664 if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3665 !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 &&
3666 options.model == MODEL_FLAT24 ) {
3670 emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, NULL));
3672 emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, NULL));
3674 emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3677 while (icount--) emitcode ("inc","dptr");
3681 if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3682 AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3684 emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3685 while (icount--) emitcode ("inc","dptr");
3686 emitcode ("mov","dps,#0");
3690 /* if the sizes are greater than 1 then we cannot */
3691 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3692 AOP_SIZE (IC_LEFT (ic)) > 1)
3695 /* we can if the aops of the left & result match or
3696 if they are in registers and the registers are the
3699 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3700 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3701 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3706 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3707 emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3708 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3713 _startLazyDPSEvaluation ();
3716 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3718 _endLazyDPSEvaluation ();
3727 /*-----------------------------------------------------------------*/
3728 /* outBitAcc - output a bit in acc */
3729 /*-----------------------------------------------------------------*/
3731 outBitAcc (operand * result)
3733 symbol *tlbl = newiTempLabel (NULL);
3734 /* if the result is a bit */
3735 if (AOP_TYPE (result) == AOP_CRY)
3737 aopPut (AOP (result), "a", 0);
3741 emitcode ("jz", "!tlabel", tlbl->key + 100);
3742 emitcode ("mov", "a,%s", one);
3743 emitcode ("", "!tlabeldef", tlbl->key + 100);
3748 /*-----------------------------------------------------------------*/
3749 /* genPlusBits - generates code for addition of two bits */
3750 /*-----------------------------------------------------------------*/
3752 genPlusBits (iCode * ic)
3754 D (emitcode (";", "genPlusBits "););
3756 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3758 symbol *lbl = newiTempLabel (NULL);
3759 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3760 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3761 emitcode ("cpl", "c");
3762 emitcode ("", "!tlabeldef", (lbl->key + 100));
3763 outBitC (IC_RESULT (ic));
3767 emitcode ("clr", "a");
3768 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3769 emitcode ("rlc", "a");
3770 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3771 emitcode ("addc", "a,#0");
3772 outAcc (IC_RESULT (ic));
3777 adjustArithmeticResult (iCode * ic)
3779 if (opIsGptr (IC_RESULT (ic)) &&
3780 opIsGptr (IC_LEFT (ic)) &&
3781 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3783 aopPut (AOP (IC_RESULT (ic)),
3784 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3788 if (opIsGptr (IC_RESULT (ic)) &&
3789 opIsGptr (IC_RIGHT (ic)) &&
3790 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3792 aopPut (AOP (IC_RESULT (ic)),
3793 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3797 if (opIsGptr (IC_RESULT (ic)) &&
3798 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3799 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3800 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3801 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3804 SNPRINTF (buff, sizeof(buff),
3805 "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3806 aopPut (AOP (IC_RESULT (ic)), buff, GPTRSIZE - 1);
3810 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
3811 // generates the result if possible. If result is generated, returns TRUE; otherwise
3812 // returns false and caller must deal with fact that result isn't aopOp'd.
3813 bool aopOp3(iCode * ic)
3815 bool dp1InUse, dp2InUse;
3818 // First, generate the right opcode. DPTR may be used if neither left nor result are
3821 // D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
3822 // AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
3823 // AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
3824 // AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
3826 // D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
3827 // AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
3828 // AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
3829 // AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
3833 // Right uses DPTR unless left or result is an AOP_STR.
3834 aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)));
3836 // if the right used DPTR, left MUST use DPTR2.
3837 // if the right used DPTR2, left MUST use DPTR.
3838 // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
3839 // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
3840 // enabling us to assign DPTR to result.
3842 if (AOP_USESDPTR(IC_RIGHT(ic)))
3846 else if (AOP_USESDPTR2(IC_RIGHT(ic)))
3852 if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
3862 aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
3864 // We've op'd the left & right. So, if left or right are the same operand as result,
3865 // we know aopOp will succeed, and we can just do it & bail.
3866 if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)) ||
3867 isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
3869 // D(emitcode(";", "aopOp3: (left | right) & result equal"););
3870 aopOp(IC_RESULT(ic),ic,TRUE, FALSE);
3874 // Note which dptrs are currently in use.
3875 dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
3876 dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
3878 // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot
3880 if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
3885 // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
3886 if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
3891 // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck
3892 if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
3897 aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
3899 // Some sanity checking...
3900 if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
3903 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
3904 __FILE__, __LINE__, ic->filename, ic->lineno);
3905 emitcode(";", ">>> unexpected DPTR here.");
3908 if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
3911 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
3912 __FILE__, __LINE__, ic->filename, ic->lineno);
3913 emitcode(";", ">>> unexpected DPTR2 here.");
3919 // Macro to aopOp all three operands of an ic. If this cannot be done,
3920 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3921 // will be set TRUE. The caller must then handle the case specially, noting
3922 // that the IC_RESULT operand is not aopOp'd.
3924 #define AOP_OP_3_NOFATAL(ic, rc) \
3925 do { rc = !aopOp3(ic); } while (0)
3927 // aopOp the left & right operands of an ic.
3928 #define AOP_OP_2(ic) \
3929 aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
3930 aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
3932 // convienience macro.
3933 #define AOP_SET_LOCALS(ic) \
3934 left = IC_LEFT(ic); \
3935 right = IC_RIGHT(ic); \
3936 result = IC_RESULT(ic);
3939 // Given an integer value of pushedSize bytes on the stack,
3940 // adjust it to be resultSize bytes, either by discarding
3941 // the most significant bytes or by zero-padding.
3943 // On exit from this macro, pushedSize will have been adjusted to
3944 // equal resultSize, and ACC may be trashed.
3945 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3946 /* If the pushed data is bigger than the result, \
3947 * simply discard unused bytes. Icky, but works. \
3949 while (pushedSize > resultSize) \
3951 D (emitcode (";", "discarding unused result byte."););\
3952 emitcode ("pop", "acc"); \
3955 if (pushedSize < resultSize) \
3957 emitcode ("clr", "a"); \
3958 /* Conversly, we haven't pushed enough here. \
3959 * just zero-pad, and all is well. \
3961 while (pushedSize < resultSize) \
3963 emitcode("push", "acc"); \
3967 assert(pushedSize == resultSize);
3969 /*-----------------------------------------------------------------*/
3970 /* genPlus - generates code for addition */
3971 /*-----------------------------------------------------------------*/
3973 genPlus (iCode * ic)
3975 int size, offset = 0;
3979 D (emitcode (";", "genPlus "););
3981 /* special cases :- */
3982 if ( AOP_IS_STR(IC_LEFT(ic)) &&
3983 isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
3984 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
3985 size = floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
3987 while (size--) emitcode ("inc","dptr");
3989 emitcode ("mov","a,dpl");
3990 emitcode ("add","a,#!constbyte",size & 0xff);
3991 emitcode ("mov","dpl,a");
3992 emitcode ("mov","a,dph");
3993 emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
3994 emitcode ("mov","dph,a");
3995 emitcode ("mov","a,dpx");
3996 emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
3997 emitcode ("mov","dpx,a");
3999 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
4002 if ( IS_SYMOP(IC_LEFT(ic)) &&
4003 OP_SYMBOL(IC_LEFT(ic))->remat &&
4004 isOperandInFarSpace(IC_RIGHT(ic))) {
4005 operand *op = IC_RIGHT(ic);
4006 IC_RIGHT(ic) = IC_LEFT(ic);
4010 AOP_OP_3_NOFATAL (ic, pushResult);
4014 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
4019 /* if literal, literal on the right or
4020 if left requires ACC or right is already
4022 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4023 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
4024 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4026 operand *t = IC_RIGHT (ic);
4027 IC_RIGHT (ic) = IC_LEFT (ic);
4029 emitcode (";", "Swapped plus args.");
4032 /* if both left & right are in bit
4034 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4035 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4041 /* if left in bit space & right literal */
4042 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4043 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4045 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4046 /* if result in bit space */
4047 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4049 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4050 emitcode ("cpl", "c");
4051 outBitC (IC_RESULT (ic));
4055 size = getDataSize (IC_RESULT (ic));
4056 _startLazyDPSEvaluation ();
4059 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4060 emitcode ("addc", "a,#0");
4061 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4063 _endLazyDPSEvaluation ();
4068 /* if I can do an increment instead
4069 of add then GOOD for ME */
4070 if (genPlusIncr (ic) == TRUE)
4072 emitcode (";", "did genPlusIncr");
4077 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4079 _startLazyDPSEvaluation ();
4082 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4084 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4086 emitcode ("add", "a,%s",
4087 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4089 emitcode ("addc", "a,%s",
4090 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4094 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4096 /* right is going to use ACC or we would have taken the
4099 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4101 D(emitcode(";", "+ AOP_ACC special case."););
4102 emitcode("xch", "a, %s", DP2_RESULT_REG);
4104 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4107 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4110 emitcode("add", "a, %s", DP2_RESULT_REG);
4114 emitcode ("add", "a,%s",
4115 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE,
4121 emitcode ("addc", "a,%s",
4122 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE,
4128 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4132 emitcode ("push", "acc");
4136 _endLazyDPSEvaluation ();
4140 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4142 size = getDataSize (IC_LEFT (ic));
4143 rSize = getDataSize (IC_RESULT (ic));
4145 ADJUST_PUSHED_RESULT(size, rSize);
4147 _startLazyDPSEvaluation ();
4150 emitcode ("pop", "acc");
4151 aopPut (AOP (IC_RESULT (ic)), "a", size);
4153 _endLazyDPSEvaluation ();
4156 adjustArithmeticResult (ic);
4159 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4160 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4161 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4164 /*-----------------------------------------------------------------*/
4165 /* genMinusDec :- does subtraction with deccrement if possible */
4166 /*-----------------------------------------------------------------*/
4168 genMinusDec (iCode * ic)
4170 unsigned int icount;
4171 unsigned int size = getDataSize (IC_RESULT (ic));
4173 /* will try to generate an increment */
4174 /* if the right side is not a literal
4176 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4179 /* if the literal value of the right hand side
4180 is greater than 4 then it is not worth it */
4181 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4184 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4185 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4187 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
4191 /* if decrement 16 bits in register */
4192 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4193 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4194 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4203 /* If the next instruction is a goto and the goto target
4204 * is <= 5 instructions previous to this, we can generate
4205 * jumps straight to that target.
4207 if (ic->next && ic->next->op == GOTO
4208 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4211 emitcode (";", "tail decrement optimized (range %d)", labelRange);
4212 tlbl = IC_LABEL (ic->next);
4217 tlbl = newiTempLabel (NULL);
4221 l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
4222 emitcode ("dec", "%s", l);
4224 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4225 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4226 IS_AOP_PREG (IC_RESULT (ic)))
4228 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4232 emitcode ("mov", "a,#!constbyte",0xff);
4233 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4235 l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
4236 emitcode ("dec", "%s", l);
4239 if (!strcmp(l, "acc"))
4241 emitcode("jnz", "!tlabel", tlbl->key + 100);
4243 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4244 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4245 IS_AOP_PREG (IC_RESULT (ic)))
4247 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4251 emitcode ("mov", "a,#!constbyte",0xff);
4252 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4254 l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
4255 emitcode ("dec", "%s", l);
4259 if (!strcmp(l, "acc"))
4261 emitcode("jnz", "!tlabel", tlbl->key + 100);
4263 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4264 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4265 IS_AOP_PREG (IC_RESULT (ic)))
4267 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4271 emitcode ("mov", "a,#!constbyte",0xff);
4272 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4274 l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
4275 emitcode ("dec", "%s", l);
4279 emitcode ("", "!tlabeldef", tlbl->key + 100);
4284 /* if the sizes are greater than 1 then we cannot */
4285 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4286 AOP_SIZE (IC_LEFT (ic)) > 1)
4289 /* we can if the aops of the left & result match or
4290 if they are in registers and the registers are the
4293 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4294 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4295 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4298 _startLazyDPSEvaluation ();
4301 emitcode ("dec", "%s",
4302 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
4304 _endLazyDPSEvaluation ();
4312 /*-----------------------------------------------------------------*/
4313 /* addSign - complete with sign */
4314 /*-----------------------------------------------------------------*/
4316 addSign (operand * result, int offset, int sign)
4318 int size = (getDataSize (result) - offset);
4321 _startLazyDPSEvaluation();
4324 emitcode ("rlc", "a");
4325 emitcode ("subb", "a,acc");
4328 aopPut (AOP (result), "a", offset++);
4335 aopPut (AOP (result), zero, offset++);
4338 _endLazyDPSEvaluation();
4342 /*-----------------------------------------------------------------*/
4343 /* genMinusBits - generates code for subtraction of two bits */
4344 /*-----------------------------------------------------------------*/
4346 genMinusBits (iCode * ic)
4348 symbol *lbl = newiTempLabel (NULL);
4350 D (emitcode (";", "genMinusBits "););
4352 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4354 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4355 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4356 emitcode ("cpl", "c");
4357 emitcode ("", "!tlabeldef", (lbl->key + 100));
4358 outBitC (IC_RESULT (ic));
4362 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4363 emitcode ("subb", "a,acc");
4364 emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4365 emitcode ("inc", "a");
4366 emitcode ("", "!tlabeldef", (lbl->key + 100));
4367 aopPut (AOP (IC_RESULT (ic)), "a", 0);
4368 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4372 /*-----------------------------------------------------------------*/
4373 /* genMinus - generates code for subtraction */
4374 /*-----------------------------------------------------------------*/
4376 genMinus (iCode * ic)
4378 int size, offset = 0;
4383 D (emitcode (";", "genMinus "););
4385 AOP_OP_3_NOFATAL(ic, pushResult);
4389 /* special cases :- */
4390 /* if both left & right are in bit space */
4391 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4392 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4398 /* if I can do an decrement instead
4399 of subtract then GOOD for ME */
4400 if (genMinusDec (ic) == TRUE)
4405 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4407 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4413 lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4418 /* if literal, add a,#-lit, else normal subb */
4419 _startLazyDPSEvaluation ();
4421 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4422 if (AOP_USESDPTR(IC_RIGHT(ic))) {
4423 emitcode ("mov","b,%s",
4424 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4425 MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4426 emitcode ("subb","a,b");
4428 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4429 emitcode ("subb", "a,%s",
4430 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE,
4434 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4435 /* first add without previous c */
4437 if (!size && lit==-1) {
4438 emitcode ("dec", "a");
4440 emitcode ("add", "a,#!constbyte",
4441 (unsigned int) (lit & 0x0FFL));
4444 emitcode ("addc", "a,#!constbyte",
4445 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4450 emitcode ("push", "acc");
4452 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4456 _endLazyDPSEvaluation ();
4460 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4462 size = getDataSize (IC_LEFT (ic));
4463 rSize = getDataSize (IC_RESULT (ic));
4465 ADJUST_PUSHED_RESULT(size, rSize);
4467 _startLazyDPSEvaluation ();
4470 emitcode ("pop", "acc");
4471 aopPut (AOP (IC_RESULT (ic)), "a", size);
4473 _endLazyDPSEvaluation ();
4476 adjustArithmeticResult (ic);
4479 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4480 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4481 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4485 /*-----------------------------------------------------------------*/
4486 /* genMultbits :- multiplication of bits */
4487 /*-----------------------------------------------------------------*/
4489 genMultbits (operand * left,
4494 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4495 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4496 aopOp(result, ic, TRUE, FALSE);
4501 /*-----------------------------------------------------------------*/
4502 /* genMultOneByte : 8*8=8/16 bit multiplication */
4503 /*-----------------------------------------------------------------*/
4505 genMultOneByte (operand * left,
4510 sym_link *opetype = operandType (result);
4514 /* (if two literals: the value is computed before) */
4515 /* if one literal, literal on the right */
4516 if (AOP_TYPE (left) == AOP_LIT)
4521 emitcode (";", "swapped left and right");
4524 if (SPEC_USIGN(opetype)
4525 // ignore the sign of left and right, what else can we do?
4526 || (SPEC_USIGN(operandType(left)) &&
4527 SPEC_USIGN(operandType(right)))) {
4528 // just an unsigned 8*8=8/16 multiply
4529 //emitcode (";","unsigned");
4530 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4531 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4532 emitcode ("mul", "ab");
4534 _G.accInUse++; _G.bInUse++;
4535 aopOp(result, ic, TRUE, FALSE);
4537 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4539 // this should never happen
4540 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4541 AOP_SIZE(result), __FILE__, lineno);
4545 aopPut (AOP (result), "a", 0);
4546 _G.accInUse--; _G.bInUse--;
4547 if (AOP_SIZE(result)==2)
4549 aopPut (AOP (result), "b", 1);
4554 // we have to do a signed multiply
4556 emitcode (";", "signed");
4557 emitcode ("clr", "F0"); // reset sign flag
4558 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4560 lbl=newiTempLabel(NULL);
4561 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4562 // left side is negative, 8-bit two's complement, this fails for -128
4563 emitcode ("setb", "F0"); // set sign flag
4564 emitcode ("cpl", "a");
4565 emitcode ("inc", "a");
4567 emitcode ("", "!tlabeldef", lbl->key+100);
4570 if (AOP_TYPE(right)==AOP_LIT) {
4571 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4572 /* AND literal negative */
4573 if ((int) val < 0) {
4574 emitcode ("cpl", "F0"); // complement sign flag
4575 emitcode ("mov", "b,#!constbyte", -val);
4577 emitcode ("mov", "b,#!constbyte", val);
4580 lbl=newiTempLabel(NULL);
4581 emitcode ("mov", "b,a");
4582 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4583 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4584 // right side is negative, 8-bit two's complement
4585 emitcode ("cpl", "F0"); // complement sign flag
4586 emitcode ("cpl", "a");
4587 emitcode ("inc", "a");
4588 emitcode ("", "!tlabeldef", lbl->key+100);
4590 emitcode ("mul", "ab");
4592 _G.accInUse++;_G.bInUse++;
4593 aopOp(result, ic, TRUE, FALSE);
4595 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4597 // this should never happen
4598 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4599 AOP_SIZE(result), __FILE__, lineno);
4603 lbl=newiTempLabel(NULL);
4604 emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4605 // only ONE op was negative, we have to do a 8/16-bit two's complement
4606 emitcode ("cpl", "a"); // lsb
4607 if (AOP_SIZE(result)==1) {
4608 emitcode ("inc", "a");
4610 emitcode ("add", "a,#1");
4611 emitcode ("xch", "a,b");
4612 emitcode ("cpl", "a"); // msb
4613 emitcode ("addc", "a,#0");
4614 emitcode ("xch", "a,b");
4617 emitcode ("", "!tlabeldef", lbl->key+100);
4618 aopPut (AOP (result), "a", 0);
4619 _G.accInUse--;_G.bInUse--;
4620 if (AOP_SIZE(result)==2) {
4621 aopPut (AOP (result), "b", 1);
4625 /*-----------------------------------------------------------------*/
4626 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
4627 /*-----------------------------------------------------------------*/
4628 static void genMultTwoByte (operand *left, operand *right,
4629 operand *result, iCode *ic)
4631 sym_link *retype = getSpec(operandType(right));
4632 sym_link *letype = getSpec(operandType(left));
4633 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4636 if (AOP_TYPE (left) == AOP_LIT) {
4641 /* save EA bit in F1 */
4642 lbl = newiTempLabel(NULL);
4643 emitcode ("setb","F1");
4644 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4645 emitcode ("clr","F1");
4646 emitcode("","!tlabeldef",lbl->key+100);
4648 /* load up MB with right */
4650 emitcode("clr","F0");
4651 if (AOP_TYPE(right) == AOP_LIT) {
4652 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4654 emitcode("setb","F0");
4657 emitcode ("mov","mb,#!constbyte",val & 0xff);
4658 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4660 lbl = newiTempLabel(NULL);
4661 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4662 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4663 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4664 emitcode ("xch", "a,b");
4665 emitcode ("cpl","a");
4666 emitcode ("add", "a,#1");
4667 emitcode ("xch", "a,b");
4668 emitcode ("cpl", "a"); // msb
4669 emitcode ("addc", "a,#0");
4670 emitcode ("setb","F0");
4671 emitcode ("","!tlabeldef",lbl->key+100);
4672 emitcode ("mov","mb,b");
4673 emitcode ("mov","mb,a");
4676 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4677 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4679 /* load up MA with left */
4681 lbl = newiTempLabel(NULL);
4682 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4683 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4684 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4685 emitcode ("xch", "a,b");
4686 emitcode ("cpl","a");
4687 emitcode ("add", "a,#1");
4688 emitcode ("xch", "a,b");
4689 emitcode ("cpl", "a"); // msb
4690 emitcode ("addc","a,#0");
4691 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4692 emitcode ("setb","F0");
4693 emitcode ("","!tlabeldef",lbl->key+100);
4694 emitcode ("mov","ma,b");
4695 emitcode ("mov","ma,a");
4697 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4698 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4700 /* wait for multiplication to finish */
4701 lbl = newiTempLabel(NULL);
4702 emitcode("","!tlabeldef", lbl->key+100);
4703 emitcode("mov","a,mcnt1");
4704 emitcode("anl","a,#!constbyte",0x80);
4705 emitcode("jnz","!tlabel",lbl->key+100);
4707 freeAsmop (left, NULL, ic, TRUE);
4708 freeAsmop (right, NULL, ic,TRUE);
4709 aopOp(result, ic, TRUE, FALSE);
4711 /* if unsigned then simple */
4713 emitcode ("mov","a,ma");
4714 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4715 emitcode ("mov","a,ma");
4716 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4717 aopPut(AOP(result),"ma",1);
4718 aopPut(AOP(result),"ma",0);
4720 emitcode("push","ma");
4721 emitcode("push","ma");
4722 emitcode("push","ma");
4724 /* negate result if needed */
4725 lbl = newiTempLabel(NULL);
4726 emitcode("jnb","F0,!tlabel",lbl->key+100);
4727 emitcode("cpl","a");
4728 emitcode("add","a,#1");
4729 emitcode("","!tlabeldef", lbl->key+100);
4730 if (AOP_TYPE(result) == AOP_ACC)
4732 D(emitcode(";", "ACC special case."););
4733 /* We know result is the only live aop, and
4734 * it's obviously not a DPTR2, so AP is available.
4736 emitcode("mov", "%s,acc", DP2_RESULT_REG);
4740 aopPut(AOP(result),"a",0);
4743 emitcode("pop","acc");
4744 lbl = newiTempLabel(NULL);
4745 emitcode("jnb","F0,!tlabel",lbl->key+100);
4746 emitcode("cpl","a");
4747 emitcode("addc","a,#0");
4748 emitcode("","!tlabeldef", lbl->key+100);
4749 aopPut(AOP(result),"a",1);
4750 emitcode("pop","acc");
4751 if (AOP_SIZE(result) >= 3) {
4752 lbl = newiTempLabel(NULL);
4753 emitcode("jnb","F0,!tlabel",lbl->key+100);
4754 emitcode("cpl","a");
4755 emitcode("addc","a,#0");
4756 emitcode("","!tlabeldef", lbl->key+100);
4757 aopPut(AOP(result),"a",2);
4759 emitcode("pop","acc");
4760 if (AOP_SIZE(result) >= 4) {
4761 lbl = newiTempLabel(NULL);
4762 emitcode("jnb","F0,!tlabel",lbl->key+100);
4763 emitcode("cpl","a");
4764 emitcode("addc","a,#0");
4765 emitcode("","!tlabeldef", lbl->key+100);
4766 aopPut(AOP(result),"a",3);
4768 if (AOP_TYPE(result) == AOP_ACC)
4770 /* We stashed the result away above. */
4771 emitcode("mov", "acc,%s", DP2_RESULT_REG);
4775 freeAsmop (result, NULL, ic, TRUE);
4777 /* restore EA bit in F1 */
4778 lbl = newiTempLabel(NULL);
4779 emitcode ("jnb","F1,!tlabel",lbl->key+100);
4780 emitcode ("setb","EA");
4781 emitcode("","!tlabeldef",lbl->key+100);
4785 /*-----------------------------------------------------------------*/
4786 /* genMult - generates code for multiplication */
4787 /*-----------------------------------------------------------------*/
4789 genMult (iCode * ic)
4791 operand *left = IC_LEFT (ic);
4792 operand *right = IC_RIGHT (ic);
4793 operand *result = IC_RESULT (ic);
4795 D (emitcode (";", "genMult "););
4797 /* assign the amsops */
4800 /* special cases first */
4802 if (AOP_TYPE (left) == AOP_CRY &&
4803 AOP_TYPE (right) == AOP_CRY)
4805 genMultbits (left, right, result, ic);
4809 /* if both are of size == 1 */
4810 if (AOP_SIZE (left) == 1 &&
4811 AOP_SIZE (right) == 1)
4813 genMultOneByte (left, right, result, ic);
4817 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4818 /* use the ds390 ARITHMETIC accel UNIT */
4819 genMultTwoByte (left, right, result, ic);
4822 /* should have been converted to function call */
4826 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4827 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4828 freeAsmop (result, NULL, ic, TRUE);
4831 /*-----------------------------------------------------------------*/
4832 /* genDivbits :- division of bits */
4833 /*-----------------------------------------------------------------*/
4835 genDivbits (operand * left,
4843 /* the result must be bit */
4844 LOAD_AB_FOR_DIV (left, right, l);
4845 emitcode ("div", "ab");
4846 emitcode ("rrc", "a");
4847 aopOp(result, ic, TRUE, FALSE);
4849 aopPut (AOP (result), "c", 0);
4852 /*-----------------------------------------------------------------*/
4853 /* genDivOneByte : 8 bit division */
4854 /*-----------------------------------------------------------------*/
4856 genDivOneByte (operand * left,
4861 sym_link *opetype = operandType (result);
4867 /* signed or unsigned */
4868 if (SPEC_USIGN (opetype))
4870 /* unsigned is easy */
4871 LOAD_AB_FOR_DIV (left, right, l);
4872 emitcode ("div", "ab");
4875 aopOp(result, ic, TRUE, FALSE);
4876 aopPut (AOP (result), "a", 0);
4879 size = AOP_SIZE (result) - 1;
4883 aopPut (AOP (result), zero, offset++);
4888 /* signed is a little bit more difficult */
4890 /* save the signs of the operands */
4891 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4892 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4893 emitcode ("push", "acc"); /* save it on the stack */
4895 /* now sign adjust for both left & right */
4896 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4897 lbl = newiTempLabel (NULL);
4898 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4899 emitcode ("cpl", "a");
4900 emitcode ("inc", "a");
4901 emitcode ("", "!tlabeldef", (lbl->key + 100));
4902 emitcode ("mov", "b,a");
4904 /* sign adjust left side */
4905 MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4907 lbl = newiTempLabel (NULL);
4908 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4909 emitcode ("cpl", "a");
4910 emitcode ("inc", "a");
4911 emitcode ("", "!tlabeldef", (lbl->key + 100));
4913 /* now the division */
4914 emitcode ("nop", "; workaround for DS80C390 div bug.");
4915 emitcode ("div", "ab");
4916 /* we are interested in the lower order
4918 emitcode ("mov", "b,a");
4919 lbl = newiTempLabel (NULL);
4920 emitcode ("pop", "acc");
4921 /* if there was an over flow we don't
4922 adjust the sign of the result */
4923 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4924 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4926 emitcode ("clr", "a");
4927 emitcode ("subb", "a,b");
4928 emitcode ("mov", "b,a");
4929 emitcode ("", "!tlabeldef", (lbl->key + 100));
4931 /* now we are done */
4932 _G.accInUse++; _G.bInUse++;
4933 aopOp(result, ic, TRUE, FALSE);
4935 aopPut (AOP (result), "b", 0);
4937 size = AOP_SIZE (result) - 1;
4941 emitcode ("mov", "c,b.7");
4942 emitcode ("subb", "a,acc");
4946 aopPut (AOP (result), "a", offset++);
4948 _G.accInUse--; _G.bInUse--;
4952 /*-----------------------------------------------------------------*/
4953 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
4954 /*-----------------------------------------------------------------*/
4955 static void genDivTwoByte (operand *left, operand *right,
4956 operand *result, iCode *ic)
4958 sym_link *retype = getSpec(operandType(right));
4959 sym_link *letype = getSpec(operandType(left));
4960 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4963 /* save EA bit in F1 */
4964 lbl = newiTempLabel(NULL);
4965 emitcode ("setb","F1");
4966 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4967 emitcode ("clr","F1");
4968 emitcode("","!tlabeldef",lbl->key+100);
4970 /* load up MA with left */
4972 emitcode("clr","F0");
4973 lbl = newiTempLabel(NULL);
4974 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4975 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4976 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4977 emitcode ("xch", "a,b");
4978 emitcode ("cpl","a");
4979 emitcode ("add", "a,#1");
4980 emitcode ("xch", "a,b");
4981 emitcode ("cpl", "a"); // msb
4982 emitcode ("addc","a,#0");
4983 emitcode ("setb","F0");
4984 emitcode ("","!tlabeldef",lbl->key+100);
4985 emitcode ("mov","ma,b");
4986 emitcode ("mov","ma,a");
4988 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4989 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4992 /* load up MB with right */
4994 if (AOP_TYPE(right) == AOP_LIT) {
4995 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4997 lbl = newiTempLabel(NULL);
4998 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4999 emitcode("setb","F0");
5000 emitcode ("","!tlabeldef",lbl->key+100);
5003 emitcode ("mov","mb,#!constbyte",val & 0xff);
5004 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5006 lbl = newiTempLabel(NULL);
5007 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5008 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5009 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5010 emitcode ("xch", "a,b");
5011 emitcode ("cpl","a");
5012 emitcode ("add", "a,#1");
5013 emitcode ("xch", "a,b");
5014 emitcode ("cpl", "a"); // msb
5015 emitcode ("addc", "a,#0");
5016 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5017 emitcode ("setb","F0");
5018 emitcode ("","!tlabeldef",lbl->key+100);
5019 emitcode ("mov","mb,b");
5020 emitcode ("mov","mb,a");
5023 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5024 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5027 /* wait for multiplication to finish */
5028 lbl = newiTempLabel(NULL);
5029 emitcode("","!tlabeldef", lbl->key+100);
5030 emitcode("mov","a,mcnt1");
5031 emitcode("anl","a,#!constbyte",0x80);
5032 emitcode("jnz","!tlabel",lbl->key+100);
5034 freeAsmop (left, NULL, ic, TRUE);
5035 freeAsmop (right, NULL, ic,TRUE);
5036 aopOp(result, ic, TRUE, FALSE);
5038 /* if unsigned then simple */
5040 aopPut(AOP(result),"ma",1);
5041 aopPut(AOP(result),"ma",0);
5043 emitcode("push","ma");
5045 /* negate result if needed */
5046 lbl = newiTempLabel(NULL);
5047 emitcode("jnb","F0,!tlabel",lbl->key+100);
5048 emitcode("cpl","a");
5049 emitcode("add","a,#1");
5050 emitcode("","!tlabeldef", lbl->key+100);
5051 aopPut(AOP(result),"a",0);
5052 emitcode("pop","acc");
5053 lbl = newiTempLabel(NULL);
5054 emitcode("jnb","F0,!tlabel",lbl->key+100);
5055 emitcode("cpl","a");
5056 emitcode("addc","a,#0");
5057 emitcode("","!tlabeldef", lbl->key+100);
5058 aopPut(AOP(result),"a",1);
5060 freeAsmop (result, NULL, ic, TRUE);
5061 /* restore EA bit in F1 */
5062 lbl = newiTempLabel(NULL);
5063 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5064 emitcode ("setb","EA");
5065 emitcode("","!tlabeldef",lbl->key+100);
5069 /*-----------------------------------------------------------------*/
5070 /* genDiv - generates code for division */
5071 /*-----------------------------------------------------------------*/
5075 operand *left = IC_LEFT (ic);
5076 operand *right = IC_RIGHT (ic);
5077 operand *result = IC_RESULT (ic);
5079 D (emitcode (";", "genDiv "););
5081 /* assign the amsops */
5084 /* special cases first */
5086 if (AOP_TYPE (left) == AOP_CRY &&
5087 AOP_TYPE (right) == AOP_CRY)
5089 genDivbits (left, right, result, ic);
5093 /* if both are of size == 1 */
5094 if (AOP_SIZE (left) == 1 &&
5095 AOP_SIZE (right) == 1)
5097 genDivOneByte (left, right, result, ic);
5101 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5102 /* use the ds390 ARITHMETIC accel UNIT */
5103 genDivTwoByte (left, right, result, ic);
5106 /* should have been converted to function call */
5109 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5110 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5111 freeAsmop (result, NULL, ic, TRUE);
5114 /*-----------------------------------------------------------------*/
5115 /* genModbits :- modulus of bits */
5116 /*-----------------------------------------------------------------*/
5118 genModbits (operand * left,
5126 /* the result must be bit */
5127 LOAD_AB_FOR_DIV (left, right, l);
5128 emitcode ("div", "ab");
5129 emitcode ("mov", "a,b");
5130 emitcode ("rrc", "a");
5131 aopOp(result, ic, TRUE, FALSE);
5132 aopPut (AOP (result), "c", 0);
5135 /*-----------------------------------------------------------------*/
5136 /* genModOneByte : 8 bit modulus */
5137 /*-----------------------------------------------------------------*/
5139 genModOneByte (operand * left,
5144 sym_link *opetype = operandType (result);
5148 /* signed or unsigned */
5149 if (SPEC_USIGN (opetype))
5151 /* unsigned is easy */
5152 LOAD_AB_FOR_DIV (left, right, l);
5153 emitcode ("div", "ab");
5154 aopOp(result, ic, TRUE, FALSE);
5155 aopPut (AOP (result), "b", 0);
5159 /* signed is a little bit more difficult */
5161 /* save the signs of the operands */
5162 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5164 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
5165 emitcode ("push", "acc"); /* save it on the stack */
5167 /* now sign adjust for both left & right */
5168 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5170 lbl = newiTempLabel (NULL);
5171 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5172 emitcode ("cpl", "a");
5173 emitcode ("inc", "a");
5174 emitcode ("", "!tlabeldef", (lbl->key + 100));
5175 emitcode ("mov", "b,a");
5177 /* sign adjust left side */
5178 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5180 lbl = newiTempLabel (NULL);
5181 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5182 emitcode ("cpl", "a");
5183 emitcode ("inc", "a");
5184 emitcode ("", "!tlabeldef", (lbl->key + 100));
5186 /* now the multiplication */
5187 emitcode ("nop", "; workaround for DS80C390 div bug.");
5188 emitcode ("div", "ab");
5189 /* we are interested in the lower order
5191 lbl = newiTempLabel (NULL);
5192 emitcode ("pop", "acc");
5193 /* if there was an over flow we don't
5194 adjust the sign of the result */
5195 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
5196 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5198 emitcode ("clr", "a");
5199 emitcode ("subb", "a,b");
5200 emitcode ("mov", "b,a");
5201 emitcode ("", "!tlabeldef", (lbl->key + 100));
5204 /* now we are done */
5205 aopOp(result, ic, TRUE, FALSE);
5206 aopPut (AOP (result), "b", 0);
5211 /*-----------------------------------------------------------------*/
5212 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
5213 /*-----------------------------------------------------------------*/
5214 static void genModTwoByte (operand *left, operand *right,
5215 operand *result, iCode *ic)
5217 sym_link *retype = getSpec(operandType(right));
5218 sym_link *letype = getSpec(operandType(left));
5219 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5222 /* load up MA with left */
5223 /* save EA bit in F1 */
5224 lbl = newiTempLabel(NULL);
5225 emitcode ("setb","F1");
5226 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5227 emitcode ("clr","F1");
5228 emitcode("","!tlabeldef",lbl->key+100);
5231 lbl = newiTempLabel(NULL);
5232 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5233 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5234 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5235 emitcode ("xch", "a,b");
5236 emitcode ("cpl","a");
5237 emitcode ("add", "a,#1");
5238 emitcode ("xch", "a,b");
5239 emitcode ("cpl", "a"); // msb
5240 emitcode ("addc","a,#0");
5241 emitcode ("","!tlabeldef",lbl->key+100);
5242 emitcode ("mov","ma,b");
5243 emitcode ("mov","ma,a");
5245 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5246 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5249 /* load up MB with right */
5251 if (AOP_TYPE(right) == AOP_LIT) {
5252 int val=floatFromVal (AOP (right)->aopu.aop_lit);
5256 emitcode ("mov","mb,#!constbyte",val & 0xff);
5257 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5259 lbl = newiTempLabel(NULL);
5260 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5261 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5262 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5263 emitcode ("xch", "a,b");
5264 emitcode ("cpl","a");
5265 emitcode ("add", "a,#1");
5266 emitcode ("xch", "a,b");
5267 emitcode ("cpl", "a"); // msb
5268 emitcode ("addc", "a,#0");
5269 emitcode ("","!tlabeldef",lbl->key+100);
5270 emitcode ("mov","mb,b");
5271 emitcode ("mov","mb,a");
5274 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5275 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5278 /* wait for multiplication to finish */
5279 lbl = newiTempLabel(NULL);
5280 emitcode("","!tlabeldef", lbl->key+100);
5281 emitcode("mov","a,mcnt1");
5282 emitcode("anl","a,#!constbyte",0x80);
5283 emitcode("jnz","!tlabel",lbl->key+100);
5285 freeAsmop (left, NULL, ic, TRUE);
5286 freeAsmop (right, NULL, ic,TRUE);
5287 aopOp(result, ic, TRUE, FALSE);
5289 aopPut(AOP(result),"mb",1);
5290 aopPut(AOP(result),"mb",0);
5291 freeAsmop (result, NULL, ic, TRUE);
5293 /* restore EA bit in F1 */
5294 lbl = newiTempLabel(NULL);
5295 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5296 emitcode ("setb","EA");
5297 emitcode("","!tlabeldef",lbl->key+100);
5301 /*-----------------------------------------------------------------*/
5302 /* genMod - generates code for division */
5303 /*-----------------------------------------------------------------*/
5307 operand *left = IC_LEFT (ic);
5308 operand *right = IC_RIGHT (ic);
5309 operand *result = IC_RESULT (ic);
5311 D (emitcode (";", "genMod "); );
5313 /* assign the amsops */
5316 /* special cases first */
5318 if (AOP_TYPE (left) == AOP_CRY &&
5319 AOP_TYPE (right) == AOP_CRY)
5321 genModbits (left, right, result, ic);
5325 /* if both are of size == 1 */
5326 if (AOP_SIZE (left) == 1 &&
5327 AOP_SIZE (right) == 1)
5329 genModOneByte (left, right, result, ic);
5333 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5334 /* use the ds390 ARITHMETIC accel UNIT */
5335 genModTwoByte (left, right, result, ic);
5339 /* should have been converted to function call */
5343 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5344 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5345 freeAsmop (result, NULL, ic, TRUE);
5348 /*-----------------------------------------------------------------*/
5349 /* genIfxJump :- will create a jump depending on the ifx */
5350 /*-----------------------------------------------------------------*/
5352 genIfxJump (iCode * ic, char *jval)
5355 symbol *tlbl = newiTempLabel (NULL);
5358 D (emitcode (";", "genIfxJump"););
5360 /* if true label then we jump if condition
5364 jlbl = IC_TRUE (ic);
5365 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5366 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5370 /* false label is present */
5371 jlbl = IC_FALSE (ic);
5372 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5373 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5375 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5376 emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5378 emitcode (inst, "!tlabel", tlbl->key + 100);
5379 emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5380 emitcode ("", "!tlabeldef", tlbl->key + 100);
5382 /* mark the icode as generated */
5386 /*-----------------------------------------------------------------*/
5387 /* genCmp :- greater or less than comparison */
5388 /*-----------------------------------------------------------------*/
5390 genCmp (operand * left, operand * right,
5391 iCode * ic, iCode * ifx, int sign)
5393 int size, offset = 0;
5394 unsigned long lit = 0L;
5397 D (emitcode (";", "genCmp"););
5399 result = IC_RESULT (ic);
5401 /* if left & right are bit variables */
5402 if (AOP_TYPE (left) == AOP_CRY &&
5403 AOP_TYPE (right) == AOP_CRY)
5405 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5406 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
5410 /* subtract right from left if at the
5411 end the carry flag is set then we know that
5412 left is greater than right */
5413 size = max (AOP_SIZE (left), AOP_SIZE (right));
5415 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5416 if ((size == 1) && !sign
5417 && (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5419 symbol *lbl = newiTempLabel (NULL);
5420 emitcode ("cjne", "%s,%s,!tlabel",
5421 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
5422 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5424 emitcode ("", "!tlabeldef", lbl->key + 100);
5428 if (AOP_TYPE (right) == AOP_LIT)
5430 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5431 /* optimize if(x < 0) or if(x >= 0) */
5440 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
5442 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5443 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5445 aopOp (result, ic, FALSE, FALSE);
5447 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5449 freeAsmop (result, NULL, ic, TRUE);
5450 genIfxJump (ifx, "acc.7");
5455 emitcode ("rlc", "a");
5457 goto release_freedLR;
5465 // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5466 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5467 // emitcode (";", "genCmp #2");
5468 if (sign && (size == 0))
5470 // emitcode (";", "genCmp #3");
5471 emitcode ("xrl", "a,#!constbyte",0x80);
5472 if (AOP_TYPE (right) == AOP_LIT)
5474 unsigned long lit = (unsigned long)
5475 floatFromVal (AOP (right)->aopu.aop_lit);
5476 // emitcode (";", "genCmp #3.1");
5477 emitcode ("subb", "a,#!constbyte",
5478 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5482 // emitcode (";", "genCmp #3.2");
5484 MOVB(aopGet (AOP (right), offset++, FALSE, FALSE, "b"));
5485 saveAccWarn = DEFAULT_ACC_WARNING;
5486 emitcode ("xrl", "b,#!constbyte",0x80);
5487 emitcode ("subb", "a,b");
5494 // emitcode (";", "genCmp #4");
5496 s = aopGet (AOP (right), offset++, FALSE, FALSE, "b");
5497 saveAccWarn = DEFAULT_ACC_WARNING;
5499 emitcode ("subb", "a,%s", s);
5506 /* Don't need the left & right operands any more; do need the result. */
5507 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5508 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5510 aopOp (result, ic, FALSE, FALSE);
5514 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5520 /* if the result is used in the next
5521 ifx conditional branch then generate
5522 code a little differently */
5525 genIfxJump (ifx, "c");
5531 /* leave the result in acc */
5533 freeAsmop (result, NULL, ic, TRUE);
5536 /*-----------------------------------------------------------------*/
5537 /* genCmpGt :- greater than comparison */
5538 /*-----------------------------------------------------------------*/
5540 genCmpGt (iCode * ic, iCode * ifx)
5542 operand *left, *right;
5543 sym_link *letype, *retype;
5546 D (emitcode (";", "genCmpGt ");
5549 left = IC_LEFT (ic);
5550 right = IC_RIGHT (ic);
5552 letype = getSpec (operandType (left));
5553 retype = getSpec (operandType (right));
5554 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5556 /* assign the left & right amsops */
5559 genCmp (right, left, ic, ifx, sign);
5562 /*-----------------------------------------------------------------*/
5563 /* genCmpLt - less than comparisons */
5564 /*-----------------------------------------------------------------*/
5566 genCmpLt (iCode * ic, iCode * ifx)
5568 operand *left, *right;
5569 sym_link *letype, *retype;
5572 D (emitcode (";", "genCmpLt "););
5574 left = IC_LEFT (ic);
5575 right = IC_RIGHT (ic);
5577 letype = getSpec (operandType (left));
5578 retype = getSpec (operandType (right));
5579 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5581 /* assign the left & right amsops */
5584 genCmp (left, right, ic, ifx, sign);
5587 /*-----------------------------------------------------------------*/
5588 /* gencjneshort - compare and jump if not equal */
5589 /*-----------------------------------------------------------------*/
5591 gencjneshort (operand * left, operand * right, symbol * lbl)
5593 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5595 unsigned long lit = 0L;
5597 D (emitcode (";", "gencjneshort");
5600 /* if the left side is a literal or
5601 if the right is in a pointer register and left
5603 if ((AOP_TYPE (left) == AOP_LIT) ||
5604 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5611 if (AOP_TYPE (right) == AOP_LIT)
5612 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5614 if (opIsGptr (left) || opIsGptr (right))
5616 /* We are comparing a generic pointer to something.
5617 * Exclude the generic type byte from the comparison.
5620 D (emitcode (";", "cjneshort: generic ptr special case."););
5624 /* if the right side is a literal then anything goes */
5625 if (AOP_TYPE (right) == AOP_LIT &&
5626 AOP_TYPE (left) != AOP_DIR)
5630 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5631 emitcode ("cjne", "a,%s,!tlabel",
5632 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5638 /* if the right side is in a register or in direct space or
5639 if the left is a pointer register & right is not */
5640 else if (AOP_TYPE (right) == AOP_REG ||
5641 AOP_TYPE (right) == AOP_DIR ||
5642 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5643 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5647 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5648 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5649 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5650 emitcode ("jnz", "!tlabel", lbl->key + 100);
5652 emitcode ("cjne", "a,%s,!tlabel",
5653 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
5660 /* right is a pointer reg need both a & b */
5663 MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5664 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
5665 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5671 /*-----------------------------------------------------------------*/
5672 /* gencjne - compare and jump if not equal */
5673 /*-----------------------------------------------------------------*/
5675 gencjne (operand * left, operand * right, symbol * lbl)
5677 symbol *tlbl = newiTempLabel (NULL);
5679 D (emitcode (";", "gencjne");
5682 gencjneshort (left, right, lbl);
5684 emitcode ("mov", "a,%s", one);
5685 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5686 emitcode ("", "!tlabeldef", lbl->key + 100);
5687 emitcode ("clr", "a");
5688 emitcode ("", "!tlabeldef", tlbl->key + 100);
5691 /*-----------------------------------------------------------------*/
5692 /* genCmpEq - generates code for equal to */
5693 /*-----------------------------------------------------------------*/
5695 genCmpEq (iCode * ic, iCode * ifx)
5697 operand *left, *right, *result;
5699 D (emitcode (";", "genCmpEq ");
5703 AOP_SET_LOCALS (ic);
5705 /* if literal, literal on the right or
5706 if the right is in a pointer register and left
5708 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5709 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5711 operand *t = IC_RIGHT (ic);
5712 IC_RIGHT (ic) = IC_LEFT (ic);
5716 if (ifx && /* !AOP_SIZE(result) */
5717 OP_SYMBOL (result) &&
5718 OP_SYMBOL (result)->regType == REG_CND)
5721 /* if they are both bit variables */
5722 if (AOP_TYPE (left) == AOP_CRY &&
5723 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5725 if (AOP_TYPE (right) == AOP_LIT)
5727 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5730 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5731 emitcode ("cpl", "c");
5735 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5739 emitcode ("clr", "c");
5741 /* AOP_TYPE(right) == AOP_CRY */
5745 symbol *lbl = newiTempLabel (NULL);
5746 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5747 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5748 emitcode ("cpl", "c");
5749 emitcode ("", "!tlabeldef", (lbl->key + 100));
5751 /* if true label then we jump if condition
5753 tlbl = newiTempLabel (NULL);
5756 emitcode ("jnc", "!tlabel", tlbl->key + 100);
5757 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5761 emitcode ("jc", "!tlabel", tlbl->key + 100);
5762 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5764 emitcode ("", "!tlabeldef", tlbl->key + 100);
5768 tlbl = newiTempLabel (NULL);
5769 gencjneshort (left, right, tlbl);
5772 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5773 emitcode ("", "!tlabeldef", tlbl->key + 100);
5777 symbol *lbl = newiTempLabel (NULL);
5778 emitcode ("sjmp", "!tlabel", lbl->key + 100);
5779 emitcode ("", "!tlabeldef", tlbl->key + 100);
5780 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5781 emitcode ("", "!tlabeldef", lbl->key + 100);
5784 /* mark the icode as generated */
5787 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5788 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5792 /* if they are both bit variables */
5793 if (AOP_TYPE (left) == AOP_CRY &&
5794 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5796 if (AOP_TYPE (right) == AOP_LIT)
5798 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5801 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5802 emitcode ("cpl", "c");
5806 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5810 emitcode ("clr", "c");
5812 /* AOP_TYPE(right) == AOP_CRY */
5816 symbol *lbl = newiTempLabel (NULL);
5817 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5818 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5819 emitcode ("cpl", "c");
5820 emitcode ("", "!tlabeldef", (lbl->key + 100));
5823 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5824 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5826 aopOp (result, ic, TRUE, FALSE);
5829 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5836 genIfxJump (ifx, "c");
5839 /* if the result is used in an arithmetic operation
5840 then put the result in place */
5845 gencjne (left, right, newiTempLabel (NULL));
5847 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5848 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5850 aopOp (result, ic, TRUE, FALSE);
5852 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5854 aopPut (AOP (result), "a", 0);
5859 genIfxJump (ifx, "a");
5862 /* if the result is used in an arithmetic operation
5863 then put the result in place */
5864 if (AOP_TYPE (result) != AOP_CRY)
5866 /* leave the result in acc */
5870 freeAsmop (result, NULL, ic, TRUE);
5873 /*-----------------------------------------------------------------*/
5874 /* ifxForOp - returns the icode containing the ifx for operand */
5875 /*-----------------------------------------------------------------*/
5877 ifxForOp (operand * op, iCode * ic)
5879 /* if true symbol then needs to be assigned */
5880 if (IS_TRUE_SYMOP (op))
5883 /* if this has register type condition and
5884 the next instruction is ifx with the same operand
5885 and live to of the operand is upto the ifx only then */
5887 ic->next->op == IFX &&
5888 IC_COND (ic->next)->key == op->key &&
5889 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5894 /*-----------------------------------------------------------------*/
5895 /* hasInc - operand is incremented before any other use */
5896 /*-----------------------------------------------------------------*/
5898 hasInc (operand *op, iCode *ic, int osize)
5900 sym_link *type = operandType(op);
5901 sym_link *retype = getSpec (type);
5902 iCode *lic = ic->next;
5905 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5906 if (!IS_SYMOP(op)) return NULL;
5908 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5909 if (IS_AGGREGATE(type->next)) return NULL;
5910 if (osize != (isize = getSize(type->next))) return NULL;
5913 /* if operand of the form op = op + <sizeof *op> */
5914 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5915 isOperandEqual(IC_RESULT(lic),op) &&
5916 isOperandLiteral(IC_RIGHT(lic)) &&
5917 operandLitValue(IC_RIGHT(lic)) == isize) {
5920 /* if the operand used or deffed */
5921 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5924 /* if GOTO or IFX */
5925 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5931 /*-----------------------------------------------------------------*/
5932 /* genAndOp - for && operation */
5933 /*-----------------------------------------------------------------*/
5935 genAndOp (iCode * ic)
5937 operand *left, *right, *result;
5940 D (emitcode (";", "genAndOp "););
5942 /* note here that && operations that are in an
5943 if statement are taken away by backPatchLabels
5944 only those used in arthmetic operations remain */
5946 AOP_SET_LOCALS (ic);
5948 /* if both are bit variables */
5949 if (AOP_TYPE (left) == AOP_CRY &&
5950 AOP_TYPE (right) == AOP_CRY)
5952 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5953 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5954 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5955 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5957 aopOp (result,ic,FALSE, FALSE);
5962 tlbl = newiTempLabel (NULL);
5964 emitcode ("jz", "!tlabel", tlbl->key + 100);
5966 emitcode ("", "!tlabeldef", tlbl->key + 100);
5967 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5968 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5970 aopOp (result,ic,FALSE, FALSE);
5973 freeAsmop (result, NULL, ic, TRUE);
5977 /*-----------------------------------------------------------------*/
5978 /* genOrOp - for || operation */
5979 /*-----------------------------------------------------------------*/
5981 genOrOp (iCode * ic)
5983 operand *left, *right, *result;
5986 D (emitcode (";", "genOrOp "););
5988 /* note here that || operations that are in an
5989 if statement are taken away by backPatchLabels
5990 only those used in arthmetic operations remain */
5992 AOP_SET_LOCALS (ic);
5994 /* if both are bit variables */
5995 if (AOP_TYPE (left) == AOP_CRY &&
5996 AOP_TYPE (right) == AOP_CRY)
5998 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5999 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6000 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6001 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6003 aopOp (result,ic,FALSE, FALSE);
6009 tlbl = newiTempLabel (NULL);
6011 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6013 emitcode ("", "!tlabeldef", tlbl->key + 100);
6014 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6015 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6017 aopOp (result,ic,FALSE, FALSE);
6022 freeAsmop (result, NULL, ic, TRUE);
6025 /*-----------------------------------------------------------------*/
6026 /* isLiteralBit - test if lit == 2^n */
6027 /*-----------------------------------------------------------------*/
6029 isLiteralBit (unsigned long lit)
6031 unsigned long pw[32] =
6032 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6033 0x100L, 0x200L, 0x400L, 0x800L,
6034 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6035 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6036 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6037 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6038 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6041 for (idx = 0; idx < 32; idx++)
6047 /*-----------------------------------------------------------------*/
6048 /* continueIfTrue - */
6049 /*-----------------------------------------------------------------*/
6051 continueIfTrue (iCode * ic)
6054 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6058 /*-----------------------------------------------------------------*/
6060 /*-----------------------------------------------------------------*/
6062 jumpIfTrue (iCode * ic)
6065 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6069 /*-----------------------------------------------------------------*/
6070 /* jmpTrueOrFalse - */
6071 /*-----------------------------------------------------------------*/
6073 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6075 // ugly but optimized by peephole
6078 symbol *nlbl = newiTempLabel (NULL);
6079 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6080 emitcode ("", "!tlabeldef", tlbl->key + 100);
6081 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6082 emitcode ("", "!tlabeldef", nlbl->key + 100);
6086 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6087 emitcode ("", "!tlabeldef", tlbl->key + 100);
6092 // Generate code to perform a bit-wise logic operation
6093 // on two operands in far space (assumed to already have been
6094 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6095 // in far space. This requires pushing the result on the stack
6096 // then popping it into the result.
6098 genFarFarLogicOp(iCode *ic, char *logicOp)
6100 int size, resultSize, compSize;
6104 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6105 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
6106 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6108 _startLazyDPSEvaluation();
6109 for (size = compSize; (size--); offset++)
6111 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6112 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6113 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6115 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6116 emitcode ("push", "acc");
6118 _endLazyDPSEvaluation();
6120 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6121 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6122 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6124 resultSize = AOP_SIZE(IC_RESULT(ic));
6126 ADJUST_PUSHED_RESULT(compSize, resultSize);
6128 _startLazyDPSEvaluation();
6131 emitcode ("pop", "acc");
6132 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6134 _endLazyDPSEvaluation();
6135 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6139 /*-----------------------------------------------------------------*/
6140 /* genAnd - code for and */
6141 /*-----------------------------------------------------------------*/
6143 genAnd (iCode * ic, iCode * ifx)
6145 operand *left, *right, *result;
6146 int size, offset = 0;
6147 unsigned long lit = 0L;
6152 D (emitcode (";", "genAnd "););
6154 AOP_OP_3_NOFATAL (ic, pushResult);
6155 AOP_SET_LOCALS (ic);
6159 genFarFarLogicOp(ic, "anl");
6164 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6166 AOP_TYPE (left), AOP_TYPE (right));
6167 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6169 AOP_SIZE (left), AOP_SIZE (right));
6172 /* if left is a literal & right is not then exchange them */
6173 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6174 #ifdef LOGIC_OPS_BROKEN
6175 || AOP_NEEDSACC (left)
6179 operand *tmp = right;
6184 /* if result = right then exchange them */
6185 if (sameRegs (AOP (result), AOP (right)))
6187 operand *tmp = right;
6192 /* if right is bit then exchange them */
6193 if (AOP_TYPE (right) == AOP_CRY &&
6194 AOP_TYPE (left) != AOP_CRY)
6196 operand *tmp = right;
6200 if (AOP_TYPE (right) == AOP_LIT)
6201 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6203 size = AOP_SIZE (result);
6206 // result = bit & yy;
6207 if (AOP_TYPE (left) == AOP_CRY)
6209 // c = bit & literal;
6210 if (AOP_TYPE (right) == AOP_LIT)
6214 if (size && sameRegs (AOP (result), AOP (left)))
6217 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6222 if (size && (AOP_TYPE (result) == AOP_CRY))
6224 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6227 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6232 emitcode ("clr", "c");
6237 if (AOP_TYPE (right) == AOP_CRY)
6240 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6241 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6246 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6248 emitcode ("rrc", "a");
6249 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6257 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6258 genIfxJump (ifx, "c");
6262 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6263 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6264 if ((AOP_TYPE (right) == AOP_LIT) &&
6265 (AOP_TYPE (result) == AOP_CRY) &&
6266 (AOP_TYPE (left) != AOP_CRY))
6268 int posbit = isLiteralBit (lit);
6273 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6276 emitcode ("mov", "c,acc.%d", posbit & 0x07);
6282 SNPRINTF (buff, sizeof(buff),
6283 "acc.%d", posbit & 0x07);
6284 genIfxJump (ifx, buff);
6288 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6295 symbol *tlbl = newiTempLabel (NULL);
6296 int sizel = AOP_SIZE (left);
6298 emitcode ("setb", "c");
6301 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6303 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6305 if ((posbit = isLiteralBit (bytelit)) != 0)
6306 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6309 if (bytelit != 0x0FFL)
6310 emitcode ("anl", "a,%s",
6311 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6312 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6317 // bit = left & literal
6320 emitcode ("clr", "c");
6321 emitcode ("", "!tlabeldef", tlbl->key + 100);
6323 // if(left & literal)
6327 jmpTrueOrFalse (ifx, tlbl);
6335 /* if left is same as result */
6336 if (sameRegs (AOP (result), AOP (left)))
6338 for (; size--; offset++)
6340 if (AOP_TYPE (right) == AOP_LIT)
6342 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6344 else if (bytelit == 0)
6345 aopPut (AOP (result), zero, offset);
6346 else if (IS_AOP_PREG (result))
6348 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6349 emitcode ("anl", "a,%s",
6350 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6351 aopPut (AOP (result), "a", offset);
6354 emitcode ("anl", "%s,%s",
6355 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6356 aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6360 if (AOP_TYPE (left) == AOP_ACC)
6361 emitcode ("anl", "a,%s",
6362 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6365 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6366 if (IS_AOP_PREG (result))
6368 emitcode ("anl", "a,%s",
6369 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6370 aopPut (AOP (result), "a", offset);
6373 emitcode ("anl", "%s,a",
6374 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6381 // left & result in different registers
6382 if (AOP_TYPE (result) == AOP_CRY)
6385 // if(size), result in bit
6386 // if(!size && ifx), conditional oper: if(left & right)
6387 symbol *tlbl = newiTempLabel (NULL);
6388 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6390 emitcode ("setb", "c");
6393 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6394 emitcode ("anl", "a,%s",
6395 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6397 if (AOP_TYPE(left)==AOP_ACC) {
6398 emitcode("mov", "b,a");
6399 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6400 emitcode("anl", "a,b");
6402 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6403 emitcode ("anl", "a,%s",
6404 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6407 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6413 emitcode ("", "!tlabeldef", tlbl->key + 100);
6417 jmpTrueOrFalse (ifx, tlbl);
6421 for (; (size--); offset++)
6424 // result = left & right
6425 if (AOP_TYPE (right) == AOP_LIT)
6427 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6429 aopPut (AOP (result),
6430 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6434 else if (bytelit == 0)
6436 aopPut (AOP (result), zero, offset);
6439 D (emitcode (";", "better literal AND."););
6440 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6441 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6442 FALSE, FALSE, DP2_RESULT_REG));
6447 // faster than result <- left, anl result,right
6448 // and better if result is SFR
6449 if (AOP_TYPE (left) == AOP_ACC)
6451 emitcode ("anl", "a,%s",
6452 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6456 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6457 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6459 emitcode("mov", "b,a");
6463 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6464 emitcode ("anl", "a,%s", rOp);
6467 aopPut (AOP (result), "a", offset);
6473 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6474 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6475 freeAsmop (result, NULL, ic, TRUE);
6479 /*-----------------------------------------------------------------*/
6480 /* genOr - code for or */
6481 /*-----------------------------------------------------------------*/
6483 genOr (iCode * ic, iCode * ifx)
6485 operand *left, *right, *result;
6486 int size, offset = 0;
6487 unsigned long lit = 0L;
6490 D (emitcode (";", "genOr "););
6492 AOP_OP_3_NOFATAL (ic, pushResult);
6493 AOP_SET_LOCALS (ic);
6497 genFarFarLogicOp(ic, "orl");
6503 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6505 AOP_TYPE (left), AOP_TYPE (right));
6506 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6508 AOP_SIZE (left), AOP_SIZE (right));
6511 /* if left is a literal & right is not then exchange them */
6512 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6513 #ifdef LOGIC_OPS_BROKEN
6514 || AOP_NEEDSACC (left) // I think this is a net loss now.
6518 operand *tmp = right;
6523 /* if result = right then exchange them */
6524 if (sameRegs (AOP (result), AOP (right)))
6526 operand *tmp = right;
6531 /* if right is bit then exchange them */
6532 if (AOP_TYPE (right) == AOP_CRY &&
6533 AOP_TYPE (left) != AOP_CRY)
6535 operand *tmp = right;
6539 if (AOP_TYPE (right) == AOP_LIT)
6540 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6542 size = AOP_SIZE (result);
6546 if (AOP_TYPE (left) == AOP_CRY)
6548 if (AOP_TYPE (right) == AOP_LIT)
6550 // c = bit & literal;
6553 // lit != 0 => result = 1
6554 if (AOP_TYPE (result) == AOP_CRY)
6557 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6559 continueIfTrue (ifx);
6562 emitcode ("setb", "c");
6566 // lit == 0 => result = left
6567 if (size && sameRegs (AOP (result), AOP (left)))
6569 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6574 if (AOP_TYPE (right) == AOP_CRY)
6577 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6578 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6583 symbol *tlbl = newiTempLabel (NULL);
6584 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6585 emitcode ("setb", "c");
6586 emitcode ("jb", "%s,!tlabel",
6587 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6589 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6590 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6592 jmpTrueOrFalse (ifx, tlbl);
6598 emitcode ("", "!tlabeldef", tlbl->key + 100);
6607 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6608 genIfxJump (ifx, "c");
6612 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6613 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6614 if ((AOP_TYPE (right) == AOP_LIT) &&
6615 (AOP_TYPE (result) == AOP_CRY) &&
6616 (AOP_TYPE (left) != AOP_CRY))
6622 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6624 continueIfTrue (ifx);
6629 // lit = 0, result = boolean(left)
6631 emitcode ("setb", "c");
6635 symbol *tlbl = newiTempLabel (NULL);
6636 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6638 emitcode ("", "!tlabeldef", tlbl->key + 100);
6642 genIfxJump (ifx, "a");
6650 /* if left is same as result */
6651 if (sameRegs (AOP (result), AOP (left)))
6653 for (; size--; offset++)
6655 if (AOP_TYPE (right) == AOP_LIT)
6657 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6663 if (IS_AOP_PREG (left))
6665 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6666 emitcode ("orl", "a,%s",
6667 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6668 aopPut (AOP (result), "a", offset);
6672 emitcode ("orl", "%s,%s",
6673 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6674 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6680 if (AOP_TYPE (left) == AOP_ACC)
6682 emitcode ("orl", "a,%s",
6683 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6687 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6688 if (IS_AOP_PREG (left))
6690 emitcode ("orl", "a,%s",
6691 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6692 aopPut (AOP (result), "a", offset);
6696 emitcode ("orl", "%s,a",
6697 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6705 // left & result in different registers
6706 if (AOP_TYPE (result) == AOP_CRY)
6709 // if(size), result in bit
6710 // if(!size && ifx), conditional oper: if(left | right)
6711 symbol *tlbl = newiTempLabel (NULL);
6712 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6714 emitcode ("setb", "c");
6717 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6718 emitcode ("orl", "a,%s",
6719 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6721 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6722 emitcode ("orl", "a,%s",
6723 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6725 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6731 emitcode ("", "!tlabeldef", tlbl->key + 100);
6735 jmpTrueOrFalse (ifx, tlbl);
6739 _startLazyDPSEvaluation();
6740 for (; (size--); offset++)
6743 // result = left & right
6744 if (AOP_TYPE (right) == AOP_LIT)
6746 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6748 aopPut (AOP (result),
6749 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6753 D (emitcode (";", "better literal OR."););
6754 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6755 emitcode ("orl", "a, %s",
6756 aopGet (AOP (right), offset,
6757 FALSE, FALSE, DP2_RESULT_REG));
6762 // faster than result <- left, anl result,right
6763 // and better if result is SFR
6764 if (AOP_TYPE (left) == AOP_ACC)
6766 emitcode ("orl", "a,%s",
6767 aopGet (AOP (right), offset,
6768 FALSE, FALSE, DP2_RESULT_REG));
6772 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6774 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6776 emitcode("mov", "b,a");
6780 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6781 emitcode ("orl", "a,%s", rOp);
6784 aopPut (AOP (result), "a", offset);
6786 _endLazyDPSEvaluation();
6791 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6792 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6793 freeAsmop (result, NULL, ic, TRUE);
6796 /*-----------------------------------------------------------------*/
6797 /* genXor - code for xclusive or */
6798 /*-----------------------------------------------------------------*/
6800 genXor (iCode * ic, iCode * ifx)
6802 operand *left, *right, *result;
6803 int size, offset = 0;
6804 unsigned long lit = 0L;
6807 D (emitcode (";", "genXor "););
6809 AOP_OP_3_NOFATAL (ic, pushResult);
6810 AOP_SET_LOCALS (ic);
6814 genFarFarLogicOp(ic, "xrl");
6819 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6821 AOP_TYPE (left), AOP_TYPE (right));
6822 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6824 AOP_SIZE (left), AOP_SIZE (right));
6827 /* if left is a literal & right is not ||
6828 if left needs acc & right does not */
6829 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6830 #ifdef LOGIC_OPS_BROKEN
6831 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6835 operand *tmp = right;
6840 /* if result = right then exchange them */
6841 if (sameRegs (AOP (result), AOP (right)))
6843 operand *tmp = right;
6848 /* if right is bit then exchange them */
6849 if (AOP_TYPE (right) == AOP_CRY &&
6850 AOP_TYPE (left) != AOP_CRY)
6852 operand *tmp = right;
6856 if (AOP_TYPE (right) == AOP_LIT)
6857 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6859 size = AOP_SIZE (result);
6863 if (AOP_TYPE (left) == AOP_CRY)
6865 if (AOP_TYPE (right) == AOP_LIT)
6867 // c = bit & literal;
6870 // lit>>1 != 0 => result = 1
6871 if (AOP_TYPE (result) == AOP_CRY)
6874 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6876 continueIfTrue (ifx);
6879 emitcode ("setb", "c");
6886 // lit == 0, result = left
6887 if (size && sameRegs (AOP (result), AOP (left)))
6889 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6893 // lit == 1, result = not(left)
6894 if (size && sameRegs (AOP (result), AOP (left)))
6896 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6901 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6902 emitcode ("cpl", "c");
6911 symbol *tlbl = newiTempLabel (NULL);
6912 if (AOP_TYPE (right) == AOP_CRY)
6915 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6919 int sizer = AOP_SIZE (right);
6921 // if val>>1 != 0, result = 1
6922 emitcode ("setb", "c");
6925 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
6927 // test the msb of the lsb
6928 emitcode ("anl", "a,#!constbyte",0xfe);
6929 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6933 emitcode ("rrc", "a");
6935 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6936 emitcode ("cpl", "c");
6937 emitcode ("", "!tlabeldef", (tlbl->key + 100));
6944 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6945 genIfxJump (ifx, "c");
6949 if (sameRegs (AOP (result), AOP (left)))
6951 /* if left is same as result */
6952 for (; size--; offset++)
6954 if (AOP_TYPE (right) == AOP_LIT)
6956 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6958 else if (IS_AOP_PREG (left))
6960 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6961 emitcode ("xrl", "a,%s",
6962 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6963 aopPut (AOP (result), "a", offset);
6966 emitcode ("xrl", "%s,%s",
6967 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6968 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6972 if (AOP_TYPE (left) == AOP_ACC)
6973 emitcode ("xrl", "a,%s",
6974 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6977 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6978 if (IS_AOP_PREG (left))
6980 emitcode ("xrl", "a,%s",
6981 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6982 aopPut (AOP (result), "a", offset);
6985 emitcode ("xrl", "%s,a",
6986 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6993 // left & result in different registers
6994 if (AOP_TYPE (result) == AOP_CRY)
6997 // if(size), result in bit
6998 // if(!size && ifx), conditional oper: if(left ^ right)
6999 symbol *tlbl = newiTempLabel (NULL);
7000 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7003 emitcode ("setb", "c");
7006 if ((AOP_TYPE (right) == AOP_LIT) &&
7007 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7009 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7013 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7014 emitcode ("xrl", "a,%s",
7015 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7017 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7018 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7020 emitcode("mov", "b,a");
7024 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7025 emitcode ("xrl", "a,%s", rOp);
7028 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7034 emitcode ("", "!tlabeldef", tlbl->key + 100);
7038 jmpTrueOrFalse (ifx, tlbl);
7042 for (; (size--); offset++)
7045 // result = left & right
7046 if (AOP_TYPE (right) == AOP_LIT)
7048 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7050 aopPut (AOP (result),
7051 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7055 D (emitcode (";", "better literal XOR."););
7056 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7057 emitcode ("xrl", "a, %s",
7058 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7062 // faster than result <- left, anl result,right
7063 // and better if result is SFR
7064 if (AOP_TYPE (left) == AOP_ACC)
7066 emitcode ("xrl", "a,%s",
7067 aopGet (AOP (right), offset,
7068 FALSE, FALSE, DP2_RESULT_REG));
7072 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7073 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7075 emitcode("mov", "b,a");
7079 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7080 emitcode ("xrl", "a,%s", rOp);
7083 aopPut (AOP (result), "a", offset);
7090 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7091 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7092 freeAsmop (result, NULL, ic, TRUE);
7095 /*-----------------------------------------------------------------*/
7096 /* genInline - write the inline code out */
7097 /*-----------------------------------------------------------------*/
7099 genInline (iCode * ic)
7101 char *buffer, *bp, *bp1;
7103 D (emitcode (";", "genInline "); );
7105 _G.inLine += (!options.asmpeep);
7107 buffer = Safe_strdup(IC_INLINE(ic));
7111 /* emit each line as a code */
7136 /* emitcode("",buffer); */
7137 _G.inLine -= (!options.asmpeep);
7140 /*-----------------------------------------------------------------*/
7141 /* genRRC - rotate right with carry */
7142 /*-----------------------------------------------------------------*/
7146 operand *left, *result;
7149 D (emitcode (";", "genRRC "););
7151 /* rotate right with carry */
7152 left = IC_LEFT (ic);
7153 result = IC_RESULT (ic);
7154 aopOp (left, ic, FALSE, FALSE);
7155 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7157 /* move it to the result */
7158 size = AOP_SIZE (result);
7162 _startLazyDPSEvaluation ();
7165 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7166 emitcode ("rrc", "a");
7167 if (AOP_SIZE (result) > 1)
7168 aopPut (AOP (result), "a", offset--);
7170 _endLazyDPSEvaluation ();
7172 /* now we need to put the carry into the
7173 highest order byte of the result */
7174 if (AOP_SIZE (result) > 1)
7176 MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7178 emitcode ("mov", "acc.7,c");
7179 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7180 freeAsmop (left, NULL, ic, TRUE);
7181 freeAsmop (result, NULL, ic, TRUE);
7184 /*-----------------------------------------------------------------*/
7185 /* genRLC - generate code for rotate left with carry */
7186 /*-----------------------------------------------------------------*/
7190 operand *left, *result;
7194 D (emitcode (";", "genRLC "););
7196 /* rotate right with carry */
7197 left = IC_LEFT (ic);
7198 result = IC_RESULT (ic);
7199 aopOp (left, ic, FALSE, FALSE);
7200 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7202 /* move it to the result */
7203 size = AOP_SIZE (result);
7207 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7209 emitcode ("add", "a,acc");
7210 if (AOP_SIZE (result) > 1)
7212 aopPut (AOP (result), "a", offset++);
7215 _startLazyDPSEvaluation ();
7218 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7220 emitcode ("rlc", "a");
7221 if (AOP_SIZE (result) > 1)
7222 aopPut (AOP (result), "a", offset++);
7224 _endLazyDPSEvaluation ();
7226 /* now we need to put the carry into the
7227 highest order byte of the result */
7228 if (AOP_SIZE (result) > 1)
7230 l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7233 emitcode ("mov", "acc.0,c");
7234 aopPut (AOP (result), "a", 0);
7235 freeAsmop (left, NULL, ic, TRUE);
7236 freeAsmop (result, NULL, ic, TRUE);
7239 /*-----------------------------------------------------------------*/
7240 /* genGetHbit - generates code get highest order bit */
7241 /*-----------------------------------------------------------------*/
7243 genGetHbit (iCode * ic)
7245 operand *left, *result;
7246 left = IC_LEFT (ic);
7247 result = IC_RESULT (ic);
7248 aopOp (left, ic, FALSE, FALSE);
7249 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7251 D (emitcode (";", "genGetHbit "););
7253 /* get the highest order byte into a */
7254 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7255 if (AOP_TYPE (result) == AOP_CRY)
7257 emitcode ("rlc", "a");
7262 emitcode ("rl", "a");
7263 emitcode ("anl", "a,#1");
7268 freeAsmop (left, NULL, ic, TRUE);
7269 freeAsmop (result, NULL, ic, TRUE);
7272 /*-----------------------------------------------------------------*/
7273 /* AccRol - rotate left accumulator by known count */
7274 /*-----------------------------------------------------------------*/
7276 AccRol (int shCount)
7278 shCount &= 0x0007; // shCount : 0..7
7285 emitcode ("rl", "a");
7288 emitcode ("rl", "a");
7289 emitcode ("rl", "a");
7292 emitcode ("swap", "a");
7293 emitcode ("rr", "a");
7296 emitcode ("swap", "a");
7299 emitcode ("swap", "a");
7300 emitcode ("rl", "a");
7303 emitcode ("rr", "a");
7304 emitcode ("rr", "a");
7307 emitcode ("rr", "a");
7312 /*-----------------------------------------------------------------*/
7313 /* AccLsh - left shift accumulator by known count */
7314 /*-----------------------------------------------------------------*/
7316 AccLsh (int shCount)
7321 emitcode ("add", "a,acc");
7322 else if (shCount == 2)
7324 emitcode ("add", "a,acc");
7325 emitcode ("add", "a,acc");
7329 /* rotate left accumulator */
7331 /* and kill the lower order bits */
7332 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7337 /*-----------------------------------------------------------------*/
7338 /* AccRsh - right shift accumulator by known count */
7339 /*-----------------------------------------------------------------*/
7341 AccRsh (int shCount)
7348 emitcode ("rrc", "a");
7352 /* rotate right accumulator */
7353 AccRol (8 - shCount);
7354 /* and kill the higher order bits */
7355 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7360 #ifdef BETTER_LITERAL_SHIFT
7361 /*-----------------------------------------------------------------*/
7362 /* AccSRsh - signed right shift accumulator by known count */
7363 /*-----------------------------------------------------------------*/
7365 AccSRsh (int shCount)
7372 emitcode ("mov", "c,acc.7");
7373 emitcode ("rrc", "a");
7375 else if (shCount == 2)
7377 emitcode ("mov", "c,acc.7");
7378 emitcode ("rrc", "a");
7379 emitcode ("mov", "c,acc.7");
7380 emitcode ("rrc", "a");
7384 tlbl = newiTempLabel (NULL);
7385 /* rotate right accumulator */
7386 AccRol (8 - shCount);
7387 /* and kill the higher order bits */
7388 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7389 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7390 emitcode ("orl", "a,#!constbyte",
7391 (unsigned char) ~SRMask[shCount]);
7392 emitcode ("", "!tlabeldef", tlbl->key + 100);
7398 #ifdef BETTER_LITERAL_SHIFT
7399 /*-----------------------------------------------------------------*/
7400 /* shiftR1Left2Result - shift right one byte from left to result */
7401 /*-----------------------------------------------------------------*/
7403 shiftR1Left2Result (operand * left, int offl,
7404 operand * result, int offr,
7405 int shCount, int sign)
7407 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7408 /* shift right accumulator */
7413 aopPut (AOP (result), "a", offr);
7417 #ifdef BETTER_LITERAL_SHIFT
7418 /*-----------------------------------------------------------------*/
7419 /* shiftL1Left2Result - shift left one byte from left to result */
7420 /*-----------------------------------------------------------------*/
7422 shiftL1Left2Result (operand * left, int offl,
7423 operand * result, int offr, int shCount)
7425 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7426 /* shift left accumulator */
7428 aopPut (AOP (result), "a", offr);
7432 #ifdef BETTER_LITERAL_SHIFT
7433 /*-----------------------------------------------------------------*/
7434 /* movLeft2Result - move byte from left to result */
7435 /*-----------------------------------------------------------------*/
7437 movLeft2Result (operand * left, int offl,
7438 operand * result, int offr, int sign)
7441 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7443 l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
7445 if (*l == '@' && (IS_AOP_PREG (result)))
7447 emitcode ("mov", "a,%s", l);
7448 aopPut (AOP (result), "a", offr);
7454 aopPut (AOP (result), l, offr);
7458 /* MSB sign in acc.7 ! */
7459 if (getDataSize (left) == offl + 1)
7461 emitcode ("mov", "a,%s", l);
7462 aopPut (AOP (result), "a", offr);
7470 #ifdef BETTER_LITERAL_SHIFT
7471 /*-----------------------------------------------------------------*/
7472 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7473 /*-----------------------------------------------------------------*/
7477 emitcode ("rrc", "a");
7478 emitcode ("xch", "a,%s", x);
7479 emitcode ("rrc", "a");
7480 emitcode ("xch", "a,%s", x);
7484 #ifdef BETTER_LITERAL_SHIFT
7486 /*-----------------------------------------------------------------*/
7487 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7488 /*-----------------------------------------------------------------*/
7492 emitcode ("xch", "a,%s", x);
7493 emitcode ("rlc", "a");
7494 emitcode ("xch", "a,%s", x);
7495 emitcode ("rlc", "a");
7499 #ifdef BETTER_LITERAL_SHIFT
7500 /*-----------------------------------------------------------------*/
7501 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7502 /*-----------------------------------------------------------------*/
7506 emitcode ("xch", "a,%s", x);
7507 emitcode ("add", "a,acc");
7508 emitcode ("xch", "a,%s", x);
7509 emitcode ("rlc", "a");
7513 #ifdef BETTER_LITERAL_SHIFT
7514 /*-----------------------------------------------------------------*/
7515 /* AccAXLsh - left shift a:x by known count (0..7) */
7516 /*-----------------------------------------------------------------*/
7518 AccAXLsh (char *x, int shCount)
7533 case 5: // AAAAABBB:CCCCCDDD
7535 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7537 emitcode ("anl", "a,#!constbyte",
7538 SLMask[shCount]); // BBB00000:CCCCCDDD
7540 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7542 AccRol (shCount); // DDDCCCCC:BBB00000
7544 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7546 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7548 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7550 emitcode ("anl", "a,#!constbyte",
7551 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7553 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7555 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7558 case 6: // AAAAAABB:CCCCCCDD
7559 emitcode ("anl", "a,#!constbyte",
7560 SRMask[shCount]); // 000000BB:CCCCCCDD
7561 emitcode ("mov", "c,acc.0"); // c = B
7562 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7564 AccAXRrl1 (x); // BCCCCCCD:D000000B
7565 AccAXRrl1 (x); // BBCCCCCC:DD000000
7567 emitcode("rrc","a");
7568 emitcode("xch","a,%s", x);
7569 emitcode("rrc","a");
7570 emitcode("mov","c,acc.0"); //<< get correct bit
7571 emitcode("xch","a,%s", x);
7573 emitcode("rrc","a");
7574 emitcode("xch","a,%s", x);
7575 emitcode("rrc","a");
7576 emitcode("xch","a,%s", x);
7579 case 7: // a:x <<= 7
7581 emitcode ("anl", "a,#!constbyte",
7582 SRMask[shCount]); // 0000000B:CCCCCCCD
7584 emitcode ("mov", "c,acc.0"); // c = B
7586 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7588 AccAXRrl1 (x); // BCCCCCCC:D0000000
7597 #ifdef BETTER_LITERAL_SHIFT
7599 /*-----------------------------------------------------------------*/
7600 /* AccAXRsh - right shift a:x known count (0..7) */
7601 /*-----------------------------------------------------------------*/
7603 AccAXRsh (char *x, int shCount)
7611 AccAXRrl1 (x); // 0->a:x
7616 AccAXRrl1 (x); // 0->a:x
7619 AccAXRrl1 (x); // 0->a:x
7624 case 5: // AAAAABBB:CCCCCDDD = a:x
7626 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7628 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7630 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7632 emitcode ("anl", "a,#!constbyte",
7633 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7635 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7637 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7639 emitcode ("anl", "a,#!constbyte",
7640 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7642 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7644 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7646 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7649 case 6: // AABBBBBB:CCDDDDDD
7651 emitcode ("mov", "c,acc.7");
7652 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7654 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7656 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7658 emitcode ("anl", "a,#!constbyte",
7659 SRMask[shCount]); // 000000AA:BBBBBBCC
7662 case 7: // ABBBBBBB:CDDDDDDD
7664 emitcode ("mov", "c,acc.7"); // c = A
7666 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7668 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7670 emitcode ("anl", "a,#!constbyte",
7671 SRMask[shCount]); // 0000000A:BBBBBBBC
7680 #ifdef BETTER_LITERAL_SHIFT
7681 /*-----------------------------------------------------------------*/
7682 /* AccAXRshS - right shift signed a:x known count (0..7) */
7683 /*-----------------------------------------------------------------*/
7685 AccAXRshS (char *x, int shCount)
7693 emitcode ("mov", "c,acc.7");
7694 AccAXRrl1 (x); // s->a:x
7698 emitcode ("mov", "c,acc.7");
7699 AccAXRrl1 (x); // s->a:x
7701 emitcode ("mov", "c,acc.7");
7702 AccAXRrl1 (x); // s->a:x
7707 case 5: // AAAAABBB:CCCCCDDD = a:x
7709 tlbl = newiTempLabel (NULL);
7710 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7712 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7714 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7716 emitcode ("anl", "a,#!constbyte",
7717 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7719 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7721 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7723 emitcode ("anl", "a,#!constbyte",
7724 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7726 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7728 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7730 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7732 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7733 emitcode ("orl", "a,#!constbyte",
7734 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7736 emitcode ("", "!tlabeldef", tlbl->key + 100);
7737 break; // SSSSAAAA:BBBCCCCC
7739 case 6: // AABBBBBB:CCDDDDDD
7741 tlbl = newiTempLabel (NULL);
7742 emitcode ("mov", "c,acc.7");
7743 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7745 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7747 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7749 emitcode ("anl", "a,#!constbyte",
7750 SRMask[shCount]); // 000000AA:BBBBBBCC
7752 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7753 emitcode ("orl", "a,#!constbyte",
7754 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7756 emitcode ("", "!tlabeldef", tlbl->key + 100);
7758 case 7: // ABBBBBBB:CDDDDDDD
7760 tlbl = newiTempLabel (NULL);
7761 emitcode ("mov", "c,acc.7"); // c = A
7763 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7765 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7767 emitcode ("anl", "a,#!constbyte",
7768 SRMask[shCount]); // 0000000A:BBBBBBBC
7770 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7771 emitcode ("orl", "a,#!constbyte",
7772 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7774 emitcode ("", "!tlabeldef", tlbl->key + 100);
7782 #ifdef BETTER_LITERAL_SHIFT
7784 _loadLeftIntoAx(char **lsb,
7790 // Get the initial value from left into a pair of registers.
7791 // MSB must be in A, LSB can be any register.
7793 // If the result is held in registers, it is an optimization
7794 // if the LSB can be held in the register which will hold the,
7795 // result LSB since this saves us from having to copy it into
7796 // the result following AccAXLsh.
7798 // If the result is addressed indirectly, this is not a gain.
7799 if (AOP_NEEDSACC(result))
7803 _startLazyDPSEvaluation();
7804 if (AOP_TYPE(left) == AOP_DPTR2)
7807 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
7808 // get LSB in DP2_RESULT_REG.
7809 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
7810 assert(!strcmp(leftByte, DP2_RESULT_REG));
7814 // get LSB into DP2_RESULT_REG
7815 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
7816 if (strcmp(leftByte, DP2_RESULT_REG))
7819 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7822 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
7823 assert(strcmp(leftByte, DP2_RESULT_REG));
7826 _endLazyDPSEvaluation();
7827 *lsb = DP2_RESULT_REG;
7831 if (sameRegs (AOP (result), AOP (left)) &&
7832 ((offl + MSB16) == offr))
7834 /* don't crash result[offr] */
7835 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
7836 emitcode ("xch", "a,%s",
7837 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
7841 movLeft2Result (left, offl, result, offr, 0);
7842 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
7844 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
7845 assert(strcmp(*lsb,"a"));
7850 _storeAxResults(char *lsb,
7854 _startLazyDPSEvaluation();
7855 if (AOP_NEEDSACC(result))
7857 /* We have to explicitly update the result LSB.
7859 emitcode("xch","a,%s", lsb);
7860 aopPut(AOP(result), "a", offr);
7861 emitcode("mov","a,%s", lsb);
7863 if (getDataSize (result) > 1)
7865 aopPut (AOP (result), "a", offr + MSB16);
7867 _endLazyDPSEvaluation();
7870 /*-----------------------------------------------------------------*/
7871 /* shiftL2Left2Result - shift left two bytes from left to result */
7872 /*-----------------------------------------------------------------*/
7874 shiftL2Left2Result (operand * left, int offl,
7875 operand * result, int offr, int shCount)
7879 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7881 AccAXLsh (lsb, shCount);
7883 _storeAxResults(lsb, result, offr);
7887 #ifdef BETTER_LITERAL_SHIFT
7888 /*-----------------------------------------------------------------*/
7889 /* shiftR2Left2Result - shift right two bytes from left to result */
7890 /*-----------------------------------------------------------------*/
7892 shiftR2Left2Result (operand * left, int offl,
7893 operand * result, int offr,
7894 int shCount, int sign)
7898 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7900 /* a:x >> shCount (x = lsb(result)) */
7903 AccAXRshS(lsb, shCount);
7907 AccAXRsh(lsb, shCount);
7910 _storeAxResults(lsb, result, offr);
7916 /*-----------------------------------------------------------------*/
7917 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7918 /*-----------------------------------------------------------------*/
7920 shiftLLeftOrResult (operand * left, int offl,
7921 operand * result, int offr, int shCount)
7923 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7924 /* shift left accumulator */
7926 /* or with result */
7927 emitcode ("orl", "a,%s",
7928 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7929 /* back to result */
7930 aopPut (AOP (result), "a", offr);
7936 /*-----------------------------------------------------------------*/
7937 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7938 /*-----------------------------------------------------------------*/
7940 shiftRLeftOrResult (operand * left, int offl,
7941 operand * result, int offr, int shCount)
7943 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7944 /* shift right accumulator */
7946 /* or with result */
7947 emitcode ("orl", "a,%s",
7948 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7949 /* back to result */
7950 aopPut (AOP (result), "a", offr);
7954 #ifdef BETTER_LITERAL_SHIFT
7955 /*-----------------------------------------------------------------*/
7956 /* genlshOne - left shift a one byte quantity by known count */
7957 /*-----------------------------------------------------------------*/
7959 genlshOne (operand * result, operand * left, int shCount)
7961 D (emitcode (";", "genlshOne "););
7962 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7966 #ifdef BETTER_LITERAL_SHIFT
7967 /*-----------------------------------------------------------------*/
7968 /* genlshTwo - left shift two bytes by known amount != 0 */
7969 /*-----------------------------------------------------------------*/
7971 genlshTwo (operand * result, operand * left, int shCount)
7975 D (emitcode (";", "genlshTwo "););
7977 size = getDataSize (result);
7979 /* if shCount >= 8 */
7984 _startLazyDPSEvaluation();
7990 _endLazyDPSEvaluation();
7991 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7992 aopPut (AOP (result), zero, LSB);
7996 movLeft2Result (left, LSB, result, MSB16, 0);
7997 aopPut (AOP (result), zero, LSB);
7998 _endLazyDPSEvaluation();
8003 aopPut (AOP (result), zero, LSB);
8004 _endLazyDPSEvaluation();
8008 /* 1 <= shCount <= 7 */
8013 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8017 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8025 /*-----------------------------------------------------------------*/
8026 /* shiftLLong - shift left one long from left to result */
8027 /* offl = LSB or MSB16 */
8028 /*-----------------------------------------------------------------*/
8030 shiftLLong (operand * left, operand * result, int offr)
8033 int size = AOP_SIZE (result);
8035 if (size >= LSB + offr)
8037 l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8039 emitcode ("add", "a,acc");
8040 if (sameRegs (AOP (left), AOP (result)) &&
8041 size >= MSB16 + offr && offr != LSB)
8042 emitcode ("xch", "a,%s",
8043 aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8045 aopPut (AOP (result), "a", LSB + offr);
8048 if (size >= MSB16 + offr)
8050 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8052 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8054 emitcode ("rlc", "a");
8055 if (sameRegs (AOP (left), AOP (result)) &&
8056 size >= MSB24 + offr && offr != LSB)
8057 emitcode ("xch", "a,%s",
8058 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8060 aopPut (AOP (result), "a", MSB16 + offr);
8063 if (size >= MSB24 + offr)
8065 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8067 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8069 emitcode ("rlc", "a");
8070 if (sameRegs (AOP (left), AOP (result)) &&
8071 size >= MSB32 + offr && offr != LSB)
8072 emitcode ("xch", "a,%s",
8073 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8075 aopPut (AOP (result), "a", MSB24 + offr);
8078 if (size > MSB32 + offr)
8080 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8082 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8084 emitcode ("rlc", "a");
8085 aopPut (AOP (result), "a", MSB32 + offr);
8088 aopPut (AOP (result), zero, LSB);
8094 /*-----------------------------------------------------------------*/
8095 /* genlshFour - shift four byte by a known amount != 0 */
8096 /*-----------------------------------------------------------------*/
8098 genlshFour (operand * result, operand * left, int shCount)
8102 D (emitcode (";", "genlshFour ");
8105 size = AOP_SIZE (result);
8107 /* if shifting more that 3 bytes */
8112 /* lowest order of left goes to the highest
8113 order of the destination */
8114 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8116 movLeft2Result (left, LSB, result, MSB32, 0);
8117 aopPut (AOP (result), zero, LSB);
8118 aopPut (AOP (result), zero, MSB16);
8119 aopPut (AOP (result), zero, MSB24);
8123 /* more than two bytes */
8124 else if (shCount >= 16)
8126 /* lower order two bytes goes to higher order two bytes */
8128 /* if some more remaining */
8130 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8133 movLeft2Result (left, MSB16, result, MSB32, 0);
8134 movLeft2Result (left, LSB, result, MSB24, 0);
8136 aopPut (AOP (result), zero, MSB16);
8137 aopPut (AOP (result), zero, LSB);
8141 /* if more than 1 byte */
8142 else if (shCount >= 8)
8144 /* lower order three bytes goes to higher order three bytes */
8149 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8151 movLeft2Result (left, LSB, result, MSB16, 0);
8157 movLeft2Result (left, MSB24, result, MSB32, 0);
8158 movLeft2Result (left, MSB16, result, MSB24, 0);
8159 movLeft2Result (left, LSB, result, MSB16, 0);
8160 aopPut (AOP (result), zero, LSB);
8162 else if (shCount == 1)
8163 shiftLLong (left, result, MSB16);
8166 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8167 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8168 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8169 aopPut (AOP (result), zero, LSB);
8174 /* 1 <= shCount <= 7 */
8175 else if (shCount <= 2)
8177 shiftLLong (left, result, LSB);
8179 shiftLLong (result, result, LSB);
8181 /* 3 <= shCount <= 7, optimize */
8184 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8185 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8186 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8191 #ifdef BETTER_LITERAL_SHIFT
8192 /*-----------------------------------------------------------------*/
8193 /* genLeftShiftLiteral - left shifting by known count */
8194 /*-----------------------------------------------------------------*/
8196 genLeftShiftLiteral (operand * left,
8201 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8204 size = getSize (operandType (result));
8206 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8208 /* We only handle certain easy cases so far. */
8210 && (shCount < (size * 8))
8214 D(emitcode (";", "genLeftShiftLiteral wimping out"););
8218 freeAsmop (right, NULL, ic, TRUE);
8220 aopOp(left, ic, FALSE, FALSE);
8221 aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8224 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8226 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8227 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8229 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8232 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8234 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8235 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8237 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8243 emitcode ("; shift left ", "result %d, left %d", size,
8247 /* I suppose that the left size >= result size */
8250 _startLazyDPSEvaluation();
8253 movLeft2Result (left, size, result, size, 0);
8255 _endLazyDPSEvaluation();
8257 else if (shCount >= (size * 8))
8259 _startLazyDPSEvaluation();
8262 aopPut (AOP (result), zero, size);
8264 _endLazyDPSEvaluation();
8271 genlshOne (result, left, shCount);
8275 genlshTwo (result, left, shCount);
8279 genlshFour (result, left, shCount);
8283 fprintf(stderr, "*** ack! mystery literal shift!\n");
8287 freeAsmop (left, NULL, ic, TRUE);
8288 freeAsmop (result, NULL, ic, TRUE);
8293 /*-----------------------------------------------------------------*/
8294 /* genLeftShift - generates code for left shifting */
8295 /*-----------------------------------------------------------------*/
8297 genLeftShift (iCode * ic)
8299 operand *left, *right, *result;
8302 symbol *tlbl, *tlbl1;
8304 D (emitcode (";", "genLeftShift "););
8306 right = IC_RIGHT (ic);
8307 left = IC_LEFT (ic);
8308 result = IC_RESULT (ic);
8310 aopOp (right, ic, FALSE, FALSE);
8313 #ifdef BETTER_LITERAL_SHIFT
8314 /* if the shift count is known then do it
8315 as efficiently as possible */
8316 if (AOP_TYPE (right) == AOP_LIT)
8318 if (genLeftShiftLiteral (left, right, result, ic))
8325 /* shift count is unknown then we have to form
8326 a loop get the loop count in B : Note: we take
8327 only the lower order byte since shifting
8328 more that 32 bits make no sense anyway, ( the
8329 largest size of an object can be only 32 bits ) */
8331 if (AOP_TYPE (right) == AOP_LIT)
8333 /* Really should be handled by genLeftShiftLiteral,
8334 * but since I'm too lazy to fix that today, at least we can make
8335 * some small improvement.
8337 emitcode("mov", "b,#!constbyte",
8338 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8342 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8343 emitcode ("inc", "b");
8345 freeAsmop (right, NULL, ic, TRUE);
8346 aopOp (left, ic, FALSE, FALSE);
8347 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8349 /* now move the left to the result if they are not the
8351 if (!sameRegs (AOP (left), AOP (result)) &&
8352 AOP_SIZE (result) > 1)
8355 size = AOP_SIZE (result);
8357 _startLazyDPSEvaluation ();
8360 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8361 if (*l == '@' && (IS_AOP_PREG (result)))
8364 emitcode ("mov", "a,%s", l);
8365 aopPut (AOP (result), "a", offset);
8368 aopPut (AOP (result), l, offset);
8371 _endLazyDPSEvaluation ();
8374 tlbl = newiTempLabel (NULL);
8375 size = AOP_SIZE (result);
8377 tlbl1 = newiTempLabel (NULL);
8379 /* if it is only one byte then */
8382 symbol *tlbl1 = newiTempLabel (NULL);
8384 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8385 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8386 emitcode ("", "!tlabeldef", tlbl->key + 100);
8387 emitcode ("add", "a,acc");
8388 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8389 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8390 aopPut (AOP (result), "a", 0);
8394 reAdjustPreg (AOP (result));
8396 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8397 emitcode ("", "!tlabeldef", tlbl->key + 100);
8398 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8399 emitcode ("add", "a,acc");
8400 aopPut (AOP (result), "a", offset++);
8401 _startLazyDPSEvaluation ();
8404 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8405 emitcode ("rlc", "a");
8406 aopPut (AOP (result), "a", offset++);
8408 _endLazyDPSEvaluation ();
8409 reAdjustPreg (AOP (result));
8411 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8412 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8414 freeAsmop (left, NULL, ic, TRUE);
8415 freeAsmop (result, NULL, ic, TRUE);
8418 #ifdef BETTER_LITERAL_SHIFT
8419 /*-----------------------------------------------------------------*/
8420 /* genrshOne - right shift a one byte quantity by known count */
8421 /*-----------------------------------------------------------------*/
8423 genrshOne (operand * result, operand * left,
8424 int shCount, int sign)
8426 D (emitcode (";", "genrshOne"););
8427 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8431 #ifdef BETTER_LITERAL_SHIFT
8432 /*-----------------------------------------------------------------*/
8433 /* genrshTwo - right shift two bytes by known amount != 0 */
8434 /*-----------------------------------------------------------------*/
8436 genrshTwo (operand * result, operand * left,
8437 int shCount, int sign)
8439 D (emitcode (";", "genrshTwo"););
8441 /* if shCount >= 8 */
8445 _startLazyDPSEvaluation();
8448 shiftR1Left2Result (left, MSB16, result, LSB,
8453 movLeft2Result (left, MSB16, result, LSB, sign);
8455 addSign (result, MSB16, sign);
8456 _endLazyDPSEvaluation();
8459 /* 1 <= shCount <= 7 */
8462 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8469 /*-----------------------------------------------------------------*/
8470 /* shiftRLong - shift right one long from left to result */
8471 /* offl = LSB or MSB16 */
8472 /*-----------------------------------------------------------------*/
8474 shiftRLong (operand * left, int offl,
8475 operand * result, int sign)
8477 int isSameRegs=sameRegs(AOP(left),AOP(result));
8479 if (isSameRegs && offl>1) {
8480 // we are in big trouble, but this shouldn't happen
8481 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8484 MOVA (aopGet (AOP (left), MSB32, FALSE, NULL));
8489 emitcode ("rlc", "a");
8490 emitcode ("subb", "a,acc");
8491 emitcode ("xch", "a,%s",
8492 aopGet(AOP(left), MSB32, FALSE, DP2_RESULT_REG));
8494 aopPut (AOP(result), zero, MSB32);
8499 emitcode ("clr", "c");
8501 emitcode ("mov", "c,acc.7");
8504 emitcode ("rrc", "a");
8506 if (isSameRegs && offl==MSB16) {
8508 "a,%s",aopGet (AOP (left), MSB24, FALSE, DP2_RESULT_REG));
8510 aopPut (AOP (result), "a", MSB32);
8511 MOVA (aopGet (AOP (left), MSB24, FALSE, NULL));
8514 emitcode ("rrc", "a");
8515 if (isSameRegs && offl==1) {
8516 emitcode ("xch", "a,%s",
8517 aopGet (AOP (left), MSB16, FALSE, DP2_RESULT_REG));
8519 aopPut (AOP (result), "a", MSB24);
8520 MOVA (aopGet (AOP (left), MSB16, FALSE, NULL));
8522 emitcode ("rrc", "a");
8523 aopPut (AOP (result), "a", MSB16 - offl);
8527 MOVA (aopGet (AOP (left), LSB, FALSE, NULL));
8528 emitcode ("rrc", "a");
8529 aopPut (AOP (result), "a", LSB);
8536 /*-----------------------------------------------------------------*/
8537 /* genrshFour - shift four byte by a known amount != 0 */
8538 /*-----------------------------------------------------------------*/
8540 genrshFour (operand * result, operand * left,
8541 int shCount, int sign)
8543 D (emitcode (";", "genrshFour");
8546 /* if shifting more that 3 bytes */
8551 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8553 movLeft2Result (left, MSB32, result, LSB, sign);
8554 addSign (result, MSB16, sign);
8556 else if (shCount >= 16)
8560 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8563 movLeft2Result (left, MSB24, result, LSB, 0);
8564 movLeft2Result (left, MSB32, result, MSB16, sign);
8566 addSign (result, MSB24, sign);
8568 else if (shCount >= 8)
8572 shiftRLong (left, MSB16, result, sign);
8573 else if (shCount == 0)
8575 movLeft2Result (left, MSB16, result, LSB, 0);
8576 movLeft2Result (left, MSB24, result, MSB16, 0);
8577 movLeft2Result (left, MSB32, result, MSB24, sign);
8578 addSign (result, MSB32, sign);
8582 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8583 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8584 /* the last shift is signed */
8585 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8586 addSign (result, MSB32, sign);
8590 { /* 1 <= shCount <= 7 */
8593 shiftRLong (left, LSB, result, sign);
8595 shiftRLong (result, LSB, result, sign);
8599 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8600 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8601 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8607 #ifdef BETTER_LITERAL_SHIFT
8608 /*-----------------------------------------------------------------*/
8609 /* genRightShiftLiteral - right shifting by known count */
8610 /*-----------------------------------------------------------------*/
8612 genRightShiftLiteral (operand * left,
8618 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8621 size = getSize (operandType (result));
8623 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8625 /* We only handle certain easy cases so far. */
8627 && (shCount < (size * 8))
8631 D(emitcode (";", "genRightShiftLiteral wimping out"););
8635 freeAsmop (right, NULL, ic, TRUE);
8637 aopOp (left, ic, FALSE, FALSE);
8638 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8641 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8645 /* test the LEFT size !!! */
8647 /* I suppose that the left size >= result size */
8650 size = getDataSize (result);
8651 _startLazyDPSEvaluation();
8654 movLeft2Result (left, size, result, size, 0);
8656 _endLazyDPSEvaluation();
8658 else if (shCount >= (size * 8))
8662 /* get sign in acc.7 */
8663 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
8665 addSign (result, LSB, sign);
8672 genrshOne (result, left, shCount, sign);
8676 genrshTwo (result, left, shCount, sign);
8680 genrshFour (result, left, shCount, sign);
8687 freeAsmop (left, NULL, ic, TRUE);
8688 freeAsmop (result, NULL, ic, TRUE);
8694 /*-----------------------------------------------------------------*/
8695 /* genSignedRightShift - right shift of signed number */
8696 /*-----------------------------------------------------------------*/
8698 genSignedRightShift (iCode * ic)
8700 operand *right, *left, *result;
8703 symbol *tlbl, *tlbl1;
8705 D (emitcode (";", "genSignedRightShift "););
8707 /* we do it the hard way put the shift count in b
8708 and loop thru preserving the sign */
8710 right = IC_RIGHT (ic);
8711 left = IC_LEFT (ic);
8712 result = IC_RESULT (ic);
8714 aopOp (right, ic, FALSE, FALSE);
8716 #ifdef BETTER_LITERAL_SHIFT
8717 if (AOP_TYPE (right) == AOP_LIT)
8719 if (genRightShiftLiteral (left, right, result, ic, 1))
8725 /* shift count is unknown then we have to form
8726 a loop get the loop count in B : Note: we take
8727 only the lower order byte since shifting
8728 more that 32 bits make no sense anyway, ( the
8729 largest size of an object can be only 32 bits ) */
8731 if (AOP_TYPE (right) == AOP_LIT)
8733 /* Really should be handled by genRightShiftLiteral,
8734 * but since I'm too lazy to fix that today, at least we can make
8735 * some small improvement.
8737 emitcode("mov", "b,#!constbyte",
8738 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8742 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8743 emitcode ("inc", "b");
8745 freeAsmop (right, NULL, ic, TRUE);
8746 aopOp (left, ic, FALSE, FALSE);
8747 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8749 /* now move the left to the result if they are not the
8751 if (!sameRegs (AOP (left), AOP (result)) &&
8752 AOP_SIZE (result) > 1)
8755 size = AOP_SIZE (result);
8757 _startLazyDPSEvaluation ();
8760 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8761 if (*l == '@' && IS_AOP_PREG (result))
8764 emitcode ("mov", "a,%s", l);
8765 aopPut (AOP (result), "a", offset);
8768 aopPut (AOP (result), l, offset);
8771 _endLazyDPSEvaluation ();
8774 /* mov the highest order bit to OVR */
8775 tlbl = newiTempLabel (NULL);
8776 tlbl1 = newiTempLabel (NULL);
8778 size = AOP_SIZE (result);
8780 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
8781 emitcode ("rlc", "a");
8782 emitcode ("mov", "ov,c");
8783 /* if it is only one byte then */
8786 MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8787 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8788 emitcode ("", "!tlabeldef", tlbl->key + 100);
8789 emitcode ("mov", "c,ov");
8790 emitcode ("rrc", "a");
8791 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8792 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8793 aopPut (AOP (result), "a", 0);
8797 reAdjustPreg (AOP (result));
8798 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8799 emitcode ("", "!tlabeldef", tlbl->key + 100);
8800 emitcode ("mov", "c,ov");
8801 _startLazyDPSEvaluation ();
8804 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8805 emitcode ("rrc", "a");
8806 aopPut (AOP (result), "a", offset--);
8808 _endLazyDPSEvaluation ();
8809 reAdjustPreg (AOP (result));
8810 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8811 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8814 freeAsmop (left, NULL, ic, TRUE);
8815 freeAsmop (result, NULL, ic, TRUE);
8818 /*-----------------------------------------------------------------*/
8819 /* genRightShift - generate code for right shifting */
8820 /*-----------------------------------------------------------------*/
8822 genRightShift (iCode * ic)
8824 operand *right, *left, *result;
8828 symbol *tlbl, *tlbl1;
8830 D (emitcode (";", "genRightShift "););
8832 /* if signed then we do it the hard way preserve the
8833 sign bit moving it inwards */
8834 retype = getSpec (operandType (IC_RESULT (ic)));
8836 if (!SPEC_USIGN (retype))
8838 genSignedRightShift (ic);
8842 /* signed & unsigned types are treated the same : i.e. the
8843 signed is NOT propagated inwards : quoting from the
8844 ANSI - standard : "for E1 >> E2, is equivalent to division
8845 by 2**E2 if unsigned or if it has a non-negative value,
8846 otherwise the result is implementation defined ", MY definition
8847 is that the sign does not get propagated */
8849 right = IC_RIGHT (ic);
8850 left = IC_LEFT (ic);
8851 result = IC_RESULT (ic);
8853 aopOp (right, ic, FALSE, FALSE);
8855 #ifdef BETTER_LITERAL_SHIFT
8856 /* if the shift count is known then do it
8857 as efficiently as possible */
8858 if (AOP_TYPE (right) == AOP_LIT)
8860 if (genRightShiftLiteral (left, right, result, ic, 0))
8867 /* shift count is unknown then we have to form
8868 a loop get the loop count in B : Note: we take
8869 only the lower order byte since shifting
8870 more that 32 bits make no sense anyway, ( the
8871 largest size of an object can be only 32 bits ) */
8873 if (AOP_TYPE (right) == AOP_LIT)
8875 /* Really should be handled by genRightShiftLiteral,
8876 * but since I'm too lazy to fix that today, at least we can make
8877 * some small improvement.
8879 emitcode("mov", "b,#!constbyte",
8880 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8884 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8885 emitcode ("inc", "b");
8887 freeAsmop (right, NULL, ic, TRUE);
8888 aopOp (left, ic, FALSE, FALSE);
8889 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8891 /* now move the left to the result if they are not the
8893 if (!sameRegs (AOP (left), AOP (result)) &&
8894 AOP_SIZE (result) > 1)
8897 size = AOP_SIZE (result);
8899 _startLazyDPSEvaluation ();
8902 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8903 if (*l == '@' && IS_AOP_PREG (result))
8906 emitcode ("mov", "a,%s", l);
8907 aopPut (AOP (result), "a", offset);
8910 aopPut (AOP (result), l, offset);
8913 _endLazyDPSEvaluation ();
8916 tlbl = newiTempLabel (NULL);
8917 tlbl1 = newiTempLabel (NULL);
8918 size = AOP_SIZE (result);
8921 /* if it is only one byte then */
8924 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8925 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8926 emitcode ("", "!tlabeldef", tlbl->key + 100);
8928 emitcode ("rrc", "a");
8929 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8930 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8931 aopPut (AOP (result), "a", 0);
8935 reAdjustPreg (AOP (result));
8936 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8937 emitcode ("", "!tlabeldef", tlbl->key + 100);
8939 _startLazyDPSEvaluation ();
8942 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8943 emitcode ("rrc", "a");
8944 aopPut (AOP (result), "a", offset--);
8946 _endLazyDPSEvaluation ();
8947 reAdjustPreg (AOP (result));
8949 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8950 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8953 freeAsmop (left, NULL, ic, TRUE);
8954 freeAsmop (result, NULL, ic, TRUE);
8957 /*-----------------------------------------------------------------*/
8958 /* genUnpackBits - generates code for unpacking bits */
8959 /*-----------------------------------------------------------------*/
8961 genUnpackBits (operand * result, char *rname, int ptype)
8968 D (emitcode (";", "genUnpackBits "););
8970 etype = getSpec (operandType (result));
8972 /* read the first byte */
8978 emitcode ("mov", "a,@%s", rname);
8982 emitcode ("movx", "a,@%s", rname);
8986 emitcode ("movx", "a,@dptr");
8990 emitcode ("clr", "a");
8991 emitcode ("movc", "a,@a+dptr");
8995 emitcode ("lcall", "__gptrget");
8999 /* if we have bitdisplacement then it fits */
9000 /* into this byte completely or if length is */
9001 /* less than a byte */
9002 if (((shCnt = SPEC_BSTR (etype)) != 0) || (SPEC_BLEN (etype) <= 8))
9005 /* shift right acc */
9008 emitcode ("anl", "a,#!constbyte",
9009 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
9010 aopPut (AOP (result), "a", offset);
9014 /* bit field did not fit in a byte */
9015 rlen = SPEC_BLEN (etype) - 8;
9016 aopPut (AOP (result), "a", offset++);
9025 emitcode ("inc", "%s", rname);
9026 emitcode ("mov", "a,@%s", rname);
9030 emitcode ("inc", "%s", rname);
9031 emitcode ("movx", "a,@%s", rname);
9035 emitcode ("inc", "dptr");
9036 emitcode ("movx", "a,@dptr");
9040 emitcode ("clr", "a");
9041 emitcode ("inc", "dptr");
9042 emitcode ("movc", "a,@a+dptr");
9046 emitcode ("inc", "dptr");
9047 emitcode ("lcall", "__gptrget");
9052 /* if we are done */
9056 aopPut (AOP (result), "a", offset++);
9062 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (rlen));
9063 aopPut (AOP (result), "a", offset);
9070 /*-----------------------------------------------------------------*/
9071 /* genDataPointerGet - generates code when ptr offset is known */
9072 /*-----------------------------------------------------------------*/
9074 genDataPointerGet (operand * left,
9080 int size, offset = 0;
9081 aopOp (result, ic, TRUE, FALSE);
9083 /* get the string representation of the name */
9084 l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9085 size = AOP_SIZE (result);
9086 _startLazyDPSEvaluation ();
9091 SNPRINTF (buff, sizeof(buff),
9092 "(%s + %d)", l + 1, offset);
9096 SNPRINTF (buff, sizeof(buff),
9099 aopPut (AOP (result), buff, offset++);
9101 _endLazyDPSEvaluation ();
9103 freeAsmop (left, NULL, ic, TRUE);
9104 freeAsmop (result, NULL, ic, TRUE);
9107 /*-----------------------------------------------------------------*/
9108 /* genNearPointerGet - emitcode for near pointer fetch */
9109 /*-----------------------------------------------------------------*/
9111 genNearPointerGet (operand * left,
9119 sym_link *rtype, *retype, *letype;
9120 sym_link *ltype = operandType (left);
9123 rtype = operandType (result);
9124 retype = getSpec (rtype);
9125 letype = getSpec (ltype);
9127 aopOp (left, ic, FALSE, FALSE);
9129 /* if left is rematerialisable and
9130 result is not bit variable type and
9131 the left is pointer to data space i.e
9132 lower 128 bytes of space */
9133 if (AOP_TYPE (left) == AOP_IMMD &&
9134 !IS_BITVAR (retype) &&
9135 !IS_BITVAR (letype) &&
9136 DCL_TYPE (ltype) == POINTER)
9138 genDataPointerGet (left, result, ic);
9142 /* if the value is already in a pointer register
9143 then don't need anything more */
9144 if (!AOP_INPREG (AOP (left)))
9146 /* otherwise get a free pointer register */
9148 preg = getFreePtr (ic, &aop, FALSE);
9149 emitcode ("mov", "%s,%s",
9151 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9155 rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9157 freeAsmop (left, NULL, ic, TRUE);
9158 aopOp (result, ic, FALSE, FALSE);
9160 /* if bitfield then unpack the bits */
9161 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9162 genUnpackBits (result, rname, POINTER);
9165 /* we have can just get the values */
9166 int size = AOP_SIZE (result);
9171 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9174 emitcode ("mov", "a,@%s", rname);
9175 aopPut (AOP (result), "a", offset);
9179 SNPRINTF (buff, sizeof(buff), "@%s", rname);
9180 aopPut (AOP (result), buff, offset);
9185 emitcode ("inc", "%s", rname);
9190 /* now some housekeeping stuff */
9193 /* we had to allocate for this iCode */
9194 if (pi) { /* post increment present */
9195 aopPut(AOP ( left ),rname,0);
9197 freeAsmop (NULL, aop, ic, TRUE);
9201 /* we did not allocate which means left
9202 already in a pointer register, then
9203 if size > 0 && this could be used again
9204 we have to point it back to where it
9206 if (AOP_SIZE (result) > 1 &&
9207 !OP_SYMBOL (left)->remat &&
9208 (OP_SYMBOL (left)->liveTo > ic->seq ||
9212 int size = AOP_SIZE (result) - 1;
9214 emitcode ("dec", "%s", rname);
9219 freeAsmop (result, NULL, ic, TRUE);
9220 if (pi) pi->generated = 1;
9223 /*-----------------------------------------------------------------*/
9224 /* genPagedPointerGet - emitcode for paged pointer fetch */
9225 /*-----------------------------------------------------------------*/
9227 genPagedPointerGet (operand * left,
9235 sym_link *rtype, *retype, *letype;
9237 rtype = operandType (result);
9238 retype = getSpec (rtype);
9239 letype = getSpec (operandType (left));
9240 aopOp (left, ic, FALSE, FALSE);
9242 /* if the value is already in a pointer register
9243 then don't need anything more */
9244 if (!AOP_INPREG (AOP (left)))
9246 /* otherwise get a free pointer register */
9248 preg = getFreePtr (ic, &aop, FALSE);
9249 emitcode ("mov", "%s,%s",
9251 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9255 rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9257 freeAsmop (left, NULL, ic, TRUE);
9258 aopOp (result, ic, FALSE, FALSE);
9260 /* if bitfield then unpack the bits */
9261 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9262 genUnpackBits (result, rname, PPOINTER);
9265 /* we have can just get the values */
9266 int size = AOP_SIZE (result);
9272 emitcode ("movx", "a,@%s", rname);
9273 aopPut (AOP (result), "a", offset);
9278 emitcode ("inc", "%s", rname);
9282 /* now some housekeeping stuff */
9285 /* we had to allocate for this iCode */
9286 if (pi) aopPut ( AOP (left), rname, 0);
9287 freeAsmop (NULL, aop, ic, TRUE);
9291 /* we did not allocate which means left
9292 already in a pointer register, then
9293 if size > 0 && this could be used again
9294 we have to point it back to where it
9296 if (AOP_SIZE (result) > 1 &&
9297 !OP_SYMBOL (left)->remat &&
9298 (OP_SYMBOL (left)->liveTo > ic->seq ||
9302 int size = AOP_SIZE (result) - 1;
9304 emitcode ("dec", "%s", rname);
9309 freeAsmop (result, NULL, ic, TRUE);
9310 if (pi) pi->generated = 1;
9313 /*-----------------------------------------------------------------*/
9314 /* genFarPointerGet - gget value from far space */
9315 /*-----------------------------------------------------------------*/
9317 genFarPointerGet (operand * left,
9318 operand * result, iCode * ic, iCode *pi)
9320 int size, offset, dopi=1;
9321 sym_link *retype = getSpec (operandType (result));
9322 sym_link *letype = getSpec (operandType (left));
9323 D (emitcode (";", "genFarPointerGet"););
9325 aopOp (left, ic, FALSE, FALSE);
9327 /* if the operand is already in dptr
9328 then we do nothing else we move the value to dptr */
9329 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9331 /* if this is remateriazable */
9332 if (AOP_TYPE (left) == AOP_IMMD)
9334 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9338 /* we need to get it byte by byte */
9339 _startLazyDPSEvaluation ();
9340 if (AOP_TYPE (left) != AOP_DPTR)
9342 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9343 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9344 if (options.model == MODEL_FLAT24)
9345 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9349 /* We need to generate a load to DPTR indirect through DPTR. */
9350 D (emitcode (";", "genFarPointerGet -- indirection special case."););
9351 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9352 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9353 if (options.model == MODEL_FLAT24)
9354 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9355 emitcode ("pop", "dph");
9356 emitcode ("pop", "dpl");
9359 _endLazyDPSEvaluation ();
9362 /* so dptr know contains the address */
9363 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9365 /* if bit then unpack */
9366 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9367 if (AOP_INDPTRn(left)) {
9368 genSetDPTR(AOP(left)->aopu.dptr);
9370 genUnpackBits (result, "dptr", FPOINTER);
9371 if (AOP_INDPTRn(left)) {
9376 size = AOP_SIZE (result);
9379 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9381 genSetDPTR(AOP(left)->aopu.dptr);
9382 emitcode ("movx", "a,@dptr");
9383 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9384 emitcode ("inc", "dptr");
9386 aopPut (AOP (result), "a", offset++);
9389 _startLazyDPSEvaluation ();
9391 if (AOP_INDPTRn(left)) {
9392 genSetDPTR(AOP(left)->aopu.dptr);
9398 emitcode ("movx", "a,@dptr");
9399 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9400 emitcode ("inc", "dptr");
9402 aopPut (AOP (result), "a", offset++);
9404 _endLazyDPSEvaluation ();
9407 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9408 if (!AOP_INDPTRn(left)) {
9409 _startLazyDPSEvaluation ();
9410 aopPut ( AOP (left), "dpl", 0);
9411 aopPut ( AOP (left), "dph", 1);
9412 if (options.model == MODEL_FLAT24)
9413 aopPut ( AOP (left), "dpx", 2);
9414 _endLazyDPSEvaluation ();
9417 } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) &&
9418 AOP_SIZE(result) > 1 &&
9420 (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
9422 size = AOP_SIZE (result) - 1;
9423 if (AOP_INDPTRn(left)) {
9424 genSetDPTR(AOP(left)->aopu.dptr);
9426 while (size--) emitcode ("lcall","__decdptr");
9427 if (AOP_INDPTRn(left)) {
9432 freeAsmop (left, NULL, ic, TRUE);
9433 freeAsmop (result, NULL, ic, TRUE);
9436 /*-----------------------------------------------------------------*/
9437 /* genCodePointerGet - get value from code space */
9438 /*-----------------------------------------------------------------*/
9440 genCodePointerGet (operand * left,
9441 operand * result, iCode * ic, iCode *pi)
9443 int size, offset, dopi=1;
9444 sym_link *retype = getSpec (operandType (result));
9446 aopOp (left, ic, FALSE, FALSE);
9448 /* if the operand is already in dptr
9449 then we do nothing else we move the value to dptr */
9450 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
9452 /* if this is remateriazable */
9453 if (AOP_TYPE (left) == AOP_IMMD)
9455 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9458 { /* we need to get it byte by byte */
9459 _startLazyDPSEvaluation ();
9460 if (AOP_TYPE (left) != AOP_DPTR)
9462 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9463 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9464 if (options.model == MODEL_FLAT24)
9465 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9469 /* We need to generate a load to DPTR indirect through DPTR. */
9470 D (emitcode (";", "gencodePointerGet -- indirection special case."););
9471 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9472 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9473 if (options.model == MODEL_FLAT24)
9474 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9475 emitcode ("pop", "dph");
9476 emitcode ("pop", "dpl");
9479 _endLazyDPSEvaluation ();
9482 /* so dptr know contains the address */
9483 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9485 /* if bit then unpack */
9486 if (IS_BITVAR (retype)) {
9487 if (AOP_INDPTRn(left)) {
9488 genSetDPTR(AOP(left)->aopu.dptr);
9490 genUnpackBits (result, "dptr", CPOINTER);
9491 if (AOP_INDPTRn(left)) {
9496 size = AOP_SIZE (result);
9498 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9500 genSetDPTR(AOP(left)->aopu.dptr);
9501 emitcode ("clr", "a");
9502 emitcode ("movc", "a,@a+dptr");
9503 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9504 emitcode ("inc", "dptr");
9506 aopPut (AOP (result), "a", offset++);
9509 _startLazyDPSEvaluation ();
9512 if (AOP_INDPTRn(left)) {
9513 genSetDPTR(AOP(left)->aopu.dptr);
9519 emitcode ("clr", "a");
9520 emitcode ("movc", "a,@a+dptr");
9521 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9522 emitcode ("inc", "dptr");
9523 aopPut (AOP (result), "a", offset++);
9525 _endLazyDPSEvaluation ();
9528 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9529 if (!AOP_INDPTRn(left)) {
9530 _startLazyDPSEvaluation ();
9532 aopPut ( AOP (left), "dpl", 0);
9533 aopPut ( AOP (left), "dph", 1);
9534 if (options.model == MODEL_FLAT24)
9535 aopPut ( AOP (left), "dpx", 2);
9537 _endLazyDPSEvaluation ();
9540 } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
9541 AOP_SIZE(result) > 1 &&
9542 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9544 size = AOP_SIZE (result) - 1;
9545 if (AOP_INDPTRn(left)) {
9546 genSetDPTR(AOP(left)->aopu.dptr);
9548 while (size--) emitcode ("lcall","__decdptr");
9549 if (AOP_INDPTRn(left)) {
9554 freeAsmop (left, NULL, ic, TRUE);
9555 freeAsmop (result, NULL, ic, TRUE);
9558 /*-----------------------------------------------------------------*/
9559 /* genGenPointerGet - gget value from generic pointer space */
9560 /*-----------------------------------------------------------------*/
9562 genGenPointerGet (operand * left,
9563 operand * result, iCode * ic, iCode * pi)
9566 sym_link *retype = getSpec (operandType (result));
9567 sym_link *letype = getSpec (operandType (left));
9569 D (emitcode (";", "genGenPointerGet "); );
9571 aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
9573 /* if the operand is already in dptr
9574 then we do nothing else we move the value to dptr */
9575 if (AOP_TYPE (left) != AOP_STR)
9577 /* if this is remateriazable */
9578 if (AOP_TYPE (left) == AOP_IMMD)
9580 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9581 if (AOP(left)->aopu.aop_immd.from_cast_remat)
9583 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
9587 emitcode ("mov", "b,#%d", pointerCode (retype));
9591 { /* we need to get it byte by byte */
9592 _startLazyDPSEvaluation ();
9593 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
9594 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
9595 if (options.model == MODEL_FLAT24) {
9596 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9597 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
9599 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9601 _endLazyDPSEvaluation ();
9605 /* so dptr-b now contains the address */
9607 aopOp (result, ic, FALSE, TRUE);
9610 /* if bit then unpack */
9611 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9613 genUnpackBits (result, "dptr", GPOINTER);
9617 size = AOP_SIZE (result);
9624 // Get two bytes at a time, results in _AP & A.
9625 // dptr will be incremented ONCE by __gptrgetWord.
9627 // Note: any change here must be coordinated
9628 // with the implementation of __gptrgetWord
9629 // in device/lib/_gptrget.c
9630 emitcode ("lcall", "__gptrgetWord");
9631 aopPut (AOP (result), DP2_RESULT_REG, offset++);
9632 aopPut (AOP (result), "a", offset++);
9637 // Only one byte to get.
9638 emitcode ("lcall", "__gptrget");
9639 aopPut (AOP (result), "a", offset++);
9642 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9644 emitcode ("inc", "dptr");
9649 if (pi && AOP_TYPE (left) != AOP_IMMD) {
9650 _startLazyDPSEvaluation ();
9652 aopPut ( AOP (left), "dpl", 0);
9653 aopPut ( AOP (left), "dph", 1);
9654 if (options.model == MODEL_FLAT24) {
9655 aopPut ( AOP (left), "dpx", 2);
9656 aopPut ( AOP (left), "b", 3);
9657 } else aopPut ( AOP (left), "b", 2);
9659 _endLazyDPSEvaluation ();
9662 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9663 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9665 size = AOP_SIZE (result) - 1;
9666 while (size--) emitcode ("lcall","__decdptr");
9669 freeAsmop (left, NULL, ic, TRUE);
9670 freeAsmop (result, NULL, ic, TRUE);
9673 /*-----------------------------------------------------------------*/
9674 /* genPointerGet - generate code for pointer get */
9675 /*-----------------------------------------------------------------*/
9677 genPointerGet (iCode * ic, iCode *pi)
9679 operand *left, *result;
9680 sym_link *type, *etype;
9683 D (emitcode (";", "genPointerGet ");
9686 left = IC_LEFT (ic);
9687 result = IC_RESULT (ic);
9689 /* depending on the type of pointer we need to
9690 move it to the correct pointer register */
9691 type = operandType (left);
9692 etype = getSpec (type);
9693 /* if left is of type of pointer then it is simple */
9694 if (IS_PTR (type) && !IS_FUNC (type->next))
9695 p_type = DCL_TYPE (type);
9698 /* we have to go by the storage class */
9699 p_type = PTR_TYPE (SPEC_OCLS (etype));
9701 /* special case when cast remat */
9702 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9703 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9704 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9705 type = operandType (left);
9706 p_type = DCL_TYPE (type);
9708 /* now that we have the pointer type we assign
9709 the pointer values */
9715 genNearPointerGet (left, result, ic, pi);
9719 genPagedPointerGet (left, result, ic, pi);
9723 genFarPointerGet (left, result, ic, pi);
9727 genCodePointerGet (left, result, ic, pi);
9731 genGenPointerGet (left, result, ic, pi);
9737 /*-----------------------------------------------------------------*/
9738 /* genPackBits - generates code for packed bit storage */
9739 /*-----------------------------------------------------------------*/
9741 genPackBits (sym_link * etype,
9743 char *rname, int p_type)
9750 blen = SPEC_BLEN (etype);
9751 bstr = SPEC_BSTR (etype);
9753 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9755 /* if the bit lenth is less than or */
9756 /* it exactly fits a byte then */
9757 if (SPEC_BLEN (etype) <= 8)
9759 /* shift left acc */
9760 AccLsh (SPEC_BSTR (etype));
9762 if (SPEC_BLEN (etype) < 8)
9763 { /* if smaller than a byte */
9769 emitcode ("mov", "b,a");
9770 emitcode ("mov", "a,@%s", rname);
9774 emitcode ("mov", "b,a");
9775 emitcode ("movx", "a,@dptr");
9779 emitcode ("push", "b");
9780 emitcode ("push", "acc");
9781 emitcode ("lcall", "__gptrget");
9782 emitcode ("pop", "b");
9786 emitcode ("anl", "a,#!constbyte", (unsigned char)
9787 ((unsigned char) (0xFF << (blen + bstr)) |
9788 (unsigned char) (0xFF >> (8 - bstr))));
9789 emitcode ("orl", "a,b");
9790 if (p_type == GPOINTER)
9791 emitcode ("pop", "b");
9798 emitcode ("mov", "@%s,a", rname);
9802 emitcode ("movx", "@dptr,a");
9806 emitcode ("lcall", "__gptrput");
9811 if (SPEC_BLEN (etype) <= 8)
9814 emitcode ("inc", "%s", rname);
9815 rLen = SPEC_BLEN (etype);
9817 /* now generate for lengths greater than one byte */
9821 l = aopGet (AOP (right), offset++, FALSE, TRUE, NULL);
9833 emitcode ("mov", "@%s,a", rname);
9836 emitcode ("mov", "@%s,%s", rname, l);
9841 emitcode ("movx", "@dptr,a");
9846 emitcode ("lcall", "__gptrput");
9849 emitcode ("inc", "%s", rname);
9854 /* last last was not complete */
9857 /* save the byte & read byte */
9861 emitcode ("mov", "b,a");
9862 emitcode ("mov", "a,@%s", rname);
9866 emitcode ("mov", "b,a");
9867 emitcode ("movx", "a,@dptr");
9871 emitcode ("push", "b");
9872 emitcode ("push", "acc");
9873 emitcode ("lcall", "__gptrget");
9874 emitcode ("pop", "b");
9878 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1 << rLen));
9879 emitcode ("orl", "a,b");
9882 if (p_type == GPOINTER)
9883 emitcode ("pop", "b");
9889 emitcode ("mov", "@%s,a", rname);
9893 emitcode ("movx", "@dptr,a");
9897 emitcode ("lcall", "__gptrput");
9901 /*-----------------------------------------------------------------*/
9902 /* genDataPointerSet - remat pointer to data space */
9903 /*-----------------------------------------------------------------*/
9905 genDataPointerSet (operand * right,
9909 int size, offset = 0;
9912 aopOp (right, ic, FALSE, FALSE);
9914 l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
9915 size = AOP_SIZE (right);
9920 SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
9924 SNPRINTF (buff, sizeof(buff), "%s", l + 1);
9927 emitcode ("mov", "%s,%s", buff,
9928 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9931 freeAsmop (right, NULL, ic, TRUE);
9932 freeAsmop (result, NULL, ic, TRUE);
9935 /*-----------------------------------------------------------------*/
9936 /* genNearPointerSet - emitcode for near pointer put */
9937 /*-----------------------------------------------------------------*/
9939 genNearPointerSet (operand * right,
9946 sym_link *retype, *letype;
9947 sym_link *ptype = operandType (result);
9949 retype = getSpec (operandType (right));
9950 letype = getSpec (ptype);
9952 aopOp (result, ic, FALSE, FALSE);
9954 /* if the result is rematerializable &
9955 in data space & not a bit variable */
9956 if (AOP_TYPE (result) == AOP_IMMD &&
9957 DCL_TYPE (ptype) == POINTER &&
9958 !IS_BITVAR (retype) &&
9959 !IS_BITVAR (letype))
9961 genDataPointerSet (right, result, ic);
9965 /* if the value is already in a pointer register
9966 then don't need anything more */
9967 if (!AOP_INPREG (AOP (result)))
9969 /* otherwise get a free pointer register */
9973 preg = getFreePtr (ic, &aop, FALSE);
9974 emitcode ("mov", "%s,%s",
9976 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
9980 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
9982 aopOp (right, ic, FALSE, FALSE);
9984 /* if bitfield then unpack the bits */
9985 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9986 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9989 /* we have can just get the values */
9990 int size = AOP_SIZE (right);
9995 l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
9999 emitcode ("mov", "@%s,a", rname);
10002 emitcode ("mov", "@%s,%s", rname, l);
10004 emitcode ("inc", "%s", rname);
10009 /* now some housekeeping stuff */
10012 /* we had to allocate for this iCode */
10013 if (pi) aopPut (AOP (result),rname,0);
10014 freeAsmop (NULL, aop, ic, TRUE);
10018 /* we did not allocate which means left
10019 already in a pointer register, then
10020 if size > 0 && this could be used again
10021 we have to point it back to where it
10023 if (AOP_SIZE (right) > 1 &&
10024 !OP_SYMBOL (result)->remat &&
10025 (OP_SYMBOL (result)->liveTo > ic->seq ||
10029 int size = AOP_SIZE (right) - 1;
10031 emitcode ("dec", "%s", rname);
10036 if (pi) pi->generated = 1;
10037 freeAsmop (result, NULL, ic, TRUE);
10038 freeAsmop (right, NULL, ic, TRUE);
10043 /*-----------------------------------------------------------------*/
10044 /* genPagedPointerSet - emitcode for Paged pointer put */
10045 /*-----------------------------------------------------------------*/
10047 genPagedPointerSet (operand * right,
10054 sym_link *retype, *letype;
10056 retype = getSpec (operandType (right));
10057 letype = getSpec (operandType (result));
10059 aopOp (result, ic, FALSE, FALSE);
10061 /* if the value is already in a pointer register
10062 then don't need anything more */
10063 if (!AOP_INPREG (AOP (result)))
10065 /* otherwise get a free pointer register */
10068 aop = newAsmop (0);
10069 preg = getFreePtr (ic, &aop, FALSE);
10070 emitcode ("mov", "%s,%s",
10072 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10073 rname = preg->name;
10076 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10078 aopOp (right, ic, FALSE, FALSE);
10080 /* if bitfield then unpack the bits */
10081 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10082 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
10085 /* we have can just get the values */
10086 int size = AOP_SIZE (right);
10091 MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10093 emitcode ("movx", "@%s,a", rname);
10096 emitcode ("inc", "%s", rname);
10102 /* now some housekeeping stuff */
10105 if (pi) aopPut (AOP (result),rname,0);
10106 /* we had to allocate for this iCode */
10107 freeAsmop (NULL, aop, ic, TRUE);
10111 /* we did not allocate which means left
10112 already in a pointer register, then
10113 if size > 0 && this could be used again
10114 we have to point it back to where it
10116 if (AOP_SIZE (right) > 1 &&
10117 !OP_SYMBOL (result)->remat &&
10118 (OP_SYMBOL (result)->liveTo > ic->seq ||
10122 int size = AOP_SIZE (right) - 1;
10124 emitcode ("dec", "%s", rname);
10129 if (pi) pi->generated = 1;
10130 freeAsmop (result, NULL, ic, TRUE);
10131 freeAsmop (right, NULL, ic, TRUE);
10136 /*-----------------------------------------------------------------*/
10137 /* genFarPointerSet - set value from far space */
10138 /*-----------------------------------------------------------------*/
10140 genFarPointerSet (operand * right,
10141 operand * result, iCode * ic, iCode *pi)
10143 int size, offset, dopi=1;
10144 sym_link *retype = getSpec (operandType (right));
10145 sym_link *letype = getSpec (operandType (result));
10147 aopOp (result, ic, FALSE, FALSE);
10149 /* if the operand is already in dptr
10150 then we do nothing else we move the value to dptr */
10151 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10153 /* if this is remateriazable */
10154 if (AOP_TYPE (result) == AOP_IMMD)
10155 emitcode ("mov", "dptr,%s",
10156 aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10159 /* we need to get it byte by byte */
10160 _startLazyDPSEvaluation ();
10161 if (AOP_TYPE (result) != AOP_DPTR)
10163 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10164 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10165 if (options.model == MODEL_FLAT24)
10166 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10170 /* We need to generate a load to DPTR indirect through DPTR. */
10171 D (emitcode (";", "genFarPointerSet -- indirection special case."););
10173 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10174 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10175 if (options.model == MODEL_FLAT24)
10176 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10177 emitcode ("pop", "dph");
10178 emitcode ("pop", "dpl");
10181 _endLazyDPSEvaluation ();
10184 /* so dptr know contains the address */
10185 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10187 /* if bit then unpack */
10188 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
10189 if (AOP_INDPTRn(result)) {
10190 genSetDPTR(AOP(result)->aopu.dptr);
10192 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
10193 if (AOP_INDPTRn(result)) {
10197 size = AOP_SIZE (right);
10199 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10201 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10203 genSetDPTR(AOP(result)->aopu.dptr);
10204 emitcode ("movx", "@dptr,a");
10205 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10206 emitcode ("inc", "dptr");
10210 _startLazyDPSEvaluation ();
10212 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10214 if (AOP_INDPTRn(result)) {
10215 genSetDPTR(AOP(result)->aopu.dptr);
10221 emitcode ("movx", "@dptr,a");
10222 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10223 emitcode ("inc", "dptr");
10225 _endLazyDPSEvaluation ();
10229 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10230 if (!AOP_INDPTRn(result)) {
10231 _startLazyDPSEvaluation ();
10233 aopPut (AOP(result),"dpl",0);
10234 aopPut (AOP(result),"dph",1);
10235 if (options.model == MODEL_FLAT24)
10236 aopPut (AOP(result),"dpx",2);
10238 _endLazyDPSEvaluation ();
10241 } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
10242 AOP_SIZE(right) > 1 &&
10243 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10245 size = AOP_SIZE (right) - 1;
10246 if (AOP_INDPTRn(result)) {
10247 genSetDPTR(AOP(result)->aopu.dptr);
10249 while (size--) emitcode ("lcall","__decdptr");
10250 if (AOP_INDPTRn(result)) {
10254 freeAsmop (result, NULL, ic, TRUE);
10255 freeAsmop (right, NULL, ic, TRUE);
10258 /*-----------------------------------------------------------------*/
10259 /* genGenPointerSet - set value from generic pointer space */
10260 /*-----------------------------------------------------------------*/
10262 genGenPointerSet (operand * right,
10263 operand * result, iCode * ic, iCode *pi)
10266 sym_link *retype = getSpec (operandType (right));
10267 sym_link *letype = getSpec (operandType (result));
10269 aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10271 /* if the operand is already in dptr
10272 then we do nothing else we move the value to dptr */
10273 if (AOP_TYPE (result) != AOP_STR)
10275 _startLazyDPSEvaluation ();
10276 /* if this is remateriazable */
10277 if (AOP_TYPE (result) == AOP_IMMD)
10279 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10280 if (AOP(result)->aopu.aop_immd.from_cast_remat)
10282 MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10287 "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10291 { /* we need to get it byte by byte */
10292 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10293 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10294 if (options.model == MODEL_FLAT24) {
10295 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10296 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10298 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10301 _endLazyDPSEvaluation ();
10303 /* so dptr + b now contains the address */
10305 aopOp (right, ic, FALSE, TRUE);
10309 /* if bit then unpack */
10310 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10312 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
10316 size = AOP_SIZE (right);
10319 _startLazyDPSEvaluation ();
10324 // Set two bytes at a time, passed in _AP & A.
10325 // dptr will be incremented ONCE by __gptrputWord.
10327 // Note: any change here must be coordinated
10328 // with the implementation of __gptrputWord
10329 // in device/lib/_gptrput.c
10330 emitcode("mov", "_ap, %s",
10331 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10332 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10336 emitcode ("lcall", "__gptrputWord");
10341 // Only one byte to put.
10342 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10346 emitcode ("lcall", "__gptrput");
10349 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10351 emitcode ("inc", "dptr");
10354 _endLazyDPSEvaluation ();
10357 if (pi && AOP_TYPE (result) != AOP_IMMD) {
10358 _startLazyDPSEvaluation ();
10360 aopPut (AOP(result),"dpl",0);
10361 aopPut (AOP(result),"dph",1);
10362 if (options.model == MODEL_FLAT24) {
10363 aopPut (AOP(result),"dpx",2);
10364 aopPut (AOP(result),"b",3);
10366 aopPut (AOP(result),"b",2);
10368 _endLazyDPSEvaluation ();
10371 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10372 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10374 size = AOP_SIZE (right) - 1;
10375 while (size--) emitcode ("lcall","__decdptr");
10377 freeAsmop (result, NULL, ic, TRUE);
10378 freeAsmop (right, NULL, ic, TRUE);
10381 /*-----------------------------------------------------------------*/
10382 /* genPointerSet - stores the value into a pointer location */
10383 /*-----------------------------------------------------------------*/
10385 genPointerSet (iCode * ic, iCode *pi)
10387 operand *right, *result;
10388 sym_link *type, *etype;
10391 D (emitcode (";", "genPointerSet "););
10393 right = IC_RIGHT (ic);
10394 result = IC_RESULT (ic);
10396 /* depending on the type of pointer we need to
10397 move it to the correct pointer register */
10398 type = operandType (result);
10399 etype = getSpec (type);
10400 /* if left is of type of pointer then it is simple */
10401 if (IS_PTR (type) && !IS_FUNC (type->next))
10403 p_type = DCL_TYPE (type);
10407 /* we have to go by the storage class */
10408 p_type = PTR_TYPE (SPEC_OCLS (etype));
10410 /* special case when cast remat */
10411 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10412 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10413 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10414 type = operandType (result);
10415 p_type = DCL_TYPE (type);
10418 /* now that we have the pointer type we assign
10419 the pointer values */
10425 genNearPointerSet (right, result, ic, pi);
10429 genPagedPointerSet (right, result, ic, pi);
10433 genFarPointerSet (right, result, ic, pi);
10437 genGenPointerSet (right, result, ic, pi);
10441 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10442 "genPointerSet: illegal pointer type");
10447 /*-----------------------------------------------------------------*/
10448 /* genIfx - generate code for Ifx statement */
10449 /*-----------------------------------------------------------------*/
10451 genIfx (iCode * ic, iCode * popIc)
10453 operand *cond = IC_COND (ic);
10456 D (emitcode (";", "genIfx "););
10458 aopOp (cond, ic, FALSE, FALSE);
10460 /* get the value into acc */
10461 if (AOP_TYPE (cond) != AOP_CRY)
10470 /* the result is now in the accumulator */
10471 freeAsmop (cond, NULL, ic, TRUE);
10473 /* if there was something to be popped then do it */
10477 /* if the condition is a bit variable */
10478 if (isbit && IS_ITEMP (cond) &&
10481 genIfxJump (ic, SPIL_LOC (cond)->rname);
10483 else if (isbit && !IS_ITEMP (cond))
10485 genIfxJump (ic, OP_SYMBOL (cond)->rname);
10489 genIfxJump (ic, "a");
10495 /*-----------------------------------------------------------------*/
10496 /* genAddrOf - generates code for address of */
10497 /*-----------------------------------------------------------------*/
10499 genAddrOf (iCode * ic)
10501 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10504 D (emitcode (";", "genAddrOf ");
10507 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10509 /* if the operand is on the stack then we
10510 need to get the stack offset of this
10512 if (sym->onStack) {
10514 /* if 10 bit stack */
10515 if (options.stack10bit) {
10517 tsprintf(buff, sizeof(buff),
10518 "#!constbyte",(options.stack_loc >> 16) & 0xff);
10519 /* if it has an offset then we need to compute it */
10520 /* emitcode ("subb", "a,#!constbyte", */
10521 /* -((sym->stack < 0) ? */
10522 /* ((short) (sym->stack - _G.nRegsSaved)) : */
10523 /* ((short) sym->stack)) & 0xff); */
10524 /* emitcode ("mov","b,a"); */
10525 /* emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
10526 /* ((short) (sym->stack - _G.nRegsSaved)) : */
10527 /* ((short) sym->stack)) >> 8) & 0xff); */
10529 emitcode ("mov", "a,_bpx");
10530 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
10531 ((char) (sym->stack - _G.nRegsSaved)) :
10532 ((char) sym->stack )) & 0xff);
10533 emitcode ("mov", "b,a");
10534 emitcode ("mov", "a,_bpx+1");
10535 emitcode ("addc","a,#!constbyte", (((sym->stack < 0) ?
10536 ((short) (sym->stack - _G.nRegsSaved)) :
10537 ((short) sym->stack )) >> 8) & 0xff);
10538 aopPut (AOP (IC_RESULT (ic)), "b", 0);
10539 aopPut (AOP (IC_RESULT (ic)), "a", 1);
10540 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10542 /* we can just move _bp */
10543 aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10544 aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10545 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10548 /* if it has an offset then we need to compute it */
10550 emitcode ("mov", "a,_bp");
10551 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10552 aopPut (AOP (IC_RESULT (ic)), "a", 0);
10554 /* we can just move _bp */
10555 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10557 /* fill the result with zero */
10558 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10561 if (options.stack10bit && size < (FPTRSIZE - 1)) {
10563 "*** warning: pointer to stack var truncated.\n");
10568 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10574 /* object not on stack then we need the name */
10575 size = AOP_SIZE (IC_RESULT (ic));
10580 char s[SDCC_NAME_MAX];
10584 tsprintf(s, sizeof(s), "!his",sym->rname);
10587 tsprintf(s, sizeof(s), "!hihis",sym->rname);
10590 tsprintf(s, sizeof(s), "!hihihis",sym->rname);
10592 default: /* should not need this (just in case) */
10593 SNPRINTF (s, sizeof(s), "#(%s >> %d)",
10600 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10603 aopPut (AOP (IC_RESULT (ic)), s, offset++);
10607 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10611 /*-----------------------------------------------------------------*/
10612 /* genArrayInit - generates code for address of */
10613 /*-----------------------------------------------------------------*/
10615 genArrayInit (iCode * ic)
10617 literalList *iLoop;
10619 int elementSize = 0, eIndex;
10620 unsigned val, lastVal;
10622 operand *left=IC_LEFT(ic);
10624 D (emitcode (";", "genArrayInit "););
10626 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10628 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10630 // Load immediate value into DPTR.
10631 emitcode("mov", "dptr, %s",
10632 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
10634 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10637 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10638 "Unexpected operand to genArrayInit.\n");
10641 // a regression because of SDCCcse.c:1.52
10642 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10643 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10644 if (options.model == MODEL_FLAT24)
10645 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10649 type = operandType(IC_LEFT(ic));
10651 if (type && type->next)
10653 elementSize = getSize(type->next);
10657 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10658 "can't determine element size in genArrayInit.\n");
10662 iLoop = IC_ARRAYILIST(ic);
10667 bool firstpass = TRUE;
10669 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
10670 iLoop->count, (int)iLoop->literalValue, elementSize);
10676 symbol *tlbl = NULL;
10678 count = ix > 256 ? 256 : ix;
10682 tlbl = newiTempLabel (NULL);
10683 if (firstpass || (count & 0xff))
10685 emitcode("mov", "b, #!constbyte", count & 0xff);
10688 emitcode ("", "!tlabeldef", tlbl->key + 100);
10693 for (eIndex = 0; eIndex < elementSize; eIndex++)
10695 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10696 if (val != lastVal)
10698 emitcode("mov", "a, #!constbyte", val);
10702 emitcode("movx", "@dptr, a");
10703 emitcode("inc", "dptr");
10708 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10714 iLoop = iLoop->next;
10717 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10720 /*-----------------------------------------------------------------*/
10721 /* genFarFarAssign - assignment when both are in far space */
10722 /*-----------------------------------------------------------------*/
10724 genFarFarAssign (operand * result, operand * right, iCode * ic)
10726 int size = AOP_SIZE (right);
10728 symbol *rSym = NULL;
10732 /* quick & easy case. */
10733 D(emitcode(";","genFarFarAssign (1 byte case)"););
10734 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
10735 freeAsmop (right, NULL, ic, FALSE);
10736 /* now assign DPTR to result */
10738 aopOp(result, ic, FALSE, FALSE);
10740 aopPut(AOP(result), "a", 0);
10741 freeAsmop(result, NULL, ic, FALSE);
10745 /* See if we've got an underlying symbol to abuse. */
10746 if (IS_SYMOP(result) && OP_SYMBOL(result))
10748 if (IS_TRUE_SYMOP(result))
10750 rSym = OP_SYMBOL(result);
10752 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10754 rSym = OP_SYMBOL(result)->usl.spillLoc;
10758 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10760 /* We can use the '390 auto-toggle feature to good effect here. */
10762 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10763 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
10764 emitcode ("mov", "dptr,#%s", rSym->rname);
10765 /* DP2 = result, DP1 = right, DP1 is current. */
10768 emitcode("movx", "a,@dptr");
10769 emitcode("movx", "@dptr,a");
10772 emitcode("inc", "dptr");
10773 emitcode("inc", "dptr");
10776 emitcode("mov", "dps,#0");
10777 freeAsmop (right, NULL, ic, FALSE);
10779 some alternative code for processors without auto-toggle
10780 no time to test now, so later well put in...kpb
10781 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10782 emitcode("mov", "dps,#1"); /* Select DPTR2. */
10783 emitcode ("mov", "dptr,#%s", rSym->rname);
10784 /* DP2 = result, DP1 = right, DP1 is current. */
10788 emitcode("movx", "a,@dptr");
10790 emitcode("inc", "dptr");
10791 emitcode("inc", "dps");
10792 emitcode("movx", "@dptr,a");
10794 emitcode("inc", "dptr");
10795 emitcode("inc", "dps");
10797 emitcode("mov", "dps,#0");
10798 freeAsmop (right, NULL, ic, FALSE);
10803 D (emitcode (";", "genFarFarAssign"););
10804 aopOp (result, ic, TRUE, TRUE);
10806 _startLazyDPSEvaluation ();
10810 aopPut (AOP (result),
10811 aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
10814 _endLazyDPSEvaluation ();
10815 freeAsmop (result, NULL, ic, FALSE);
10816 freeAsmop (right, NULL, ic, FALSE);
10820 /*-----------------------------------------------------------------*/
10821 /* genAssign - generate code for assignment */
10822 /*-----------------------------------------------------------------*/
10824 genAssign (iCode * ic)
10826 operand *result, *right;
10828 unsigned long lit = 0L;
10830 D (emitcode (";", "genAssign ");
10833 result = IC_RESULT (ic);
10834 right = IC_RIGHT (ic);
10836 /* if they are the same */
10837 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10840 aopOp (right, ic, FALSE, FALSE);
10842 emitcode (";", "genAssign: resultIsFar = %s",
10843 isOperandInFarSpace (result) ?
10846 /* special case both in far space */
10847 if ((AOP_TYPE (right) == AOP_DPTR ||
10848 AOP_TYPE (right) == AOP_DPTR2) &&
10849 /* IS_TRUE_SYMOP(result) && */
10850 isOperandInFarSpace (result))
10852 genFarFarAssign (result, right, ic);
10856 aopOp (result, ic, TRUE, FALSE);
10858 /* if they are the same registers */
10859 if (sameRegs (AOP (right), AOP (result)))
10862 /* if the result is a bit */
10863 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10865 /* if the right size is a literal then
10866 we know what the value is */
10867 if (AOP_TYPE (right) == AOP_LIT)
10869 if (((int) operandLitValue (right)))
10870 aopPut (AOP (result), one, 0);
10872 aopPut (AOP (result), zero, 0);
10876 /* the right is also a bit variable */
10877 if (AOP_TYPE (right) == AOP_CRY)
10879 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10880 aopPut (AOP (result), "c", 0);
10884 /* we need to or */
10886 aopPut (AOP (result), "a", 0);
10890 /* bit variables done */
10892 size = AOP_SIZE (result);
10894 if (AOP_TYPE (right) == AOP_LIT)
10895 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10898 (AOP_TYPE (result) != AOP_REG) &&
10899 (AOP_TYPE (right) == AOP_LIT) &&
10900 !IS_FLOAT (operandType (right)))
10902 _startLazyDPSEvaluation ();
10903 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10905 aopPut (AOP (result),
10906 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10911 /* And now fill the rest with zeros. */
10914 emitcode ("clr", "a");
10918 aopPut (AOP (result), "a", offset++);
10920 _endLazyDPSEvaluation ();
10924 _startLazyDPSEvaluation ();
10927 aopPut (AOP (result),
10928 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10932 _endLazyDPSEvaluation ();
10936 freeAsmop (right, NULL, ic, FALSE);
10937 freeAsmop (result, NULL, ic, TRUE);
10940 /*-----------------------------------------------------------------*/
10941 /* genJumpTab - generates code for jump table */
10942 /*-----------------------------------------------------------------*/
10944 genJumpTab (iCode * ic)
10949 D (emitcode (";", "genJumpTab ");
10952 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10953 /* get the condition into accumulator */
10954 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
10956 /* multiply by four! */
10957 emitcode ("add", "a,acc");
10958 emitcode ("add", "a,acc");
10959 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10961 jtab = newiTempLabel (NULL);
10962 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
10963 emitcode ("jmp", "@a+dptr");
10964 emitcode ("", "!tlabeldef", jtab->key + 100);
10965 /* now generate the jump labels */
10966 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10967 jtab = setNextItem (IC_JTLABELS (ic)))
10968 emitcode ("ljmp", "!tlabel", jtab->key + 100);
10972 /*-----------------------------------------------------------------*/
10973 /* genCast - gen code for casting */
10974 /*-----------------------------------------------------------------*/
10976 genCast (iCode * ic)
10978 operand *result = IC_RESULT (ic);
10979 sym_link *ctype = operandType (IC_LEFT (ic));
10980 sym_link *rtype = operandType (IC_RIGHT (ic));
10981 operand *right = IC_RIGHT (ic);
10984 D (emitcode (";", "genCast "););
10986 /* if they are equivalent then do nothing */
10987 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10990 aopOp (right, ic, FALSE, FALSE);
10991 aopOp (result, ic, FALSE, AOP_USESDPTR(right));
10993 /* if the result is a bit */
10994 // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10995 if (IS_BITVAR(OP_SYMBOL(result)->type))
10997 /* if the right size is a literal then
10998 we know what the value is */
10999 if (AOP_TYPE (right) == AOP_LIT)
11001 if (((int) operandLitValue (right)))
11002 aopPut (AOP (result), one, 0);
11004 aopPut (AOP (result), zero, 0);
11009 /* the right is also a bit variable */
11010 if (AOP_TYPE (right) == AOP_CRY)
11012 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11013 aopPut (AOP (result), "c", 0);
11017 /* we need to or */
11019 aopPut (AOP (result), "a", 0);
11023 /* if they are the same size : or less */
11024 if (AOP_SIZE (result) <= AOP_SIZE (right))
11027 /* if they are in the same place */
11028 if (sameRegs (AOP (right), AOP (result)))
11031 /* if they in different places then copy */
11032 size = AOP_SIZE (result);
11034 _startLazyDPSEvaluation ();
11037 aopPut (AOP (result),
11038 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11042 _endLazyDPSEvaluation ();
11047 /* if the result is of type pointer */
11048 if (IS_PTR (ctype))
11052 sym_link *type = operandType (right);
11054 /* pointer to generic pointer */
11055 if (IS_GENPTR (ctype))
11059 p_type = DCL_TYPE (type);
11063 #if OLD_CAST_BEHAVIOR
11064 /* KV: we are converting a non-pointer type to
11065 * a generic pointer. This (ifdef'd out) code
11066 * says that the resulting generic pointer
11067 * should have the same class as the storage
11068 * location of the non-pointer variable.
11070 * For example, converting an int (which happens
11071 * to be stored in DATA space) to a pointer results
11072 * in a DATA generic pointer; if the original int
11073 * in XDATA space, so will be the resulting pointer.
11075 * I don't like that behavior, and thus this change:
11076 * all such conversions will be forced to XDATA and
11077 * throw a warning. If you want some non-XDATA
11078 * type, or you want to suppress the warning, you
11079 * must go through an intermediate cast, like so:
11081 * char _generic *gp = (char _xdata *)(intVar);
11083 sym_link *etype = getSpec (type);
11085 /* we have to go by the storage class */
11086 if (SPEC_OCLS (etype) != generic)
11088 p_type = PTR_TYPE (SPEC_OCLS (etype));
11093 /* Converting unknown class (i.e. register variable)
11094 * to generic pointer. This is not good, but
11095 * we'll make a guess (and throw a warning).
11098 werror (W_INT_TO_GEN_PTR_CAST);
11102 /* the first two bytes are known */
11103 size = GPTRSIZE - 1;
11105 _startLazyDPSEvaluation ();
11108 aopPut (AOP (result),
11109 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11113 _endLazyDPSEvaluation ();
11115 /* the last byte depending on type */
11117 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11122 // pointerTypeToGPByte will have bitched.
11126 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11127 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11132 /* just copy the pointers */
11133 size = AOP_SIZE (result);
11135 _startLazyDPSEvaluation ();
11138 aopPut (AOP (result),
11139 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11143 _endLazyDPSEvaluation ();
11147 /* so we now know that the size of destination is greater
11148 than the size of the source */
11149 /* we move to result for the size of source */
11150 size = AOP_SIZE (right);
11152 _startLazyDPSEvaluation ();
11155 aopPut (AOP (result),
11156 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11160 _endLazyDPSEvaluation ();
11162 /* now depending on the sign of the source && destination */
11163 size = AOP_SIZE (result) - AOP_SIZE (right);
11164 /* if unsigned or not an integral type */
11165 /* also, if the source is a bit, we don't need to sign extend, because
11166 * it can't possibly have set the sign bit.
11168 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
11172 aopPut (AOP (result), zero, offset++);
11177 /* we need to extend the sign :{ */
11178 MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11179 FALSE, FALSE, NULL));
11180 emitcode ("rlc", "a");
11181 emitcode ("subb", "a,acc");
11183 aopPut (AOP (result), "a", offset++);
11186 /* we are done hurray !!!! */
11189 freeAsmop (right, NULL, ic, TRUE);
11190 freeAsmop (result, NULL, ic, TRUE);
11194 /*-----------------------------------------------------------------*/
11195 /* genDjnz - generate decrement & jump if not zero instrucion */
11196 /*-----------------------------------------------------------------*/
11198 genDjnz (iCode * ic, iCode * ifx)
11200 symbol *lbl, *lbl1;
11204 /* if the if condition has a false label
11205 then we cannot save */
11206 if (IC_FALSE (ifx))
11209 /* if the minus is not of the form
11211 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11212 !IS_OP_LITERAL (IC_RIGHT (ic)))
11215 if (operandLitValue (IC_RIGHT (ic)) != 1)
11218 /* if the size of this greater than one then no
11220 if (getSize (operandType (IC_RESULT (ic))) > 1)
11223 /* otherwise we can save BIG */
11224 D(emitcode(";", "genDjnz"););
11226 lbl = newiTempLabel (NULL);
11227 lbl1 = newiTempLabel (NULL);
11229 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11231 if (AOP_NEEDSACC(IC_RESULT(ic)))
11233 /* If the result is accessed indirectly via
11234 * the accumulator, we must explicitly write
11235 * it back after the decrement.
11237 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11239 if (strcmp(rByte, "a"))
11241 /* Something is hopelessly wrong */
11242 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11243 __FILE__, __LINE__);
11244 /* We can just give up; the generated code will be inefficient,
11245 * but what the hey.
11247 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11250 emitcode ("dec", "%s", rByte);
11251 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11252 emitcode ("jnz", "!tlabel", lbl->key + 100);
11254 else if (IS_AOP_PREG (IC_RESULT (ic)))
11256 emitcode ("dec", "%s",
11257 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11258 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11259 emitcode ("jnz", "!tlabel", lbl->key + 100);
11263 emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11266 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11267 emitcode ("", "!tlabeldef", lbl->key + 100);
11268 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11269 emitcode ("", "!tlabeldef", lbl1->key + 100);
11271 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11272 ifx->generated = 1;
11276 /*-----------------------------------------------------------------*/
11277 /* genReceive - generate code for a receive iCode */
11278 /*-----------------------------------------------------------------*/
11280 genReceive (iCode * ic)
11282 int size = getSize (operandType (IC_RESULT (ic)));
11286 D (emitcode (";", "genReceive "););
11288 if (ic->argreg == 1)
11290 /* first parameter */
11291 if (AOP_IS_STR(IC_RESULT(ic)))
11293 /* Nothing to do: it's already in the proper place. */
11300 useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11301 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11302 IS_TRUE_SYMOP (IC_RESULT (ic)));
11305 aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11308 /* Sanity checking... */
11309 if (AOP_USESDPTR(IC_RESULT(ic)))
11311 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11312 "genReceive got unexpected DPTR.");
11314 assignResultValue (IC_RESULT (ic));
11319 /* second receive onwards */
11320 /* this gets a little tricky since unused recevies will be
11321 eliminated, we have saved the reg in the type field . and
11322 we use that to figure out which register to use */
11323 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11324 rb1off = ic->argreg;
11327 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11330 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11333 /*-----------------------------------------------------------------*/
11334 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
11335 /*-----------------------------------------------------------------*/
11336 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11338 operand *from , *to , *count;
11343 /* we know it has to be 3 parameters */
11344 assert (nparms == 3);
11346 rsave = newBitVect(16);
11347 /* save DPTR if it needs to be saved */
11348 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11349 if (bitVectBitValue(ic->rMask,i))
11350 rsave = bitVectSetBit(rsave,i);
11352 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11353 ds390_rUmaskForOp (IC_RESULT(ic))));
11360 aopOp (from, ic->next, FALSE, FALSE);
11362 /* get from into DPTR1 */
11363 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11364 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11365 if (options.model == MODEL_FLAT24) {
11366 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11369 freeAsmop (from, NULL, ic, FALSE);
11370 aopOp (to, ic, FALSE, FALSE);
11371 /* get "to" into DPTR */
11372 /* if the operand is already in dptr
11373 then we do nothing else we move the value to dptr */
11374 if (AOP_TYPE (to) != AOP_STR) {
11375 /* if already in DPTR then we need to push */
11376 if (AOP_TYPE(to) == AOP_DPTR) {
11377 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11378 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11379 if (options.model == MODEL_FLAT24)
11380 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11381 emitcode ("pop", "dph");
11382 emitcode ("pop", "dpl");
11384 _startLazyDPSEvaluation ();
11385 /* if this is remateriazable */
11386 if (AOP_TYPE (to) == AOP_IMMD) {
11387 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11388 } else { /* we need to get it byte by byte */
11389 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11390 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11391 if (options.model == MODEL_FLAT24) {
11392 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11395 _endLazyDPSEvaluation ();
11398 freeAsmop (to, NULL, ic, FALSE);
11399 _G.dptrInUse = _G.dptr1InUse = 1;
11400 aopOp (count, ic->next->next, FALSE,FALSE);
11401 lbl =newiTempLabel(NULL);
11403 /* now for the actual copy */
11404 if (AOP_TYPE(count) == AOP_LIT &&
11405 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11406 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11408 emitcode ("lcall","__bi_memcpyc2x_s");
11410 emitcode ("lcall","__bi_memcpyx2x_s");
11412 freeAsmop (count, NULL, ic, FALSE);
11414 symbol *lbl1 = newiTempLabel(NULL);
11416 emitcode (";"," Auto increment but no djnz");
11417 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11418 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11419 freeAsmop (count, NULL, ic, FALSE);
11420 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11421 emitcode ("","!tlabeldef",lbl->key+100);
11423 emitcode ("clr","a");
11424 emitcode ("movc", "a,@a+dptr");
11426 emitcode ("movx", "a,@dptr");
11427 emitcode ("movx", "@dptr,a");
11428 emitcode ("inc", "dptr");
11429 emitcode ("inc", "dptr");
11430 emitcode ("mov","a,b");
11431 emitcode ("orl","a,_ap");
11432 emitcode ("jz","!tlabel",lbl1->key+100);
11433 emitcode ("mov","a,_ap");
11434 emitcode ("add","a,#!constbyte",0xFF);
11435 emitcode ("mov","_ap,a");
11436 emitcode ("mov","a,b");
11437 emitcode ("addc","a,#!constbyte",0xFF);
11438 emitcode ("mov","b,a");
11439 emitcode ("sjmp","!tlabel",lbl->key+100);
11440 emitcode ("","!tlabeldef",lbl1->key+100);
11442 emitcode ("mov", "dps,#0");
11443 _G.dptrInUse = _G.dptr1InUse = 0;
11444 unsavermask(rsave);
11448 /*-----------------------------------------------------------------*/
11449 /* genMemcmpX2X - gen code for memcmp xdata to xdata */
11450 /*-----------------------------------------------------------------*/
11451 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11453 operand *from , *to , *count;
11458 /* we know it has to be 3 parameters */
11459 assert (nparms == 3);
11461 rsave = newBitVect(16);
11462 /* save DPTR if it needs to be saved */
11463 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11464 if (bitVectBitValue(ic->rMask,i))
11465 rsave = bitVectSetBit(rsave,i);
11467 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11468 ds390_rUmaskForOp (IC_RESULT(ic))));
11475 aopOp (from, ic->next, FALSE, FALSE);
11477 /* get from into DPTR1 */
11478 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11479 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11480 if (options.model == MODEL_FLAT24) {
11481 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11484 freeAsmop (from, NULL, ic, FALSE);
11485 aopOp (to, ic, FALSE, FALSE);
11486 /* get "to" into DPTR */
11487 /* if the operand is already in dptr
11488 then we do nothing else we move the value to dptr */
11489 if (AOP_TYPE (to) != AOP_STR) {
11490 /* if already in DPTR then we need to push */
11491 if (AOP_TYPE(to) == AOP_DPTR) {
11492 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11493 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11494 if (options.model == MODEL_FLAT24)
11495 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11496 emitcode ("pop", "dph");
11497 emitcode ("pop", "dpl");
11499 _startLazyDPSEvaluation ();
11500 /* if this is remateriazable */
11501 if (AOP_TYPE (to) == AOP_IMMD) {
11502 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11503 } else { /* we need to get it byte by byte */
11504 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11505 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11506 if (options.model == MODEL_FLAT24) {
11507 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11510 _endLazyDPSEvaluation ();
11513 freeAsmop (to, NULL, ic, FALSE);
11514 _G.dptrInUse = _G.dptr1InUse = 1;
11515 aopOp (count, ic->next->next, FALSE,FALSE);
11516 lbl =newiTempLabel(NULL);
11517 lbl2 =newiTempLabel(NULL);
11519 /* now for the actual compare */
11520 if (AOP_TYPE(count) == AOP_LIT &&
11521 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11522 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11524 emitcode("lcall","__bi_memcmpc2x_s");
11526 emitcode("lcall","__bi_memcmpx2x_s");
11527 freeAsmop (count, NULL, ic, FALSE);
11528 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11529 aopPut(AOP(IC_RESULT(ic)),"a",0);
11530 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11532 symbol *lbl1 = newiTempLabel(NULL);
11534 emitcode("push","ar0");
11535 emitcode (";"," Auto increment but no djnz");
11536 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11537 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11538 freeAsmop (count, NULL, ic, FALSE);
11539 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11540 emitcode ("","!tlabeldef",lbl->key+100);
11542 emitcode ("clr","a");
11543 emitcode ("movc", "a,@a+dptr");
11545 emitcode ("movx", "a,@dptr");
11546 emitcode ("mov","r0,a");
11547 emitcode ("movx", "a,@dptr");
11548 emitcode ("clr","c");
11549 emitcode ("subb","a,r0");
11550 emitcode ("jnz","!tlabel",lbl2->key+100);
11551 emitcode ("inc", "dptr");
11552 emitcode ("inc", "dptr");
11553 emitcode ("mov","a,b");
11554 emitcode ("orl","a,_ap");
11555 emitcode ("jz","!tlabel",lbl1->key+100);
11556 emitcode ("mov","a,_ap");
11557 emitcode ("add","a,#!constbyte",0xFF);
11558 emitcode ("mov","_ap,a");
11559 emitcode ("mov","a,b");
11560 emitcode ("addc","a,#!constbyte",0xFF);
11561 emitcode ("mov","b,a");
11562 emitcode ("sjmp","!tlabel",lbl->key+100);
11563 emitcode ("","!tlabeldef",lbl1->key+100);
11564 emitcode ("clr","a");
11565 emitcode ("","!tlabeldef",lbl2->key+100);
11566 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11567 aopPut(AOP(IC_RESULT(ic)),"a",0);
11568 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11569 emitcode("pop","ar0");
11570 emitcode ("mov", "dps,#0");
11572 _G.dptrInUse = _G.dptr1InUse = 0;
11573 unsavermask(rsave);
11577 /*-----------------------------------------------------------------*/
11578 /* genInp - gen code for __builtin_inp read data from a mem mapped */
11579 /* port, first parameter output area second parameter pointer to */
11580 /* port third parameter count */
11581 /*-----------------------------------------------------------------*/
11582 static void genInp( iCode *ic, int nparms, operand **parms)
11584 operand *from , *to , *count;
11589 /* we know it has to be 3 parameters */
11590 assert (nparms == 3);
11592 rsave = newBitVect(16);
11593 /* save DPTR if it needs to be saved */
11594 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11595 if (bitVectBitValue(ic->rMask,i))
11596 rsave = bitVectSetBit(rsave,i);
11598 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11599 ds390_rUmaskForOp (IC_RESULT(ic))));
11606 aopOp (from, ic->next, FALSE, FALSE);
11608 /* get from into DPTR1 */
11609 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11610 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11611 if (options.model == MODEL_FLAT24) {
11612 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11615 freeAsmop (from, NULL, ic, FALSE);
11616 aopOp (to, ic, FALSE, FALSE);
11617 /* get "to" into DPTR */
11618 /* if the operand is already in dptr
11619 then we do nothing else we move the value to dptr */
11620 if (AOP_TYPE (to) != AOP_STR) {
11621 /* if already in DPTR then we need to push */
11622 if (AOP_TYPE(to) == AOP_DPTR) {
11623 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11624 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11625 if (options.model == MODEL_FLAT24)
11626 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11627 emitcode ("pop", "dph");
11628 emitcode ("pop", "dpl");
11630 _startLazyDPSEvaluation ();
11631 /* if this is remateriazable */
11632 if (AOP_TYPE (to) == AOP_IMMD) {
11633 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11634 } else { /* we need to get it byte by byte */
11635 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11636 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11637 if (options.model == MODEL_FLAT24) {
11638 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11641 _endLazyDPSEvaluation ();
11644 freeAsmop (to, NULL, ic, FALSE);
11646 _G.dptrInUse = _G.dptr1InUse = 1;
11647 aopOp (count, ic->next->next, FALSE,FALSE);
11648 lbl =newiTempLabel(NULL);
11650 /* now for the actual copy */
11651 if (AOP_TYPE(count) == AOP_LIT &&
11652 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11653 emitcode (";","OH JOY auto increment with djnz (very fast)");
11654 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11655 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11656 freeAsmop (count, NULL, ic, FALSE);
11657 emitcode ("","!tlabeldef",lbl->key+100);
11658 emitcode ("movx", "a,@dptr"); /* read data from port */
11659 emitcode ("dec","dps"); /* switch to DPTR */
11660 emitcode ("movx", "@dptr,a"); /* save into location */
11661 emitcode ("inc", "dptr"); /* point to next area */
11662 emitcode ("inc","dps"); /* switch to DPTR2 */
11663 emitcode ("djnz","b,!tlabel",lbl->key+100);
11665 symbol *lbl1 = newiTempLabel(NULL);
11667 emitcode (";"," Auto increment but no djnz");
11668 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11669 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11670 freeAsmop (count, NULL, ic, FALSE);
11671 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11672 emitcode ("","!tlabeldef",lbl->key+100);
11673 emitcode ("movx", "a,@dptr");
11674 emitcode ("dec","dps"); /* switch to DPTR */
11675 emitcode ("movx", "@dptr,a");
11676 emitcode ("inc", "dptr");
11677 emitcode ("inc","dps"); /* switch to DPTR2 */
11678 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
11679 /* emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
11680 emitcode ("mov","a,b");
11681 emitcode ("orl","a,_ap");
11682 emitcode ("jz","!tlabel",lbl1->key+100);
11683 emitcode ("mov","a,_ap");
11684 emitcode ("add","a,#!constbyte",0xFF);
11685 emitcode ("mov","_ap,a");
11686 emitcode ("mov","a,b");
11687 emitcode ("addc","a,#!constbyte",0xFF);
11688 emitcode ("mov","b,a");
11689 emitcode ("sjmp","!tlabel",lbl->key+100);
11690 emitcode ("","!tlabeldef",lbl1->key+100);
11692 emitcode ("mov", "dps,#0");
11693 _G.dptrInUse = _G.dptr1InUse = 0;
11694 unsavermask(rsave);
11698 /*-----------------------------------------------------------------*/
11699 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
11700 /* port, first parameter output area second parameter pointer to */
11701 /* port third parameter count */
11702 /*-----------------------------------------------------------------*/
11703 static void genOutp( iCode *ic, int nparms, operand **parms)
11705 operand *from , *to , *count;
11710 /* we know it has to be 3 parameters */
11711 assert (nparms == 3);
11713 rsave = newBitVect(16);
11714 /* save DPTR if it needs to be saved */
11715 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11716 if (bitVectBitValue(ic->rMask,i))
11717 rsave = bitVectSetBit(rsave,i);
11719 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11720 ds390_rUmaskForOp (IC_RESULT(ic))));
11727 aopOp (from, ic->next, FALSE, FALSE);
11729 /* get from into DPTR1 */
11730 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11731 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11732 if (options.model == MODEL_FLAT24) {
11733 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11736 freeAsmop (from, NULL, ic, FALSE);
11737 aopOp (to, ic, FALSE, FALSE);
11738 /* get "to" into DPTR */
11739 /* if the operand is already in dptr
11740 then we do nothing else we move the value to dptr */
11741 if (AOP_TYPE (to) != AOP_STR) {
11742 /* if already in DPTR then we need to push */
11743 if (AOP_TYPE(to) == AOP_DPTR) {
11744 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11745 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11746 if (options.model == MODEL_FLAT24)
11747 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11748 emitcode ("pop", "dph");
11749 emitcode ("pop", "dpl");
11751 _startLazyDPSEvaluation ();
11752 /* if this is remateriazable */
11753 if (AOP_TYPE (to) == AOP_IMMD) {
11754 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11755 } else { /* we need to get it byte by byte */
11756 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11757 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11758 if (options.model == MODEL_FLAT24) {
11759 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11762 _endLazyDPSEvaluation ();
11765 freeAsmop (to, NULL, ic, FALSE);
11767 _G.dptrInUse = _G.dptr1InUse = 1;
11768 aopOp (count, ic->next->next, FALSE,FALSE);
11769 lbl =newiTempLabel(NULL);
11771 /* now for the actual copy */
11772 if (AOP_TYPE(count) == AOP_LIT &&
11773 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11774 emitcode (";","OH JOY auto increment with djnz (very fast)");
11775 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
11776 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11777 emitcode ("","!tlabeldef",lbl->key+100);
11778 emitcode ("movx", "a,@dptr"); /* read data from port */
11779 emitcode ("inc","dps"); /* switch to DPTR2 */
11780 emitcode ("movx", "@dptr,a"); /* save into location */
11781 emitcode ("inc", "dptr"); /* point to next area */
11782 emitcode ("dec","dps"); /* switch to DPTR */
11783 emitcode ("djnz","b,!tlabel",lbl->key+100);
11784 freeAsmop (count, NULL, ic, FALSE);
11786 symbol *lbl1 = newiTempLabel(NULL);
11788 emitcode (";"," Auto increment but no djnz");
11789 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11790 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11791 freeAsmop (count, NULL, ic, FALSE);
11792 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
11793 emitcode ("","!tlabeldef",lbl->key+100);
11794 emitcode ("movx", "a,@dptr");
11795 emitcode ("inc", "dptr");
11796 emitcode ("inc","dps"); /* switch to DPTR2 */
11797 emitcode ("movx", "@dptr,a");
11798 emitcode ("dec","dps"); /* switch to DPTR */
11799 emitcode ("mov","a,b");
11800 emitcode ("orl","a,_ap");
11801 emitcode ("jz","!tlabel",lbl1->key+100);
11802 emitcode ("mov","a,_ap");
11803 emitcode ("add","a,#!constbyte",0xFF);
11804 emitcode ("mov","_ap,a");
11805 emitcode ("mov","a,b");
11806 emitcode ("addc","a,#!constbyte",0xFF);
11807 emitcode ("mov","b,a");
11808 emitcode ("sjmp","!tlabel",lbl->key+100);
11809 emitcode ("","!tlabeldef",lbl1->key+100);
11811 emitcode ("mov", "dps,#0");
11812 _G.dptrInUse = _G.dptr1InUse = 0;
11813 unsavermask(rsave);
11817 /*-----------------------------------------------------------------*/
11818 /* genSwapW - swap lower & high order bytes */
11819 /*-----------------------------------------------------------------*/
11820 static void genSwapW(iCode *ic, int nparms, operand **parms)
11824 assert (nparms==1);
11827 dest=IC_RESULT(ic);
11829 assert(getSize(operandType(src))==2);
11831 aopOp (src, ic, FALSE, FALSE);
11832 emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
11834 MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
11836 freeAsmop (src, NULL, ic, FALSE);
11838 aopOp (dest,ic, FALSE, FALSE);
11839 aopPut(AOP(dest),"b",0);
11840 aopPut(AOP(dest),"a",1);
11841 freeAsmop (dest, NULL, ic, FALSE);
11844 /*-----------------------------------------------------------------*/
11845 /* genMemsetX - gencode for memSetX data */
11846 /*-----------------------------------------------------------------*/
11847 static void genMemsetX(iCode *ic, int nparms, operand **parms)
11849 operand *to , *val , *count;
11855 /* we know it has to be 3 parameters */
11856 assert (nparms == 3);
11862 /* save DPTR if it needs to be saved */
11863 rsave = newBitVect(16);
11864 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11865 if (bitVectBitValue(ic->rMask,i))
11866 rsave = bitVectSetBit(rsave,i);
11868 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11869 ds390_rUmaskForOp (IC_RESULT(ic))));
11872 aopOp (to, ic, FALSE, FALSE);
11873 /* get "to" into DPTR */
11874 /* if the operand is already in dptr
11875 then we do nothing else we move the value to dptr */
11876 if (AOP_TYPE (to) != AOP_STR) {
11877 /* if already in DPTR then we need to push */
11878 if (AOP_TYPE(to) == AOP_DPTR) {
11879 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11880 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11881 if (options.model == MODEL_FLAT24)
11882 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11883 emitcode ("pop", "dph");
11884 emitcode ("pop", "dpl");
11886 _startLazyDPSEvaluation ();
11887 /* if this is remateriazable */
11888 if (AOP_TYPE (to) == AOP_IMMD) {
11889 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11890 } else { /* we need to get it byte by byte */
11891 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11892 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11893 if (options.model == MODEL_FLAT24) {
11894 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11897 _endLazyDPSEvaluation ();
11900 freeAsmop (to, NULL, ic, FALSE);
11902 aopOp (val, ic->next->next, FALSE,FALSE);
11903 aopOp (count, ic->next->next, FALSE,FALSE);
11904 lbl =newiTempLabel(NULL);
11905 /* now for the actual copy */
11906 if (AOP_TYPE(count) == AOP_LIT &&
11907 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11908 l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
11909 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11911 emitcode ("","!tlabeldef",lbl->key+100);
11912 emitcode ("movx", "@dptr,a");
11913 emitcode ("inc", "dptr");
11914 emitcode ("djnz","b,!tlabel",lbl->key+100);
11916 symbol *lbl1 = newiTempLabel(NULL);
11918 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11919 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11920 emitcode ("","!tlabeldef",lbl->key+100);
11921 MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
11922 emitcode ("movx", "@dptr,a");
11923 emitcode ("inc", "dptr");
11924 emitcode ("mov","a,b");
11925 emitcode ("orl","a,_ap");
11926 emitcode ("jz","!tlabel",lbl1->key+100);
11927 emitcode ("mov","a,_ap");
11928 emitcode ("add","a,#!constbyte",0xFF);
11929 emitcode ("mov","_ap,a");
11930 emitcode ("mov","a,b");
11931 emitcode ("addc","a,#!constbyte",0xFF);
11932 emitcode ("mov","b,a");
11933 emitcode ("sjmp","!tlabel",lbl->key+100);
11934 emitcode ("","!tlabeldef",lbl1->key+100);
11936 freeAsmop (count, NULL, ic, FALSE);
11937 unsavermask(rsave);
11940 /*-----------------------------------------------------------------*/
11941 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
11942 /*-----------------------------------------------------------------*/
11943 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
11946 operand *pnum, *result;
11949 assert (nparms==1);
11950 /* save registers that need to be saved */
11951 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11952 ds390_rUmaskForOp (IC_RESULT(ic))));
11955 aopOp (pnum, ic, FALSE, FALSE);
11956 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
11957 freeAsmop (pnum, NULL, ic, FALSE);
11958 emitcode ("lcall","NatLib_LoadPrimitive");
11959 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11960 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
11961 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
11962 for (i = (size-1) ; i >= 0 ; i-- ) {
11963 emitcode ("push","a%s",javaRet[i]);
11965 for (i=0; i < size ; i++ ) {
11966 emitcode ("pop","a%s",
11967 aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
11970 for (i = 0 ; i < size ; i++ ) {
11971 aopPut(AOP(result),javaRet[i],i);
11974 freeAsmop (result, NULL, ic, FALSE);
11975 unsavermask(rsave);
11978 /*-----------------------------------------------------------------*/
11979 /* genNatLibLoadPointer - calls TINI api function to load pointer */
11980 /*-----------------------------------------------------------------*/
11981 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
11984 operand *pnum, *result;
11988 assert (nparms==1);
11989 /* save registers that need to be saved */
11990 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11991 ds390_rUmaskForOp (IC_RESULT(ic))));
11994 aopOp (pnum, ic, FALSE, FALSE);
11995 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
11996 freeAsmop (pnum, NULL, ic, FALSE);
11997 emitcode ("lcall","NatLib_LoadPointer");
11998 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11999 if (AOP_TYPE(result)!=AOP_STR) {
12000 for (i = 0 ; i < size ; i++ ) {
12001 aopPut(AOP(result),fReturn[i],i);
12004 freeAsmop (result, NULL, ic, FALSE);
12005 unsavermask(rsave);
12008 /*-----------------------------------------------------------------*/
12009 /* genNatLibInstallStateBlock - */
12010 /*-----------------------------------------------------------------*/
12011 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
12012 operand **parms, const char *name)
12015 operand *psb, *handle;
12016 assert (nparms==2);
12018 /* save registers that need to be saved */
12019 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12020 ds390_rUmaskForOp (IC_RESULT(ic))));
12024 /* put pointer to state block into DPTR1 */
12025 aopOp (psb, ic, FALSE, FALSE);
12026 if (AOP_TYPE (psb) == AOP_IMMD) {
12027 emitcode ("mov","dps,#1");
12028 emitcode ("mov", "dptr,%s",
12029 aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12030 emitcode ("mov","dps,#0");
12032 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12033 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12034 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12036 freeAsmop (psb, NULL, ic, FALSE);
12038 /* put libraryID into DPTR */
12039 emitcode ("mov","dptr,#LibraryID");
12041 /* put handle into r3:r2 */
12042 aopOp (handle, ic, FALSE, FALSE);
12043 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12044 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12045 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12046 emitcode ("pop","ar3");
12047 emitcode ("pop","ar2");
12049 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12050 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12052 freeAsmop (psb, NULL, ic, FALSE);
12054 /* make the call */
12055 emitcode ("lcall","NatLib_Install%sStateBlock",name);
12057 /* put return value into place*/
12059 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12061 aopPut(AOP(IC_RESULT(ic)),"a",0);
12062 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12063 unsavermask(rsave);
12066 /*-----------------------------------------------------------------*/
12067 /* genNatLibRemoveStateBlock - */
12068 /*-----------------------------------------------------------------*/
12069 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12075 /* save registers that need to be saved */
12076 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12077 ds390_rUmaskForOp (IC_RESULT(ic))));
12079 /* put libraryID into DPTR */
12080 emitcode ("mov","dptr,#LibraryID");
12081 /* make the call */
12082 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12083 unsavermask(rsave);
12086 /*-----------------------------------------------------------------*/
12087 /* genNatLibGetStateBlock - */
12088 /*-----------------------------------------------------------------*/
12089 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12090 operand **parms,const char *name)
12093 symbol *lbl = newiTempLabel(NULL);
12096 /* save registers that need to be saved */
12097 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12098 ds390_rUmaskForOp (IC_RESULT(ic))));
12100 /* put libraryID into DPTR */
12101 emitcode ("mov","dptr,#LibraryID");
12102 /* make the call */
12103 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12104 emitcode ("jnz","!tlabel",lbl->key+100);
12106 /* put return value into place */
12107 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12108 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12109 emitcode ("push","ar3");
12110 emitcode ("push","ar2");
12111 emitcode ("pop","%s",
12112 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12113 emitcode ("pop","%s",
12114 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12116 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12117 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12119 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12120 emitcode ("","!tlabeldef",lbl->key+100);
12121 unsavermask(rsave);
12124 /*-----------------------------------------------------------------*/
12125 /* genMMMalloc - */
12126 /*-----------------------------------------------------------------*/
12127 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12128 int size, const char *name)
12133 symbol *lbl = newiTempLabel(NULL);
12135 assert (nparms == 1);
12136 /* save registers that need to be saved */
12137 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12138 ds390_rUmaskForOp (IC_RESULT(ic))));
12141 aopOp (bsize,ic,FALSE,FALSE);
12143 /* put the size in R4-R2 */
12144 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12145 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12146 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12148 emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12149 emitcode("pop","ar4");
12151 emitcode("pop","ar3");
12152 emitcode("pop","ar2");
12154 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12155 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12157 emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12160 freeAsmop (bsize, NULL, ic, FALSE);
12162 /* make the call */
12163 emitcode ("lcall","MM_%s",name);
12164 emitcode ("jz","!tlabel",lbl->key+100);
12165 emitcode ("mov","r2,#!constbyte",0xff);
12166 emitcode ("mov","r3,#!constbyte",0xff);
12167 emitcode ("","!tlabeldef",lbl->key+100);
12168 /* we don't care about the pointer : we just save the handle */
12169 rsym = OP_SYMBOL(IC_RESULT(ic));
12170 if (rsym->liveFrom != rsym->liveTo) {
12171 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12172 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12173 emitcode ("push","ar3");
12174 emitcode ("push","ar2");
12175 emitcode ("pop","%s",
12176 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12177 emitcode ("pop","%s",
12178 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12180 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12181 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12183 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12185 unsavermask(rsave);
12188 /*-----------------------------------------------------------------*/
12190 /*-----------------------------------------------------------------*/
12191 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12196 assert (nparms == 1);
12197 /* save registers that need to be saved */
12198 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12199 ds390_rUmaskForOp (IC_RESULT(ic))));
12202 aopOp (handle,ic,FALSE,FALSE);
12204 /* put the size in R4-R2 */
12205 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12206 emitcode("push","%s",
12207 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12208 emitcode("push","%s",
12209 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12210 emitcode("pop","ar3");
12211 emitcode("pop","ar2");
12213 emitcode ("mov","r2,%s",
12214 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12215 emitcode ("mov","r3,%s",
12216 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12218 freeAsmop (handle, NULL, ic, FALSE);
12220 /* make the call */
12221 emitcode ("lcall","MM_Deref");
12224 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12225 if (rsym->liveFrom != rsym->liveTo) {
12226 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12227 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12228 _startLazyDPSEvaluation ();
12230 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12231 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12232 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12234 _endLazyDPSEvaluation ();
12239 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12240 unsavermask(rsave);
12243 /*-----------------------------------------------------------------*/
12244 /* genMMUnrestrictedPersist - */
12245 /*-----------------------------------------------------------------*/
12246 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12251 assert (nparms == 1);
12252 /* save registers that need to be saved */
12253 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12254 ds390_rUmaskForOp (IC_RESULT(ic))));
12257 aopOp (handle,ic,FALSE,FALSE);
12259 /* put the size in R3-R2 */
12260 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12261 emitcode("push","%s",
12262 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12263 emitcode("push","%s",
12264 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12265 emitcode("pop","ar3");
12266 emitcode("pop","ar2");
12268 emitcode ("mov","r2,%s",
12269 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12270 emitcode ("mov","r3,%s",
12271 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12273 freeAsmop (handle, NULL, ic, FALSE);
12275 /* make the call */
12276 emitcode ("lcall","MM_UnrestrictedPersist");
12279 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12280 if (rsym->liveFrom != rsym->liveTo) {
12281 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12282 aopPut(AOP(IC_RESULT(ic)),"a",0);
12283 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12286 unsavermask(rsave);
12289 /*-----------------------------------------------------------------*/
12290 /* genSystemExecJavaProcess - */
12291 /*-----------------------------------------------------------------*/
12292 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12295 operand *handle, *pp;
12297 assert (nparms==2);
12298 /* save registers that need to be saved */
12299 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12300 ds390_rUmaskForOp (IC_RESULT(ic))));
12305 /* put the handle in R3-R2 */
12306 aopOp (handle,ic,FALSE,FALSE);
12307 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12308 emitcode("push","%s",
12309 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12310 emitcode("push","%s",
12311 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12312 emitcode("pop","ar3");
12313 emitcode("pop","ar2");
12315 emitcode ("mov","r2,%s",
12316 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12317 emitcode ("mov","r3,%s",
12318 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12320 freeAsmop (handle, NULL, ic, FALSE);
12322 /* put pointer in DPTR */
12323 aopOp (pp,ic,FALSE,FALSE);
12324 if (AOP_TYPE(pp) == AOP_IMMD) {
12325 emitcode ("mov", "dptr,%s",
12326 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12327 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12328 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12329 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12330 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12332 freeAsmop (handle, NULL, ic, FALSE);
12334 /* make the call */
12335 emitcode ("lcall","System_ExecJavaProcess");
12337 /* put result in place */
12339 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12340 if (rsym->liveFrom != rsym->liveTo) {
12341 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12342 aopPut(AOP(IC_RESULT(ic)),"a",0);
12343 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12347 unsavermask(rsave);
12350 /*-----------------------------------------------------------------*/
12351 /* genSystemRTCRegisters - */
12352 /*-----------------------------------------------------------------*/
12353 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12359 assert (nparms==1);
12360 /* save registers that need to be saved */
12361 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12362 ds390_rUmaskForOp (IC_RESULT(ic))));
12365 /* put pointer in DPTR */
12366 aopOp (pp,ic,FALSE,FALSE);
12367 if (AOP_TYPE (pp) == AOP_IMMD) {
12368 emitcode ("mov","dps,#1");
12369 emitcode ("mov", "dptr,%s",
12370 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12371 emitcode ("mov","dps,#0");
12373 emitcode ("mov","dpl1,%s",
12374 aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12375 emitcode ("mov","dph1,%s",
12376 aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12377 emitcode ("mov","dpx1,%s",
12378 aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12380 freeAsmop (pp, NULL, ic, FALSE);
12382 /* make the call */
12383 emitcode ("lcall","System_%sRTCRegisters",name);
12385 unsavermask(rsave);
12388 /*-----------------------------------------------------------------*/
12389 /* genSystemThreadSleep - */
12390 /*-----------------------------------------------------------------*/
12391 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12396 assert (nparms==1);
12397 /* save registers that need to be saved */
12398 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12399 ds390_rUmaskForOp (IC_RESULT(ic))));
12402 aopOp(to,ic,FALSE,FALSE);
12403 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12404 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12405 emitcode ("push","%s",
12406 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12407 emitcode ("push","%s",
12408 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12409 emitcode ("push","%s",
12410 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12411 emitcode ("push","%s",
12412 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12413 emitcode ("pop","ar3");
12414 emitcode ("pop","ar2");
12415 emitcode ("pop","ar1");
12416 emitcode ("pop","ar0");
12418 emitcode ("mov","r0,%s",
12419 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12420 emitcode ("mov","r1,%s",
12421 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12422 emitcode ("mov","r2,%s",
12423 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12424 emitcode ("mov","r3,%s",
12425 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12427 freeAsmop (to, NULL, ic, FALSE);
12429 /* suspend in acc */
12431 aopOp(s,ic,FALSE,FALSE);
12432 emitcode ("mov","a,%s",
12433 aopGet(AOP(s),0,FALSE,TRUE,NULL));
12434 freeAsmop (s, NULL, ic, FALSE);
12436 /* make the call */
12437 emitcode ("lcall","System_%s",name);
12439 unsavermask(rsave);
12442 /*-----------------------------------------------------------------*/
12443 /* genSystemThreadResume - */
12444 /*-----------------------------------------------------------------*/
12445 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12450 assert (nparms==2);
12451 /* save registers that need to be saved */
12452 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12453 ds390_rUmaskForOp (IC_RESULT(ic))));
12459 aopOp(pid,ic,FALSE,FALSE);
12460 emitcode ("mov","r0,%s",
12461 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12462 freeAsmop (pid, NULL, ic, FALSE);
12465 aopOp(tid,ic,FALSE,FALSE);
12466 emitcode ("mov","a,%s",
12467 aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
12468 freeAsmop (tid, NULL, ic, FALSE);
12470 emitcode ("lcall","System_ThreadResume");
12472 /* put result into place */
12474 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12475 if (rsym->liveFrom != rsym->liveTo) {
12476 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12477 aopPut(AOP(IC_RESULT(ic)),"a",0);
12478 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12481 unsavermask(rsave);
12484 /*-----------------------------------------------------------------*/
12485 /* genSystemProcessResume - */
12486 /*-----------------------------------------------------------------*/
12487 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
12492 assert (nparms==1);
12493 /* save registers that need to be saved */
12494 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12495 ds390_rUmaskForOp (IC_RESULT(ic))));
12500 aopOp(pid,ic,FALSE,FALSE);
12501 emitcode ("mov","a,%s",
12502 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12503 freeAsmop (pid, NULL, ic, FALSE);
12505 emitcode ("lcall","System_ProcessResume");
12507 unsavermask(rsave);
12510 /*-----------------------------------------------------------------*/
12512 /*-----------------------------------------------------------------*/
12513 static void genSystem (iCode *ic,int nparms,char *name)
12515 assert(nparms == 0);
12517 emitcode ("lcall","System_%s",name);
12520 /*-----------------------------------------------------------------*/
12521 /* genSystemPoll - */
12522 /*-----------------------------------------------------------------*/
12523 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
12528 assert (nparms==1);
12529 /* save registers that need to be saved */
12530 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12531 ds390_rUmaskForOp (IC_RESULT(ic))));
12534 aopOp (fp,ic,FALSE,FALSE);
12535 if (AOP_TYPE (fp) == AOP_IMMD) {
12536 emitcode ("mov", "dptr,%s",
12537 aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
12538 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
12539 emitcode ("mov","dpl,%s",
12540 aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
12541 emitcode ("mov","dph,%s",
12542 aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
12543 emitcode ("mov","dpx,%s",
12544 aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
12546 freeAsmop (fp, NULL, ic, FALSE);
12548 emitcode ("lcall","System_%sPoll",name);
12550 /* put result into place */
12552 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12553 if (rsym->liveFrom != rsym->liveTo) {
12554 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12555 aopPut(AOP(IC_RESULT(ic)),"a",0);
12556 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12559 unsavermask(rsave);
12562 /*-----------------------------------------------------------------*/
12563 /* genSystemGetCurrentID - */
12564 /*-----------------------------------------------------------------*/
12565 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
12567 assert (nparms==0);
12569 emitcode ("lcall","System_GetCurrent%sId",name);
12570 /* put result into place */
12572 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12573 if (rsym->liveFrom != rsym->liveTo) {
12574 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12575 aopPut(AOP(IC_RESULT(ic)),"a",0);
12576 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12581 /*-----------------------------------------------------------------*/
12582 /* genBuiltIn - calls the appropriate function to generating code */
12583 /* for a built in function */
12584 /*-----------------------------------------------------------------*/
12585 static void genBuiltIn (iCode *ic)
12587 operand *bi_parms[MAX_BUILTIN_ARGS];
12592 /* get all the arguments for a built in function */
12593 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
12595 /* which function is it */
12596 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
12597 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
12598 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
12599 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
12600 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
12601 } else if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
12602 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
12603 } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
12604 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
12605 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
12606 genMemsetX(bi_iCode,nbi_parms,bi_parms);
12607 } else if (strcmp(bif->name,"__builtin_inp")==0) {
12608 genInp(bi_iCode,nbi_parms,bi_parms);
12609 } else if (strcmp(bif->name,"__builtin_outp")==0) {
12610 genOutp(bi_iCode,nbi_parms,bi_parms);
12611 } else if (strcmp(bif->name,"__builtin_swapw")==0) {
12612 genSwapW(bi_iCode,nbi_parms,bi_parms);
12613 /* JavaNative builtIns */
12614 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
12615 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
12616 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
12617 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
12618 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
12619 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
12620 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
12621 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
12622 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
12623 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12624 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
12625 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12626 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
12627 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
12628 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
12629 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
12630 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
12631 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12632 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
12633 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12634 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
12635 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
12636 } else if (strcmp(bif->name,"MM_Malloc")==0) {
12637 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
12638 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
12639 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
12640 } else if (strcmp(bif->name,"MM_Free")==0) {
12641 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
12642 } else if (strcmp(bif->name,"MM_Deref")==0) {
12643 genMMDeref(bi_iCode,nbi_parms,bi_parms);
12644 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
12645 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
12646 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
12647 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
12648 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
12649 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
12650 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
12651 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
12652 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
12653 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
12654 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
12655 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
12656 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
12657 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
12658 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
12659 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
12660 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12661 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12662 } else if (strcmp(bif->name,"System_SaveThread")==0) {
12663 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12664 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12665 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12666 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
12667 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
12668 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
12669 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
12670 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
12671 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
12672 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
12673 genSystem(bi_iCode,nbi_parms,"ProcessYield");
12674 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
12675 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
12676 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
12677 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
12678 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
12679 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
12680 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
12681 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
12682 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
12683 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
12685 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
12691 /*-----------------------------------------------------------------*/
12692 /* gen390Code - generate code for Dallas 390 based controllers */
12693 /*-----------------------------------------------------------------*/
12695 gen390Code (iCode * lic)
12700 lineHead = lineCurr = NULL;
12701 dptrn[1][0] = "dpl1";
12702 dptrn[1][1] = "dph1";
12703 dptrn[1][2] = "dpx1";
12705 if (options.model == MODEL_FLAT24) {
12706 fReturnSizeDS390 = 5;
12707 fReturn = fReturn24;
12709 fReturnSizeDS390 = 4;
12710 fReturn = fReturn16;
12711 options.stack10bit=0;
12714 /* print the allocation information */
12716 printAllocInfo (currFunc, codeOutFile);
12718 /* if debug information required */
12719 if (options.debug && currFunc)
12721 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
12723 if (IS_STATIC (currFunc->etype))
12724 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
12726 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
12729 /* stack pointer name */
12730 if (options.useXstack)
12736 for (ic = lic; ic; ic = ic->next)
12739 if (ic->lineno && cln != ic->lineno)
12744 emitcode ("", "C$%s$%d$%d$%d ==.",
12745 FileBaseName (ic->filename), ic->lineno,
12746 ic->level, ic->block);
12749 if (!options.noCcodeInAsm) {
12750 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
12751 printCLine(ic->filename, ic->lineno));
12755 if (options.iCodeInAsm) {
12756 emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
12758 /* if the result is marked as
12759 spilt and rematerializable or code for
12760 this has already been generated then
12762 if (resultRemat (ic) || ic->generated)
12765 /* depending on the operation */
12785 /* IPOP happens only when trying to restore a
12786 spilt live range, if there is an ifx statement
12787 following this pop then the if statement might
12788 be using some of the registers being popped which
12789 would destory the contents of the register so
12790 we need to check for this condition and handle it */
12792 ic->next->op == IFX &&
12793 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
12794 genIfx (ic->next, ic);
12812 genEndFunction (ic);
12832 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
12849 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
12853 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
12860 /* note these two are xlated by algebraic equivalence
12861 during parsing SDCC.y */
12862 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12863 "got '>=' or '<=' shouldn't have come here");
12867 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
12879 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
12883 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
12887 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
12911 genRightShift (ic);
12914 case GET_VALUE_AT_ADDRESS:
12915 genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
12919 if (POINTER_SET (ic))
12920 genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
12946 if (ic->builtinSEND) genBuiltIn(ic);
12947 else addSet (&_G.sendSet, ic);
12960 /* now we are ready to call the
12961 peep hole optimizer */
12962 if (!options.nopeep)
12963 peepHole (&lineHead);
12965 /* now do the actual printing */
12966 printLine (lineHead, codeOutFile);