1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for DS80C390
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7 DS390 adaptation by Kevin Vigor <kevin@vigor.nu>
9 This program is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 2, or (at your option) any
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 In other words, you are welcome to use, share and improve this program.
24 You are forbidden to forbid anyone else to use, share and improve
25 what you give them. Help stamp out software-hoarding!
26 -------------------------------------------------------------------------*/
36 #include "SDCCglobl.h"
39 #ifdef HAVE_SYS_ISA_DEFS_H
40 #include <sys/isa_defs.h>
42 #ifdef HAVE_MACHINE_ENDIAN_H
43 #include <machine/endian.h>
48 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
49 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
50 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
56 #define BETTER_LITERAL_SHIFT
58 char *aopLiteral (value * val, int offset);
61 /* this is the down and dirty file with all kinds of
62 kludgy & hacky stuff. This is what it is all about
63 CODE GENERATION for a specific MCU . some of the
64 routines may be reusable, will have to see */
66 static char *zero = "#0";
67 static char *one = "#1";
72 #define TR_DPTR(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_DPTR1 %s ", s); }
73 #define TR_AP(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_AP %s ", s); }
75 unsigned fReturnSizeDS390 = 5; /* shared with ralloc.c */
76 static char *fReturn24[] =
77 {"dpl", "dph", "dpx", "b", "a"};
78 static char *fReturn16[] =
79 {"dpl", "dph", "b", "a"};
80 static char **fReturn = fReturn24;
81 static char *accUse[] =
83 static char *dptrn[2][3];
84 static char *javaRet[] = { "r0","r1","r2","r3"};
85 static short rbank = -1;
102 static char *rb1regs[] = {
103 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
106 static void saveRBank (int, iCode *, bool);
108 #define RESULTONSTACK(x) \
109 (IC_RESULT(x) && IC_RESULT(x)->aop && \
110 IC_RESULT(x)->aop->type == AOP_STK )
112 /* #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x); */
113 #define MOVA(x) { char *_mova_tmp = strdup(x); \
114 if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \
116 emitcode("mov","a,%s",_mova_tmp); \
120 #define CLRC emitcode("clr","c")
121 #define SETC emitcode("setb","c")
123 // A scratch register which will be used to hold
124 // result bytes from operands in far space via DPTR2.
125 #define DP2_RESULT_REG "_ap"
127 static lineNode *lineHead = NULL;
128 static lineNode *lineCurr = NULL;
130 static unsigned char SLMask[] =
131 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
132 0xE0, 0xC0, 0x80, 0x00};
133 static unsigned char SRMask[] =
134 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
135 0x07, 0x03, 0x01, 0x00};
141 #define PROTECT_SP {if (options.protect_sp_update) { \
142 symbol *lbl = newiTempLabel(NULL); \
143 emitcode ("setb","F1"); \
144 emitcode ("jbc","EA,!tlabel",lbl->key+100); \
145 emitcode ("clr","F1"); \
146 emitcode ("","!tlabeldef",lbl->key+100); \
148 #define UNPROTECT_SP { if (options.protect_sp_update) { \
149 symbol *lbl = newiTempLabel(NULL); \
150 emitcode ("jnb","F1,!tlabel",lbl->key+100); \
151 emitcode ("setb","EA"); \
152 emitcode ("","!tlabeldef",lbl->key+100); \
156 /*-----------------------------------------------------------------*/
157 /* emitcode - writes the code into a file : for now it is simple */
158 /*-----------------------------------------------------------------*/
160 emitcode (char *inst, char *fmt,...)
163 char lb[INITIAL_INLINEASM];
171 sprintf (lb, "%s\t", inst);
173 sprintf (lb, "%s", inst);
174 tvsprintf (lb + (strlen (lb)), fmt, ap);
177 tvsprintf (lb, fmt, ap);
179 while (isspace (*lbp))
183 lineCurr = (lineCurr ?
184 connectLine (lineCurr, newLineNode (lb)) :
185 (lineHead = newLineNode (lb)));
186 lineCurr->isInline = _G.inLine;
187 lineCurr->isDebug = _G.debugLine;
191 /*-----------------------------------------------------------------*/
192 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
193 /*-----------------------------------------------------------------*/
195 getFreePtr (iCode * ic, asmop ** aopp, bool result)
197 bool r0iu = FALSE, r1iu = FALSE;
198 bool r0ou = FALSE, r1ou = FALSE;
200 /* the logic: if r0 & r1 used in the instruction
201 then we are in trouble otherwise */
203 /* first check if r0 & r1 are used by this
204 instruction, in which case we are in trouble */
205 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
206 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
211 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
212 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
214 /* if no usage of r0 then return it */
217 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
218 (*aopp)->type = AOP_R0;
220 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
223 /* if no usage of r1 then return it */
226 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
227 (*aopp)->type = AOP_R1;
229 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
232 /* now we know they both have usage */
233 /* if r0 not used in this instruction */
236 /* push it if not already pushed */
239 emitcode ("push", "%s",
240 ds390_regWithIdx (R0_IDX)->dname);
244 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
245 (*aopp)->type = AOP_R0;
247 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
250 /* if r1 not used then */
254 /* push it if not already pushed */
257 emitcode ("push", "%s",
258 ds390_regWithIdx (R1_IDX)->dname);
262 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
263 (*aopp)->type = AOP_R1;
264 return ds390_regWithIdx (R1_IDX);
268 /* I said end of world but not quite end of world yet */
269 /* if this is a result then we can push it on the stack */
272 (*aopp)->type = AOP_STK;
276 /* other wise this is true end of the world */
277 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
278 "getFreePtr should never reach here");
282 /*-----------------------------------------------------------------*/
283 /* newAsmop - creates a new asmOp */
284 /*-----------------------------------------------------------------*/
286 newAsmop (short type)
290 aop = Safe_calloc (1, sizeof (asmop));
295 static int _currentDPS; /* Current processor DPS. */
296 static int _desiredDPS; /* DPS value compiler thinks we should be using. */
297 static int _lazyDPS = 0; /* if non-zero, we are doing lazy evaluation of DPS changes. */
299 /*-----------------------------------------------------------------*/
300 /* genSetDPTR: generate code to select which DPTR is in use (zero */
301 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390 */
302 /* alternate DPTR (DPL1/DPH1/DPX1). */
303 /*-----------------------------------------------------------------*/
308 /* If we are doing lazy evaluation, simply note the desired
309 * change, but don't emit any code yet.
319 emitcode ("mov", "dps,#0");
324 emitcode ("mov", "dps,#1");
328 /*-----------------------------------------------------------------*/
329 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
331 /* Any code that operates on DPTR (NB: not on the individual */
332 /* components, like DPH) *must* call _flushLazyDPS() before using */
333 /* DPTR within a lazy DPS evaluation block. */
335 /* Note that aopPut and aopGet already contain the proper calls to */
336 /* _flushLazyDPS, so it is safe to use these calls within a lazy */
337 /* DPS evaluation block. */
339 /* Also, _flushLazyDPS must be called before any flow control */
340 /* operations that could potentially branch out of the block. */
342 /* Lazy DPS evaluation is simply an optimization (though an */
343 /* important one), so if in doubt, leave it out. */
344 /*-----------------------------------------------------------------*/
346 _startLazyDPSEvaluation (void)
350 #ifdef BETTER_LITERAL_SHIFT
357 /*-----------------------------------------------------------------*/
358 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
359 /* desired one. Call before using DPTR within a lazy DPS evaluation */
361 /*-----------------------------------------------------------------*/
371 if (_desiredDPS != _currentDPS)
375 emitcode ("inc", "dps");
379 emitcode ("dec", "dps");
381 _currentDPS = _desiredDPS;
385 /*-----------------------------------------------------------------*/
386 /* _endLazyDPSEvaluation: end lazy DPS evaluation block. */
388 /* Forces us back to the safe state (standard DPTR selected). */
389 /*-----------------------------------------------------------------*/
391 _endLazyDPSEvaluation (void)
393 #ifdef BETTER_LITERAL_SHIFT
412 /*-----------------------------------------------------------------*/
413 /* pointerCode - returns the code for a pointer type */
414 /*-----------------------------------------------------------------*/
416 pointerCode (sym_link * etype)
419 return PTR_TYPE (SPEC_OCLS (etype));
423 /*-----------------------------------------------------------------*/
424 /* aopForSym - for a true symbol */
425 /*-----------------------------------------------------------------*/
427 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
430 memmap *space = SPEC_OCLS (sym->etype);
432 /* if already has one */
436 /* assign depending on the storage class */
437 /* if it is on the stack or indirectly addressable */
438 /* space we need to assign either r0 or r1 to it */
439 if ((sym->onStack && !options.stack10bit) || sym->iaccess)
441 sym->aop = aop = newAsmop (0);
442 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
443 aop->size = getSize (sym->type);
445 /* now assign the address of the variable to
446 the pointer register */
447 if (aop->type != AOP_STK)
453 emitcode ("push", "acc");
456 emitcode ("push", "b");
458 emitcode ("mov", "a,_bp");
459 emitcode ("add", "a,#!constbyte",
461 ((char) (sym->stack - _G.nRegsSaved)) :
462 ((char) sym->stack)) & 0xff);
463 emitcode ("mov", "%s,a",
464 aop->aopu.aop_ptr->name);
467 emitcode ("pop", "b");
470 emitcode ("pop", "acc");
473 emitcode ("mov", "%s,#%s",
474 aop->aopu.aop_ptr->name,
476 aop->paged = space->paged;
479 aop->aopu.aop_stk = sym->stack;
483 if (sym->onStack && options.stack10bit)
485 short stack_val = -((sym->stack < 0) ?
486 ((short) (sym->stack - _G.nRegsSaved)) :
487 ((short) sym->stack)) ;
488 if (useDP2 && _G.dptr1InUse) {
489 emitcode ("push","dpl1");
490 emitcode ("push","dph1");
491 emitcode ("push","dpx1");
492 } else if (_G.dptrInUse ) {
493 emitcode ("push","dpl");
494 emitcode ("push","dph");
495 emitcode ("push","dpx");
497 /* It's on the 10 bit stack, which is located in
500 if (stack_val < 0 && stack_val > -5) { /* between -5 & -1 */
502 if (options.model == MODEL_FLAT24)
503 emitcode ("mov", "dpx1,#!constbyte", (options.stack_loc >> 16) & 0xff);
505 emitcode ("mov", "dph1,_bpx+1");
506 emitcode ("mov", "dpl1,_bpx");
507 emitcode ("mov","dps,#1");
509 if (options.model == MODEL_FLAT24)
510 emitcode ("mov", "dpx,#!constbyte", (options.stack_loc >> 16) & 0xff);
511 emitcode ("mov", "dph,_bpx+1");
512 emitcode ("mov", "dpl,_bpx");
514 stack_val = -stack_val;
515 while (stack_val--) {
516 emitcode ("inc","dptr");
519 emitcode("mov","dps,#0");
523 emitcode ("push", "acc");
526 emitcode ("push", "b");
528 emitcode ("mov", "a,_bpx");
529 emitcode ("clr","c");
530 emitcode ("subb", "a,#!constbyte", stack_val & 0xff);
531 emitcode ("mov","b,a");
532 emitcode ("mov","a,_bpx+1");
533 emitcode ("subb","a,#!constbyte",(stack_val >> 8) & 0xff);
535 if (options.model == MODEL_FLAT24)
536 emitcode ("mov", "dpx1,#!constbyte", (options.stack_loc >> 16) & 0xff);
538 emitcode ("mov", "dph1,a");
539 emitcode ("mov", "dpl1,b");
541 if (options.model == MODEL_FLAT24)
542 emitcode ("mov", "dpx,#!constbyte", (options.stack_loc >> 16) & 0xff);
543 emitcode ("mov", "dph,a");
544 emitcode ("mov", "dpl,b");
548 emitcode ("pop", "b");
551 emitcode ("pop", "acc");
553 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
554 aop->size = getSize (sym->type);
558 /* if in bit space */
559 if (IN_BITSPACE (space))
561 sym->aop = aop = newAsmop (AOP_CRY);
562 aop->aopu.aop_dir = sym->rname;
563 aop->size = getSize (sym->type);
566 /* if it is in direct space */
567 if (IN_DIRSPACE (space))
569 sym->aop = aop = newAsmop (AOP_DIR);
570 aop->aopu.aop_dir = sym->rname;
571 aop->size = getSize (sym->type);
575 /* special case for a function */
576 if (IS_FUNC (sym->type))
578 sym->aop = aop = newAsmop (AOP_IMMD);
579 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
580 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
581 aop->size = FPTRSIZE;
585 /* only remaining is far space */
586 /* in which case DPTR gets the address */
587 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
592 emitcode ("mov", "dptr,#%s", sym->rname);
597 emitcode ("mov", "dptr,#%s", sym->rname);
599 aop->size = getSize (sym->type);
601 /* if it is in code space */
602 if (IN_CODESPACE (space))
608 /*-----------------------------------------------------------------*/
609 /* aopForRemat - rematerialzes an object */
610 /*-----------------------------------------------------------------*/
612 aopForRemat (symbol * sym)
614 iCode *ic = sym->rematiCode;
615 asmop *aop = newAsmop (AOP_IMMD);
622 val += (int) operandLitValue (IC_RIGHT (ic));
623 else if (ic->op == '-')
624 val -= (int) operandLitValue (IC_RIGHT (ic));
625 else if (IS_CAST_ICODE(ic)) {
626 sym_link *from_type = operandType(IC_RIGHT(ic));
627 aop->aopu.aop_immd.from_cast_remat = 1;
628 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
629 ptr_type = DCL_TYPE(from_type);
630 if (ptr_type == IPOINTER) {
637 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
641 sprintf (buffer, "(%s %c 0x%04x)",
642 OP_SYMBOL (IC_LEFT (ic))->rname,
643 val >= 0 ? '+' : '-',
646 if (IS_ASSIGN_ICODE(ic) && isOperandLiteral(IC_RIGHT(ic)))
647 sprintf(buffer,"0x%x",(int) operandLitValue (IC_RIGHT (ic)));
649 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
652 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
653 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
654 /* set immd2 field if required */
655 if (aop->aopu.aop_immd.from_cast_remat) {
656 tsprintf(buffer,"#!constbyte",ptr_type);
657 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
658 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
664 /*-----------------------------------------------------------------*/
665 /* aopHasRegs - returns true if aop has regs between from-to */
666 /*-----------------------------------------------------------------*/
667 static int aopHasRegs(asmop *aop, int from, int to)
671 if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
673 for (; size < aop->size ; size++) {
675 for (reg = from ; reg <= to ; reg++)
676 if (aop->aopu.aop_reg[size] == ds390_regWithIdx(reg)) return 1;
681 /*-----------------------------------------------------------------*/
682 /* regsInCommon - two operands have some registers in common */
683 /*-----------------------------------------------------------------*/
685 regsInCommon (operand * op1, operand * op2)
690 /* if they have registers in common */
691 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
694 sym1 = OP_SYMBOL (op1);
695 sym2 = OP_SYMBOL (op2);
697 if (sym1->nRegs == 0 || sym2->nRegs == 0)
700 for (i = 0; i < sym1->nRegs; i++)
706 for (j = 0; j < sym2->nRegs; j++)
711 if (sym2->regs[j] == sym1->regs[i])
719 /*-----------------------------------------------------------------*/
720 /* operandsEqu - equivalent */
721 /*-----------------------------------------------------------------*/
723 operandsEqu (operand * op1, operand * op2)
727 /* if they not symbols */
728 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
731 sym1 = OP_SYMBOL (op1);
732 sym2 = OP_SYMBOL (op2);
734 /* if both are itemps & one is spilt
735 and the other is not then false */
736 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
737 sym1->isspilt != sym2->isspilt)
740 /* if they are the same */
744 if (strcmp (sym1->rname, sym2->rname) == 0)
748 /* if left is a tmp & right is not */
749 if (IS_ITEMP (op1) &&
752 (sym1->usl.spillLoc == sym2))
755 if (IS_ITEMP (op2) &&
759 (sym2->usl.spillLoc == sym1))
765 /*-----------------------------------------------------------------*/
766 /* sameRegs - two asmops have the same registers */
767 /*-----------------------------------------------------------------*/
769 sameRegs (asmop * aop1, asmop * aop2)
775 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
782 if (aop1->type != AOP_REG ||
783 aop2->type != AOP_REG)
786 if (aop1->size != aop2->size)
789 for (i = 0; i < aop1->size; i++)
790 if (aop1->aopu.aop_reg[i] !=
791 aop2->aopu.aop_reg[i])
797 /*-----------------------------------------------------------------*/
798 /* aopOp - allocates an asmop for an operand : */
799 /*-----------------------------------------------------------------*/
801 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
810 /* if this a literal */
811 if (IS_OP_LITERAL (op))
813 op->aop = aop = newAsmop (AOP_LIT);
814 aop->aopu.aop_lit = op->operand.valOperand;
815 aop->size = getSize (operandType (op));
819 /* if already has a asmop then continue */
823 /* if the underlying symbol has a aop */
824 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
826 op->aop = OP_SYMBOL (op)->aop;
830 /* if this is a true symbol */
831 if (IS_TRUE_SYMOP (op))
833 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
837 /* this is a temporary : this has
843 e) can be a return use only */
845 sym = OP_SYMBOL (op);
848 /* if the type is a conditional */
849 if (sym->regType == REG_CND)
851 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
856 /* if it is spilt then two situations
858 b) has a spill location */
859 if (sym->isspilt || sym->nRegs == 0)
862 /* rematerialize it NOW */
865 sym->aop = op->aop = aop =
867 aop->size = getSize (sym->type);
874 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
875 aop->size = getSize (sym->type);
876 for (i = 0; i < 2; i++)
877 aop->aopu.aop_str[i] = accUse[i];
887 /* a AOP_STR uses DPTR, but DPTR is already in use;
890 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"AOP_STR with DPTR in use!");
893 aop = op->aop = sym->aop = newAsmop (AOP_STR);
894 aop->size = getSize (sym->type);
895 for (i = 0; i < (int) fReturnSizeDS390; i++)
896 aop->aopu.aop_str[i] = fReturn[i];
900 if (sym->dptr) { /* has been allocated to a DPTRn */
901 aop = op->aop = sym->aop = newAsmop (AOP_DPTRn);
902 aop->size = getSize (sym->type);
903 aop->aopu.dptr = sym->dptr;
906 /* else spill location */
907 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
908 /* force a new aop if sizes differ */
909 sym->usl.spillLoc->aop = NULL;
911 sym->aop = op->aop = aop =
912 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
913 aop->size = getSize (sym->type);
917 /* must be in a register */
918 sym->aop = op->aop = aop = newAsmop (AOP_REG);
919 aop->size = sym->nRegs;
920 for (i = 0; i < sym->nRegs; i++)
921 aop->aopu.aop_reg[i] = sym->regs[i];
924 /*-----------------------------------------------------------------*/
925 /* freeAsmop - free up the asmop given to an operand */
926 /*----------------------------------------------------------------*/
928 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
945 /* depending on the asmop type only three cases need work AOP_RO
946 , AOP_R1 && AOP_STK */
954 emitcode ("pop", "ar0");
958 bitVectUnSetBit (ic->rUsed, R0_IDX);
966 emitcode ("pop", "ar1");
970 bitVectUnSetBit (ic->rUsed, R1_IDX);
976 int stk = aop->aopu.aop_stk + aop->size;
977 bitVectUnSetBit (ic->rUsed, R0_IDX);
978 bitVectUnSetBit (ic->rUsed, R1_IDX);
980 getFreePtr (ic, &aop, FALSE);
982 if (options.stack10bit)
984 /* I'm not sure what to do here yet... */
987 "*** Warning: probably generating bad code for "
988 "10 bit stack mode.\n");
993 emitcode ("mov", "a,_bp");
994 emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
995 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
999 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1004 emitcode ("pop", "acc");
1005 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1008 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1011 freeAsmop (op, NULL, ic, TRUE);
1014 emitcode ("pop", "ar0");
1020 emitcode ("pop", "ar1");
1025 if (_G.dptr1InUse) {
1026 emitcode ("pop","dpx1");
1027 emitcode ("pop","dph1");
1028 emitcode ("pop","dpl1");
1033 emitcode ("pop","dpx");
1034 emitcode ("pop","dph");
1035 emitcode ("pop","dpl");
1040 /* all other cases just dealloc */
1046 OP_SYMBOL (op)->aop = NULL;
1047 /* if the symbol has a spill */
1049 SPIL_LOC (op)->aop = NULL;
1054 /*------------------------------------------------------------------*/
1055 /* aopGet - for fetching value of the aop */
1057 /* Set canClobberACC if you are sure it is OK to clobber the value */
1058 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe, */
1059 /* just less efficient. */
1060 /*------------------------------------------------------------------*/
1063 aopGet (asmop * aop,
1072 /* offset is greater than
1074 if (offset > (aop->size - 1) &&
1075 aop->type != AOP_LIT)
1078 /* depending on type */
1084 /* if we need to increment it */
1085 while (offset > aop->coff)
1087 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1091 while (offset < aop->coff)
1093 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1100 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1101 return (dname ? "acc" : "a");
1103 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1104 rs = Safe_calloc (1, strlen (s) + 1);
1109 assert(offset <= 3);
1110 return dptrn[aop->aopu.dptr][offset];
1115 if (aop->type == AOP_DPTR2)
1121 emitcode ("xch", "a, %s", DP2_RESULT_REG);
1127 while (offset > aop->coff)
1129 emitcode ("inc", "dptr");
1133 while (offset < aop->coff)
1135 emitcode ("lcall", "__decdptr");
1142 emitcode ("clr", "a");
1143 emitcode ("movc", "a,@a+dptr");
1147 emitcode ("movx", "a,@dptr");
1150 if (aop->type == AOP_DPTR2)
1156 emitcode ("xch", "a, %s", DP2_RESULT_REG);
1157 return DP2_RESULT_REG;
1160 return (dname ? "acc" : "a");
1163 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1164 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1166 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1170 tsprintf(s,"#!his",aop->aopu.aop_immd.aop_immd1);
1173 tsprintf(s,"#!hihis",aop->aopu.aop_immd.aop_immd1);
1176 tsprintf(s,"#!hihihis",aop->aopu.aop_immd.aop_immd1);
1178 default: /* should not need this (just in case) */
1179 sprintf (s, "#(%s >> %d)",
1180 aop->aopu.aop_immd.aop_immd1,
1186 aop->aopu.aop_immd.aop_immd1);
1187 rs = Safe_calloc (1, strlen (s) + 1);
1193 sprintf (s, "(%s + %d)",
1197 sprintf (s, "%s", aop->aopu.aop_dir);
1198 rs = Safe_calloc (1, strlen (s) + 1);
1204 return aop->aopu.aop_reg[offset]->dname;
1206 return aop->aopu.aop_reg[offset]->name;
1209 emitcode ("clr", "a");
1210 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1211 emitcode ("rlc", "a");
1212 return (dname ? "acc" : "a");
1215 if (!offset && dname)
1217 return aop->aopu.aop_str[offset];
1220 return aopLiteral (aop->aopu.aop_lit, offset);
1224 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1228 return aop->aopu.aop_str[offset];
1232 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1233 "aopget got unsupported aop->type");
1236 /*-----------------------------------------------------------------*/
1237 /* aopPut - puts a string for a aop */
1238 /*-----------------------------------------------------------------*/
1240 aopPut (asmop * aop, char *s, int offset)
1244 if (aop->size && offset > (aop->size - 1))
1246 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1247 "aopPut got offset > aop->size");
1251 /* will assign value to value */
1252 /* depending on where it is ofcourse */
1257 sprintf (d, "(%s + %d)",
1258 aop->aopu.aop_dir, offset);
1260 sprintf (d, "%s", aop->aopu.aop_dir);
1263 emitcode ("mov", "%s,%s", d, s);
1268 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1269 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1272 strcmp (s, "r0") == 0 ||
1273 strcmp (s, "r1") == 0 ||
1274 strcmp (s, "r2") == 0 ||
1275 strcmp (s, "r3") == 0 ||
1276 strcmp (s, "r4") == 0 ||
1277 strcmp (s, "r5") == 0 ||
1278 strcmp (s, "r6") == 0 ||
1279 strcmp (s, "r7") == 0)
1280 emitcode ("mov", "%s,%s",
1281 aop->aopu.aop_reg[offset]->dname, s);
1283 emitcode ("mov", "%s,%s",
1284 aop->aopu.aop_reg[offset]->name, s);
1289 emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1295 if (aop->type == AOP_DPTR2)
1303 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1304 "aopPut writting to code space");
1308 while (offset > aop->coff)
1311 emitcode ("inc", "dptr");
1314 while (offset < aop->coff)
1317 emitcode ("lcall", "__decdptr");
1322 /* if not in accumulater */
1325 emitcode ("movx", "@dptr,a");
1327 if (aop->type == AOP_DPTR2)
1335 while (offset > aop->coff)
1338 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1340 while (offset < aop->coff)
1343 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1350 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1356 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1358 else if (strcmp (s, "r0") == 0 ||
1359 strcmp (s, "r1") == 0 ||
1360 strcmp (s, "r2") == 0 ||
1361 strcmp (s, "r3") == 0 ||
1362 strcmp (s, "r4") == 0 ||
1363 strcmp (s, "r5") == 0 ||
1364 strcmp (s, "r6") == 0 ||
1365 strcmp (s, "r7") == 0)
1368 sprintf (buffer, "a%s", s);
1369 emitcode ("mov", "@%s,%s",
1370 aop->aopu.aop_ptr->name, buffer);
1373 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1378 if (strcmp (s, "a") == 0)
1379 emitcode ("push", "acc");
1383 emitcode ("push", "acc");
1385 emitcode ("push", s);
1391 /* if bit variable */
1392 if (!aop->aopu.aop_dir)
1394 emitcode ("clr", "a");
1395 emitcode ("rlc", "a");
1400 emitcode ("clr", "%s", aop->aopu.aop_dir);
1402 emitcode ("setb", "%s", aop->aopu.aop_dir);
1403 else if (!strcmp (s, "c"))
1404 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1407 if (strcmp (s, "a"))
1412 /* set C, if a >= 1 */
1413 emitcode ("add", "a,#!constbyte",0xff);
1414 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1422 if (strcmp (aop->aopu.aop_str[offset], s))
1423 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1428 if (!offset && (strcmp (s, "acc") == 0))
1431 if (strcmp (aop->aopu.aop_str[offset], s))
1432 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1436 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1437 "aopPut got unsupported aop->type");
1444 /*--------------------------------------------------------------------*/
1445 /* reAdjustPreg - points a register back to where it should (coff==0) */
1446 /*--------------------------------------------------------------------*/
1448 reAdjustPreg (asmop * aop)
1450 if ((aop->coff==0) || (aop->size <= 1)) {
1459 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1463 if (aop->type == AOP_DPTR2)
1470 emitcode ("lcall", "__decdptr");
1473 if (aop->type == AOP_DPTR2)
1483 #define AOP(op) op->aop
1484 #define AOP_TYPE(op) AOP(op)->type
1485 #define AOP_SIZE(op) AOP(op)->size
1486 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1487 AOP_TYPE(x) == AOP_R0))
1489 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1490 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1493 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1494 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1495 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1496 #define AOP_INDPTRn(x) (AOP_TYPE(x) == AOP_DPTRn)
1497 #define AOP_USESDPTR(x) (AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_STR)
1499 /* Workaround for DS80C390 bug: div ab may return bogus results
1500 * if A is accessed in instruction immediately before the div.
1502 * Will be fixed in B4 rev of processor, Dallas claims.
1505 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1506 if (!AOP_NEEDSACC(RIGHT)) \
1508 /* We can load A first, then B, since \
1509 * B (the RIGHT operand) won't clobber A, \
1510 * thus avoiding touching A right before the div. \
1512 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1513 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1515 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1519 /* Just stuff in a nop after loading A. */ \
1520 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1521 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1523 emitcode("nop", "; workaround for DS80C390 div bug."); \
1526 /*-----------------------------------------------------------------*/
1527 /* genNotFloat - generates not for float operations */
1528 /*-----------------------------------------------------------------*/
1530 genNotFloat (operand * op, operand * res)
1536 D (emitcode (";", "genNotFloat ");
1539 /* we will put 127 in the first byte of
1541 aopPut (AOP (res), "#127", 0);
1542 size = AOP_SIZE (op) - 1;
1545 _startLazyDPSEvaluation ();
1546 l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE);
1551 emitcode ("orl", "a,%s",
1553 offset++, FALSE, FALSE, FALSE));
1555 _endLazyDPSEvaluation ();
1557 tlbl = newiTempLabel (NULL);
1558 aopPut (res->aop, one, 1);
1559 emitcode ("jz", "!tlabel", (tlbl->key + 100));
1560 aopPut (res->aop, zero, 1);
1561 emitcode ("", "!tlabeldef", (tlbl->key + 100));
1563 size = res->aop->size - 2;
1565 /* put zeros in the rest */
1567 aopPut (res->aop, zero, offset++);
1570 /*-----------------------------------------------------------------*/
1571 /* opIsGptr: returns non-zero if the passed operand is */
1572 /* a generic pointer type. */
1573 /*-----------------------------------------------------------------*/
1575 opIsGptr (operand * op)
1577 sym_link *type = operandType (op);
1579 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1586 /*-----------------------------------------------------------------*/
1587 /* getDataSize - get the operand data size */
1588 /*-----------------------------------------------------------------*/
1590 getDataSize (operand * op)
1593 size = AOP_SIZE (op);
1594 if (size == GPTRSIZE)
1596 sym_link *type = operandType (op);
1597 if (IS_GENPTR (type))
1599 /* generic pointer; arithmetic operations
1600 * should ignore the high byte (pointer type).
1608 /*-----------------------------------------------------------------*/
1609 /* outAcc - output Acc */
1610 /*-----------------------------------------------------------------*/
1612 outAcc (operand * result)
1615 size = getDataSize (result);
1618 aopPut (AOP (result), "a", 0);
1621 /* unsigned or positive */
1624 aopPut (AOP (result), zero, offset++);
1629 /*-----------------------------------------------------------------*/
1630 /* outBitC - output a bit C */
1631 /*-----------------------------------------------------------------*/
1633 outBitC (operand * result)
1635 /* if the result is bit */
1636 if (AOP_TYPE (result) == AOP_CRY)
1638 aopPut (AOP (result), "c", 0);
1642 emitcode ("clr", "a");
1643 emitcode ("rlc", "a");
1648 /*-----------------------------------------------------------------*/
1649 /* toBoolean - emit code for orl a,operator(sizeop) */
1650 /*-----------------------------------------------------------------*/
1652 toBoolean (operand * oper)
1654 int size = AOP_SIZE (oper) - 1;
1658 /* The generic part of a generic pointer should
1659 * not participate in it's truth value.
1661 * i.e. 0x10000000 is zero.
1663 if (opIsGptr (oper))
1665 D (emitcode (";", "toBoolean: generic ptr special case.");
1670 _startLazyDPSEvaluation ();
1671 if (AOP_NEEDSACC (oper) && size)
1674 emitcode ("push", "b");
1675 emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1679 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1685 emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1689 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1692 _endLazyDPSEvaluation ();
1696 emitcode ("mov", "a,b");
1697 emitcode ("pop", "b");
1702 /*-----------------------------------------------------------------*/
1703 /* genNot - generate code for ! operation */
1704 /*-----------------------------------------------------------------*/
1709 sym_link *optype = operandType (IC_LEFT (ic));
1711 D (emitcode (";", "genNot ");
1714 /* assign asmOps to operand & result */
1715 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1716 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1718 /* if in bit space then a special case */
1719 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1721 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1722 emitcode ("cpl", "c");
1723 outBitC (IC_RESULT (ic));
1727 /* if type float then do float */
1728 if (IS_FLOAT (optype))
1730 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1734 toBoolean (IC_LEFT (ic));
1736 tlbl = newiTempLabel (NULL);
1737 emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1738 emitcode ("", "!tlabeldef", tlbl->key + 100);
1739 outBitC (IC_RESULT (ic));
1742 /* release the aops */
1743 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1744 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1748 /*-----------------------------------------------------------------*/
1749 /* genCpl - generate code for complement */
1750 /*-----------------------------------------------------------------*/
1758 D (emitcode (";", "genCpl ");
1762 /* assign asmOps to operand & result */
1763 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1764 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1766 /* special case if in bit space */
1767 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1768 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1769 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1770 emitcode ("cpl", "c");
1771 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1774 tlbl=newiTempLabel(NULL);
1775 emitcode ("cjne", "%s,#0x01,%05d$",
1776 aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE,TRUE), tlbl->key+100);
1777 emitcode ("", "%05d$:", tlbl->key+100);
1778 outBitC (IC_RESULT(ic));
1782 size = AOP_SIZE (IC_RESULT (ic));
1783 _startLazyDPSEvaluation ();
1786 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1788 emitcode ("cpl", "a");
1789 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1791 _endLazyDPSEvaluation ();
1795 /* release the aops */
1796 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1797 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1800 /*-----------------------------------------------------------------*/
1801 /* genUminusFloat - unary minus for floating points */
1802 /*-----------------------------------------------------------------*/
1804 genUminusFloat (operand * op, operand * result)
1806 int size, offset = 0;
1808 /* for this we just need to flip the
1809 first it then copy the rest in place */
1810 D (emitcode (";", "genUminusFloat");
1813 _startLazyDPSEvaluation ();
1814 size = AOP_SIZE (op) - 1;
1815 l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1818 emitcode ("cpl", "acc.7");
1819 aopPut (AOP (result), "a", 3);
1823 aopPut (AOP (result),
1824 aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1828 _endLazyDPSEvaluation ();
1831 /*-----------------------------------------------------------------*/
1832 /* genUminus - unary minus code generation */
1833 /*-----------------------------------------------------------------*/
1835 genUminus (iCode * ic)
1838 sym_link *optype, *rtype;
1840 D (emitcode (";", "genUminus ");
1845 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1846 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1848 /* if both in bit space then special
1850 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1851 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1854 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1855 emitcode ("cpl", "c");
1856 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1860 optype = operandType (IC_LEFT (ic));
1861 rtype = operandType (IC_RESULT (ic));
1863 /* if float then do float stuff */
1864 if (IS_FLOAT (optype))
1866 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1870 /* otherwise subtract from zero */
1871 size = AOP_SIZE (IC_LEFT (ic));
1873 _startLazyDPSEvaluation ();
1876 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1877 if (!strcmp (l, "a"))
1881 emitcode ("cpl", "a");
1882 emitcode ("addc", "a,#0");
1888 emitcode ("clr", "a");
1889 emitcode ("subb", "a,%s", l);
1891 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1893 _endLazyDPSEvaluation ();
1895 /* if any remaining bytes in the result */
1896 /* we just need to propagate the sign */
1897 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1899 emitcode ("rlc", "a");
1900 emitcode ("subb", "a,acc");
1902 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1906 /* release the aops */
1907 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1908 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1911 /*-----------------------------------------------------------------*/
1912 /* savermask - saves registers in the mask */
1913 /*-----------------------------------------------------------------*/
1914 static void savermask(bitVect *rs_mask)
1917 if (options.useXstack) {
1918 if (bitVectBitValue (rs_mask, R0_IDX))
1919 emitcode ("mov", "b,r0");
1920 emitcode ("mov", "r0,%s", spname);
1921 for (i = 0; i < ds390_nRegs; i++) {
1922 if (bitVectBitValue (rs_mask, i)) {
1924 emitcode ("mov", "a,b");
1926 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1927 emitcode ("movx", "@r0,a");
1928 emitcode ("inc", "r0");
1931 emitcode ("mov", "%s,r0", spname);
1932 if (bitVectBitValue (rs_mask, R0_IDX))
1933 emitcode ("mov", "r0,b");
1935 for (i = 0; i < ds390_nRegs; i++) {
1936 if (bitVectBitValue (rs_mask, i))
1937 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
1942 /*-----------------------------------------------------------------*/
1943 /* saveRegisters - will look for a call and save the registers */
1944 /*-----------------------------------------------------------------*/
1946 saveRegisters (iCode * lic)
1952 for (ic = lic; ic; ic = ic->next)
1953 if (ic->op == CALL || ic->op == PCALL)
1958 fprintf (stderr, "found parameter push with no function call\n");
1962 /* if the registers have been saved already then
1964 if (ic->regsSaved || IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic)))) return ;
1966 /* special case if DPTR alive across a function call then must save it
1967 even though callee saves */
1968 if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
1970 rsave = newBitVect(ic->rMask->size);
1971 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
1972 if (bitVectBitValue(ic->rMask,i))
1973 rsave = bitVectSetBit(rsave,i);
1975 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
1977 /* safe the registers in use at this time but skip the
1978 ones for the result */
1979 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1980 ds390_rUmaskForOp (IC_RESULT(ic)));
1986 /*-----------------------------------------------------------------*/
1987 /* usavermask - restore registers with mask */
1988 /*-----------------------------------------------------------------*/
1989 static void unsavermask(bitVect *rs_mask)
1992 if (options.useXstack) {
1993 emitcode ("mov", "r0,%s", spname);
1994 for (i = ds390_nRegs; i >= 0; i--) {
1995 if (bitVectBitValue (rs_mask, i)) {
1996 emitcode ("dec", "r0");
1997 emitcode ("movx", "a,@r0");
1999 emitcode ("mov", "b,a");
2001 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
2004 emitcode ("mov", "%s,r0", spname);
2005 if (bitVectBitValue (rs_mask, R0_IDX))
2006 emitcode ("mov", "r0,b");
2008 for (i = ds390_nRegs; i >= 0; i--) {
2009 if (bitVectBitValue (rs_mask, i))
2010 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2015 /*-----------------------------------------------------------------*/
2016 /* unsaveRegisters - pop the pushed registers */
2017 /*-----------------------------------------------------------------*/
2019 unsaveRegisters (iCode * ic)
2023 if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2025 rsave = newBitVect(ic->rMask->size);
2026 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2027 if (bitVectBitValue(ic->rMask,i))
2028 rsave = bitVectSetBit(rsave,i);
2030 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2032 /* restore the registers in use at this time but skip the
2033 ones for the result */
2034 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2035 ds390_rUmaskForOp (IC_RESULT(ic)));
2041 /*-----------------------------------------------------------------*/
2043 /*-----------------------------------------------------------------*/
2045 pushSide (operand * oper, int size)
2048 _startLazyDPSEvaluation ();
2051 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
2052 if (AOP_TYPE (oper) != AOP_REG &&
2053 AOP_TYPE (oper) != AOP_DIR &&
2056 emitcode ("mov", "a,%s", l);
2057 emitcode ("push", "acc");
2060 emitcode ("push", "%s", l);
2062 _endLazyDPSEvaluation ();
2065 /*-----------------------------------------------------------------*/
2066 /* assignResultValue - */
2067 /*-----------------------------------------------------------------*/
2069 assignResultValue (operand * oper)
2072 int size = AOP_SIZE (oper);
2074 _startLazyDPSEvaluation ();
2077 aopPut (AOP (oper), fReturn[offset], offset);
2080 _endLazyDPSEvaluation ();
2084 /*-----------------------------------------------------------------*/
2085 /* genXpush - pushes onto the external stack */
2086 /*-----------------------------------------------------------------*/
2088 genXpush (iCode * ic)
2090 asmop *aop = newAsmop (0);
2092 int size, offset = 0;
2094 D (emitcode (";", "genXpush ");
2097 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2098 r = getFreePtr (ic, &aop, FALSE);
2101 emitcode ("mov", "%s,_spx", r->name);
2103 size = AOP_SIZE (IC_LEFT (ic));
2104 _startLazyDPSEvaluation ();
2108 char *l = aopGet (AOP (IC_LEFT (ic)),
2109 offset++, FALSE, FALSE, TRUE);
2111 emitcode ("movx", "@%s,a", r->name);
2112 emitcode ("inc", "%s", r->name);
2115 _endLazyDPSEvaluation ();
2118 emitcode ("mov", "_spx,%s", r->name);
2120 freeAsmop (NULL, aop, ic, TRUE);
2121 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2124 /*-----------------------------------------------------------------*/
2125 /* genIpush - genrate code for pushing this gets a little complex */
2126 /*-----------------------------------------------------------------*/
2128 genIpush (iCode * ic)
2130 int size, offset = 0;
2133 D (emitcode (";", "genIpush ");
2136 /* if this is not a parm push : ie. it is spill push
2137 and spill push is always done on the local stack */
2141 /* and the item is spilt then do nothing */
2142 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2145 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2146 size = AOP_SIZE (IC_LEFT (ic));
2147 /* push it on the stack */
2148 _startLazyDPSEvaluation ();
2151 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
2157 emitcode ("push", "%s", l);
2159 _endLazyDPSEvaluation ();
2163 /* this is a paramter push: in this case we call
2164 the routine to find the call and save those
2165 registers that need to be saved */
2168 /* if use external stack then call the external
2169 stack pushing routine */
2170 if (options.useXstack)
2176 /* then do the push */
2177 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2179 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2180 size = AOP_SIZE (IC_LEFT (ic));
2182 _startLazyDPSEvaluation ();
2185 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
2186 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2187 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2190 emitcode ("mov", "a,%s", l);
2191 emitcode ("push", "acc");
2194 emitcode ("push", "%s", l);
2196 _endLazyDPSEvaluation ();
2198 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2201 /*-----------------------------------------------------------------*/
2202 /* genIpop - recover the registers: can happen only for spilling */
2203 /*-----------------------------------------------------------------*/
2205 genIpop (iCode * ic)
2209 D (emitcode (";", "genIpop ");
2213 /* if the temp was not pushed then */
2214 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2217 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2218 size = AOP_SIZE (IC_LEFT (ic));
2219 offset = (size - 1);
2220 _startLazyDPSEvaluation ();
2223 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2224 FALSE, TRUE, TRUE));
2226 _endLazyDPSEvaluation ();
2228 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2231 /*-----------------------------------------------------------------*/
2232 /* unsaveRBank - restores the resgister bank from stack */
2233 /*-----------------------------------------------------------------*/
2235 unsaveRBank (int bank, iCode * ic, bool popPsw)
2241 if (options.useXstack)
2245 /* Assume r0 is available for use. */
2246 r = ds390_regWithIdx (R0_IDX);;
2251 r = getFreePtr (ic, &aop, FALSE);
2253 emitcode ("mov", "%s,_spx", r->name);
2258 if (options.useXstack)
2260 emitcode ("movx", "a,@%s", r->name);
2261 emitcode ("mov", "psw,a");
2262 emitcode ("dec", "%s", r->name);
2266 emitcode ("pop", "psw");
2270 for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2272 if (options.useXstack)
2274 emitcode ("movx", "a,@%s", r->name);
2275 emitcode ("mov", "(%s+%d),a",
2276 regs390[i].base, 8 * bank + regs390[i].offset);
2277 emitcode ("dec", "%s", r->name);
2281 emitcode ("pop", "(%s+%d)",
2282 regs390[i].base, 8 * bank + regs390[i].offset);
2285 if (options.useXstack)
2287 emitcode ("mov", "_spx,%s", r->name);
2292 freeAsmop (NULL, aop, ic, TRUE);
2296 /*-----------------------------------------------------------------*/
2297 /* saveRBank - saves an entire register bank on the stack */
2298 /*-----------------------------------------------------------------*/
2300 saveRBank (int bank, iCode * ic, bool pushPsw)
2306 if (options.useXstack)
2310 /* Assume r0 is available for use. */
2311 r = ds390_regWithIdx (R0_IDX);;
2316 r = getFreePtr (ic, &aop, FALSE);
2318 emitcode ("mov", "%s,_spx", r->name);
2321 for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2323 if (options.useXstack)
2325 emitcode ("inc", "%s", r->name);
2326 emitcode ("mov", "a,(%s+%d)",
2327 regs390[i].base, 8 * bank + regs390[i].offset);
2328 emitcode ("movx", "@%s,a", r->name);
2331 emitcode ("push", "(%s+%d)",
2332 regs390[i].base, 8 * bank + regs390[i].offset);
2337 if (options.useXstack)
2339 emitcode ("mov", "a,psw");
2340 emitcode ("movx", "@%s,a", r->name);
2341 emitcode ("inc", "%s", r->name);
2342 emitcode ("mov", "_spx,%s", r->name);
2346 emitcode ("push", "psw");
2349 emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2354 freeAsmop (NULL, aop, ic, TRUE);
2363 /*-----------------------------------------------------------------*/
2364 /* genSend - gen code for SEND */
2365 /*-----------------------------------------------------------------*/
2366 static void genSend(set *sendSet)
2370 static int rb1_count = 0;
2372 for (sic = setFirstItem (sendSet); sic;
2373 sic = setNextItem (sendSet)) {
2374 int size, offset = 0;
2376 size=getSize(operandType(IC_LEFT(sic)));
2377 D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2378 if (sendCount == 0) { /* first parameter */
2379 // we know that dpl(hxb) is the result, so
2381 _startLazyDPSEvaluation ();
2383 aopOp (IC_LEFT (sic), sic, FALSE,
2384 (IS_SYMOP(IC_LEFT(sic)) && OP_SYMBOL(IC_LEFT(sic))->ruonly ? FALSE : TRUE));
2386 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2389 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2390 FALSE, FALSE, TRUE);
2391 if (strcmp (l, fReturn[offset])) {
2392 emitcode ("mov", "%s,%s",
2398 _endLazyDPSEvaluation ();
2399 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2401 } else { /* if more parameter in registers */
2402 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2404 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
2405 FALSE, FALSE, TRUE));
2407 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2413 /*-----------------------------------------------------------------*/
2414 /* genCall - generates a call statement */
2415 /*-----------------------------------------------------------------*/
2417 genCall (iCode * ic)
2420 bool restoreBank = FALSE;
2421 bool swapBanks = FALSE;
2423 D (emitcode (";", "genCall "););
2425 /* if we are calling a not _naked function that is not using
2426 the same register bank then we need to save the
2427 destination registers on the stack */
2428 dtype = operandType (IC_LEFT (ic));
2429 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2430 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2431 IFFUNC_ISISR (currFunc->type))
2435 /* This is unexpected; the bank should have been saved in
2438 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2444 /* if caller saves & we have not saved then */
2448 /* if send set is not empty the assign */
2449 /* We've saved all the registers we care about;
2450 * therefore, we may clobber any register not used
2451 * in the calling convention (i.e. anything not in
2456 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2457 genSend(reverseSet(_G.sendSet));
2459 genSend(_G.sendSet);
2466 emitcode ("mov", "psw,#!constbyte",
2467 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2471 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2472 OP_SYMBOL (IC_LEFT (ic))->rname :
2473 OP_SYMBOL (IC_LEFT (ic))->name));
2477 emitcode ("mov", "psw,#!constbyte",
2478 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2481 /* if we need assign a result value */
2482 if ((IS_ITEMP (IC_RESULT (ic)) &&
2483 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2484 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2485 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2486 IS_TRUE_SYMOP (IC_RESULT (ic)))
2488 if (isOperandInFarSpace (IC_RESULT (ic))
2489 && getSize (operandType (IC_RESULT (ic))) <= 2)
2491 int size = getSize (operandType (IC_RESULT (ic)));
2493 /* Special case for 1 or 2 byte return in far space. */
2497 emitcode ("mov", "b,%s", fReturn[1]);
2500 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2501 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2505 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2507 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2512 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2515 assignResultValue (IC_RESULT (ic));
2517 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2521 /* adjust the stack for parameters if
2523 if (ic->parmBytes) {
2525 if (options.stack10bit) {
2526 if (ic->parmBytes <= 10) {
2527 emitcode(";","stack adjustment for parms");
2528 for (i=0; i < ic->parmBytes ; i++) {
2529 emitcode("pop","acc");
2533 emitcode ("clr","c");
2534 emitcode ("mov","a,sp");
2535 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2536 emitcode ("mov","sp,a");
2537 emitcode ("mov","a,esp");
2538 emitcode ("anl","a,#3");
2539 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2540 emitcode ("mov","esp,a");
2544 if (ic->parmBytes > 3) {
2545 emitcode ("mov", "a,%s", spname);
2546 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2547 emitcode ("mov", "%s,a", spname);
2549 for (i = 0; i < ic->parmBytes; i++)
2550 emitcode ("dec", "%s", spname);
2554 /* if we hade saved some registers then unsave them */
2556 unsaveRegisters (ic);
2558 /* if register bank was saved then pop them */
2560 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2563 /*-----------------------------------------------------------------*/
2564 /* genPcall - generates a call by pointer statement */
2565 /*-----------------------------------------------------------------*/
2567 genPcall (iCode * ic)
2570 symbol *rlbl = newiTempLabel (NULL);
2571 bool restoreBank=FALSE;
2573 D (emitcode (";", "genPcall ");
2577 /* if caller saves & we have not saved then */
2581 /* if we are calling a function that is not using
2582 the same register bank then we need to save the
2583 destination registers on the stack */
2584 dtype = operandType (IC_LEFT (ic));
2585 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2586 IFFUNC_ISISR (currFunc->type) &&
2587 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2588 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2592 /* push the return address on to the stack */
2593 emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2594 emitcode ("push", "acc");
2595 emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2596 emitcode ("push", "acc");
2598 if (options.model == MODEL_FLAT24)
2600 emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2601 emitcode ("push", "acc");
2604 /* now push the calling address */
2605 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2607 pushSide (IC_LEFT (ic), FPTRSIZE);
2609 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2611 /* if send set is not empty the assign */
2614 genSend(reverseSet(_G.sendSet));
2618 emitcode ("ret", "");
2619 emitcode ("", "!tlabeldef", (rlbl->key + 100));
2622 /* if we need assign a result value */
2623 if ((IS_ITEMP (IC_RESULT (ic)) &&
2624 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2625 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2626 IS_TRUE_SYMOP (IC_RESULT (ic)))
2630 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2633 assignResultValue (IC_RESULT (ic));
2635 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2638 /* adjust the stack for parameters if
2643 if (options.stack10bit) {
2644 if (ic->parmBytes <= 10) {
2645 emitcode(";","stack adjustment for parms");
2646 for (i=0; i < ic->parmBytes ; i++) {
2647 emitcode("pop","acc");
2651 emitcode ("clr","c");
2652 emitcode ("mov","a,sp");
2653 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2654 emitcode ("mov","sp,a");
2655 emitcode ("mov","a,esp");
2656 emitcode ("anl","a,#3");
2657 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2658 emitcode ("mov","esp,a");
2662 if (ic->parmBytes > 3) {
2663 emitcode ("mov", "a,%s", spname);
2664 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2665 emitcode ("mov", "%s,a", spname);
2668 for (i = 0; i < ic->parmBytes; i++)
2669 emitcode ("dec", "%s", spname);
2673 /* if register bank was saved then unsave them */
2675 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2677 /* if we hade saved some registers then
2680 unsaveRegisters (ic);
2684 /*-----------------------------------------------------------------*/
2685 /* resultRemat - result is rematerializable */
2686 /*-----------------------------------------------------------------*/
2688 resultRemat (iCode * ic)
2690 if (SKIP_IC (ic) || ic->op == IFX)
2693 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2695 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2696 if (sym->remat && !POINTER_SET (ic))
2703 #if defined(__BORLANDC__) || defined(_MSC_VER)
2704 #define STRCASECMP stricmp
2706 #define STRCASECMP strcasecmp
2709 /*-----------------------------------------------------------------*/
2710 /* inExcludeList - return 1 if the string is in exclude Reg list */
2711 /*-----------------------------------------------------------------*/
2713 inExcludeList (char *s)
2717 if (options.excludeRegs[i] &&
2718 STRCASECMP (options.excludeRegs[i], "none") == 0)
2721 for (i = 0; options.excludeRegs[i]; i++)
2723 if (options.excludeRegs[i] &&
2724 STRCASECMP (s, options.excludeRegs[i]) == 0)
2730 /*-----------------------------------------------------------------*/
2731 /* genFunction - generated code for function entry */
2732 /*-----------------------------------------------------------------*/
2734 genFunction (iCode * ic)
2738 bool switchedPSW = FALSE;
2740 D (emitcode (";", "genFunction "););
2743 /* create the function header */
2744 emitcode (";", "-----------------------------------------");
2745 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2746 emitcode (";", "-----------------------------------------");
2748 emitcode ("", "%s:", sym->rname);
2749 ftype = operandType (IC_LEFT (ic));
2751 if (IFFUNC_ISNAKED(ftype))
2753 emitcode(";", "naked function: no prologue.");
2757 if (options.stack_probe)
2758 emitcode ("lcall","__stack_probe");
2759 /* if critical function then turn interrupts off */
2760 if (IFFUNC_ISCRITICAL (ftype))
2761 emitcode ("clr", "ea");
2763 /* here we need to generate the equates for the
2764 register bank if required */
2765 if (FUNC_REGBANK (ftype) != rbank)
2769 rbank = FUNC_REGBANK (ftype);
2770 for (i = 0; i < ds390_nRegs; i++)
2772 if (regs390[i].print) {
2773 if (strcmp (regs390[i].base, "0") == 0)
2774 emitcode ("", "%s !equ !constbyte",
2776 8 * rbank + regs390[i].offset);
2778 emitcode ("", "%s !equ %s + !constbyte",
2781 8 * rbank + regs390[i].offset);
2786 /* if this is an interrupt service routine then
2787 save acc, b, dpl, dph */
2788 if (IFFUNC_ISISR (sym->type))
2790 if (!inExcludeList ("acc"))
2791 emitcode ("push", "acc");
2792 if (!inExcludeList ("b"))
2793 emitcode ("push", "b");
2794 if (!inExcludeList ("dpl"))
2795 emitcode ("push", "dpl");
2796 if (!inExcludeList ("dph"))
2797 emitcode ("push", "dph");
2798 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2800 emitcode ("push", "dpx");
2801 /* Make sure we're using standard DPTR */
2802 emitcode ("push", "dps");
2803 emitcode ("mov", "dps,#0");
2804 if (options.stack10bit)
2806 /* This ISR could conceivably use DPTR2. Better save it. */
2807 emitcode ("push", "dpl1");
2808 emitcode ("push", "dph1");
2809 emitcode ("push", "dpx1");
2810 emitcode ("push", DP2_RESULT_REG);
2813 /* if this isr has no bank i.e. is going to
2814 run with bank 0 , then we need to save more
2816 if (!FUNC_REGBANK (sym->type))
2820 /* if this function does not call any other
2821 function then we can be economical and
2822 save only those registers that are used */
2823 if (!IFFUNC_HASFCALL(sym->type))
2826 /* if any registers used */
2829 /* save the registers used */
2830 for (i = 0; i < sym->regsUsed->size; i++)
2832 if (bitVectBitValue (sym->regsUsed, i) ||
2833 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2834 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2841 /* this function has a function call cannot
2842 determines register usage so we will have to push the
2844 saveRBank (0, ic, FALSE);
2845 if (options.parms_in_bank1) {
2846 for (i=0; i < 8 ; i++ ) {
2847 emitcode ("push","%s",rb1regs[i]);
2854 /* This ISR uses a non-zero bank.
2856 * We assume that the bank is available for our
2859 * However, if this ISR calls a function which uses some
2860 * other bank, we must save that bank entirely.
2862 unsigned long banksToSave = 0;
2864 if (IFFUNC_HASFCALL(sym->type))
2867 #define MAX_REGISTER_BANKS 4
2872 for (i = ic; i; i = i->next)
2874 if (i->op == ENDFUNCTION)
2876 /* we got to the end OK. */
2884 dtype = operandType (IC_LEFT(i));
2886 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2888 /* Mark this bank for saving. */
2889 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2891 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2895 banksToSave |= (1 << FUNC_REGBANK(dtype));
2898 /* And note that we don't need to do it in
2906 /* This is a mess; we have no idea what
2907 * register bank the called function might
2910 * The only thing I can think of to do is
2911 * throw a warning and hope.
2913 werror(W_FUNCPTR_IN_USING_ISR);
2917 if (banksToSave && options.useXstack)
2919 /* Since we aren't passing it an ic,
2920 * saveRBank will assume r0 is available to abuse.
2922 * So switch to our (trashable) bank now, so
2923 * the caller's R0 isn't trashed.
2925 emitcode ("push", "psw");
2926 emitcode ("mov", "psw,#!constbyte",
2927 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2931 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2933 if (banksToSave & (1 << ix))
2935 saveRBank(ix, NULL, FALSE);
2939 // jwk: this needs a closer look
2940 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2945 /* if callee-save to be used for this function
2946 then save the registers being used in this function */
2947 if (IFFUNC_CALLEESAVES(sym->type))
2951 /* if any registers used */
2954 /* save the registers used */
2955 for (i = 0; i < sym->regsUsed->size; i++)
2957 if (bitVectBitValue (sym->regsUsed, i) ||
2958 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2960 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2968 /* set the register bank to the desired value */
2969 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
2972 emitcode ("push", "psw");
2973 emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2976 if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
2977 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
2978 if (options.stack10bit) {
2979 emitcode ("push","_bpx");
2980 emitcode ("push","_bpx+1");
2981 emitcode ("mov","_bpx,%s",spname);
2982 emitcode ("mov","_bpx+1,esp");
2983 emitcode ("anl","_bpx+1,#3");
2985 if (options.useXstack) {
2986 emitcode ("mov", "r0,%s", spname);
2987 emitcode ("mov", "a,_bp");
2988 emitcode ("movx", "@r0,a");
2989 emitcode ("inc", "%s", spname);
2991 /* set up the stack */
2992 emitcode ("push", "_bp"); /* save the callers stack */
2994 emitcode ("mov", "_bp,%s", spname);
2998 /* adjust the stack for the function */
3001 if (options.stack10bit) {
3002 if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
3003 assert (sym->recvSize <= 4);
3004 if (sym->stack <= 8) {
3005 while (i--) emitcode ("push","acc");
3008 emitcode ("mov","a,sp");
3009 emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3010 emitcode ("mov","sp,a");
3011 emitcode ("mov","a,esp");
3012 emitcode ("anl","a,#3");
3013 emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3014 emitcode ("mov","esp,a");
3019 werror (W_STACK_OVERFLOW, sym->name);
3021 if (i > 3 && sym->recvSize < 4) {
3023 emitcode ("mov", "a,sp");
3024 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3025 emitcode ("mov", "sp,a");
3029 emitcode ("inc", "sp");
3036 emitcode ("mov", "a,_spx");
3037 emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3038 emitcode ("mov", "_spx,a");
3043 /*-----------------------------------------------------------------*/
3044 /* genEndFunction - generates epilogue for functions */
3045 /*-----------------------------------------------------------------*/
3047 genEndFunction (iCode * ic)
3049 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3051 D (emitcode (";", "genEndFunction "););
3053 if (IFFUNC_ISNAKED(sym->type))
3055 emitcode(";", "naked function: no epilogue.");
3059 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3060 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3062 if (options.stack10bit) {
3064 emitcode ("mov", "sp,_bpx", spname);
3065 emitcode ("mov", "esp,_bpx+1", spname);
3068 emitcode ("mov", "%s,_bp", spname);
3072 /* if use external stack but some variables were
3073 added to the local stack then decrement the
3075 if (options.useXstack && sym->stack) {
3076 emitcode ("mov", "a,sp");
3077 emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3078 emitcode ("mov", "sp,a");
3082 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3083 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3085 if (options.useXstack) {
3086 emitcode ("mov", "r0,%s", spname);
3087 emitcode ("movx", "a,@r0");
3088 emitcode ("mov", "_bp,a");
3089 emitcode ("dec", "%s", spname);
3091 if (options.stack10bit) {
3092 emitcode ("pop", "_bpx+1");
3093 emitcode ("pop", "_bpx");
3095 emitcode ("pop", "_bp");
3100 /* restore the register bank */
3101 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3103 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3104 || !options.useXstack)
3106 /* Special case of ISR using non-zero bank with useXstack
3109 emitcode ("pop", "psw");
3113 if (IFFUNC_ISISR (sym->type))
3116 /* now we need to restore the registers */
3117 /* if this isr has no bank i.e. is going to
3118 run with bank 0 , then we need to save more
3120 if (!FUNC_REGBANK (sym->type))
3123 /* if this function does not call any other
3124 function then we can be economical and
3125 save only those registers that are used */
3126 if (!IFFUNC_HASFCALL(sym->type))
3129 /* if any registers used */
3132 /* save the registers used */
3133 for (i = sym->regsUsed->size; i >= 0; i--)
3135 if (bitVectBitValue (sym->regsUsed, i) ||
3136 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3137 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3144 /* this function has a function call cannot
3145 determines register usage so we will have to pop the
3147 if (options.parms_in_bank1) {
3148 for (i = 7 ; i >= 0 ; i-- ) {
3149 emitcode ("pop","%s",rb1regs[i]);
3152 unsaveRBank (0, ic, FALSE);
3157 /* This ISR uses a non-zero bank.
3159 * Restore any register banks saved by genFunction
3162 // jwk: this needs a closer look
3163 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3166 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3168 if (savedBanks & (1 << ix))
3170 unsaveRBank(ix, NULL, FALSE);
3174 if (options.useXstack)
3176 /* Restore bank AFTER calling unsaveRBank,
3177 * since it can trash r0.
3179 emitcode ("pop", "psw");
3183 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3185 if (options.stack10bit)
3187 emitcode ("pop", DP2_RESULT_REG);
3188 emitcode ("pop", "dpx1");
3189 emitcode ("pop", "dph1");
3190 emitcode ("pop", "dpl1");
3192 emitcode ("pop", "dps");
3193 emitcode ("pop", "dpx");
3195 if (!inExcludeList ("dph"))
3196 emitcode ("pop", "dph");
3197 if (!inExcludeList ("dpl"))
3198 emitcode ("pop", "dpl");
3199 if (!inExcludeList ("b"))
3200 emitcode ("pop", "b");
3201 if (!inExcludeList ("acc"))
3202 emitcode ("pop", "acc");
3204 if (IFFUNC_ISCRITICAL (sym->type))
3205 emitcode ("setb", "ea");
3207 /* if debug then send end of function */
3208 if (options.debug && currFunc) {
3210 emitcode ("", "C$%s$%d$%d$%d ==.",
3211 FileBaseName (ic->filename), currFunc->lastLine,
3212 ic->level, ic->block);
3213 if (IS_STATIC (currFunc->etype))
3214 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3216 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3220 emitcode ("reti", "");
3224 if (IFFUNC_ISCRITICAL (sym->type))
3225 emitcode ("setb", "ea");
3227 if (IFFUNC_CALLEESAVES(sym->type))
3231 /* if any registers used */
3234 /* save the registers used */
3235 for (i = sym->regsUsed->size; i >= 0; i--)
3237 if (bitVectBitValue (sym->regsUsed, i) ||
3238 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3239 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3245 /* if debug then send end of function */
3246 if (options.debug && currFunc)
3249 emitcode ("", "C$%s$%d$%d$%d ==.",
3250 FileBaseName (ic->filename), currFunc->lastLine,
3251 ic->level, ic->block);
3252 if (IS_STATIC (currFunc->etype))
3253 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3255 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3259 emitcode ("ret", "");
3264 /*-----------------------------------------------------------------*/
3265 /* genJavaNativeRet - generate code for return JavaNative */
3266 /*-----------------------------------------------------------------*/
3267 static void genJavaNativeRet(iCode *ic)
3271 aopOp (IC_LEFT (ic), ic, FALSE,
3272 (IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly ? FALSE :TRUE));
3273 size = AOP_SIZE (IC_LEFT (ic));
3277 /* it is assigned to GPR0-R3 then push them */
3278 if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3279 aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3280 for (i = 0 ; i < size ; i++ ) {
3281 emitcode ("push","%s",aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,FALSE));
3283 for (i = (size-1) ; i >= 0 ; i--) {
3284 emitcode ("pop","a%s",javaRet[i]);
3287 for (i = 0 ; i < size ; i++)
3288 emitcode ("mov","%s,%s",javaRet[i],aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,FALSE));
3290 for (i = size ; i < 4 ; i++ )
3291 emitcode ("mov","%s,#0",javaRet[i]);
3295 /*-----------------------------------------------------------------*/
3296 /* genRet - generate code for return statement */
3297 /*-----------------------------------------------------------------*/
3301 int size, offset = 0, pushed = 0;
3303 D (emitcode (";", "genRet ");
3306 /* if we have no return value then
3307 just generate the "ret" */
3311 /* if this is a JavaNative function then return
3312 value in different register */
3313 if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3314 genJavaNativeRet(ic);
3317 /* we have something to return then
3318 move the return value into place */
3319 aopOp (IC_LEFT (ic), ic, FALSE,
3320 (IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly ? FALSE :TRUE));
3321 size = AOP_SIZE (IC_LEFT (ic));
3323 _startLazyDPSEvaluation ();
3327 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3329 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3330 FALSE, TRUE, FALSE);
3331 emitcode ("push", "%s", l);
3336 /* Since A is the last element of fReturn,
3337 * is is OK to clobber it in the aopGet.
3339 l = aopGet (AOP (IC_LEFT (ic)), offset,
3340 FALSE, FALSE, TRUE);
3341 if (strcmp (fReturn[offset], l))
3342 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3345 _endLazyDPSEvaluation ();
3352 if (strcmp (fReturn[pushed], "a"))
3353 emitcode ("pop", fReturn[pushed]);
3355 emitcode ("pop", "acc");
3358 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3361 /* generate a jump to the return label
3362 if the next is not the return statement */
3363 if (!(ic->next && ic->next->op == LABEL &&
3364 IC_LABEL (ic->next) == returnLabel))
3366 emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3370 /*-----------------------------------------------------------------*/
3371 /* genLabel - generates a label */
3372 /*-----------------------------------------------------------------*/
3374 genLabel (iCode * ic)
3376 /* special case never generate */
3377 if (IC_LABEL (ic) == entryLabel)
3380 D (emitcode (";", "genLabel ");
3383 emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3386 /*-----------------------------------------------------------------*/
3387 /* genGoto - generates a ljmp */
3388 /*-----------------------------------------------------------------*/
3390 genGoto (iCode * ic)
3392 D (emitcode (";", "genGoto ");
3394 emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3397 /*-----------------------------------------------------------------*/
3398 /* findLabelBackwards: walks back through the iCode chain looking */
3399 /* for the given label. Returns number of iCode instructions */
3400 /* between that label and given ic. */
3401 /* Returns zero if label not found. */
3402 /*-----------------------------------------------------------------*/
3404 findLabelBackwards (iCode * ic, int key)
3413 /* If we have any pushes or pops, we cannot predict the distance.
3414 I don't like this at all, this should be dealt with in the
3416 if (ic->op == IPUSH || ic->op == IPOP) {
3420 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3422 /* printf("findLabelBackwards = %d\n", count); */
3430 /*-----------------------------------------------------------------*/
3431 /* genPlusIncr :- does addition with increment if possible */
3432 /*-----------------------------------------------------------------*/
3434 genPlusIncr (iCode * ic)
3436 unsigned int icount;
3437 unsigned int size = getDataSize (IC_RESULT (ic));
3439 /* will try to generate an increment */
3440 /* if the right side is not a literal
3442 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3445 /* if the literal value of the right hand side
3446 is greater than 4 then it is not worth it */
3447 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3450 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3451 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3453 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
3457 /* if increment 16 bits in register */
3459 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3460 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3461 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3469 /* If the next instruction is a goto and the goto target
3470 * is <= 5 instructions previous to this, we can generate
3471 * jumps straight to that target.
3473 if (ic->next && ic->next->op == GOTO
3474 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3477 emitcode (";", "tail increment optimized (range %d)", labelRange);
3478 tlbl = IC_LABEL (ic->next);
3483 tlbl = newiTempLabel (NULL);
3486 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3487 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3488 IS_AOP_PREG (IC_RESULT (ic)))
3489 emitcode ("cjne", "%s,#0,!tlabel"
3490 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3494 emitcode ("clr", "a");
3495 emitcode ("cjne", "a,%s,!tlabel"
3496 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3500 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3503 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3504 IS_AOP_PREG (IC_RESULT (ic)))
3505 emitcode ("cjne", "%s,#0,!tlabel"
3506 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3509 emitcode ("cjne", "a,%s,!tlabel"
3510 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3513 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3517 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3518 IS_AOP_PREG (IC_RESULT (ic)))
3519 emitcode ("cjne", "%s,#0,!tlabel"
3520 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3524 emitcode ("cjne", "a,%s,!tlabel"
3525 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3528 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3533 emitcode ("", "!tlabeldef", tlbl->key + 100);
3538 if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3539 !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 &&
3540 options.model == MODEL_FLAT24 ) {
3544 emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, FALSE));
3546 emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, FALSE));
3548 emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3551 while (icount--) emitcode ("inc","dptr");
3555 if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3556 AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3558 emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3559 while (icount--) emitcode ("inc","dptr");
3560 emitcode ("mov","dps,#0");
3564 /* if the sizes are greater than 1 then we cannot */
3565 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3566 AOP_SIZE (IC_LEFT (ic)) > 1)
3569 /* we can if the aops of the left & result match or
3570 if they are in registers and the registers are the
3573 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3574 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3575 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3580 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3581 emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3582 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3587 _startLazyDPSEvaluation ();
3590 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3592 _endLazyDPSEvaluation ();
3601 /*-----------------------------------------------------------------*/
3602 /* outBitAcc - output a bit in acc */
3603 /*-----------------------------------------------------------------*/
3605 outBitAcc (operand * result)
3607 symbol *tlbl = newiTempLabel (NULL);
3608 /* if the result is a bit */
3609 if (AOP_TYPE (result) == AOP_CRY)
3611 aopPut (AOP (result), "a", 0);
3615 emitcode ("jz", "!tlabel", tlbl->key + 100);
3616 emitcode ("mov", "a,%s", one);
3617 emitcode ("", "!tlabeldef", tlbl->key + 100);
3622 /*-----------------------------------------------------------------*/
3623 /* genPlusBits - generates code for addition of two bits */
3624 /*-----------------------------------------------------------------*/
3626 genPlusBits (iCode * ic)
3628 D (emitcode (";", "genPlusBits ");
3630 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3632 symbol *lbl = newiTempLabel (NULL);
3633 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3634 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3635 emitcode ("cpl", "c");
3636 emitcode ("", "!tlabeldef", (lbl->key + 100));
3637 outBitC (IC_RESULT (ic));
3641 emitcode ("clr", "a");
3642 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3643 emitcode ("rlc", "a");
3644 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3645 emitcode ("addc", "a,#0");
3646 outAcc (IC_RESULT (ic));
3651 adjustArithmeticResult (iCode * ic)
3653 if (opIsGptr (IC_RESULT (ic)) &&
3654 opIsGptr (IC_LEFT (ic)) &&
3655 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3657 aopPut (AOP (IC_RESULT (ic)),
3658 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3662 if (opIsGptr (IC_RESULT (ic)) &&
3663 opIsGptr (IC_RIGHT (ic)) &&
3664 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3666 aopPut (AOP (IC_RESULT (ic)),
3667 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3671 if (opIsGptr (IC_RESULT (ic)) &&
3672 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3673 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3674 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3675 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3678 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3679 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3683 #ifdef KEVIN_SCREWED_UP
3684 // Macro to aopOp all three operands of an ic. If this cannot be done,
3685 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3686 // will be set TRUE. The caller must then handle the case specially, noting
3687 // that the IC_RESULT operand is not aopOp'd.
3688 #define AOP_OP_3_NOFATAL(ic, rc) \
3689 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3690 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR) || \
3691 ((OP_SYMBOL(IC_RESULT(ic))->ruonly) && !isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)))); \
3692 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3693 (isOperandInFarSpace(IC_RESULT(ic)) || (OP_SYMBOL(IC_RESULT(ic))->ruonly && !isOperandEqual(IC_LEFT(ic),IC_RESULT(ic))))) \
3695 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3700 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3701 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3703 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3704 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3706 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3708 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3712 // aopOp the left & right operands of an ic.
3713 #define AOP_OP_2(ic) \
3714 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3715 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3717 #else // Kevin didn't screw up...
3719 #define AOP_IS_STR(x) (IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
3721 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
3722 // generates the result if possible. If result is generated, returns TRUE; otherwise
3723 // returns false and caller must deal with fact that result isn't aopOp'd.
3724 bool aopOp3(iCode * ic)
3726 bool dp1InUse, dp2InUse;
3728 // First, generate the right opcode. DPTR may be used if neither left nor result are
3731 // D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
3732 // AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
3733 // AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
3734 // AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
3737 aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)));
3739 // Now, the left opcode. This can use DPTR if the right didn't AND the result is not
3740 // AOP_STR (however, if the result is the same operand as the left, then DPTR may be used).
3741 aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)) ||
3742 (AOP_IS_STR(IC_RESULT(ic)) && !isOperandEqual(IC_LEFT(ic),IC_RESULT(ic))));
3744 // We've op'd the left. So, if left & result are the same operand, we know aopOp
3745 // will succeed, and we can just do it & bail.
3746 if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)))
3748 // D(emitcode(";", "aopOp3: left & result equal"););
3749 aopOp(IC_RESULT(ic),ic,TRUE, FALSE);
3753 // Note which dptrs are currently in use.
3754 dp1InUse = (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR) || (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) ||
3755 AOP_IS_STR(IC_RIGHT(ic)) || AOP_IS_STR(IC_LEFT(ic));
3756 dp2InUse = (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR2) || (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2);
3758 // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot generate it.
3759 if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
3764 // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck
3765 if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
3770 aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
3772 // SOme sanity checking...
3773 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 &&
3774 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2)
3777 "Ack: got unexpected DP2! (%s:%d %s:%d)\n",
3778 __FILE__, __LINE__, ic->filename, ic->lineno);
3784 // Macro to aopOp all three operands of an ic. If this cannot be done,
3785 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3786 // will be set TRUE. The caller must then handle the case specially, noting
3787 // that the IC_RESULT operand is not aopOp'd.
3789 #define AOP_OP_3_NOFATAL(ic, rc) \
3790 do { rc = !aopOp3(ic); } while (0)
3792 // aopOp the left & right operands of an ic.
3793 #define AOP_OP_2(ic) \
3794 aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
3795 aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
3799 // convienience macro.
3800 #define AOP_SET_LOCALS(ic) \
3801 left = IC_LEFT(ic); \
3802 right = IC_RIGHT(ic); \
3803 result = IC_RESULT(ic);
3806 // Given an integer value of pushedSize bytes on the stack,
3807 // adjust it to be resultSize bytes, either by discarding
3808 // the most significant bytes or by zero-padding.
3810 // On exit from this macro, pushedSize will have been adjusted to
3811 // equal resultSize, and ACC may be trashed.
3812 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3813 /* If the pushed data is bigger than the result, \
3814 * simply discard unused bytes. Icky, but works. \
3816 while (pushedSize > resultSize) \
3818 D (emitcode (";", "discarding unused result byte."););\
3819 emitcode ("pop", "acc"); \
3822 if (pushedSize < resultSize) \
3824 emitcode ("clr", "a"); \
3825 /* Conversly, we haven't pushed enough here. \
3826 * just zero-pad, and all is well. \
3828 while (pushedSize < resultSize) \
3830 emitcode("push", "acc"); \
3834 assert(pushedSize == resultSize);
3836 /*-----------------------------------------------------------------*/
3837 /* genPlus - generates code for addition */
3838 /*-----------------------------------------------------------------*/
3840 genPlus (iCode * ic)
3842 int size, offset = 0;
3843 bool pushResult = FALSE;
3846 D (emitcode (";", "genPlus "););
3848 /* special cases :- */
3849 if ( IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly &&
3850 isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
3851 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
3852 size = floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
3854 while (size--) emitcode ("inc","dptr");
3856 emitcode ("mov","a,dpl");
3857 emitcode ("add","a,#!constbyte",size & 0xff);
3858 emitcode ("mov","dpl,a");
3859 emitcode ("mov","a,dph");
3860 emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
3861 emitcode ("mov","dph,a");
3862 emitcode ("mov","a,dpx");
3863 emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
3864 emitcode ("mov","dpx,a");
3866 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
3869 if ( IS_SYMOP(IC_LEFT(ic)) &&
3870 OP_SYMBOL(IC_LEFT(ic))->remat &&
3871 isOperandInFarSpace(IC_RIGHT(ic))) {
3872 operand *op = IC_RIGHT(ic);
3873 IC_RIGHT(ic) = IC_LEFT(ic);
3877 AOP_OP_3_NOFATAL (ic, pushResult);
3880 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3885 /* if literal, literal on the right or
3886 if left requires ACC or right is already
3888 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3889 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3890 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3892 operand *t = IC_RIGHT (ic);
3893 IC_RIGHT (ic) = IC_LEFT (ic);
3895 emitcode (";", "Swapped plus args.");
3898 /* if both left & right are in bit
3900 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3901 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3907 /* if left in bit space & right literal */
3908 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3909 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3911 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3912 /* if result in bit space */
3913 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3915 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3916 emitcode ("cpl", "c");
3917 outBitC (IC_RESULT (ic));
3921 size = getDataSize (IC_RESULT (ic));
3922 _startLazyDPSEvaluation ();
3925 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3926 emitcode ("addc", "a,#0");
3927 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3929 _endLazyDPSEvaluation ();
3934 /* if I can do an increment instead
3935 of add then GOOD for ME */
3936 if (genPlusIncr (ic) == TRUE)
3938 emitcode (";", "did genPlusIncr");
3943 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3945 _startLazyDPSEvaluation ();
3948 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3950 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3952 emitcode ("add", "a,%s",
3953 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3955 emitcode ("addc", "a,%s",
3956 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3960 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3962 /* right is going to use ACC or we would have taken the
3965 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3967 D(emitcode(";", "+ AOP_ACC special case."););
3968 emitcode("xch", "a, %s", DP2_RESULT_REG);
3970 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3973 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3976 emitcode("add", "a, %s", DP2_RESULT_REG);
3980 emitcode ("add", "a,%s",
3981 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
3986 emitcode ("addc", "a,%s",
3987 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3992 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3996 emitcode ("push", "acc");
4000 _endLazyDPSEvaluation ();
4004 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4006 size = getDataSize (IC_LEFT (ic));
4007 rSize = getDataSize (IC_RESULT (ic));
4009 ADJUST_PUSHED_RESULT(size, rSize);
4011 _startLazyDPSEvaluation ();
4014 emitcode ("pop", "acc");
4015 aopPut (AOP (IC_RESULT (ic)), "a", size);
4017 _endLazyDPSEvaluation ();
4020 adjustArithmeticResult (ic);
4023 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4024 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4025 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4028 /*-----------------------------------------------------------------*/
4029 /* genMinusDec :- does subtraction with deccrement if possible */
4030 /*-----------------------------------------------------------------*/
4032 genMinusDec (iCode * ic)
4034 unsigned int icount;
4035 unsigned int size = getDataSize (IC_RESULT (ic));
4037 /* will try to generate an increment */
4038 /* if the right side is not a literal
4040 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4043 /* if the literal value of the right hand side
4044 is greater than 4 then it is not worth it */
4045 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4048 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4049 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4051 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
4055 /* if decrement 16 bits in register */
4056 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4057 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4058 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4066 /* If the next instruction is a goto and the goto target
4067 * is <= 5 instructions previous to this, we can generate
4068 * jumps straight to that target.
4070 if (ic->next && ic->next->op == GOTO
4071 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4074 emitcode (";", "tail decrement optimized (range %d)", labelRange);
4075 tlbl = IC_LABEL (ic->next);
4080 tlbl = newiTempLabel (NULL);
4084 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
4085 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4086 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4087 IS_AOP_PREG (IC_RESULT (ic)))
4088 emitcode ("cjne", "%s,#!constbyte,!tlabel"
4089 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE), 0xff
4093 emitcode ("mov", "a,#!constbyte",0xff);
4094 emitcode ("cjne", "a,%s,!tlabel"
4095 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
4098 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
4101 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4102 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4103 IS_AOP_PREG (IC_RESULT (ic)))
4104 emitcode ("cjne", "%s,#!constbyte,!tlabel"
4105 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE),0xff
4109 emitcode ("cjne", "a,%s,!tlabel"
4110 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
4113 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
4117 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4118 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4119 IS_AOP_PREG (IC_RESULT (ic)))
4120 emitcode ("cjne", "%s,#!constbyte,!tlabel"
4121 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE),0xff
4125 emitcode ("cjne", "a,%s,!tlabel"
4126 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
4129 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
4133 emitcode ("", "!tlabeldef", tlbl->key + 100);
4138 /* if the sizes are greater than 1 then we cannot */
4139 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4140 AOP_SIZE (IC_LEFT (ic)) > 1)
4143 /* we can if the aops of the left & result match or
4144 if they are in registers and the registers are the
4147 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4148 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4149 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4152 _startLazyDPSEvaluation ();
4155 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
4157 _endLazyDPSEvaluation ();
4165 /*-----------------------------------------------------------------*/
4166 /* addSign - complete with sign */
4167 /*-----------------------------------------------------------------*/
4169 addSign (operand * result, int offset, int sign)
4171 int size = (getDataSize (result) - offset);
4174 _startLazyDPSEvaluation();
4177 emitcode ("rlc", "a");
4178 emitcode ("subb", "a,acc");
4181 aopPut (AOP (result), "a", offset++);
4188 aopPut (AOP (result), zero, offset++);
4191 _endLazyDPSEvaluation();
4195 /*-----------------------------------------------------------------*/
4196 /* genMinusBits - generates code for subtraction of two bits */
4197 /*-----------------------------------------------------------------*/
4199 genMinusBits (iCode * ic)
4201 symbol *lbl = newiTempLabel (NULL);
4203 D (emitcode (";", "genMinusBits "););
4205 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4207 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4208 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4209 emitcode ("cpl", "c");
4210 emitcode ("", "!tlabeldef", (lbl->key + 100));
4211 outBitC (IC_RESULT (ic));
4215 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4216 emitcode ("subb", "a,acc");
4217 emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4218 emitcode ("inc", "a");
4219 emitcode ("", "!tlabeldef", (lbl->key + 100));
4220 aopPut (AOP (IC_RESULT (ic)), "a", 0);
4221 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4225 /*-----------------------------------------------------------------*/
4226 /* genMinus - generates code for subtraction */
4227 /*-----------------------------------------------------------------*/
4229 genMinus (iCode * ic)
4231 int size, offset = 0;
4233 unsigned long lit = 0L;
4234 bool pushResult = FALSE;
4236 D (emitcode (";", "genMinus "););
4238 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
4239 aopOp (IC_RIGHT (ic), ic, FALSE,
4240 (AOP_INDPTRn(IC_LEFT(ic)) ? FALSE : (AOP_USESDPTR(IC_LEFT(ic)) ? TRUE : FALSE)));
4241 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
4242 ((AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2)
4243 || OP_SYMBOL(IC_RESULT(ic))->ruonly))
4249 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
4251 /* special cases :- */
4252 /* if both left & right are in bit space */
4253 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4254 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4260 /* if I can do an decrement instead
4261 of subtract then GOOD for ME */
4262 if (genMinusDec (ic) == TRUE)
4267 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4269 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4275 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4280 /* if literal, add a,#-lit, else normal subb */
4281 _startLazyDPSEvaluation ();
4283 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
4284 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4285 if (AOP_USESDPTR(IC_RIGHT(ic))) {
4286 emitcode ("mov","b,a");
4287 MOVA(aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
4288 emitcode ("xch","a,b");
4289 emitcode ("subb","a,b");
4291 emitcode ("subb", "a,%s",
4292 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
4295 /* first add without previous c */
4297 if (!size && lit==-1) {
4298 emitcode ("dec", "a");
4300 emitcode ("add", "a,#!constbyte",
4301 (unsigned int) (lit & 0x0FFL));
4304 emitcode ("addc", "a,#!constbyte",
4305 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4310 emitcode ("push", "acc");
4312 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4316 _endLazyDPSEvaluation ();
4320 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4322 size = getDataSize (IC_LEFT (ic));
4323 rSize = getDataSize (IC_RESULT (ic));
4325 ADJUST_PUSHED_RESULT(size, rSize);
4327 _startLazyDPSEvaluation ();
4330 emitcode ("pop", "acc");
4331 aopPut (AOP (IC_RESULT (ic)), "a", size);
4333 _endLazyDPSEvaluation ();
4336 adjustArithmeticResult (ic);
4339 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4340 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4341 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4345 /*-----------------------------------------------------------------*/
4346 /* genMultbits :- multiplication of bits */
4347 /*-----------------------------------------------------------------*/
4349 genMultbits (operand * left,
4354 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4355 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4356 aopOp(result, ic, TRUE, FALSE);
4361 /*-----------------------------------------------------------------*/
4362 /* genMultOneByte : 8*8=8/16 bit multiplication */
4363 /*-----------------------------------------------------------------*/
4365 genMultOneByte (operand * left,
4370 sym_link *opetype = operandType (result);
4374 /* (if two literals: the value is computed before) */
4375 /* if one literal, literal on the right */
4376 if (AOP_TYPE (left) == AOP_LIT)
4381 emitcode (";", "swapped left and right");
4384 if (SPEC_USIGN(opetype)
4385 // ignore the sign of left and right, what else can we do?
4386 || (SPEC_USIGN(operandType(left)) &&
4387 SPEC_USIGN(operandType(right)))) {
4388 // just an unsigned 8*8=8/16 multiply
4389 //emitcode (";","unsigned");
4390 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4391 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4392 emitcode ("mul", "ab");
4394 _G.accInUse++; _G.bInUse++;
4395 aopOp(result, ic, TRUE, FALSE);
4397 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4399 // this should never happen
4400 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4401 AOP_SIZE(result), __FILE__, lineno);
4405 aopPut (AOP (result), "a", 0);
4406 _G.accInUse--; _G.bInUse--;
4407 if (AOP_SIZE(result)==2)
4409 aopPut (AOP (result), "b", 1);
4414 // we have to do a signed multiply
4416 emitcode (";", "signed");
4417 emitcode ("clr", "F0"); // reset sign flag
4418 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4420 lbl=newiTempLabel(NULL);
4421 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4422 // left side is negative, 8-bit two's complement, this fails for -128
4423 emitcode ("setb", "F0"); // set sign flag
4424 emitcode ("cpl", "a");
4425 emitcode ("inc", "a");
4427 emitcode ("", "!tlabeldef", lbl->key+100);
4430 if (AOP_TYPE(right)==AOP_LIT) {
4431 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4432 /* AND literal negative */
4433 if ((int) val < 0) {
4434 emitcode ("cpl", "F0"); // complement sign flag
4435 emitcode ("mov", "b,#!constbyte", -val);
4437 emitcode ("mov", "b,#!constbyte", val);
4440 lbl=newiTempLabel(NULL);
4441 emitcode ("mov", "b,a");
4442 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4443 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4444 // right side is negative, 8-bit two's complement
4445 emitcode ("cpl", "F0"); // complement sign flag
4446 emitcode ("cpl", "a");
4447 emitcode ("inc", "a");
4448 emitcode ("", "!tlabeldef", lbl->key+100);
4450 emitcode ("mul", "ab");
4452 _G.accInUse++;_G.bInUse++;
4453 aopOp(result, ic, TRUE, FALSE);
4455 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4457 // this should never happen
4458 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4459 AOP_SIZE(result), __FILE__, lineno);
4463 lbl=newiTempLabel(NULL);
4464 emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4465 // only ONE op was negative, we have to do a 8/16-bit two's complement
4466 emitcode ("cpl", "a"); // lsb
4467 if (AOP_SIZE(result)==1) {
4468 emitcode ("inc", "a");
4470 emitcode ("add", "a,#1");
4471 emitcode ("xch", "a,b");
4472 emitcode ("cpl", "a"); // msb
4473 emitcode ("addc", "a,#0");
4474 emitcode ("xch", "a,b");
4477 emitcode ("", "!tlabeldef", lbl->key+100);
4478 aopPut (AOP (result), "a", 0);
4479 _G.accInUse--;_G.bInUse--;
4480 if (AOP_SIZE(result)==2) {
4481 aopPut (AOP (result), "b", 1);
4485 /*-----------------------------------------------------------------*/
4486 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
4487 /*-----------------------------------------------------------------*/
4488 static void genMultTwoByte (operand *left, operand *right,
4489 operand *result, iCode *ic)
4491 sym_link *retype = getSpec(operandType(right));
4492 sym_link *letype = getSpec(operandType(left));
4493 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4496 if (AOP_TYPE (left) == AOP_LIT) {
4501 /* save EA bit in F1 */
4502 lbl = newiTempLabel(NULL);
4503 emitcode ("setb","F1");
4504 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4505 emitcode ("clr","F1");
4506 emitcode("","!tlabeldef",lbl->key+100);
4508 /* load up MB with right */
4510 emitcode("clr","F0");
4511 if (AOP_TYPE(right) == AOP_LIT) {
4512 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4514 emitcode("setb","F0");
4517 emitcode ("mov","mb,#!constbyte",val & 0xff);
4518 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4520 lbl = newiTempLabel(NULL);
4521 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4522 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4523 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4524 emitcode ("xch", "a,b");
4525 emitcode ("cpl","a");
4526 emitcode ("add", "a,#1");
4527 emitcode ("xch", "a,b");
4528 emitcode ("cpl", "a"); // msb
4529 emitcode ("addc", "a,#0");
4530 emitcode ("setb","F0");
4531 emitcode ("","!tlabeldef",lbl->key+100);
4532 emitcode ("mov","mb,b");
4533 emitcode ("mov","mb,a");
4536 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4537 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4539 /* load up MA with left */
4541 lbl = newiTempLabel(NULL);
4542 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4543 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4544 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4545 emitcode ("xch", "a,b");
4546 emitcode ("cpl","a");
4547 emitcode ("add", "a,#1");
4548 emitcode ("xch", "a,b");
4549 emitcode ("cpl", "a"); // msb
4550 emitcode ("addc","a,#0");
4551 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4552 emitcode ("setb","F0");
4553 emitcode ("","!tlabeldef",lbl->key+100);
4554 emitcode ("mov","ma,b");
4555 emitcode ("mov","ma,a");
4557 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4558 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4560 /* wait for multiplication to finish */
4561 lbl = newiTempLabel(NULL);
4562 emitcode("","!tlabeldef", lbl->key+100);
4563 emitcode("mov","a,mcnt1");
4564 emitcode("anl","a,#!constbyte",0x80);
4565 emitcode("jnz","!tlabel",lbl->key+100);
4567 freeAsmop (left, NULL, ic, TRUE);
4568 freeAsmop (right, NULL, ic,TRUE);
4569 aopOp(result, ic, TRUE, FALSE);
4571 /* if unsigned then simple */
4573 emitcode ("mov","a,ma");
4574 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4575 emitcode ("mov","a,ma");
4576 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4577 aopPut(AOP(result),"ma",1);
4578 aopPut(AOP(result),"ma",0);
4580 emitcode("push","ma");
4581 emitcode("push","ma");
4582 emitcode("push","ma");
4584 /* negate result if needed */
4585 lbl = newiTempLabel(NULL);
4586 emitcode("jnb","F0,!tlabel",lbl->key+100);
4587 emitcode("cpl","a");
4588 emitcode("add","a,#1");
4589 emitcode("","!tlabeldef", lbl->key+100);
4590 if (AOP_TYPE(result) == AOP_ACC)
4592 D(emitcode(";", "ACC special case."););
4593 /* We know result is the only live aop, and
4594 * it's obviously not a DPTR2, so AP is available.
4596 emitcode("mov", "%s,acc", DP2_RESULT_REG);
4600 aopPut(AOP(result),"a",0);
4603 emitcode("pop","acc");
4604 lbl = newiTempLabel(NULL);
4605 emitcode("jnb","F0,!tlabel",lbl->key+100);
4606 emitcode("cpl","a");
4607 emitcode("addc","a,#0");
4608 emitcode("","!tlabeldef", lbl->key+100);
4609 aopPut(AOP(result),"a",1);
4610 emitcode("pop","acc");
4611 if (AOP_SIZE(result) >= 3) {
4612 lbl = newiTempLabel(NULL);
4613 emitcode("jnb","F0,!tlabel",lbl->key+100);
4614 emitcode("cpl","a");
4615 emitcode("addc","a,#0");
4616 emitcode("","!tlabeldef", lbl->key+100);
4617 aopPut(AOP(result),"a",2);
4619 emitcode("pop","acc");
4620 if (AOP_SIZE(result) >= 4) {
4621 lbl = newiTempLabel(NULL);
4622 emitcode("jnb","F0,!tlabel",lbl->key+100);
4623 emitcode("cpl","a");
4624 emitcode("addc","a,#0");
4625 emitcode("","!tlabeldef", lbl->key+100);
4626 aopPut(AOP(result),"a",3);
4628 if (AOP_TYPE(result) == AOP_ACC)
4630 /* We stashed the result away above. */
4631 emitcode("mov", "acc,%s", DP2_RESULT_REG);
4635 freeAsmop (result, NULL, ic, TRUE);
4637 /* restore EA bit in F1 */
4638 lbl = newiTempLabel(NULL);
4639 emitcode ("jnb","F1,!tlabel",lbl->key+100);
4640 emitcode ("setb","EA");
4641 emitcode("","!tlabeldef",lbl->key+100);
4645 /*-----------------------------------------------------------------*/
4646 /* genMult - generates code for multiplication */
4647 /*-----------------------------------------------------------------*/
4649 genMult (iCode * ic)
4651 operand *left = IC_LEFT (ic);
4652 operand *right = IC_RIGHT (ic);
4653 operand *result = IC_RESULT (ic);
4655 D (emitcode (";", "genMult "););
4657 /* assign the amsops */
4660 /* special cases first */
4662 if (AOP_TYPE (left) == AOP_CRY &&
4663 AOP_TYPE (right) == AOP_CRY)
4665 genMultbits (left, right, result, ic);
4669 /* if both are of size == 1 */
4670 if (AOP_SIZE (left) == 1 &&
4671 AOP_SIZE (right) == 1)
4673 genMultOneByte (left, right, result, ic);
4677 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4678 /* use the ds390 ARITHMETIC accel UNIT */
4679 genMultTwoByte (left, right, result, ic);
4682 /* should have been converted to function call */
4686 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4687 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4688 freeAsmop (result, NULL, ic, TRUE);
4691 /*-----------------------------------------------------------------*/
4692 /* genDivbits :- division of bits */
4693 /*-----------------------------------------------------------------*/
4695 genDivbits (operand * left,
4703 /* the result must be bit */
4704 LOAD_AB_FOR_DIV (left, right, l);
4705 emitcode ("div", "ab");
4706 emitcode ("rrc", "a");
4707 aopOp(result, ic, TRUE, FALSE);
4709 aopPut (AOP (result), "c", 0);
4712 /*-----------------------------------------------------------------*/
4713 /* genDivOneByte : 8 bit division */
4714 /*-----------------------------------------------------------------*/
4716 genDivOneByte (operand * left,
4721 sym_link *opetype = operandType (result);
4727 /* signed or unsigned */
4728 if (SPEC_USIGN (opetype))
4730 /* unsigned is easy */
4731 LOAD_AB_FOR_DIV (left, right, l);
4732 emitcode ("div", "ab");
4735 aopOp(result, ic, TRUE, FALSE);
4736 aopPut (AOP (result), "a", 0);
4739 size = AOP_SIZE (result) - 1;
4743 aopPut (AOP (result), zero, offset++);
4748 /* signed is a little bit more difficult */
4750 /* save the signs of the operands */
4751 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4753 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4754 emitcode ("push", "acc"); /* save it on the stack */
4756 /* now sign adjust for both left & right */
4757 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4759 lbl = newiTempLabel (NULL);
4760 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4761 emitcode ("cpl", "a");
4762 emitcode ("inc", "a");
4763 emitcode ("", "!tlabeldef", (lbl->key + 100));
4764 emitcode ("mov", "b,a");
4766 /* sign adjust left side */
4767 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4770 lbl = newiTempLabel (NULL);
4771 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4772 emitcode ("cpl", "a");
4773 emitcode ("inc", "a");
4774 emitcode ("", "!tlabeldef", (lbl->key + 100));
4776 /* now the division */
4777 emitcode ("nop", "; workaround for DS80C390 div bug.");
4778 emitcode ("div", "ab");
4779 /* we are interested in the lower order
4781 emitcode ("mov", "b,a");
4782 lbl = newiTempLabel (NULL);
4783 emitcode ("pop", "acc");
4784 /* if there was an over flow we don't
4785 adjust the sign of the result */
4786 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4787 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4789 emitcode ("clr", "a");
4790 emitcode ("subb", "a,b");
4791 emitcode ("mov", "b,a");
4792 emitcode ("", "!tlabeldef", (lbl->key + 100));
4794 /* now we are done */
4795 _G.accInUse++; _G.bInUse++;
4796 aopOp(result, ic, TRUE, FALSE);
4798 aopPut (AOP (result), "b", 0);
4800 size = AOP_SIZE (result) - 1;
4804 emitcode ("mov", "c,b.7");
4805 emitcode ("subb", "a,acc");
4809 aopPut (AOP (result), "a", offset++);
4811 _G.accInUse--; _G.bInUse--;
4815 /*-----------------------------------------------------------------*/
4816 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
4817 /*-----------------------------------------------------------------*/
4818 static void genDivTwoByte (operand *left, operand *right,
4819 operand *result, iCode *ic)
4821 sym_link *retype = getSpec(operandType(right));
4822 sym_link *letype = getSpec(operandType(left));
4823 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4826 /* save EA bit in F1 */
4827 lbl = newiTempLabel(NULL);
4828 emitcode ("setb","F1");
4829 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4830 emitcode ("clr","F1");
4831 emitcode("","!tlabeldef",lbl->key+100);
4833 /* load up MA with left */
4835 emitcode("clr","F0");
4836 lbl = newiTempLabel(NULL);
4837 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4838 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4839 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4840 emitcode ("xch", "a,b");
4841 emitcode ("cpl","a");
4842 emitcode ("add", "a,#1");
4843 emitcode ("xch", "a,b");
4844 emitcode ("cpl", "a"); // msb
4845 emitcode ("addc","a,#0");
4846 emitcode ("setb","F0");
4847 emitcode ("","!tlabeldef",lbl->key+100);
4848 emitcode ("mov","ma,b");
4849 emitcode ("mov","ma,a");
4851 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4852 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4855 /* load up MB with right */
4857 if (AOP_TYPE(right) == AOP_LIT) {
4858 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4860 lbl = newiTempLabel(NULL);
4861 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4862 emitcode("setb","F0");
4863 emitcode ("","!tlabeldef",lbl->key+100);
4866 emitcode ("mov","mb,#!constbyte",val & 0xff);
4867 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4869 lbl = newiTempLabel(NULL);
4870 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4871 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4872 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4873 emitcode ("xch", "a,b");
4874 emitcode ("cpl","a");
4875 emitcode ("add", "a,#1");
4876 emitcode ("xch", "a,b");
4877 emitcode ("cpl", "a"); // msb
4878 emitcode ("addc", "a,#0");
4879 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4880 emitcode ("setb","F0");
4881 emitcode ("","!tlabeldef",lbl->key+100);
4882 emitcode ("mov","mb,b");
4883 emitcode ("mov","mb,a");
4886 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4887 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4890 /* wait for multiplication to finish */
4891 lbl = newiTempLabel(NULL);
4892 emitcode("","!tlabeldef", lbl->key+100);
4893 emitcode("mov","a,mcnt1");
4894 emitcode("anl","a,#!constbyte",0x80);
4895 emitcode("jnz","!tlabel",lbl->key+100);
4897 freeAsmop (left, NULL, ic, TRUE);
4898 freeAsmop (right, NULL, ic,TRUE);
4899 aopOp(result, ic, TRUE, FALSE);
4901 /* if unsigned then simple */
4903 aopPut(AOP(result),"ma",1);
4904 aopPut(AOP(result),"ma",0);
4906 emitcode("push","ma");
4908 /* negate result if needed */
4909 lbl = newiTempLabel(NULL);
4910 emitcode("jnb","F0,!tlabel",lbl->key+100);
4911 emitcode("cpl","a");
4912 emitcode("add","a,#1");
4913 emitcode("","!tlabeldef", lbl->key+100);
4914 aopPut(AOP(result),"a",0);
4915 emitcode("pop","acc");
4916 lbl = newiTempLabel(NULL);
4917 emitcode("jnb","F0,!tlabel",lbl->key+100);
4918 emitcode("cpl","a");
4919 emitcode("addc","a,#0");
4920 emitcode("","!tlabeldef", lbl->key+100);
4921 aopPut(AOP(result),"a",1);
4923 freeAsmop (result, NULL, ic, TRUE);
4924 /* restore EA bit in F1 */
4925 lbl = newiTempLabel(NULL);
4926 emitcode ("jnb","F1,!tlabel",lbl->key+100);
4927 emitcode ("setb","EA");
4928 emitcode("","!tlabeldef",lbl->key+100);
4932 /*-----------------------------------------------------------------*/
4933 /* genDiv - generates code for division */
4934 /*-----------------------------------------------------------------*/
4938 operand *left = IC_LEFT (ic);
4939 operand *right = IC_RIGHT (ic);
4940 operand *result = IC_RESULT (ic);
4942 D (emitcode (";", "genDiv "););
4944 /* assign the amsops */
4947 /* special cases first */
4949 if (AOP_TYPE (left) == AOP_CRY &&
4950 AOP_TYPE (right) == AOP_CRY)
4952 genDivbits (left, right, result, ic);
4956 /* if both are of size == 1 */
4957 if (AOP_SIZE (left) == 1 &&
4958 AOP_SIZE (right) == 1)
4960 genDivOneByte (left, right, result, ic);
4964 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4965 /* use the ds390 ARITHMETIC accel UNIT */
4966 genDivTwoByte (left, right, result, ic);
4969 /* should have been converted to function call */
4972 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4973 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4974 freeAsmop (result, NULL, ic, TRUE);
4977 /*-----------------------------------------------------------------*/
4978 /* genModbits :- modulus of bits */
4979 /*-----------------------------------------------------------------*/
4981 genModbits (operand * left,
4989 /* the result must be bit */
4990 LOAD_AB_FOR_DIV (left, right, l);
4991 emitcode ("div", "ab");
4992 emitcode ("mov", "a,b");
4993 emitcode ("rrc", "a");
4994 aopOp(result, ic, TRUE, FALSE);
4995 aopPut (AOP (result), "c", 0);
4998 /*-----------------------------------------------------------------*/
4999 /* genModOneByte : 8 bit modulus */
5000 /*-----------------------------------------------------------------*/
5002 genModOneByte (operand * left,
5007 sym_link *opetype = operandType (result);
5011 /* signed or unsigned */
5012 if (SPEC_USIGN (opetype))
5014 /* unsigned is easy */
5015 LOAD_AB_FOR_DIV (left, right, l);
5016 emitcode ("div", "ab");
5017 aopOp(result, ic, TRUE, FALSE);
5018 aopPut (AOP (result), "b", 0);
5022 /* signed is a little bit more difficult */
5024 /* save the signs of the operands */
5025 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
5028 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
5029 emitcode ("push", "acc"); /* save it on the stack */
5031 /* now sign adjust for both left & right */
5032 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
5035 lbl = newiTempLabel (NULL);
5036 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5037 emitcode ("cpl", "a");
5038 emitcode ("inc", "a");
5039 emitcode ("", "!tlabeldef", (lbl->key + 100));
5040 emitcode ("mov", "b,a");
5042 /* sign adjust left side */
5043 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
5046 lbl = newiTempLabel (NULL);
5047 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5048 emitcode ("cpl", "a");
5049 emitcode ("inc", "a");
5050 emitcode ("", "!tlabeldef", (lbl->key + 100));
5052 /* now the multiplication */
5053 emitcode ("nop", "; workaround for DS80C390 div bug.");
5054 emitcode ("div", "ab");
5055 /* we are interested in the lower order
5057 lbl = newiTempLabel (NULL);
5058 emitcode ("pop", "acc");
5059 /* if there was an over flow we don't
5060 adjust the sign of the result */
5061 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
5062 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5064 emitcode ("clr", "a");
5065 emitcode ("subb", "a,b");
5066 emitcode ("mov", "b,a");
5067 emitcode ("", "!tlabeldef", (lbl->key + 100));
5070 /* now we are done */
5071 aopOp(result, ic, TRUE, FALSE);
5072 aopPut (AOP (result), "b", 0);
5077 /*-----------------------------------------------------------------*/
5078 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
5079 /*-----------------------------------------------------------------*/
5080 static void genModTwoByte (operand *left, operand *right,
5081 operand *result, iCode *ic)
5083 sym_link *retype = getSpec(operandType(right));
5084 sym_link *letype = getSpec(operandType(left));
5085 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5088 /* load up MA with left */
5089 /* save EA bit in F1 */
5090 lbl = newiTempLabel(NULL);
5091 emitcode ("setb","F1");
5092 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5093 emitcode ("clr","F1");
5094 emitcode("","!tlabeldef",lbl->key+100);
5097 lbl = newiTempLabel(NULL);
5098 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
5099 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
5100 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5101 emitcode ("xch", "a,b");
5102 emitcode ("cpl","a");
5103 emitcode ("add", "a,#1");
5104 emitcode ("xch", "a,b");
5105 emitcode ("cpl", "a"); // msb
5106 emitcode ("addc","a,#0");
5107 emitcode ("","!tlabeldef",lbl->key+100);
5108 emitcode ("mov","ma,b");
5109 emitcode ("mov","ma,a");
5111 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
5112 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
5115 /* load up MB with right */
5117 if (AOP_TYPE(right) == AOP_LIT) {
5118 int val=floatFromVal (AOP (right)->aopu.aop_lit);
5122 emitcode ("mov","mb,#!constbyte",val & 0xff);
5123 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5125 lbl = newiTempLabel(NULL);
5126 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
5127 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
5128 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5129 emitcode ("xch", "a,b");
5130 emitcode ("cpl","a");
5131 emitcode ("add", "a,#1");
5132 emitcode ("xch", "a,b");
5133 emitcode ("cpl", "a"); // msb
5134 emitcode ("addc", "a,#0");
5135 emitcode ("","!tlabeldef",lbl->key+100);
5136 emitcode ("mov","mb,b");
5137 emitcode ("mov","mb,a");
5140 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
5141 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
5144 /* wait for multiplication to finish */
5145 lbl = newiTempLabel(NULL);
5146 emitcode("","!tlabeldef", lbl->key+100);
5147 emitcode("mov","a,mcnt1");
5148 emitcode("anl","a,#!constbyte",0x80);
5149 emitcode("jnz","!tlabel",lbl->key+100);
5151 freeAsmop (left, NULL, ic, TRUE);
5152 freeAsmop (right, NULL, ic,TRUE);
5153 aopOp(result, ic, TRUE, FALSE);
5155 aopPut(AOP(result),"mb",1);
5156 aopPut(AOP(result),"mb",0);
5157 freeAsmop (result, NULL, ic, TRUE);
5159 /* restore EA bit in F1 */
5160 lbl = newiTempLabel(NULL);
5161 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5162 emitcode ("setb","EA");
5163 emitcode("","!tlabeldef",lbl->key+100);
5167 /*-----------------------------------------------------------------*/
5168 /* genMod - generates code for division */
5169 /*-----------------------------------------------------------------*/
5173 operand *left = IC_LEFT (ic);
5174 operand *right = IC_RIGHT (ic);
5175 operand *result = IC_RESULT (ic);
5177 D (emitcode (";", "genMod "); );
5179 /* assign the amsops */
5182 /* special cases first */
5184 if (AOP_TYPE (left) == AOP_CRY &&
5185 AOP_TYPE (right) == AOP_CRY)
5187 genModbits (left, right, result, ic);
5191 /* if both are of size == 1 */
5192 if (AOP_SIZE (left) == 1 &&
5193 AOP_SIZE (right) == 1)
5195 genModOneByte (left, right, result, ic);
5199 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5200 /* use the ds390 ARITHMETIC accel UNIT */
5201 genModTwoByte (left, right, result, ic);
5205 /* should have been converted to function call */
5209 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5210 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5211 freeAsmop (result, NULL, ic, TRUE);
5214 /*-----------------------------------------------------------------*/
5215 /* genIfxJump :- will create a jump depending on the ifx */
5216 /*-----------------------------------------------------------------*/
5218 genIfxJump (iCode * ic, char *jval)
5221 symbol *tlbl = newiTempLabel (NULL);
5224 D (emitcode (";", "genIfxJump ");
5227 /* if true label then we jump if condition
5231 jlbl = IC_TRUE (ic);
5232 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5233 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5237 /* false label is present */
5238 jlbl = IC_FALSE (ic);
5239 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5240 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5242 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5243 emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5245 emitcode (inst, "!tlabel", tlbl->key + 100);
5246 emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5247 emitcode ("", "!tlabeldef", tlbl->key + 100);
5249 /* mark the icode as generated */
5253 /*-----------------------------------------------------------------*/
5254 /* genCmp :- greater or less than comparison */
5255 /*-----------------------------------------------------------------*/
5257 genCmp (operand * left, operand * right,
5258 iCode * ic, iCode * ifx, int sign)
5260 int size, offset = 0;
5261 unsigned long lit = 0L;
5264 D (emitcode (";", "genCmp");
5267 result = IC_RESULT (ic);
5269 /* if left & right are bit variables */
5270 if (AOP_TYPE (left) == AOP_CRY &&
5271 AOP_TYPE (right) == AOP_CRY)
5273 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5274 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
5278 /* subtract right from left if at the
5279 end the carry flag is set then we know that
5280 left is greater than right */
5281 size = max (AOP_SIZE (left), AOP_SIZE (right));
5283 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5284 if ((size == 1) && !sign &&
5285 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5287 symbol *lbl = newiTempLabel (NULL);
5288 emitcode ("cjne", "%s,%s,!tlabel",
5289 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5290 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5292 emitcode ("", "!tlabeldef", lbl->key + 100);
5296 if (AOP_TYPE (right) == AOP_LIT)
5298 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5299 /* optimize if(x < 0) or if(x >= 0) */
5308 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
5310 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5311 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5313 aopOp (result, ic, FALSE, FALSE);
5315 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5317 freeAsmop (result, NULL, ic, TRUE);
5318 genIfxJump (ifx, "acc.7");
5323 emitcode ("rlc", "a");
5325 goto release_freedLR;
5333 //emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5334 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5335 //emitcode (";", "genCmp #2");
5336 if (sign && (size == 0))
5338 //emitcode (";", "genCmp #3");
5339 emitcode ("xrl", "a,#!constbyte",0x80);
5340 if (AOP_TYPE (right) == AOP_LIT)
5342 unsigned long lit = (unsigned long)
5343 floatFromVal (AOP (right)->aopu.aop_lit);
5344 //emitcode (";", "genCmp #3.1");
5345 emitcode ("subb", "a,#!constbyte",
5346 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5350 //emitcode (";", "genCmp #3.2");
5351 if (AOP_NEEDSACC (right))
5353 emitcode ("push", "acc");
5355 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
5356 FALSE, FALSE, FALSE));
5357 emitcode ("xrl", "b,#!constbyte",0x80);
5358 if (AOP_NEEDSACC (right))
5360 emitcode ("pop", "acc");
5362 emitcode ("subb", "a,b");
5369 //emitcode (";", "genCmp #4");
5370 if (AOP_NEEDSACC (right))
5373 //emitcode (";", "genCmp #4.1");
5374 emitcode ("xch", "a, b");
5375 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
5376 emitcode ("xch", "a, b");
5381 //emitcode (";", "genCmp #4.2");
5382 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
5385 emitcode ("subb", "a,%s", s);
5392 /* Don't need the left & right operands any more; do need the result. */
5393 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5394 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5396 aopOp (result, ic, FALSE, FALSE);
5400 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5406 /* if the result is used in the next
5407 ifx conditional branch then generate
5408 code a little differently */
5411 genIfxJump (ifx, "c");
5417 /* leave the result in acc */
5419 freeAsmop (result, NULL, ic, TRUE);
5422 /*-----------------------------------------------------------------*/
5423 /* genCmpGt :- greater than comparison */
5424 /*-----------------------------------------------------------------*/
5426 genCmpGt (iCode * ic, iCode * ifx)
5428 operand *left, *right;
5429 sym_link *letype, *retype;
5432 D (emitcode (";", "genCmpGt ");
5435 left = IC_LEFT (ic);
5436 right = IC_RIGHT (ic);
5438 letype = getSpec (operandType (left));
5439 retype = getSpec (operandType (right));
5440 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5442 /* assign the left & right amsops */
5445 genCmp (right, left, ic, ifx, sign);
5448 /*-----------------------------------------------------------------*/
5449 /* genCmpLt - less than comparisons */
5450 /*-----------------------------------------------------------------*/
5452 genCmpLt (iCode * ic, iCode * ifx)
5454 operand *left, *right;
5455 sym_link *letype, *retype;
5458 D (emitcode (";", "genCmpLt "););
5460 left = IC_LEFT (ic);
5461 right = IC_RIGHT (ic);
5463 letype = getSpec (operandType (left));
5464 retype = getSpec (operandType (right));
5465 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5467 /* assign the left & right amsops */
5470 genCmp (left, right, ic, ifx, sign);
5473 /*-----------------------------------------------------------------*/
5474 /* gencjneshort - compare and jump if not equal */
5475 /*-----------------------------------------------------------------*/
5477 gencjneshort (operand * left, operand * right, symbol * lbl)
5479 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5481 unsigned long lit = 0L;
5483 D (emitcode (";", "gencjneshort");
5486 /* if the left side is a literal or
5487 if the right is in a pointer register and left
5489 if ((AOP_TYPE (left) == AOP_LIT) ||
5490 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5497 if (AOP_TYPE (right) == AOP_LIT)
5498 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5500 if (opIsGptr (left) || opIsGptr (right))
5502 /* We are comparing a generic pointer to something.
5503 * Exclude the generic type byte from the comparison.
5506 D (emitcode (";", "cjneshort: generic ptr special case.");
5511 /* if the right side is a literal then anything goes */
5512 if (AOP_TYPE (right) == AOP_LIT &&
5513 AOP_TYPE (left) != AOP_DIR)
5517 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5519 emitcode ("cjne", "a,%s,!tlabel",
5520 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5526 /* if the right side is in a register or in direct space or
5527 if the left is a pointer register & right is not */
5528 else if (AOP_TYPE (right) == AOP_REG ||
5529 AOP_TYPE (right) == AOP_DIR ||
5530 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5531 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5535 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5536 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5537 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5538 emitcode ("jnz", "!tlabel", lbl->key + 100);
5540 emitcode ("cjne", "a,%s,!tlabel",
5541 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
5548 /* right is a pointer reg need both a & b */
5551 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5552 if (strcmp (l, "b"))
5553 emitcode ("mov", "b,%s", l);
5554 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5555 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5561 /*-----------------------------------------------------------------*/
5562 /* gencjne - compare and jump if not equal */
5563 /*-----------------------------------------------------------------*/
5565 gencjne (operand * left, operand * right, symbol * lbl)
5567 symbol *tlbl = newiTempLabel (NULL);
5569 D (emitcode (";", "gencjne");
5572 gencjneshort (left, right, lbl);
5574 emitcode ("mov", "a,%s", one);
5575 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5576 emitcode ("", "!tlabeldef", lbl->key + 100);
5577 emitcode ("clr", "a");
5578 emitcode ("", "!tlabeldef", tlbl->key + 100);
5581 /*-----------------------------------------------------------------*/
5582 /* genCmpEq - generates code for equal to */
5583 /*-----------------------------------------------------------------*/
5585 genCmpEq (iCode * ic, iCode * ifx)
5587 operand *left, *right, *result;
5589 D (emitcode (";", "genCmpEq ");
5593 AOP_SET_LOCALS (ic);
5595 /* if literal, literal on the right or
5596 if the right is in a pointer register and left
5598 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5599 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5601 operand *t = IC_RIGHT (ic);
5602 IC_RIGHT (ic) = IC_LEFT (ic);
5606 if (ifx && /* !AOP_SIZE(result) */
5607 OP_SYMBOL (result) &&
5608 OP_SYMBOL (result)->regType == REG_CND)
5611 /* if they are both bit variables */
5612 if (AOP_TYPE (left) == AOP_CRY &&
5613 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5615 if (AOP_TYPE (right) == AOP_LIT)
5617 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5620 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5621 emitcode ("cpl", "c");
5625 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5629 emitcode ("clr", "c");
5631 /* AOP_TYPE(right) == AOP_CRY */
5635 symbol *lbl = newiTempLabel (NULL);
5636 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5637 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5638 emitcode ("cpl", "c");
5639 emitcode ("", "!tlabeldef", (lbl->key + 100));
5641 /* if true label then we jump if condition
5643 tlbl = newiTempLabel (NULL);
5646 emitcode ("jnc", "!tlabel", tlbl->key + 100);
5647 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5651 emitcode ("jc", "!tlabel", tlbl->key + 100);
5652 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5654 emitcode ("", "!tlabeldef", tlbl->key + 100);
5658 tlbl = newiTempLabel (NULL);
5659 gencjneshort (left, right, tlbl);
5662 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5663 emitcode ("", "!tlabeldef", tlbl->key + 100);
5667 symbol *lbl = newiTempLabel (NULL);
5668 emitcode ("sjmp", "!tlabel", lbl->key + 100);
5669 emitcode ("", "!tlabeldef", tlbl->key + 100);
5670 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5671 emitcode ("", "!tlabeldef", lbl->key + 100);
5674 /* mark the icode as generated */
5677 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5678 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5682 /* if they are both bit variables */
5683 if (AOP_TYPE (left) == AOP_CRY &&
5684 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5686 if (AOP_TYPE (right) == AOP_LIT)
5688 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5691 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5692 emitcode ("cpl", "c");
5696 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5700 emitcode ("clr", "c");
5702 /* AOP_TYPE(right) == AOP_CRY */
5706 symbol *lbl = newiTempLabel (NULL);
5707 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5708 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5709 emitcode ("cpl", "c");
5710 emitcode ("", "!tlabeldef", (lbl->key + 100));
5713 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5714 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5716 aopOp (result, ic, TRUE, FALSE);
5719 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5726 genIfxJump (ifx, "c");
5729 /* if the result is used in an arithmetic operation
5730 then put the result in place */
5735 gencjne (left, right, newiTempLabel (NULL));
5737 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5738 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5740 aopOp (result, ic, TRUE, FALSE);
5742 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5744 aopPut (AOP (result), "a", 0);
5749 genIfxJump (ifx, "a");
5752 /* if the result is used in an arithmetic operation
5753 then put the result in place */
5754 if (AOP_TYPE (result) != AOP_CRY)
5756 /* leave the result in acc */
5760 freeAsmop (result, NULL, ic, TRUE);
5763 /*-----------------------------------------------------------------*/
5764 /* ifxForOp - returns the icode containing the ifx for operand */
5765 /*-----------------------------------------------------------------*/
5767 ifxForOp (operand * op, iCode * ic)
5769 /* if true symbol then needs to be assigned */
5770 if (IS_TRUE_SYMOP (op))
5773 /* if this has register type condition and
5774 the next instruction is ifx with the same operand
5775 and live to of the operand is upto the ifx only then */
5777 ic->next->op == IFX &&
5778 IC_COND (ic->next)->key == op->key &&
5779 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5784 /*-----------------------------------------------------------------*/
5785 /* hasInc - operand is incremented before any other use */
5786 /*-----------------------------------------------------------------*/
5788 hasInc (operand *op, iCode *ic, int osize)
5790 sym_link *type = operandType(op);
5791 sym_link *retype = getSpec (type);
5792 iCode *lic = ic->next;
5795 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5796 if (!IS_SYMOP(op)) return NULL;
5798 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5799 if (IS_AGGREGATE(type->next)) return NULL;
5800 if (osize != (isize = getSize(type->next))) return NULL;
5803 /* if operand of the form op = op + <sizeof *op> */
5804 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5805 isOperandEqual(IC_RESULT(lic),op) &&
5806 isOperandLiteral(IC_RIGHT(lic)) &&
5807 operandLitValue(IC_RIGHT(lic)) == isize) {
5810 /* if the operand used or deffed */
5811 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5814 /* if GOTO or IFX */
5815 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5821 /*-----------------------------------------------------------------*/
5822 /* genAndOp - for && operation */
5823 /*-----------------------------------------------------------------*/
5825 genAndOp (iCode * ic)
5827 operand *left, *right, *result;
5830 D (emitcode (";", "genAndOp "););
5832 /* note here that && operations that are in an
5833 if statement are taken away by backPatchLabels
5834 only those used in arthmetic operations remain */
5836 AOP_SET_LOCALS (ic);
5838 /* if both are bit variables */
5839 if (AOP_TYPE (left) == AOP_CRY &&
5840 AOP_TYPE (right) == AOP_CRY)
5842 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5843 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5844 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5845 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5847 aopOp (result,ic,FALSE, FALSE);
5852 tlbl = newiTempLabel (NULL);
5854 emitcode ("jz", "!tlabel", tlbl->key + 100);
5856 emitcode ("", "!tlabeldef", tlbl->key + 100);
5857 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5858 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5860 aopOp (result,ic,FALSE, FALSE);
5863 freeAsmop (result, NULL, ic, TRUE);
5867 /*-----------------------------------------------------------------*/
5868 /* genOrOp - for || operation */
5869 /*-----------------------------------------------------------------*/
5871 genOrOp (iCode * ic)
5873 operand *left, *right, *result;
5876 D (emitcode (";", "genOrOp "););
5878 /* note here that || operations that are in an
5879 if statement are taken away by backPatchLabels
5880 only those used in arthmetic operations remain */
5882 AOP_SET_LOCALS (ic);
5884 /* if both are bit variables */
5885 if (AOP_TYPE (left) == AOP_CRY &&
5886 AOP_TYPE (right) == AOP_CRY)
5888 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5889 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5890 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5891 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5893 aopOp (result,ic,FALSE, FALSE);
5899 tlbl = newiTempLabel (NULL);
5901 emitcode ("jnz", "!tlabel", tlbl->key + 100);
5903 emitcode ("", "!tlabeldef", tlbl->key + 100);
5904 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5905 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5907 aopOp (result,ic,FALSE, FALSE);
5912 freeAsmop (result, NULL, ic, TRUE);
5915 /*-----------------------------------------------------------------*/
5916 /* isLiteralBit - test if lit == 2^n */
5917 /*-----------------------------------------------------------------*/
5919 isLiteralBit (unsigned long lit)
5921 unsigned long pw[32] =
5922 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5923 0x100L, 0x200L, 0x400L, 0x800L,
5924 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5925 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5926 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5927 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5928 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5931 for (idx = 0; idx < 32; idx++)
5937 /*-----------------------------------------------------------------*/
5938 /* continueIfTrue - */
5939 /*-----------------------------------------------------------------*/
5941 continueIfTrue (iCode * ic)
5944 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
5948 /*-----------------------------------------------------------------*/
5950 /*-----------------------------------------------------------------*/
5952 jumpIfTrue (iCode * ic)
5955 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
5959 /*-----------------------------------------------------------------*/
5960 /* jmpTrueOrFalse - */
5961 /*-----------------------------------------------------------------*/
5963 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5965 // ugly but optimized by peephole
5968 symbol *nlbl = newiTempLabel (NULL);
5969 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
5970 emitcode ("", "!tlabeldef", tlbl->key + 100);
5971 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
5972 emitcode ("", "!tlabeldef", nlbl->key + 100);
5976 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
5977 emitcode ("", "!tlabeldef", tlbl->key + 100);
5982 // Generate code to perform a bit-wise logic operation
5983 // on two operands in far space (assumed to already have been
5984 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5985 // in far space. This requires pushing the result on the stack
5986 // then popping it into the result.
5988 genFarFarLogicOp(iCode *ic, char *logicOp)
5990 int size, resultSize, compSize;
5994 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5995 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
5996 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5998 _startLazyDPSEvaluation();
5999 for (size = compSize; (size--); offset++)
6001 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
6002 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6003 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
6005 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6006 emitcode ("push", "acc");
6008 _endLazyDPSEvaluation();
6010 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6011 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6012 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6014 resultSize = AOP_SIZE(IC_RESULT(ic));
6016 ADJUST_PUSHED_RESULT(compSize, resultSize);
6018 _startLazyDPSEvaluation();
6021 emitcode ("pop", "acc");
6022 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6024 _endLazyDPSEvaluation();
6025 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6029 /*-----------------------------------------------------------------*/
6030 /* genAnd - code for and */
6031 /*-----------------------------------------------------------------*/
6033 genAnd (iCode * ic, iCode * ifx)
6035 operand *left, *right, *result;
6036 int size, offset = 0;
6037 unsigned long lit = 0L;
6042 D (emitcode (";", "genAnd "););
6044 AOP_OP_3_NOFATAL (ic, pushResult);
6045 AOP_SET_LOCALS (ic);
6049 genFarFarLogicOp(ic, "anl");
6054 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6056 AOP_TYPE (left), AOP_TYPE (right));
6057 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6059 AOP_SIZE (left), AOP_SIZE (right));
6062 /* if left is a literal & right is not then exchange them */
6063 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6064 #ifdef LOGIC_OPS_BROKEN
6065 || AOP_NEEDSACC (left)
6069 operand *tmp = right;
6074 /* if result = right then exchange them */
6075 if (sameRegs (AOP (result), AOP (right)))
6077 operand *tmp = right;
6082 /* if right is bit then exchange them */
6083 if (AOP_TYPE (right) == AOP_CRY &&
6084 AOP_TYPE (left) != AOP_CRY)
6086 operand *tmp = right;
6090 if (AOP_TYPE (right) == AOP_LIT)
6091 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6093 size = AOP_SIZE (result);
6096 // result = bit & yy;
6097 if (AOP_TYPE (left) == AOP_CRY)
6099 // c = bit & literal;
6100 if (AOP_TYPE (right) == AOP_LIT)
6104 if (size && sameRegs (AOP (result), AOP (left)))
6107 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6112 if (size && (AOP_TYPE (result) == AOP_CRY))
6114 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6117 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6122 emitcode ("clr", "c");
6127 if (AOP_TYPE (right) == AOP_CRY)
6130 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6131 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6136 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
6138 emitcode ("rrc", "a");
6139 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6147 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6148 genIfxJump (ifx, "c");
6152 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6153 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6154 if ((AOP_TYPE (right) == AOP_LIT) &&
6155 (AOP_TYPE (result) == AOP_CRY) &&
6156 (AOP_TYPE (left) != AOP_CRY))
6158 int posbit = isLiteralBit (lit);
6163 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
6166 emitcode ("mov", "c,acc.%d", posbit & 0x07);
6172 sprintf (buffer, "acc.%d", posbit & 0x07);
6173 genIfxJump (ifx, buffer);
6177 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6184 symbol *tlbl = newiTempLabel (NULL);
6185 int sizel = AOP_SIZE (left);
6187 emitcode ("setb", "c");
6190 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6192 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6194 if ((posbit = isLiteralBit (bytelit)) != 0)
6195 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6198 if (bytelit != 0x0FFL)
6199 emitcode ("anl", "a,%s",
6200 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
6201 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6206 // bit = left & literal
6209 emitcode ("clr", "c");
6210 emitcode ("", "!tlabeldef", tlbl->key + 100);
6212 // if(left & literal)
6216 jmpTrueOrFalse (ifx, tlbl);
6224 /* if left is same as result */
6225 if (sameRegs (AOP (result), AOP (left)))
6227 for (; size--; offset++)
6229 if (AOP_TYPE (right) == AOP_LIT)
6231 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6233 else if (bytelit == 0)
6234 aopPut (AOP (result), zero, offset);
6235 else if (IS_AOP_PREG (result))
6237 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6238 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6239 aopPut (AOP (result), "a", offset);
6242 emitcode ("anl", "%s,%s",
6243 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6244 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6248 if (AOP_TYPE (left) == AOP_ACC)
6249 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6252 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6253 if (IS_AOP_PREG (result))
6255 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6256 aopPut (AOP (result), "a", offset);
6260 emitcode ("anl", "%s,a",
6261 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6268 // left & result in different registers
6269 if (AOP_TYPE (result) == AOP_CRY)
6272 // if(size), result in bit
6273 // if(!size && ifx), conditional oper: if(left & right)
6274 symbol *tlbl = newiTempLabel (NULL);
6275 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6277 emitcode ("setb", "c");
6280 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6281 emitcode ("anl", "a,%s",
6282 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6284 if (AOP_TYPE(left)==AOP_ACC) {
6285 emitcode("mov", "b,a");
6286 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6287 emitcode("anl", "a,b");
6289 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6290 emitcode ("anl", "a,%s",
6291 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6294 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6300 emitcode ("", "!tlabeldef", tlbl->key + 100);
6304 jmpTrueOrFalse (ifx, tlbl);
6308 for (; (size--); offset++)
6311 // result = left & right
6312 if (AOP_TYPE (right) == AOP_LIT)
6314 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6316 aopPut (AOP (result),
6317 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6321 else if (bytelit == 0)
6323 aopPut (AOP (result), zero, offset);
6326 D (emitcode (";", "better literal AND."););
6327 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6328 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6329 FALSE, FALSE, FALSE));
6334 // faster than result <- left, anl result,right
6335 // and better if result is SFR
6336 if (AOP_TYPE (left) == AOP_ACC)
6338 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
6339 FALSE, FALSE, FALSE));
6343 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6344 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6346 emitcode("mov", "b,a");
6350 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6351 emitcode ("anl", "a,%s", rOp);
6354 aopPut (AOP (result), "a", offset);
6360 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6361 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6362 freeAsmop (result, NULL, ic, TRUE);
6366 /*-----------------------------------------------------------------*/
6367 /* genOr - code for or */
6368 /*-----------------------------------------------------------------*/
6370 genOr (iCode * ic, iCode * ifx)
6372 operand *left, *right, *result;
6373 int size, offset = 0;
6374 unsigned long lit = 0L;
6377 D (emitcode (";", "genOr "););
6379 AOP_OP_3_NOFATAL (ic, pushResult);
6380 AOP_SET_LOCALS (ic);
6384 genFarFarLogicOp(ic, "orl");
6390 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6392 AOP_TYPE (left), AOP_TYPE (right));
6393 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6395 AOP_SIZE (left), AOP_SIZE (right));
6398 /* if left is a literal & right is not then exchange them */
6399 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6400 #ifdef LOGIC_OPS_BROKEN
6401 || AOP_NEEDSACC (left) // I think this is a net loss now.
6405 operand *tmp = right;
6410 /* if result = right then exchange them */
6411 if (sameRegs (AOP (result), AOP (right)))
6413 operand *tmp = right;
6418 /* if right is bit then exchange them */
6419 if (AOP_TYPE (right) == AOP_CRY &&
6420 AOP_TYPE (left) != AOP_CRY)
6422 operand *tmp = right;
6426 if (AOP_TYPE (right) == AOP_LIT)
6427 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6429 size = AOP_SIZE (result);
6433 if (AOP_TYPE (left) == AOP_CRY)
6435 if (AOP_TYPE (right) == AOP_LIT)
6437 // c = bit & literal;
6440 // lit != 0 => result = 1
6441 if (AOP_TYPE (result) == AOP_CRY)
6444 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6446 continueIfTrue (ifx);
6449 emitcode ("setb", "c");
6453 // lit == 0 => result = left
6454 if (size && sameRegs (AOP (result), AOP (left)))
6456 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6461 if (AOP_TYPE (right) == AOP_CRY)
6464 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6465 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6470 symbol *tlbl = newiTempLabel (NULL);
6471 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6472 emitcode ("setb", "c");
6473 emitcode ("jb", "%s,!tlabel",
6474 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6476 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6477 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6479 jmpTrueOrFalse (ifx, tlbl);
6485 emitcode ("", "!tlabeldef", tlbl->key + 100);
6494 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6495 genIfxJump (ifx, "c");
6499 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6500 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6501 if ((AOP_TYPE (right) == AOP_LIT) &&
6502 (AOP_TYPE (result) == AOP_CRY) &&
6503 (AOP_TYPE (left) != AOP_CRY))
6509 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6511 continueIfTrue (ifx);
6516 // lit = 0, result = boolean(left)
6518 emitcode ("setb", "c");
6522 symbol *tlbl = newiTempLabel (NULL);
6523 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6525 emitcode ("", "!tlabeldef", tlbl->key + 100);
6529 genIfxJump (ifx, "a");
6537 /* if left is same as result */
6538 if (sameRegs (AOP (result), AOP (left)))
6540 for (; size--; offset++)
6542 if (AOP_TYPE (right) == AOP_LIT)
6544 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6550 if (IS_AOP_PREG (left))
6552 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6553 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6554 aopPut (AOP (result), "a", offset);
6558 emitcode ("orl", "%s,%s",
6559 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6560 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6566 if (AOP_TYPE (left) == AOP_ACC)
6568 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6572 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6573 if (IS_AOP_PREG (left))
6575 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6576 aopPut (AOP (result), "a", offset);
6580 emitcode ("orl", "%s,a",
6581 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6589 // left & result in different registers
6590 if (AOP_TYPE (result) == AOP_CRY)
6593 // if(size), result in bit
6594 // if(!size && ifx), conditional oper: if(left | right)
6595 symbol *tlbl = newiTempLabel (NULL);
6596 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6598 emitcode ("setb", "c");
6601 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6602 emitcode ("orl", "a,%s",
6603 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6605 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6606 emitcode ("orl", "a,%s",
6607 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6609 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6615 emitcode ("", "!tlabeldef", tlbl->key + 100);
6619 jmpTrueOrFalse (ifx, tlbl);
6623 _startLazyDPSEvaluation();
6624 for (; (size--); offset++)
6627 // result = left & right
6628 if (AOP_TYPE (right) == AOP_LIT)
6630 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6632 aopPut (AOP (result),
6633 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6637 D (emitcode (";", "better literal OR."););
6638 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6639 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
6640 FALSE, FALSE, FALSE));
6645 // faster than result <- left, anl result,right
6646 // and better if result is SFR
6647 if (AOP_TYPE (left) == AOP_ACC)
6649 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
6650 FALSE, FALSE, FALSE));
6654 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6656 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6658 emitcode("mov", "b,a");
6662 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6663 emitcode ("orl", "a,%s", rOp);
6666 aopPut (AOP (result), "a", offset);
6668 _endLazyDPSEvaluation();
6673 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6674 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6675 freeAsmop (result, NULL, ic, TRUE);
6678 /*-----------------------------------------------------------------*/
6679 /* genXor - code for xclusive or */
6680 /*-----------------------------------------------------------------*/
6682 genXor (iCode * ic, iCode * ifx)
6684 operand *left, *right, *result;
6685 int size, offset = 0;
6686 unsigned long lit = 0L;
6689 D (emitcode (";", "genXor "););
6691 AOP_OP_3_NOFATAL (ic, pushResult);
6692 AOP_SET_LOCALS (ic);
6696 genFarFarLogicOp(ic, "xrl");
6701 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6703 AOP_TYPE (left), AOP_TYPE (right));
6704 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6706 AOP_SIZE (left), AOP_SIZE (right));
6709 /* if left is a literal & right is not ||
6710 if left needs acc & right does not */
6711 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6712 #ifdef LOGIC_OPS_BROKEN
6713 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6717 operand *tmp = right;
6722 /* if result = right then exchange them */
6723 if (sameRegs (AOP (result), AOP (right)))
6725 operand *tmp = right;
6730 /* if right is bit then exchange them */
6731 if (AOP_TYPE (right) == AOP_CRY &&
6732 AOP_TYPE (left) != AOP_CRY)
6734 operand *tmp = right;
6738 if (AOP_TYPE (right) == AOP_LIT)
6739 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6741 size = AOP_SIZE (result);
6745 if (AOP_TYPE (left) == AOP_CRY)
6747 if (AOP_TYPE (right) == AOP_LIT)
6749 // c = bit & literal;
6752 // lit>>1 != 0 => result = 1
6753 if (AOP_TYPE (result) == AOP_CRY)
6756 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6758 continueIfTrue (ifx);
6761 emitcode ("setb", "c");
6768 // lit == 0, result = left
6769 if (size && sameRegs (AOP (result), AOP (left)))
6771 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6775 // lit == 1, result = not(left)
6776 if (size && sameRegs (AOP (result), AOP (left)))
6778 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6783 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6784 emitcode ("cpl", "c");
6793 symbol *tlbl = newiTempLabel (NULL);
6794 if (AOP_TYPE (right) == AOP_CRY)
6797 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6801 int sizer = AOP_SIZE (right);
6803 // if val>>1 != 0, result = 1
6804 emitcode ("setb", "c");
6807 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
6809 // test the msb of the lsb
6810 emitcode ("anl", "a,#!constbyte",0xfe);
6811 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6815 emitcode ("rrc", "a");
6817 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6818 emitcode ("cpl", "c");
6819 emitcode ("", "!tlabeldef", (tlbl->key + 100));
6826 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6827 genIfxJump (ifx, "c");
6831 if (sameRegs (AOP (result), AOP (left)))
6833 /* if left is same as result */
6834 for (; size--; offset++)
6836 if (AOP_TYPE (right) == AOP_LIT)
6838 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6840 else if (IS_AOP_PREG (left))
6842 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6843 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6844 aopPut (AOP (result), "a", offset);
6847 emitcode ("xrl", "%s,%s",
6848 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6849 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6853 if (AOP_TYPE (left) == AOP_ACC)
6854 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6857 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6858 if (IS_AOP_PREG (left))
6860 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6861 aopPut (AOP (result), "a", offset);
6864 emitcode ("xrl", "%s,a",
6865 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6872 // left & result in different registers
6873 if (AOP_TYPE (result) == AOP_CRY)
6876 // if(size), result in bit
6877 // if(!size && ifx), conditional oper: if(left ^ right)
6878 symbol *tlbl = newiTempLabel (NULL);
6879 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6882 emitcode ("setb", "c");
6885 if ((AOP_TYPE (right) == AOP_LIT) &&
6886 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6888 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6892 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6893 emitcode ("xrl", "a,%s",
6894 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6896 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6897 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6899 emitcode("mov", "b,a");
6903 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6904 emitcode ("xrl", "a,%s", rOp);
6907 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6913 emitcode ("", "!tlabeldef", tlbl->key + 100);
6917 jmpTrueOrFalse (ifx, tlbl);
6921 for (; (size--); offset++)
6924 // result = left & right
6925 if (AOP_TYPE (right) == AOP_LIT)
6927 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6929 aopPut (AOP (result),
6930 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6934 D (emitcode (";", "better literal XOR."););
6935 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6936 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
6937 FALSE, FALSE, FALSE));
6941 // faster than result <- left, anl result,right
6942 // and better if result is SFR
6943 if (AOP_TYPE (left) == AOP_ACC)
6945 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
6946 FALSE, FALSE, FALSE));
6950 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6951 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6953 emitcode("mov", "b,a");
6957 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6958 emitcode ("xrl", "a,%s", rOp);
6961 aopPut (AOP (result), "a", offset);
6968 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6969 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6970 freeAsmop (result, NULL, ic, TRUE);
6973 /*-----------------------------------------------------------------*/
6974 /* genInline - write the inline code out */
6975 /*-----------------------------------------------------------------*/
6977 genInline (iCode * ic)
6979 char *buffer, *bp, *bp1;
6981 D (emitcode (";", "genInline ");
6984 _G.inLine += (!options.asmpeep);
6986 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6987 strcpy (buffer, IC_INLINE (ic));
6989 /* emit each line as a code */
7014 /* emitcode("",buffer); */
7015 _G.inLine -= (!options.asmpeep);
7018 /*-----------------------------------------------------------------*/
7019 /* genRRC - rotate right with carry */
7020 /*-----------------------------------------------------------------*/
7024 operand *left, *result;
7025 int size, offset = 0;
7028 D (emitcode (";", "genRRC ");
7031 /* rotate right with carry */
7032 left = IC_LEFT (ic);
7033 result = IC_RESULT (ic);
7034 aopOp (left, ic, FALSE, FALSE);
7035 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7037 /* move it to the result */
7038 size = AOP_SIZE (result);
7042 _startLazyDPSEvaluation ();
7045 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
7047 emitcode ("rrc", "a");
7048 if (AOP_SIZE (result) > 1)
7049 aopPut (AOP (result), "a", offset--);
7051 _endLazyDPSEvaluation ();
7053 /* now we need to put the carry into the
7054 highest order byte of the result */
7055 if (AOP_SIZE (result) > 1)
7057 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
7060 emitcode ("mov", "acc.7,c");
7061 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7062 freeAsmop (left, NULL, ic, TRUE);
7063 freeAsmop (result, NULL, ic, TRUE);
7066 /*-----------------------------------------------------------------*/
7067 /* genRLC - generate code for rotate left with carry */
7068 /*-----------------------------------------------------------------*/
7072 operand *left, *result;
7073 int size, offset = 0;
7076 D (emitcode (";", "genRLC ");
7079 /* rotate right with carry */
7080 left = IC_LEFT (ic);
7081 result = IC_RESULT (ic);
7082 aopOp (left, ic, FALSE, FALSE);
7083 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7085 /* move it to the result */
7086 size = AOP_SIZE (result);
7090 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
7092 emitcode ("add", "a,acc");
7093 if (AOP_SIZE (result) > 1)
7095 aopPut (AOP (result), "a", offset++);
7098 _startLazyDPSEvaluation ();
7101 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
7103 emitcode ("rlc", "a");
7104 if (AOP_SIZE (result) > 1)
7105 aopPut (AOP (result), "a", offset++);
7107 _endLazyDPSEvaluation ();
7109 /* now we need to put the carry into the
7110 highest order byte of the result */
7111 if (AOP_SIZE (result) > 1)
7113 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
7116 emitcode ("mov", "acc.0,c");
7117 aopPut (AOP (result), "a", 0);
7118 freeAsmop (left, NULL, ic, TRUE);
7119 freeAsmop (result, NULL, ic, TRUE);
7122 /*-----------------------------------------------------------------*/
7123 /* genGetHbit - generates code get highest order bit */
7124 /*-----------------------------------------------------------------*/
7126 genGetHbit (iCode * ic)
7128 operand *left, *result;
7129 left = IC_LEFT (ic);
7130 result = IC_RESULT (ic);
7131 aopOp (left, ic, FALSE, FALSE);
7132 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7134 D (emitcode (";", "genGetHbit ");
7137 /* get the highest order byte into a */
7138 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
7139 if (AOP_TYPE (result) == AOP_CRY)
7141 emitcode ("rlc", "a");
7146 emitcode ("rl", "a");
7147 emitcode ("anl", "a,#1");
7152 freeAsmop (left, NULL, ic, TRUE);
7153 freeAsmop (result, NULL, ic, TRUE);
7156 /*-----------------------------------------------------------------*/
7157 /* AccRol - rotate left accumulator by known count */
7158 /*-----------------------------------------------------------------*/
7160 AccRol (int shCount)
7162 shCount &= 0x0007; // shCount : 0..7
7169 emitcode ("rl", "a");
7172 emitcode ("rl", "a");
7173 emitcode ("rl", "a");
7176 emitcode ("swap", "a");
7177 emitcode ("rr", "a");
7180 emitcode ("swap", "a");
7183 emitcode ("swap", "a");
7184 emitcode ("rl", "a");
7187 emitcode ("rr", "a");
7188 emitcode ("rr", "a");
7191 emitcode ("rr", "a");
7196 /*-----------------------------------------------------------------*/
7197 /* AccLsh - left shift accumulator by known count */
7198 /*-----------------------------------------------------------------*/
7200 AccLsh (int shCount)
7205 emitcode ("add", "a,acc");
7206 else if (shCount == 2)
7208 emitcode ("add", "a,acc");
7209 emitcode ("add", "a,acc");
7213 /* rotate left accumulator */
7215 /* and kill the lower order bits */
7216 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7221 /*-----------------------------------------------------------------*/
7222 /* AccRsh - right shift accumulator by known count */
7223 /*-----------------------------------------------------------------*/
7225 AccRsh (int shCount)
7232 emitcode ("rrc", "a");
7236 /* rotate right accumulator */
7237 AccRol (8 - shCount);
7238 /* and kill the higher order bits */
7239 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7244 #ifdef BETTER_LITERAL_SHIFT
7245 /*-----------------------------------------------------------------*/
7246 /* AccSRsh - signed right shift accumulator by known count */
7247 /*-----------------------------------------------------------------*/
7249 AccSRsh (int shCount)
7256 emitcode ("mov", "c,acc.7");
7257 emitcode ("rrc", "a");
7259 else if (shCount == 2)
7261 emitcode ("mov", "c,acc.7");
7262 emitcode ("rrc", "a");
7263 emitcode ("mov", "c,acc.7");
7264 emitcode ("rrc", "a");
7268 tlbl = newiTempLabel (NULL);
7269 /* rotate right accumulator */
7270 AccRol (8 - shCount);
7271 /* and kill the higher order bits */
7272 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7273 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7274 emitcode ("orl", "a,#!constbyte",
7275 (unsigned char) ~SRMask[shCount]);
7276 emitcode ("", "!tlabeldef", tlbl->key + 100);
7282 #ifdef BETTER_LITERAL_SHIFT
7283 /*-----------------------------------------------------------------*/
7284 /* shiftR1Left2Result - shift right one byte from left to result */
7285 /*-----------------------------------------------------------------*/
7287 shiftR1Left2Result (operand * left, int offl,
7288 operand * result, int offr,
7289 int shCount, int sign)
7291 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7292 /* shift right accumulator */
7297 aopPut (AOP (result), "a", offr);
7301 #ifdef BETTER_LITERAL_SHIFT
7302 /*-----------------------------------------------------------------*/
7303 /* shiftL1Left2Result - shift left one byte from left to result */
7304 /*-----------------------------------------------------------------*/
7306 shiftL1Left2Result (operand * left, int offl,
7307 operand * result, int offr, int shCount)
7309 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7310 /* shift left accumulator */
7312 aopPut (AOP (result), "a", offr);
7316 #ifdef BETTER_LITERAL_SHIFT
7317 /*-----------------------------------------------------------------*/
7318 /* movLeft2Result - move byte from left to result */
7319 /*-----------------------------------------------------------------*/
7321 movLeft2Result (operand * left, int offl,
7322 operand * result, int offr, int sign)
7325 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7327 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
7329 if (*l == '@' && (IS_AOP_PREG (result)))
7331 emitcode ("mov", "a,%s", l);
7332 aopPut (AOP (result), "a", offr);
7338 aopPut (AOP (result), l, offr);
7342 /* MSB sign in acc.7 ! */
7343 if (getDataSize (left) == offl + 1)
7345 emitcode ("mov", "a,%s", l);
7346 aopPut (AOP (result), "a", offr);
7354 #ifdef BETTER_LITERAL_SHIFT
7355 /*-----------------------------------------------------------------*/
7356 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7357 /*-----------------------------------------------------------------*/
7361 emitcode ("rrc", "a");
7362 emitcode ("xch", "a,%s", x);
7363 emitcode ("rrc", "a");
7364 emitcode ("xch", "a,%s", x);
7368 #ifdef BETTER_LITERAL_SHIFT
7370 /*-----------------------------------------------------------------*/
7371 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7372 /*-----------------------------------------------------------------*/
7376 emitcode ("xch", "a,%s", x);
7377 emitcode ("rlc", "a");
7378 emitcode ("xch", "a,%s", x);
7379 emitcode ("rlc", "a");
7383 #ifdef BETTER_LITERAL_SHIFT
7384 /*-----------------------------------------------------------------*/
7385 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7386 /*-----------------------------------------------------------------*/
7390 emitcode ("xch", "a,%s", x);
7391 emitcode ("add", "a,acc");
7392 emitcode ("xch", "a,%s", x);
7393 emitcode ("rlc", "a");
7397 #ifdef BETTER_LITERAL_SHIFT
7398 /*-----------------------------------------------------------------*/
7399 /* AccAXLsh - left shift a:x by known count (0..7) */
7400 /*-----------------------------------------------------------------*/
7402 AccAXLsh (char *x, int shCount)
7417 case 5: // AAAAABBB:CCCCCDDD
7419 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7421 emitcode ("anl", "a,#!constbyte",
7422 SLMask[shCount]); // BBB00000:CCCCCDDD
7424 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7426 AccRol (shCount); // DDDCCCCC:BBB00000
7428 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7430 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7432 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7434 emitcode ("anl", "a,#!constbyte",
7435 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7437 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7439 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7442 case 6: // AAAAAABB:CCCCCCDD
7443 emitcode ("anl", "a,#!constbyte",
7444 SRMask[shCount]); // 000000BB:CCCCCCDD
7445 emitcode ("mov", "c,acc.0"); // c = B
7446 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7448 AccAXRrl1 (x); // BCCCCCCD:D000000B
7449 AccAXRrl1 (x); // BBCCCCCC:DD000000
7451 emitcode("rrc","a");
7452 emitcode("xch","a,%s", x);
7453 emitcode("rrc","a");
7454 emitcode("mov","c,acc.0"); //<< get correct bit
7455 emitcode("xch","a,%s", x);
7457 emitcode("rrc","a");
7458 emitcode("xch","a,%s", x);
7459 emitcode("rrc","a");
7460 emitcode("xch","a,%s", x);
7463 case 7: // a:x <<= 7
7465 emitcode ("anl", "a,#!constbyte",
7466 SRMask[shCount]); // 0000000B:CCCCCCCD
7468 emitcode ("mov", "c,acc.0"); // c = B
7470 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7472 AccAXRrl1 (x); // BCCCCCCC:D0000000
7481 #ifdef BETTER_LITERAL_SHIFT
7483 /*-----------------------------------------------------------------*/
7484 /* AccAXRsh - right shift a:x known count (0..7) */
7485 /*-----------------------------------------------------------------*/
7487 AccAXRsh (char *x, int shCount)
7495 AccAXRrl1 (x); // 0->a:x
7500 AccAXRrl1 (x); // 0->a:x
7503 AccAXRrl1 (x); // 0->a:x
7508 case 5: // AAAAABBB:CCCCCDDD = a:x
7510 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7512 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7514 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7516 emitcode ("anl", "a,#!constbyte",
7517 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7519 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7521 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7523 emitcode ("anl", "a,#!constbyte",
7524 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7526 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7528 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7530 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7533 case 6: // AABBBBBB:CCDDDDDD
7535 emitcode ("mov", "c,acc.7");
7536 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7538 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7540 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7542 emitcode ("anl", "a,#!constbyte",
7543 SRMask[shCount]); // 000000AA:BBBBBBCC
7546 case 7: // ABBBBBBB:CDDDDDDD
7548 emitcode ("mov", "c,acc.7"); // c = A
7550 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7552 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7554 emitcode ("anl", "a,#!constbyte",
7555 SRMask[shCount]); // 0000000A:BBBBBBBC
7564 #ifdef BETTER_LITERAL_SHIFT
7565 /*-----------------------------------------------------------------*/
7566 /* AccAXRshS - right shift signed a:x known count (0..7) */
7567 /*-----------------------------------------------------------------*/
7569 AccAXRshS (char *x, int shCount)
7577 emitcode ("mov", "c,acc.7");
7578 AccAXRrl1 (x); // s->a:x
7582 emitcode ("mov", "c,acc.7");
7583 AccAXRrl1 (x); // s->a:x
7585 emitcode ("mov", "c,acc.7");
7586 AccAXRrl1 (x); // s->a:x
7591 case 5: // AAAAABBB:CCCCCDDD = a:x
7593 tlbl = newiTempLabel (NULL);
7594 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7596 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7598 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7600 emitcode ("anl", "a,#!constbyte",
7601 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7603 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7605 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7607 emitcode ("anl", "a,#!constbyte",
7608 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7610 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7612 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7614 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7616 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7617 emitcode ("orl", "a,#!constbyte",
7618 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7620 emitcode ("", "!tlabeldef", tlbl->key + 100);
7621 break; // SSSSAAAA:BBBCCCCC
7623 case 6: // AABBBBBB:CCDDDDDD
7625 tlbl = newiTempLabel (NULL);
7626 emitcode ("mov", "c,acc.7");
7627 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7629 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7631 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7633 emitcode ("anl", "a,#!constbyte",
7634 SRMask[shCount]); // 000000AA:BBBBBBCC
7636 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7637 emitcode ("orl", "a,#!constbyte",
7638 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7640 emitcode ("", "!tlabeldef", tlbl->key + 100);
7642 case 7: // ABBBBBBB:CDDDDDDD
7644 tlbl = newiTempLabel (NULL);
7645 emitcode ("mov", "c,acc.7"); // c = A
7647 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7649 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7651 emitcode ("anl", "a,#!constbyte",
7652 SRMask[shCount]); // 0000000A:BBBBBBBC
7654 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7655 emitcode ("orl", "a,#!constbyte",
7656 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7658 emitcode ("", "!tlabeldef", tlbl->key + 100);
7666 #ifdef BETTER_LITERAL_SHIFT
7668 _loadLeftIntoAx(char **lsb,
7674 // Get the initial value from left into a pair of registers.
7675 // MSB must be in A, LSB can be any register.
7677 // If the result is held in registers, it is an optimization
7678 // if the LSB can be held in the register which will hold the,
7679 // result LSB since this saves us from having to copy it into
7680 // the result following AccAXLsh.
7682 // If the result is addressed indirectly, this is not a gain.
7683 if (AOP_NEEDSACC(result))
7687 _startLazyDPSEvaluation();
7688 if (AOP_TYPE(left) == AOP_DPTR2)
7691 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
7692 // get LSB in DP2_RESULT_REG.
7693 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
7694 assert(!strcmp(leftByte, DP2_RESULT_REG));
7698 // get LSB into DP2_RESULT_REG
7699 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
7700 if (strcmp(leftByte, DP2_RESULT_REG))
7703 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7706 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
7707 assert(strcmp(leftByte, DP2_RESULT_REG));
7710 _endLazyDPSEvaluation();
7711 *lsb = DP2_RESULT_REG;
7715 if (sameRegs (AOP (result), AOP (left)) &&
7716 ((offl + MSB16) == offr))
7718 /* don't crash result[offr] */
7719 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
7720 emitcode ("xch", "a,%s",
7721 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
7725 movLeft2Result (left, offl, result, offr, 0);
7726 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
7728 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
7729 assert(strcmp(*lsb,"a"));
7734 _storeAxResults(char *lsb,
7738 _startLazyDPSEvaluation();
7739 if (AOP_NEEDSACC(result))
7741 /* We have to explicitly update the result LSB.
7743 emitcode("xch","a,%s", lsb);
7744 aopPut(AOP(result), "a", offr);
7745 emitcode("mov","a,%s", lsb);
7747 if (getDataSize (result) > 1)
7749 aopPut (AOP (result), "a", offr + MSB16);
7751 _endLazyDPSEvaluation();
7754 /*-----------------------------------------------------------------*/
7755 /* shiftL2Left2Result - shift left two bytes from left to result */
7756 /*-----------------------------------------------------------------*/
7758 shiftL2Left2Result (operand * left, int offl,
7759 operand * result, int offr, int shCount)
7763 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7765 AccAXLsh (lsb, shCount);
7767 _storeAxResults(lsb, result, offr);
7771 #ifdef BETTER_LITERAL_SHIFT
7772 /*-----------------------------------------------------------------*/
7773 /* shiftR2Left2Result - shift right two bytes from left to result */
7774 /*-----------------------------------------------------------------*/
7776 shiftR2Left2Result (operand * left, int offl,
7777 operand * result, int offr,
7778 int shCount, int sign)
7782 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7784 /* a:x >> shCount (x = lsb(result)) */
7787 AccAXRshS(lsb, shCount);
7791 AccAXRsh(lsb, shCount);
7794 _storeAxResults(lsb, result, offr);
7800 /*-----------------------------------------------------------------*/
7801 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7802 /*-----------------------------------------------------------------*/
7804 shiftLLeftOrResult (operand * left, int offl,
7805 operand * result, int offr, int shCount)
7807 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7808 /* shift left accumulator */
7810 /* or with result */
7811 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7812 /* back to result */
7813 aopPut (AOP (result), "a", offr);
7819 /*-----------------------------------------------------------------*/
7820 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7821 /*-----------------------------------------------------------------*/
7823 shiftRLeftOrResult (operand * left, int offl,
7824 operand * result, int offr, int shCount)
7826 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7827 /* shift right accumulator */
7829 /* or with result */
7830 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7831 /* back to result */
7832 aopPut (AOP (result), "a", offr);
7836 #ifdef BETTER_LITERAL_SHIFT
7837 /*-----------------------------------------------------------------*/
7838 /* genlshOne - left shift a one byte quantity by known count */
7839 /*-----------------------------------------------------------------*/
7841 genlshOne (operand * result, operand * left, int shCount)
7843 D (emitcode (";", "genlshOne "););
7844 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7848 #ifdef BETTER_LITERAL_SHIFT
7849 /*-----------------------------------------------------------------*/
7850 /* genlshTwo - left shift two bytes by known amount != 0 */
7851 /*-----------------------------------------------------------------*/
7853 genlshTwo (operand * result, operand * left, int shCount)
7857 D (emitcode (";", "genlshTwo "););
7859 size = getDataSize (result);
7861 /* if shCount >= 8 */
7866 _startLazyDPSEvaluation();
7872 _endLazyDPSEvaluation();
7873 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7874 aopPut (AOP (result), zero, LSB);
7878 movLeft2Result (left, LSB, result, MSB16, 0);
7879 aopPut (AOP (result), zero, LSB);
7880 _endLazyDPSEvaluation();
7885 aopPut (AOP (result), zero, LSB);
7886 _endLazyDPSEvaluation();
7890 /* 1 <= shCount <= 7 */
7895 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7899 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7907 /*-----------------------------------------------------------------*/
7908 /* shiftLLong - shift left one long from left to result */
7909 /* offl = LSB or MSB16 */
7910 /*-----------------------------------------------------------------*/
7912 shiftLLong (operand * left, operand * result, int offr)
7915 int size = AOP_SIZE (result);
7917 if (size >= LSB + offr)
7919 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
7921 emitcode ("add", "a,acc");
7922 if (sameRegs (AOP (left), AOP (result)) &&
7923 size >= MSB16 + offr && offr != LSB)
7924 emitcode ("xch", "a,%s",
7925 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
7927 aopPut (AOP (result), "a", LSB + offr);
7930 if (size >= MSB16 + offr)
7932 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7934 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
7937 emitcode ("rlc", "a");
7938 if (sameRegs (AOP (left), AOP (result)) &&
7939 size >= MSB24 + offr && offr != LSB)
7940 emitcode ("xch", "a,%s",
7941 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
7943 aopPut (AOP (result), "a", MSB16 + offr);
7946 if (size >= MSB24 + offr)
7948 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7950 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
7953 emitcode ("rlc", "a");
7954 if (sameRegs (AOP (left), AOP (result)) &&
7955 size >= MSB32 + offr && offr != LSB)
7956 emitcode ("xch", "a,%s",
7957 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
7959 aopPut (AOP (result), "a", MSB24 + offr);
7962 if (size > MSB32 + offr)
7964 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7966 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7969 emitcode ("rlc", "a");
7970 aopPut (AOP (result), "a", MSB32 + offr);
7973 aopPut (AOP (result), zero, LSB);
7979 /*-----------------------------------------------------------------*/
7980 /* genlshFour - shift four byte by a known amount != 0 */
7981 /*-----------------------------------------------------------------*/
7983 genlshFour (operand * result, operand * left, int shCount)
7987 D (emitcode (";", "genlshFour ");
7990 size = AOP_SIZE (result);
7992 /* if shifting more that 3 bytes */
7997 /* lowest order of left goes to the highest
7998 order of the destination */
7999 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8001 movLeft2Result (left, LSB, result, MSB32, 0);
8002 aopPut (AOP (result), zero, LSB);
8003 aopPut (AOP (result), zero, MSB16);
8004 aopPut (AOP (result), zero, MSB24);
8008 /* more than two bytes */
8009 else if (shCount >= 16)
8011 /* lower order two bytes goes to higher order two bytes */
8013 /* if some more remaining */
8015 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8018 movLeft2Result (left, MSB16, result, MSB32, 0);
8019 movLeft2Result (left, LSB, result, MSB24, 0);
8021 aopPut (AOP (result), zero, MSB16);
8022 aopPut (AOP (result), zero, LSB);
8026 /* if more than 1 byte */
8027 else if (shCount >= 8)
8029 /* lower order three bytes goes to higher order three bytes */
8034 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8036 movLeft2Result (left, LSB, result, MSB16, 0);
8042 movLeft2Result (left, MSB24, result, MSB32, 0);
8043 movLeft2Result (left, MSB16, result, MSB24, 0);
8044 movLeft2Result (left, LSB, result, MSB16, 0);
8045 aopPut (AOP (result), zero, LSB);
8047 else if (shCount == 1)
8048 shiftLLong (left, result, MSB16);
8051 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8052 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8053 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8054 aopPut (AOP (result), zero, LSB);
8059 /* 1 <= shCount <= 7 */
8060 else if (shCount <= 2)
8062 shiftLLong (left, result, LSB);
8064 shiftLLong (result, result, LSB);
8066 /* 3 <= shCount <= 7, optimize */
8069 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8070 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8071 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8076 #ifdef BETTER_LITERAL_SHIFT
8077 /*-----------------------------------------------------------------*/
8078 /* genLeftShiftLiteral - left shifting by known count */
8079 /*-----------------------------------------------------------------*/
8081 genLeftShiftLiteral (operand * left,
8086 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8089 size = getSize (operandType (result));
8091 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8093 /* We only handle certain easy cases so far. */
8095 && (shCount < (size * 8))
8099 D(emitcode (";", "genLeftShiftLiteral wimping out"););
8103 freeAsmop (right, NULL, ic, TRUE);
8105 aopOp(left, ic, FALSE, FALSE);
8106 aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
8109 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8111 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8112 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8114 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8117 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8119 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8120 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8122 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8128 emitcode ("; shift left ", "result %d, left %d", size,
8132 /* I suppose that the left size >= result size */
8135 _startLazyDPSEvaluation();
8138 movLeft2Result (left, size, result, size, 0);
8140 _endLazyDPSEvaluation();
8142 else if (shCount >= (size * 8))
8144 _startLazyDPSEvaluation();
8147 aopPut (AOP (result), zero, size);
8149 _endLazyDPSEvaluation();
8156 genlshOne (result, left, shCount);
8160 genlshTwo (result, left, shCount);
8164 genlshFour (result, left, shCount);
8168 fprintf(stderr, "*** ack! mystery literal shift!\n");
8172 freeAsmop (left, NULL, ic, TRUE);
8173 freeAsmop (result, NULL, ic, TRUE);
8178 /*-----------------------------------------------------------------*/
8179 /* genLeftShift - generates code for left shifting */
8180 /*-----------------------------------------------------------------*/
8182 genLeftShift (iCode * ic)
8184 operand *left, *right, *result;
8187 symbol *tlbl, *tlbl1;
8189 D (emitcode (";", "genLeftShift "););
8191 right = IC_RIGHT (ic);
8192 left = IC_LEFT (ic);
8193 result = IC_RESULT (ic);
8195 aopOp (right, ic, FALSE, FALSE);
8198 #ifdef BETTER_LITERAL_SHIFT
8199 /* if the shift count is known then do it
8200 as efficiently as possible */
8201 if (AOP_TYPE (right) == AOP_LIT)
8203 if (genLeftShiftLiteral (left, right, result, ic))
8210 /* shift count is unknown then we have to form
8211 a loop get the loop count in B : Note: we take
8212 only the lower order byte since shifting
8213 more that 32 bits make no sense anyway, ( the
8214 largest size of an object can be only 32 bits ) */
8216 if (AOP_TYPE (right) == AOP_LIT)
8218 /* Really should be handled by genLeftShiftLiteral,
8219 * but since I'm too lazy to fix that today, at least we can make
8220 * some small improvement.
8222 emitcode("mov", "b,#!constbyte",
8223 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8227 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8228 emitcode ("inc", "b");
8230 freeAsmop (right, NULL, ic, TRUE);
8231 aopOp (left, ic, FALSE, FALSE);
8232 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8234 /* now move the left to the result if they are not the
8236 if (!sameRegs (AOP (left), AOP (result)) &&
8237 AOP_SIZE (result) > 1)
8240 size = AOP_SIZE (result);
8242 _startLazyDPSEvaluation ();
8245 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8246 if (*l == '@' && (IS_AOP_PREG (result)))
8249 emitcode ("mov", "a,%s", l);
8250 aopPut (AOP (result), "a", offset);
8253 aopPut (AOP (result), l, offset);
8256 _endLazyDPSEvaluation ();
8259 tlbl = newiTempLabel (NULL);
8260 size = AOP_SIZE (result);
8262 tlbl1 = newiTempLabel (NULL);
8264 /* if it is only one byte then */
8267 symbol *tlbl1 = newiTempLabel (NULL);
8269 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8271 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8272 emitcode ("", "!tlabeldef", tlbl->key + 100);
8273 emitcode ("add", "a,acc");
8274 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8275 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8276 aopPut (AOP (result), "a", 0);
8280 reAdjustPreg (AOP (result));
8282 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8283 emitcode ("", "!tlabeldef", tlbl->key + 100);
8284 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8286 emitcode ("add", "a,acc");
8287 aopPut (AOP (result), "a", offset++);
8288 _startLazyDPSEvaluation ();
8291 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8293 emitcode ("rlc", "a");
8294 aopPut (AOP (result), "a", offset++);
8296 _endLazyDPSEvaluation ();
8297 reAdjustPreg (AOP (result));
8299 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8300 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8302 freeAsmop (left, NULL, ic, TRUE);
8303 freeAsmop (result, NULL, ic, TRUE);
8306 #ifdef BETTER_LITERAL_SHIFT
8307 /*-----------------------------------------------------------------*/
8308 /* genrshOne - right shift a one byte quantity by known count */
8309 /*-----------------------------------------------------------------*/
8311 genrshOne (operand * result, operand * left,
8312 int shCount, int sign)
8314 D (emitcode (";", "genrshOne"););
8315 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8319 #ifdef BETTER_LITERAL_SHIFT
8320 /*-----------------------------------------------------------------*/
8321 /* genrshTwo - right shift two bytes by known amount != 0 */
8322 /*-----------------------------------------------------------------*/
8324 genrshTwo (operand * result, operand * left,
8325 int shCount, int sign)
8327 D (emitcode (";", "genrshTwo"););
8329 /* if shCount >= 8 */
8333 _startLazyDPSEvaluation();
8336 shiftR1Left2Result (left, MSB16, result, LSB,
8341 movLeft2Result (left, MSB16, result, LSB, sign);
8343 addSign (result, MSB16, sign);
8344 _endLazyDPSEvaluation();
8347 /* 1 <= shCount <= 7 */
8350 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8357 /*-----------------------------------------------------------------*/
8358 /* shiftRLong - shift right one long from left to result */
8359 /* offl = LSB or MSB16 */
8360 /*-----------------------------------------------------------------*/
8362 shiftRLong (operand * left, int offl,
8363 operand * result, int sign)
8365 int isSameRegs=sameRegs(AOP(left),AOP(result));
8367 if (isSameRegs && offl>1) {
8368 // we are in big trouble, but this shouldn't happen
8369 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8372 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
8377 emitcode ("rlc", "a");
8378 emitcode ("subb", "a,acc");
8379 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
8381 aopPut (AOP(result), zero, MSB32);
8386 emitcode ("clr", "c");
8388 emitcode ("mov", "c,acc.7");
8391 emitcode ("rrc", "a");
8393 if (isSameRegs && offl==MSB16) {
8394 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
8396 aopPut (AOP (result), "a", MSB32);
8397 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
8400 emitcode ("rrc", "a");
8401 if (isSameRegs && offl==1) {
8402 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
8404 aopPut (AOP (result), "a", MSB24);
8405 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
8407 emitcode ("rrc", "a");
8408 aopPut (AOP (result), "a", MSB16 - offl);
8412 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
8413 emitcode ("rrc", "a");
8414 aopPut (AOP (result), "a", LSB);
8421 /*-----------------------------------------------------------------*/
8422 /* genrshFour - shift four byte by a known amount != 0 */
8423 /*-----------------------------------------------------------------*/
8425 genrshFour (operand * result, operand * left,
8426 int shCount, int sign)
8428 D (emitcode (";", "genrshFour");
8431 /* if shifting more that 3 bytes */
8436 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8438 movLeft2Result (left, MSB32, result, LSB, sign);
8439 addSign (result, MSB16, sign);
8441 else if (shCount >= 16)
8445 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8448 movLeft2Result (left, MSB24, result, LSB, 0);
8449 movLeft2Result (left, MSB32, result, MSB16, sign);
8451 addSign (result, MSB24, sign);
8453 else if (shCount >= 8)
8457 shiftRLong (left, MSB16, result, sign);
8458 else if (shCount == 0)
8460 movLeft2Result (left, MSB16, result, LSB, 0);
8461 movLeft2Result (left, MSB24, result, MSB16, 0);
8462 movLeft2Result (left, MSB32, result, MSB24, sign);
8463 addSign (result, MSB32, sign);
8467 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8468 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8469 /* the last shift is signed */
8470 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8471 addSign (result, MSB32, sign);
8475 { /* 1 <= shCount <= 7 */
8478 shiftRLong (left, LSB, result, sign);
8480 shiftRLong (result, LSB, result, sign);
8484 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8485 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8486 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8492 #ifdef BETTER_LITERAL_SHIFT
8493 /*-----------------------------------------------------------------*/
8494 /* genRightShiftLiteral - right shifting by known count */
8495 /*-----------------------------------------------------------------*/
8497 genRightShiftLiteral (operand * left,
8503 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8506 size = getSize (operandType (result));
8508 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8510 /* We only handle certain easy cases so far. */
8512 && (shCount < (size * 8))
8516 D(emitcode (";", "genRightShiftLiteral wimping out"););
8520 freeAsmop (right, NULL, ic, TRUE);
8522 aopOp (left, ic, FALSE, FALSE);
8523 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8526 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8530 /* test the LEFT size !!! */
8532 /* I suppose that the left size >= result size */
8535 size = getDataSize (result);
8536 _startLazyDPSEvaluation();
8539 movLeft2Result (left, size, result, size, 0);
8541 _endLazyDPSEvaluation();
8543 else if (shCount >= (size * 8))
8547 /* get sign in acc.7 */
8548 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
8550 addSign (result, LSB, sign);
8551 freeAsmop (left, NULL, ic, TRUE);
8552 freeAsmop (result, NULL, ic, TRUE);
8559 genrshOne (result, left, shCount, sign);
8563 genrshTwo (result, left, shCount, sign);
8567 genrshFour (result, left, shCount, sign);
8574 freeAsmop (left, NULL, ic, TRUE);
8575 freeAsmop (result, NULL, ic, TRUE);
8581 /*-----------------------------------------------------------------*/
8582 /* genSignedRightShift - right shift of signed number */
8583 /*-----------------------------------------------------------------*/
8585 genSignedRightShift (iCode * ic)
8587 operand *right, *left, *result;
8590 symbol *tlbl, *tlbl1;
8592 D (emitcode (";", "genSignedRightShift "););
8594 /* we do it the hard way put the shift count in b
8595 and loop thru preserving the sign */
8597 right = IC_RIGHT (ic);
8598 left = IC_LEFT (ic);
8599 result = IC_RESULT (ic);
8601 aopOp (right, ic, FALSE, FALSE);
8603 #ifdef BETTER_LITERAL_SHIFT
8604 if (AOP_TYPE (right) == AOP_LIT)
8606 if (genRightShiftLiteral (left, right, result, ic, 1))
8612 /* shift count is unknown then we have to form
8613 a loop get the loop count in B : Note: we take
8614 only the lower order byte since shifting
8615 more that 32 bits make no sense anyway, ( the
8616 largest size of an object can be only 32 bits ) */
8618 if (AOP_TYPE (right) == AOP_LIT)
8620 /* Really should be handled by genRightShiftLiteral,
8621 * but since I'm too lazy to fix that today, at least we can make
8622 * some small improvement.
8624 emitcode("mov", "b,#!constbyte",
8625 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8629 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8630 emitcode ("inc", "b");
8632 freeAsmop (right, NULL, ic, TRUE);
8633 aopOp (left, ic, FALSE, FALSE);
8634 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8636 /* now move the left to the result if they are not the
8638 if (!sameRegs (AOP (left), AOP (result)) &&
8639 AOP_SIZE (result) > 1)
8642 size = AOP_SIZE (result);
8644 _startLazyDPSEvaluation ();
8647 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8648 if (*l == '@' && IS_AOP_PREG (result))
8651 emitcode ("mov", "a,%s", l);
8652 aopPut (AOP (result), "a", offset);
8655 aopPut (AOP (result), l, offset);
8658 _endLazyDPSEvaluation ();
8661 /* mov the highest order bit to OVR */
8662 tlbl = newiTempLabel (NULL);
8663 tlbl1 = newiTempLabel (NULL);
8665 size = AOP_SIZE (result);
8667 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
8668 emitcode ("rlc", "a");
8669 emitcode ("mov", "ov,c");
8670 /* if it is only one byte then */
8673 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8675 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8676 emitcode ("", "!tlabeldef", tlbl->key + 100);
8677 emitcode ("mov", "c,ov");
8678 emitcode ("rrc", "a");
8679 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8680 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8681 aopPut (AOP (result), "a", 0);
8685 reAdjustPreg (AOP (result));
8686 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8687 emitcode ("", "!tlabeldef", tlbl->key + 100);
8688 emitcode ("mov", "c,ov");
8689 _startLazyDPSEvaluation ();
8692 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8694 emitcode ("rrc", "a");
8695 aopPut (AOP (result), "a", offset--);
8697 _endLazyDPSEvaluation ();
8698 reAdjustPreg (AOP (result));
8699 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8700 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8703 freeAsmop (left, NULL, ic, TRUE);
8704 freeAsmop (result, NULL, ic, TRUE);
8707 /*-----------------------------------------------------------------*/
8708 /* genRightShift - generate code for right shifting */
8709 /*-----------------------------------------------------------------*/
8711 genRightShift (iCode * ic)
8713 operand *right, *left, *result;
8717 symbol *tlbl, *tlbl1;
8719 D (emitcode (";", "genRightShift "););
8721 /* if signed then we do it the hard way preserve the
8722 sign bit moving it inwards */
8723 retype = getSpec (operandType (IC_RESULT (ic)));
8725 if (!SPEC_USIGN (retype))
8727 genSignedRightShift (ic);
8731 /* signed & unsigned types are treated the same : i.e. the
8732 signed is NOT propagated inwards : quoting from the
8733 ANSI - standard : "for E1 >> E2, is equivalent to division
8734 by 2**E2 if unsigned or if it has a non-negative value,
8735 otherwise the result is implementation defined ", MY definition
8736 is that the sign does not get propagated */
8738 right = IC_RIGHT (ic);
8739 left = IC_LEFT (ic);
8740 result = IC_RESULT (ic);
8742 aopOp (right, ic, FALSE, FALSE);
8744 #ifdef BETTER_LITERAL_SHIFT
8745 /* if the shift count is known then do it
8746 as efficiently as possible */
8747 if (AOP_TYPE (right) == AOP_LIT)
8749 if (genRightShiftLiteral (left, right, result, ic, 0))
8756 /* shift count is unknown then we have to form
8757 a loop get the loop count in B : Note: we take
8758 only the lower order byte since shifting
8759 more that 32 bits make no sense anyway, ( the
8760 largest size of an object can be only 32 bits ) */
8762 if (AOP_TYPE (right) == AOP_LIT)
8764 /* Really should be handled by genRightShiftLiteral,
8765 * but since I'm too lazy to fix that today, at least we can make
8766 * some small improvement.
8768 emitcode("mov", "b,#!constbyte",
8769 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8773 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8774 emitcode ("inc", "b");
8776 freeAsmop (right, NULL, ic, TRUE);
8777 aopOp (left, ic, FALSE, FALSE);
8778 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8780 /* now move the left to the result if they are not the
8782 if (!sameRegs (AOP (left), AOP (result)) &&
8783 AOP_SIZE (result) > 1)
8786 size = AOP_SIZE (result);
8788 _startLazyDPSEvaluation ();
8791 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8792 if (*l == '@' && IS_AOP_PREG (result))
8795 emitcode ("mov", "a,%s", l);
8796 aopPut (AOP (result), "a", offset);
8799 aopPut (AOP (result), l, offset);
8802 _endLazyDPSEvaluation ();
8805 tlbl = newiTempLabel (NULL);
8806 tlbl1 = newiTempLabel (NULL);
8807 size = AOP_SIZE (result);
8810 /* if it is only one byte then */
8813 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8815 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8816 emitcode ("", "!tlabeldef", tlbl->key + 100);
8818 emitcode ("rrc", "a");
8819 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8820 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8821 aopPut (AOP (result), "a", 0);
8825 reAdjustPreg (AOP (result));
8826 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8827 emitcode ("", "!tlabeldef", tlbl->key + 100);
8829 _startLazyDPSEvaluation ();
8832 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8834 emitcode ("rrc", "a");
8835 aopPut (AOP (result), "a", offset--);
8837 _endLazyDPSEvaluation ();
8838 reAdjustPreg (AOP (result));
8840 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8841 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8844 freeAsmop (left, NULL, ic, TRUE);
8845 freeAsmop (result, NULL, ic, TRUE);
8848 /*-----------------------------------------------------------------*/
8849 /* genUnpackBits - generates code for unpacking bits */
8850 /*-----------------------------------------------------------------*/
8852 genUnpackBits (operand * result, char *rname, int ptype)
8859 D (emitcode (";", "genUnpackBits ");
8862 etype = getSpec (operandType (result));
8864 /* read the first byte */
8870 emitcode ("mov", "a,@%s", rname);
8874 emitcode ("movx", "a,@%s", rname);
8878 emitcode ("movx", "a,@dptr");
8882 emitcode ("clr", "a");
8883 emitcode ("movc", "a,@a+dptr");
8887 emitcode ("lcall", "__gptrget");
8891 /* if we have bitdisplacement then it fits */
8892 /* into this byte completely or if length is */
8893 /* less than a byte */
8894 if ((shCnt = SPEC_BSTR (etype)) ||
8895 (SPEC_BLEN (etype) <= 8))
8898 /* shift right acc */
8901 emitcode ("anl", "a,#!constbyte",
8902 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8903 aopPut (AOP (result), "a", offset);
8907 /* bit field did not fit in a byte */
8908 rlen = SPEC_BLEN (etype) - 8;
8909 aopPut (AOP (result), "a", offset++);
8918 emitcode ("inc", "%s", rname);
8919 emitcode ("mov", "a,@%s", rname);
8923 emitcode ("inc", "%s", rname);
8924 emitcode ("movx", "a,@%s", rname);
8928 emitcode ("inc", "dptr");
8929 emitcode ("movx", "a,@dptr");
8933 emitcode ("clr", "a");
8934 emitcode ("inc", "dptr");
8935 emitcode ("movc", "a,@a+dptr");
8939 emitcode ("inc", "dptr");
8940 emitcode ("lcall", "__gptrget");
8945 /* if we are done */
8949 aopPut (AOP (result), "a", offset++);
8955 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (rlen));
8956 aopPut (AOP (result), "a", offset);
8963 /*-----------------------------------------------------------------*/
8964 /* genDataPointerGet - generates code when ptr offset is known */
8965 /*-----------------------------------------------------------------*/
8967 genDataPointerGet (operand * left,
8973 int size, offset = 0;
8974 aopOp (result, ic, TRUE, FALSE);
8976 /* get the string representation of the name */
8977 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8978 size = AOP_SIZE (result);
8979 _startLazyDPSEvaluation ();
8983 sprintf (buffer, "(%s + %d)", l + 1, offset);
8985 sprintf (buffer, "%s", l + 1);
8986 aopPut (AOP (result), buffer, offset++);
8988 _endLazyDPSEvaluation ();
8990 freeAsmop (left, NULL, ic, TRUE);
8991 freeAsmop (result, NULL, ic, TRUE);
8994 /*-----------------------------------------------------------------*/
8995 /* genNearPointerGet - emitcode for near pointer fetch */
8996 /*-----------------------------------------------------------------*/
8998 genNearPointerGet (operand * left,
9006 sym_link *rtype, *retype, *letype;
9007 sym_link *ltype = operandType (left);
9010 rtype = operandType (result);
9011 retype = getSpec (rtype);
9012 letype = getSpec (ltype);
9014 aopOp (left, ic, FALSE, FALSE);
9016 /* if left is rematerialisable and
9017 result is not bit variable type and
9018 the left is pointer to data space i.e
9019 lower 128 bytes of space */
9020 if (AOP_TYPE (left) == AOP_IMMD &&
9021 !IS_BITVAR (retype) &&
9022 !IS_BITVAR (letype) &&
9023 DCL_TYPE (ltype) == POINTER)
9025 genDataPointerGet (left, result, ic);
9029 /* if the value is already in a pointer register
9030 then don't need anything more */
9031 if (!AOP_INPREG (AOP (left)))
9033 /* otherwise get a free pointer register */
9035 preg = getFreePtr (ic, &aop, FALSE);
9036 emitcode ("mov", "%s,%s",
9038 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
9042 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
9044 freeAsmop (left, NULL, ic, TRUE);
9045 aopOp (result, ic, FALSE, FALSE);
9047 /* if bitfield then unpack the bits */
9048 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9049 genUnpackBits (result, rname, POINTER);
9052 /* we have can just get the values */
9053 int size = AOP_SIZE (result);
9058 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9061 emitcode ("mov", "a,@%s", rname);
9062 aopPut (AOP (result), "a", offset);
9066 sprintf (buffer, "@%s", rname);
9067 aopPut (AOP (result), buffer, offset);
9071 emitcode ("inc", "%s", rname);
9075 /* now some housekeeping stuff */
9078 /* we had to allocate for this iCode */
9079 if (pi) { /* post increment present */
9080 aopPut(AOP ( left ),rname,0);
9082 freeAsmop (NULL, aop, ic, TRUE);
9086 /* we did not allocate which means left
9087 already in a pointer register, then
9088 if size > 0 && this could be used again
9089 we have to point it back to where it
9091 if (AOP_SIZE (result) > 1 &&
9092 !OP_SYMBOL (left)->remat &&
9093 (OP_SYMBOL (left)->liveTo > ic->seq ||
9097 int size = AOP_SIZE (result) - 1;
9099 emitcode ("dec", "%s", rname);
9104 freeAsmop (result, NULL, ic, TRUE);
9105 if (pi) pi->generated = 1;
9108 /*-----------------------------------------------------------------*/
9109 /* genPagedPointerGet - emitcode for paged pointer fetch */
9110 /*-----------------------------------------------------------------*/
9112 genPagedPointerGet (operand * left,
9120 sym_link *rtype, *retype, *letype;
9122 rtype = operandType (result);
9123 retype = getSpec (rtype);
9124 letype = getSpec (operandType (left));
9125 aopOp (left, ic, FALSE, FALSE);
9127 /* if the value is already in a pointer register
9128 then don't need anything more */
9129 if (!AOP_INPREG (AOP (left)))
9131 /* otherwise get a free pointer register */
9133 preg = getFreePtr (ic, &aop, FALSE);
9134 emitcode ("mov", "%s,%s",
9136 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
9140 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
9142 freeAsmop (left, NULL, ic, TRUE);
9143 aopOp (result, ic, FALSE, FALSE);
9145 /* if bitfield then unpack the bits */
9146 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9147 genUnpackBits (result, rname, PPOINTER);
9150 /* we have can just get the values */
9151 int size = AOP_SIZE (result);
9157 emitcode ("movx", "a,@%s", rname);
9158 aopPut (AOP (result), "a", offset);
9163 emitcode ("inc", "%s", rname);
9167 /* now some housekeeping stuff */
9170 /* we had to allocate for this iCode */
9171 if (pi) aopPut ( AOP (left), rname, 0);
9172 freeAsmop (NULL, aop, ic, TRUE);
9176 /* we did not allocate which means left
9177 already in a pointer register, then
9178 if size > 0 && this could be used again
9179 we have to point it back to where it
9181 if (AOP_SIZE (result) > 1 &&
9182 !OP_SYMBOL (left)->remat &&
9183 (OP_SYMBOL (left)->liveTo > ic->seq ||
9187 int size = AOP_SIZE (result) - 1;
9189 emitcode ("dec", "%s", rname);
9194 freeAsmop (result, NULL, ic, TRUE);
9195 if (pi) pi->generated = 1;
9198 /*-----------------------------------------------------------------*/
9199 /* genFarPointerGet - gget value from far space */
9200 /*-----------------------------------------------------------------*/
9202 genFarPointerGet (operand * left,
9203 operand * result, iCode * ic, iCode *pi)
9205 int size, offset, dopi=1;
9206 sym_link *retype = getSpec (operandType (result));
9207 sym_link *letype = getSpec (operandType (left));
9208 D (emitcode (";", "genFarPointerGet");
9211 aopOp (left, ic, FALSE, FALSE);
9213 /* if the operand is already in dptr
9214 then we do nothing else we move the value to dptr */
9215 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9217 /* if this is remateriazable */
9218 if (AOP_TYPE (left) == AOP_IMMD)
9220 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9224 /* we need to get it byte by byte */
9225 _startLazyDPSEvaluation ();
9226 if (AOP_TYPE (left) != AOP_DPTR)
9228 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9229 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9230 if (options.model == MODEL_FLAT24)
9231 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9235 /* We need to generate a load to DPTR indirect through DPTR. */
9236 D (emitcode (";", "genFarPointerGet -- indirection special case.");
9238 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
9239 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
9240 if (options.model == MODEL_FLAT24)
9241 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9242 emitcode ("pop", "dph");
9243 emitcode ("pop", "dpl");
9246 _endLazyDPSEvaluation ();
9249 /* so dptr know contains the address */
9250 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9252 /* if bit then unpack */
9253 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9254 if (AOP_INDPTRn(left)) {
9255 genSetDPTR(AOP(left)->aopu.dptr);
9257 genUnpackBits (result, "dptr", FPOINTER);
9258 if (AOP_INDPTRn(left)) {
9263 size = AOP_SIZE (result);
9266 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9268 genSetDPTR(AOP(left)->aopu.dptr);
9269 emitcode ("movx", "a,@dptr");
9270 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9271 emitcode ("inc", "dptr");
9273 aopPut (AOP (result), "a", offset++);
9276 _startLazyDPSEvaluation ();
9278 if (AOP_INDPTRn(left)) {
9279 genSetDPTR(AOP(left)->aopu.dptr);
9285 emitcode ("movx", "a,@dptr");
9286 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9287 emitcode ("inc", "dptr");
9289 aopPut (AOP (result), "a", offset++);
9291 _endLazyDPSEvaluation ();
9294 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9295 if (!AOP_INDPTRn(left)) {
9296 aopPut ( AOP (left), "dpl", 0);
9297 aopPut ( AOP (left), "dph", 1);
9298 if (options.model == MODEL_FLAT24)
9299 aopPut ( AOP (left), "dpx", 2);
9302 } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
9303 AOP_SIZE(result) > 1 &&
9304 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9306 size = AOP_SIZE (result) - 1;
9307 if (AOP_INDPTRn(left)) {
9308 genSetDPTR(AOP(left)->aopu.dptr);
9310 while (size--) emitcode ("lcall","__decdptr");
9311 if (AOP_INDPTRn(left)) {
9316 freeAsmop (left, NULL, ic, TRUE);
9317 freeAsmop (result, NULL, ic, TRUE);
9320 /*-----------------------------------------------------------------*/
9321 /* genCodePointerGet - get value from code space */
9322 /*-----------------------------------------------------------------*/
9324 genCodePointerGet (operand * left,
9325 operand * result, iCode * ic, iCode *pi)
9327 int size, offset, dopi=1;
9328 sym_link *retype = getSpec (operandType (result));
9330 aopOp (left, ic, FALSE, FALSE);
9332 /* if the operand is already in dptr
9333 then we do nothing else we move the value to dptr */
9334 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
9336 /* if this is remateriazable */
9337 if (AOP_TYPE (left) == AOP_IMMD)
9339 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9342 { /* we need to get it byte by byte */
9343 _startLazyDPSEvaluation ();
9344 if (AOP_TYPE (left) != AOP_DPTR)
9346 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9347 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9348 if (options.model == MODEL_FLAT24)
9349 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9353 /* We need to generate a load to DPTR indirect through DPTR. */
9354 D (emitcode (";", "gencodePointerGet -- indirection special case.");
9356 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
9357 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
9358 if (options.model == MODEL_FLAT24)
9359 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9360 emitcode ("pop", "dph");
9361 emitcode ("pop", "dpl");
9364 _endLazyDPSEvaluation ();
9367 /* so dptr know contains the address */
9368 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9370 /* if bit then unpack */
9371 if (IS_BITVAR (retype)) {
9372 if (AOP_INDPTRn(left)) {
9373 genSetDPTR(AOP(left)->aopu.dptr);
9375 genUnpackBits (result, "dptr", CPOINTER);
9376 if (AOP_INDPTRn(left)) {
9381 size = AOP_SIZE (result);
9383 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9385 genSetDPTR(AOP(left)->aopu.dptr);
9386 emitcode ("clr", "a");
9387 emitcode ("movc", "a,@a+dptr");
9388 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9389 emitcode ("inc", "dptr");
9391 aopPut (AOP (result), "a", offset++);
9394 _startLazyDPSEvaluation ();
9397 if (AOP_INDPTRn(left)) {
9398 genSetDPTR(AOP(left)->aopu.dptr);
9404 emitcode ("clr", "a");
9405 emitcode ("movc", "a,@a+dptr");
9406 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9407 emitcode ("inc", "dptr");
9408 aopPut (AOP (result), "a", offset++);
9410 _endLazyDPSEvaluation ();
9413 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9414 if (!AOP_INDPTRn(left)) {
9415 aopPut ( AOP (left), "dpl", 0);
9416 aopPut ( AOP (left), "dph", 1);
9417 if (options.model == MODEL_FLAT24)
9418 aopPut ( AOP (left), "dpx", 2);
9421 } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
9422 AOP_SIZE(result) > 1 &&
9423 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9425 size = AOP_SIZE (result) - 1;
9426 if (AOP_INDPTRn(left)) {
9427 genSetDPTR(AOP(left)->aopu.dptr);
9429 while (size--) emitcode ("lcall","__decdptr");
9430 if (AOP_INDPTRn(left)) {
9435 freeAsmop (left, NULL, ic, TRUE);
9436 freeAsmop (result, NULL, ic, TRUE);
9439 /*-----------------------------------------------------------------*/
9440 /* genGenPointerGet - gget value from generic pointer space */
9441 /*-----------------------------------------------------------------*/
9443 genGenPointerGet (operand * left,
9444 operand * result, iCode * ic, iCode * pi)
9447 sym_link *retype = getSpec (operandType (result));
9448 sym_link *letype = getSpec (operandType (left));
9450 D (emitcode (";", "genGenPointerGet "); );
9452 aopOp (left, ic, FALSE, (OP_SYMBOL(left)->ruonly ? FALSE : TRUE));
9454 /* if the operand is already in dptr
9455 then we do nothing else we move the value to dptr */
9456 if (AOP_TYPE (left) != AOP_STR)
9458 /* if this is remateriazable */
9459 if (AOP_TYPE (left) == AOP_IMMD)
9461 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9462 if (AOP(left)->aopu.aop_immd.from_cast_remat)
9463 emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, FALSE));
9465 emitcode ("mov", "b,#%d", pointerCode (retype));
9468 { /* we need to get it byte by byte */
9469 _startLazyDPSEvaluation ();
9470 #if 0 // I see no point at all to this code.
9471 // So I yanked it. Kill at some future date if no bugs rear their heads.
9472 if (AOP(left)->type==AOP_DPTR2) {
9474 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
9477 emitcode ("mov", "dpl,%s", l);
9478 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
9481 emitcode ("mov", "dph,%s", l);
9482 if (options.model == MODEL_FLAT24) {
9483 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
9486 emitcode ("mov", "dpx,%s", l);
9487 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9489 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9495 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
9496 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
9497 if (options.model == MODEL_FLAT24) {
9498 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9499 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9501 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9504 _endLazyDPSEvaluation ();
9508 /* so dptr-b now contains the address */
9510 aopOp (result, ic, FALSE, TRUE);
9513 /* if bit then unpack */
9514 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9516 genUnpackBits (result, "dptr", GPOINTER);
9520 size = AOP_SIZE (result);
9527 // Get two bytes at a time, results in _AP & A.
9528 // dptr will be incremented ONCE by __gptrgetWord.
9530 // Note: any change here must be coordinated
9531 // with the implementation of __gptrgetWord
9532 // in device/lib/_gptrget.c
9533 emitcode ("lcall", "__gptrgetWord");
9534 aopPut (AOP (result), DP2_RESULT_REG, offset++);
9535 aopPut (AOP (result), "a", offset++);
9540 // Only one byte to get.
9541 emitcode ("lcall", "__gptrget");
9542 aopPut (AOP (result), "a", offset++);
9545 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9547 emitcode ("inc", "dptr");
9552 if (pi && AOP_TYPE (left) != AOP_IMMD) {
9553 aopPut ( AOP (left), "dpl", 0);
9554 aopPut ( AOP (left), "dph", 1);
9555 if (options.model == MODEL_FLAT24) {
9556 aopPut ( AOP (left), "dpx", 2);
9557 aopPut ( AOP (left), "b", 3);
9558 } else aopPut ( AOP (left), "b", 2);
9560 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9561 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9563 size = AOP_SIZE (result) - 1;
9564 while (size--) emitcode ("lcall","__decdptr");
9567 freeAsmop (left, NULL, ic, TRUE);
9568 freeAsmop (result, NULL, ic, TRUE);
9571 /*-----------------------------------------------------------------*/
9572 /* genPointerGet - generate code for pointer get */
9573 /*-----------------------------------------------------------------*/
9575 genPointerGet (iCode * ic, iCode *pi)
9577 operand *left, *result;
9578 sym_link *type, *etype;
9581 D (emitcode (";", "genPointerGet ");
9584 left = IC_LEFT (ic);
9585 result = IC_RESULT (ic);
9587 /* depending on the type of pointer we need to
9588 move it to the correct pointer register */
9589 type = operandType (left);
9590 etype = getSpec (type);
9591 /* if left is of type of pointer then it is simple */
9592 if (IS_PTR (type) && !IS_FUNC (type->next))
9593 p_type = DCL_TYPE (type);
9596 /* we have to go by the storage class */
9597 p_type = PTR_TYPE (SPEC_OCLS (etype));
9599 /* special case when cast remat */
9600 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9601 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9602 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9603 type = operandType (left);
9604 p_type = DCL_TYPE (type);
9606 /* now that we have the pointer type we assign
9607 the pointer values */
9613 genNearPointerGet (left, result, ic, pi);
9617 genPagedPointerGet (left, result, ic, pi);
9621 genFarPointerGet (left, result, ic, pi);
9625 genCodePointerGet (left, result, ic, pi);
9629 genGenPointerGet (left, result, ic, pi);
9635 /*-----------------------------------------------------------------*/
9636 /* genPackBits - generates code for packed bit storage */
9637 /*-----------------------------------------------------------------*/
9639 genPackBits (sym_link * etype,
9641 char *rname, int p_type)
9649 blen = SPEC_BLEN (etype);
9650 bstr = SPEC_BSTR (etype);
9652 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9655 /* if the bit lenth is less than or */
9656 /* it exactly fits a byte then */
9657 if (SPEC_BLEN (etype) <= 8)
9659 shCount = SPEC_BSTR (etype);
9661 /* shift left acc */
9664 if (SPEC_BLEN (etype) < 8)
9665 { /* if smaller than a byte */
9671 emitcode ("mov", "b,a");
9672 emitcode ("mov", "a,@%s", rname);
9676 emitcode ("mov", "b,a");
9677 emitcode ("movx", "a,@dptr");
9681 emitcode ("push", "b");
9682 emitcode ("push", "acc");
9683 emitcode ("lcall", "__gptrget");
9684 emitcode ("pop", "b");
9688 emitcode ("anl", "a,#!constbyte", (unsigned char)
9689 ((unsigned char) (0xFF << (blen + bstr)) |
9690 (unsigned char) (0xFF >> (8 - bstr))));
9691 emitcode ("orl", "a,b");
9692 if (p_type == GPOINTER)
9693 emitcode ("pop", "b");
9700 emitcode ("mov", "@%s,a", rname);
9704 emitcode ("movx", "@dptr,a");
9708 emitcode ("lcall", "__gptrput");
9713 if (SPEC_BLEN (etype) <= 8)
9716 emitcode ("inc", "%s", rname);
9717 rLen = SPEC_BLEN (etype);
9719 /* now generate for lengths greater than one byte */
9723 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
9735 emitcode ("mov", "@%s,a", rname);
9738 emitcode ("mov", "@%s,%s", rname, l);
9743 emitcode ("movx", "@dptr,a");
9748 emitcode ("lcall", "__gptrput");
9751 emitcode ("inc", "%s", rname);
9756 /* last last was not complete */
9759 /* save the byte & read byte */
9763 emitcode ("mov", "b,a");
9764 emitcode ("mov", "a,@%s", rname);
9768 emitcode ("mov", "b,a");
9769 emitcode ("movx", "a,@dptr");
9773 emitcode ("push", "b");
9774 emitcode ("push", "acc");
9775 emitcode ("lcall", "__gptrget");
9776 emitcode ("pop", "b");
9780 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1 << rLen));
9781 emitcode ("orl", "a,b");
9784 if (p_type == GPOINTER)
9785 emitcode ("pop", "b");
9791 emitcode ("mov", "@%s,a", rname);
9795 emitcode ("movx", "@dptr,a");
9799 emitcode ("lcall", "__gptrput");
9803 /*-----------------------------------------------------------------*/
9804 /* genDataPointerSet - remat pointer to data space */
9805 /*-----------------------------------------------------------------*/
9807 genDataPointerSet (operand * right,
9811 int size, offset = 0;
9812 char *l, buffer[256];
9814 aopOp (right, ic, FALSE, FALSE);
9816 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
9817 size = AOP_SIZE (right);
9821 sprintf (buffer, "(%s + %d)", l + 1, offset);
9823 sprintf (buffer, "%s", l + 1);
9824 emitcode ("mov", "%s,%s", buffer,
9825 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
9828 freeAsmop (right, NULL, ic, TRUE);
9829 freeAsmop (result, NULL, ic, TRUE);
9832 /*-----------------------------------------------------------------*/
9833 /* genNearPointerSet - emitcode for near pointer put */
9834 /*-----------------------------------------------------------------*/
9836 genNearPointerSet (operand * right,
9844 sym_link *retype, *letype;
9845 sym_link *ptype = operandType (result);
9847 retype = getSpec (operandType (right));
9848 letype = getSpec (ptype);
9850 aopOp (result, ic, FALSE, FALSE);
9852 /* if the result is rematerializable &
9853 in data space & not a bit variable */
9854 if (AOP_TYPE (result) == AOP_IMMD &&
9855 DCL_TYPE (ptype) == POINTER &&
9856 !IS_BITVAR (retype) &&
9857 !IS_BITVAR (letype))
9859 genDataPointerSet (right, result, ic);
9863 /* if the value is already in a pointer register
9864 then don't need anything more */
9865 if (!AOP_INPREG (AOP (result)))
9867 /* otherwise get a free pointer register */
9869 preg = getFreePtr (ic, &aop, FALSE);
9870 emitcode ("mov", "%s,%s",
9872 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9876 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9878 aopOp (right, ic, FALSE, FALSE);
9880 /* if bitfield then unpack the bits */
9881 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9882 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9885 /* we have can just get the values */
9886 int size = AOP_SIZE (right);
9891 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
9895 emitcode ("mov", "@%s,a", rname);
9898 emitcode ("mov", "@%s,%s", rname, l);
9900 emitcode ("inc", "%s", rname);
9905 /* now some housekeeping stuff */
9908 /* we had to allocate for this iCode */
9909 if (pi) aopPut (AOP (result),rname,0);
9910 freeAsmop (NULL, aop, ic, TRUE);
9914 /* we did not allocate which means left
9915 already in a pointer register, then
9916 if size > 0 && this could be used again
9917 we have to point it back to where it
9919 if (AOP_SIZE (right) > 1 &&
9920 !OP_SYMBOL (result)->remat &&
9921 (OP_SYMBOL (result)->liveTo > ic->seq ||
9925 int size = AOP_SIZE (right) - 1;
9927 emitcode ("dec", "%s", rname);
9932 if (pi) pi->generated = 1;
9933 freeAsmop (result, NULL, ic, TRUE);
9934 freeAsmop (right, NULL, ic, TRUE);
9939 /*-----------------------------------------------------------------*/
9940 /* genPagedPointerSet - emitcode for Paged pointer put */
9941 /*-----------------------------------------------------------------*/
9943 genPagedPointerSet (operand * right,
9951 sym_link *retype, *letype;
9953 retype = getSpec (operandType (right));
9954 letype = getSpec (operandType (result));
9956 aopOp (result, ic, FALSE, FALSE);
9958 /* if the value is already in a pointer register
9959 then don't need anything more */
9960 if (!AOP_INPREG (AOP (result)))
9962 /* otherwise get a free pointer register */
9964 preg = getFreePtr (ic, &aop, FALSE);
9965 emitcode ("mov", "%s,%s",
9967 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9971 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9973 aopOp (right, ic, FALSE, FALSE);
9975 /* if bitfield then unpack the bits */
9976 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9977 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
9980 /* we have can just get the values */
9981 int size = AOP_SIZE (right);
9986 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
9989 emitcode ("movx", "@%s,a", rname);
9992 emitcode ("inc", "%s", rname);
9998 /* now some housekeeping stuff */
10001 if (pi) aopPut (AOP (result),rname,0);
10002 /* we had to allocate for this iCode */
10003 freeAsmop (NULL, aop, ic, TRUE);
10007 /* we did not allocate which means left
10008 already in a pointer register, then
10009 if size > 0 && this could be used again
10010 we have to point it back to where it
10012 if (AOP_SIZE (right) > 1 &&
10013 !OP_SYMBOL (result)->remat &&
10014 (OP_SYMBOL (result)->liveTo > ic->seq ||
10018 int size = AOP_SIZE (right) - 1;
10020 emitcode ("dec", "%s", rname);
10025 if (pi) pi->generated = 1;
10026 freeAsmop (result, NULL, ic, TRUE);
10027 freeAsmop (right, NULL, ic, TRUE);
10032 /*-----------------------------------------------------------------*/
10033 /* genFarPointerSet - set value from far space */
10034 /*-----------------------------------------------------------------*/
10036 genFarPointerSet (operand * right,
10037 operand * result, iCode * ic, iCode *pi)
10039 int size, offset, dopi=1;
10040 sym_link *retype = getSpec (operandType (right));
10041 sym_link *letype = getSpec (operandType (result));
10043 aopOp (result, ic, FALSE, FALSE);
10045 /* if the operand is already in dptr
10046 then we do nothing else we move the value to dptr */
10047 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10049 /* if this is remateriazable */
10050 if (AOP_TYPE (result) == AOP_IMMD)
10051 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
10054 /* we need to get it byte by byte */
10055 _startLazyDPSEvaluation ();
10056 if (AOP_TYPE (result) != AOP_DPTR)
10058 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
10059 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
10060 if (options.model == MODEL_FLAT24)
10061 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
10065 /* We need to generate a load to DPTR indirect through DPTR. */
10066 D (emitcode (";", "genFarPointerSet -- indirection special case.");
10068 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
10069 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
10070 if (options.model == MODEL_FLAT24)
10071 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
10072 emitcode ("pop", "dph");
10073 emitcode ("pop", "dpl");
10076 _endLazyDPSEvaluation ();
10079 /* so dptr know contains the address */
10080 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10082 /* if bit then unpack */
10083 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
10084 if (AOP_INDPTRn(result)) {
10085 genSetDPTR(AOP(result)->aopu.dptr);
10087 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
10088 if (AOP_INDPTRn(result)) {
10092 size = AOP_SIZE (right);
10094 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10096 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
10099 genSetDPTR(AOP(result)->aopu.dptr);
10100 emitcode ("movx", "@dptr,a");
10101 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10102 emitcode ("inc", "dptr");
10106 _startLazyDPSEvaluation ();
10108 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
10111 if (AOP_INDPTRn(result)) {
10112 genSetDPTR(AOP(result)->aopu.dptr);
10118 emitcode ("movx", "@dptr,a");
10119 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10120 emitcode ("inc", "dptr");
10122 _endLazyDPSEvaluation ();
10126 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10127 if (!AOP_INDPTRn(result)) {
10128 aopPut (AOP(result),"dpl",0);
10129 aopPut (AOP(result),"dph",1);
10130 if (options.model == MODEL_FLAT24)
10131 aopPut (AOP(result),"dpx",2);
10134 } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
10135 AOP_SIZE(right) > 1 &&
10136 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10138 size = AOP_SIZE (right) - 1;
10139 if (AOP_INDPTRn(result)) {
10140 genSetDPTR(AOP(result)->aopu.dptr);
10142 while (size--) emitcode ("lcall","__decdptr");
10143 if (AOP_INDPTRn(result)) {
10147 freeAsmop (result, NULL, ic, TRUE);
10148 freeAsmop (right, NULL, ic, TRUE);
10151 /*-----------------------------------------------------------------*/
10152 /* genGenPointerSet - set value from generic pointer space */
10153 /*-----------------------------------------------------------------*/
10155 genGenPointerSet (operand * right,
10156 operand * result, iCode * ic, iCode *pi)
10159 sym_link *retype = getSpec (operandType (right));
10160 sym_link *letype = getSpec (operandType (result));
10162 aopOp (result, ic, FALSE, OP_SYMBOL(result)->ruonly ? FALSE : TRUE);
10164 /* if the operand is already in dptr
10165 then we do nothing else we move the value to dptr */
10166 if (AOP_TYPE (result) != AOP_STR)
10168 _startLazyDPSEvaluation ();
10169 /* if this is remateriazable */
10170 if (AOP_TYPE (result) == AOP_IMMD)
10172 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
10173 if (AOP(result)->aopu.aop_immd.from_cast_remat)
10174 emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, FALSE));
10176 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
10179 { /* we need to get it byte by byte */
10180 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
10181 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
10182 if (options.model == MODEL_FLAT24) {
10183 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
10184 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
10186 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
10189 _endLazyDPSEvaluation ();
10191 /* so dptr know contains the address */
10192 aopOp (right, ic, FALSE, TRUE);
10194 /* if bit then unpack */
10195 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10196 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
10199 size = AOP_SIZE (right);
10202 _startLazyDPSEvaluation ();
10205 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
10211 emitcode ("lcall", "__gptrput");
10212 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10213 emitcode ("inc", "dptr");
10215 _endLazyDPSEvaluation ();
10218 if (pi && AOP_TYPE (result) != AOP_IMMD) {
10219 aopPut (AOP(result),"dpl",0);
10220 aopPut (AOP(result),"dph",1);
10221 if (options.model == MODEL_FLAT24) {
10222 aopPut (AOP(result),"dpx",2);
10223 aopPut (AOP(result),"b",3);
10225 aopPut (AOP(result),"b",2);
10228 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10229 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10231 size = AOP_SIZE (right) - 1;
10232 while (size--) emitcode ("lcall","__decdptr");
10234 freeAsmop (result, NULL, ic, TRUE);
10235 freeAsmop (right, NULL, ic, TRUE);
10238 /*-----------------------------------------------------------------*/
10239 /* genPointerSet - stores the value into a pointer location */
10240 /*-----------------------------------------------------------------*/
10242 genPointerSet (iCode * ic, iCode *pi)
10244 operand *right, *result;
10245 sym_link *type, *etype;
10248 D (emitcode (";", "genPointerSet ");
10251 right = IC_RIGHT (ic);
10252 result = IC_RESULT (ic);
10254 /* depending on the type of pointer we need to
10255 move it to the correct pointer register */
10256 type = operandType (result);
10257 etype = getSpec (type);
10258 /* if left is of type of pointer then it is simple */
10259 if (IS_PTR (type) && !IS_FUNC (type->next))
10261 p_type = DCL_TYPE (type);
10265 /* we have to go by the storage class */
10266 p_type = PTR_TYPE (SPEC_OCLS (etype));
10268 /* special case when cast remat */
10269 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10270 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10271 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10272 type = operandType (result);
10273 p_type = DCL_TYPE (type);
10276 /* now that we have the pointer type we assign
10277 the pointer values */
10283 genNearPointerSet (right, result, ic, pi);
10287 genPagedPointerSet (right, result, ic, pi);
10291 genFarPointerSet (right, result, ic, pi);
10295 genGenPointerSet (right, result, ic, pi);
10299 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10300 "genPointerSet: illegal pointer type");
10305 /*-----------------------------------------------------------------*/
10306 /* genIfx - generate code for Ifx statement */
10307 /*-----------------------------------------------------------------*/
10309 genIfx (iCode * ic, iCode * popIc)
10311 operand *cond = IC_COND (ic);
10314 D (emitcode (";", "genIfx "););
10316 aopOp (cond, ic, FALSE, FALSE);
10318 /* get the value into acc */
10319 if (AOP_TYPE (cond) != AOP_CRY)
10323 /* the result is now in the accumulator */
10324 freeAsmop (cond, NULL, ic, TRUE);
10326 /* if there was something to be popped then do it */
10330 /* if the condition is a bit variable */
10331 if (isbit && IS_ITEMP (cond) &&
10333 genIfxJump (ic, SPIL_LOC (cond)->rname);
10334 else if (isbit && !IS_ITEMP (cond))
10335 genIfxJump (ic, OP_SYMBOL (cond)->rname);
10337 genIfxJump (ic, "a");
10342 /*-----------------------------------------------------------------*/
10343 /* genAddrOf - generates code for address of */
10344 /*-----------------------------------------------------------------*/
10346 genAddrOf (iCode * ic)
10348 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10351 D (emitcode (";", "genAddrOf ");
10354 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10356 /* if the operand is on the stack then we
10357 need to get the stack offset of this
10359 if (sym->onStack) {
10361 /* if 10 bit stack */
10362 if (options.stack10bit) {
10364 tsprintf(buff,"#!constbyte",(options.stack_loc >> 16) & 0xff);
10365 /* if it has an offset then we need to compute it */
10366 /* emitcode ("subb", "a,#!constbyte", */
10367 /* -((sym->stack < 0) ? */
10368 /* ((short) (sym->stack - _G.nRegsSaved)) : */
10369 /* ((short) sym->stack)) & 0xff); */
10370 /* emitcode ("mov","b,a"); */
10371 /* emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
10372 /* ((short) (sym->stack - _G.nRegsSaved)) : */
10373 /* ((short) sym->stack)) >> 8) & 0xff); */
10375 emitcode ("mov", "a,_bpx");
10376 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
10377 ((char) (sym->stack - _G.nRegsSaved)) :
10378 ((char) sym->stack )) & 0xff);
10379 emitcode ("mov", "b,a");
10380 emitcode ("mov", "a,_bpx+1");
10381 emitcode ("addc","a,#!constbyte", (((sym->stack < 0) ?
10382 ((short) (sym->stack - _G.nRegsSaved)) :
10383 ((short) sym->stack )) >> 8) & 0xff);
10384 aopPut (AOP (IC_RESULT (ic)), "b", 0);
10385 aopPut (AOP (IC_RESULT (ic)), "a", 1);
10386 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10388 /* we can just move _bp */
10389 aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10390 aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10391 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10394 /* if it has an offset then we need to compute it */
10396 emitcode ("mov", "a,_bp");
10397 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10398 aopPut (AOP (IC_RESULT (ic)), "a", 0);
10400 /* we can just move _bp */
10401 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10403 /* fill the result with zero */
10404 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10407 if (options.stack10bit && size < (FPTRSIZE - 1)) {
10409 "*** warning: pointer to stack var truncated.\n");
10414 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10420 /* object not on stack then we need the name */
10421 size = AOP_SIZE (IC_RESULT (ic));
10426 char s[SDCC_NAME_MAX];
10430 tsprintf(s,"!his",sym->rname);
10433 tsprintf(s,"!hihis",sym->rname);
10436 tsprintf(s,"!hihihis",sym->rname);
10438 default: /* should not need this (just in case) */
10439 sprintf (s, "#(%s >> %d)",
10444 sprintf (s, "#%s", sym->rname);
10445 aopPut (AOP (IC_RESULT (ic)), s, offset++);
10449 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10453 /*-----------------------------------------------------------------*/
10454 /* genArrayInit - generates code for address of */
10455 /*-----------------------------------------------------------------*/
10457 genArrayInit (iCode * ic)
10459 literalList *iLoop;
10461 int elementSize = 0, eIndex;
10462 unsigned val, lastVal;
10464 operand *left=IC_LEFT(ic);
10466 D (emitcode (";", "genArrayInit "););
10468 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10470 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10472 // Load immediate value into DPTR.
10473 emitcode("mov", "dptr, %s",
10474 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
10476 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10479 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10480 "Unexpected operand to genArrayInit.\n");
10483 // a regression because of SDCCcse.c:1.52
10484 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
10485 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
10486 if (options.model == MODEL_FLAT24)
10487 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
10491 type = operandType(IC_LEFT(ic));
10493 if (type && type->next)
10495 elementSize = getSize(type->next);
10499 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10500 "can't determine element size in genArrayInit.\n");
10504 iLoop = IC_ARRAYILIST(ic);
10509 bool firstpass = TRUE;
10511 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
10512 iLoop->count, (int)iLoop->literalValue, elementSize);
10518 symbol *tlbl = NULL;
10520 count = ix > 256 ? 256 : ix;
10524 tlbl = newiTempLabel (NULL);
10525 if (firstpass || (count & 0xff))
10527 emitcode("mov", "b, #!constbyte", count & 0xff);
10530 emitcode ("", "!tlabeldef", tlbl->key + 100);
10535 for (eIndex = 0; eIndex < elementSize; eIndex++)
10537 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10538 if (val != lastVal)
10540 emitcode("mov", "a, #!constbyte", val);
10544 emitcode("movx", "@dptr, a");
10545 emitcode("inc", "dptr");
10550 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10556 iLoop = iLoop->next;
10559 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10562 /*-----------------------------------------------------------------*/
10563 /* genFarFarAssign - assignment when both are in far space */
10564 /*-----------------------------------------------------------------*/
10566 genFarFarAssign (operand * result, operand * right, iCode * ic)
10568 int size = AOP_SIZE (right);
10570 symbol *rSym = NULL;
10574 /* quick & easy case. */
10575 D(emitcode(";","genFarFarAssign (1 byte case)"););
10576 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
10577 freeAsmop (right, NULL, ic, FALSE);
10578 /* now assign DPTR to result */
10580 aopOp(result, ic, FALSE, FALSE);
10582 aopPut(AOP(result), "a", 0);
10583 freeAsmop(result, NULL, ic, FALSE);
10587 /* See if we've got an underlying symbol to abuse. */
10588 if (IS_SYMOP(result) && OP_SYMBOL(result))
10590 if (IS_TRUE_SYMOP(result))
10592 rSym = OP_SYMBOL(result);
10594 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10596 rSym = OP_SYMBOL(result)->usl.spillLoc;
10600 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10602 /* We can use the '390 auto-toggle feature to good effect here. */
10604 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10605 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
10606 emitcode ("mov", "dptr,#%s", rSym->rname);
10607 /* DP2 = result, DP1 = right, DP1 is current. */
10610 emitcode("movx", "a,@dptr");
10611 emitcode("movx", "@dptr,a");
10614 emitcode("inc", "dptr");
10615 emitcode("inc", "dptr");
10618 emitcode("mov", "dps,#0");
10619 freeAsmop (right, NULL, ic, FALSE);
10621 some alternative code for processors without auto-toggle
10622 no time to test now, so later well put in...kpb
10623 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10624 emitcode("mov", "dps,#1"); /* Select DPTR2. */
10625 emitcode ("mov", "dptr,#%s", rSym->rname);
10626 /* DP2 = result, DP1 = right, DP1 is current. */
10630 emitcode("movx", "a,@dptr");
10632 emitcode("inc", "dptr");
10633 emitcode("inc", "dps");
10634 emitcode("movx", "@dptr,a");
10636 emitcode("inc", "dptr");
10637 emitcode("inc", "dps");
10639 emitcode("mov", "dps,#0");
10640 freeAsmop (right, NULL, ic, FALSE);
10645 D (emitcode (";", "genFarFarAssign"););
10646 aopOp (result, ic, TRUE, TRUE);
10648 _startLazyDPSEvaluation ();
10652 aopPut (AOP (result),
10653 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
10656 _endLazyDPSEvaluation ();
10657 freeAsmop (result, NULL, ic, FALSE);
10658 freeAsmop (right, NULL, ic, FALSE);
10662 /*-----------------------------------------------------------------*/
10663 /* genAssign - generate code for assignment */
10664 /*-----------------------------------------------------------------*/
10666 genAssign (iCode * ic)
10668 operand *result, *right;
10670 unsigned long lit = 0L;
10672 D (emitcode (";", "genAssign ");
10675 result = IC_RESULT (ic);
10676 right = IC_RIGHT (ic);
10678 /* if they are the same */
10679 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10682 aopOp (right, ic, FALSE, FALSE);
10684 emitcode (";", "genAssign: resultIsFar = %s",
10685 isOperandInFarSpace (result) ?
10688 /* special case both in far space */
10689 if ((AOP_TYPE (right) == AOP_DPTR ||
10690 AOP_TYPE (right) == AOP_DPTR2) &&
10691 /* IS_TRUE_SYMOP(result) && */
10692 isOperandInFarSpace (result))
10694 genFarFarAssign (result, right, ic);
10698 aopOp (result, ic, TRUE, FALSE);
10700 /* if they are the same registers */
10701 if (sameRegs (AOP (right), AOP (result)))
10704 /* if the result is a bit */
10705 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10707 /* if the right size is a literal then
10708 we know what the value is */
10709 if (AOP_TYPE (right) == AOP_LIT)
10711 if (((int) operandLitValue (right)))
10712 aopPut (AOP (result), one, 0);
10714 aopPut (AOP (result), zero, 0);
10718 /* the right is also a bit variable */
10719 if (AOP_TYPE (right) == AOP_CRY)
10721 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10722 aopPut (AOP (result), "c", 0);
10726 /* we need to or */
10728 aopPut (AOP (result), "a", 0);
10732 /* bit variables done */
10734 size = AOP_SIZE (result);
10736 if (AOP_TYPE (right) == AOP_LIT)
10737 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10740 (AOP_TYPE (result) != AOP_REG) &&
10741 (AOP_TYPE (right) == AOP_LIT) &&
10742 !IS_FLOAT (operandType (right)))
10744 _startLazyDPSEvaluation ();
10745 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10747 aopPut (AOP (result),
10748 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
10753 /* And now fill the rest with zeros. */
10756 emitcode ("clr", "a");
10760 aopPut (AOP (result), "a", offset++);
10762 _endLazyDPSEvaluation ();
10766 _startLazyDPSEvaluation ();
10769 aopPut (AOP (result),
10770 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10774 _endLazyDPSEvaluation ();
10778 freeAsmop (right, NULL, ic, FALSE);
10779 freeAsmop (result, NULL, ic, TRUE);
10782 /*-----------------------------------------------------------------*/
10783 /* genJumpTab - generates code for jump table */
10784 /*-----------------------------------------------------------------*/
10786 genJumpTab (iCode * ic)
10791 D (emitcode (";", "genJumpTab ");
10794 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10795 /* get the condition into accumulator */
10796 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
10798 /* multiply by four! */
10799 emitcode ("add", "a,acc");
10800 emitcode ("add", "a,acc");
10801 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10803 jtab = newiTempLabel (NULL);
10804 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
10805 emitcode ("jmp", "@a+dptr");
10806 emitcode ("", "!tlabeldef", jtab->key + 100);
10807 /* now generate the jump labels */
10808 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10809 jtab = setNextItem (IC_JTLABELS (ic)))
10810 emitcode ("ljmp", "!tlabel", jtab->key + 100);
10814 /*-----------------------------------------------------------------*/
10815 /* genCast - gen code for casting */
10816 /*-----------------------------------------------------------------*/
10818 genCast (iCode * ic)
10820 operand *result = IC_RESULT (ic);
10821 sym_link *ctype = operandType (IC_LEFT (ic));
10822 sym_link *rtype = operandType (IC_RIGHT (ic));
10823 operand *right = IC_RIGHT (ic);
10826 D (emitcode (";", "genCast ");
10829 /* if they are equivalent then do nothing */
10830 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10833 aopOp (right, ic, FALSE, FALSE);
10834 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
10836 /* if the result is a bit */
10837 // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10838 if (IS_BITVAR(OP_SYMBOL(result)->type))
10840 /* if the right size is a literal then
10841 we know what the value is */
10842 if (AOP_TYPE (right) == AOP_LIT)
10844 if (((int) operandLitValue (right)))
10845 aopPut (AOP (result), one, 0);
10847 aopPut (AOP (result), zero, 0);
10852 /* the right is also a bit variable */
10853 if (AOP_TYPE (right) == AOP_CRY)
10855 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10856 aopPut (AOP (result), "c", 0);
10860 /* we need to or */
10862 aopPut (AOP (result), "a", 0);
10866 /* if they are the same size : or less */
10867 if (AOP_SIZE (result) <= AOP_SIZE (right))
10870 /* if they are in the same place */
10871 if (sameRegs (AOP (right), AOP (result)))
10874 /* if they in different places then copy */
10875 size = AOP_SIZE (result);
10877 _startLazyDPSEvaluation ();
10880 aopPut (AOP (result),
10881 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10885 _endLazyDPSEvaluation ();
10890 /* if the result is of type pointer */
10891 if (IS_PTR (ctype))
10895 sym_link *type = operandType (right);
10897 /* pointer to generic pointer */
10898 if (IS_GENPTR (ctype))
10902 p_type = DCL_TYPE (type);
10906 #if OLD_CAST_BEHAVIOR
10907 /* KV: we are converting a non-pointer type to
10908 * a generic pointer. This (ifdef'd out) code
10909 * says that the resulting generic pointer
10910 * should have the same class as the storage
10911 * location of the non-pointer variable.
10913 * For example, converting an int (which happens
10914 * to be stored in DATA space) to a pointer results
10915 * in a DATA generic pointer; if the original int
10916 * in XDATA space, so will be the resulting pointer.
10918 * I don't like that behavior, and thus this change:
10919 * all such conversions will be forced to XDATA and
10920 * throw a warning. If you want some non-XDATA
10921 * type, or you want to suppress the warning, you
10922 * must go through an intermediate cast, like so:
10924 * char _generic *gp = (char _xdata *)(intVar);
10926 sym_link *etype = getSpec (type);
10928 /* we have to go by the storage class */
10929 if (SPEC_OCLS (etype) != generic)
10931 p_type = PTR_TYPE (SPEC_OCLS (etype));
10936 /* Converting unknown class (i.e. register variable)
10937 * to generic pointer. This is not good, but
10938 * we'll make a guess (and throw a warning).
10941 werror (W_INT_TO_GEN_PTR_CAST);
10945 /* the first two bytes are known */
10946 size = GPTRSIZE - 1;
10948 _startLazyDPSEvaluation ();
10951 aopPut (AOP (result),
10952 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10956 _endLazyDPSEvaluation ();
10958 /* the last byte depending on type */
10960 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
10965 // pointerTypeToGPByte will have bitched.
10969 sprintf(gpValStr, "#0x%d", gpVal);
10970 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
10975 /* just copy the pointers */
10976 size = AOP_SIZE (result);
10978 _startLazyDPSEvaluation ();
10981 aopPut (AOP (result),
10982 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10986 _endLazyDPSEvaluation ();
10990 /* so we now know that the size of destination is greater
10991 than the size of the source */
10992 /* we move to result for the size of source */
10993 size = AOP_SIZE (right);
10995 _startLazyDPSEvaluation ();
10998 aopPut (AOP (result),
10999 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
11003 _endLazyDPSEvaluation ();
11005 /* now depending on the sign of the source && destination */
11006 size = AOP_SIZE (result) - AOP_SIZE (right);
11007 /* if unsigned or not an integral type */
11008 /* also, if the source is a bit, we don't need to sign extend, because
11009 * it can't possibly have set the sign bit.
11011 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
11015 aopPut (AOP (result), zero, offset++);
11020 /* we need to extend the sign :{ */
11021 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
11022 FALSE, FALSE, TRUE);
11024 emitcode ("rlc", "a");
11025 emitcode ("subb", "a,acc");
11027 aopPut (AOP (result), "a", offset++);
11030 /* we are done hurray !!!! */
11033 freeAsmop (right, NULL, ic, TRUE);
11034 freeAsmop (result, NULL, ic, TRUE);
11038 /*-----------------------------------------------------------------*/
11039 /* genDjnz - generate decrement & jump if not zero instrucion */
11040 /*-----------------------------------------------------------------*/
11042 genDjnz (iCode * ic, iCode * ifx)
11044 symbol *lbl, *lbl1;
11048 /* if the if condition has a false label
11049 then we cannot save */
11050 if (IC_FALSE (ifx))
11053 /* if the minus is not of the form
11055 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11056 !IS_OP_LITERAL (IC_RIGHT (ic)))
11059 if (operandLitValue (IC_RIGHT (ic)) != 1)
11062 /* if the size of this greater than one then no
11064 if (getSize (operandType (IC_RESULT (ic))) > 1)
11067 /* otherwise we can save BIG */
11068 D(emitcode(";", "genDjnz"););
11070 lbl = newiTempLabel (NULL);
11071 lbl1 = newiTempLabel (NULL);
11073 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11075 if (AOP_NEEDSACC(IC_RESULT(ic)))
11077 /* If the result is accessed indirectly via
11078 * the accumulator, we must explicitly write
11079 * it back after the decrement.
11081 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
11083 if (strcmp(rByte, "a"))
11085 /* Something is hopelessly wrong */
11086 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11087 __FILE__, __LINE__);
11088 /* We can just give up; the generated code will be inefficient,
11089 * but what the hey.
11091 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11094 emitcode ("dec", "%s", rByte);
11095 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11096 emitcode ("jnz", "!tlabel", lbl->key + 100);
11098 else if (IS_AOP_PREG (IC_RESULT (ic)))
11100 emitcode ("dec", "%s",
11101 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
11102 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
11103 emitcode ("jnz", "!tlabel", lbl->key + 100);
11107 emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
11110 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11111 emitcode ("", "!tlabeldef", lbl->key + 100);
11112 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11113 emitcode ("", "!tlabeldef", lbl1->key + 100);
11115 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11116 ifx->generated = 1;
11120 /*-----------------------------------------------------------------*/
11121 /* genReceive - generate code for a receive iCode */
11122 /*-----------------------------------------------------------------*/
11124 genReceive (iCode * ic)
11127 int size = getSize (operandType (IC_RESULT (ic)));
11131 D (emitcode (";", "genReceive ");
11134 if (ic->argreg == 1) { /* first parameter */
11135 if (isOperandInFarSpace (IC_RESULT (ic)) &&
11136 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11137 IS_TRUE_SYMOP (IC_RESULT (ic))))
11139 offset = fReturnSizeDS390 - size;
11142 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
11143 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
11146 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11147 size = AOP_SIZE (IC_RESULT (ic));
11151 emitcode ("pop", "acc");
11152 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
11157 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11159 assignResultValue (IC_RESULT (ic));
11161 } else { /* second receive onwards */
11162 /* this gets a little tricky since unused recevies will be
11163 eliminated, we have saved the reg in the type field . and
11164 we use that to figure out which register to use */
11165 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11166 rb1off = ic->argreg;
11168 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11172 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11175 /*-----------------------------------------------------------------*/
11176 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
11177 /*-----------------------------------------------------------------*/
11178 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11180 operand *from , *to , *count;
11185 /* we know it has to be 3 parameters */
11186 assert (nparms == 3);
11188 rsave = newBitVect(16);
11189 /* save DPTR if it needs to be saved */
11190 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11191 if (bitVectBitValue(ic->rMask,i))
11192 rsave = bitVectSetBit(rsave,i);
11194 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11195 ds390_rUmaskForOp (IC_RESULT(ic))));
11202 aopOp (from, ic->next, FALSE, FALSE);
11204 /* get from into DPTR1 */
11205 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
11206 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
11207 if (options.model == MODEL_FLAT24) {
11208 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
11211 freeAsmop (from, NULL, ic, FALSE);
11212 aopOp (to, ic, FALSE, FALSE);
11213 /* get "to" into DPTR */
11214 /* if the operand is already in dptr
11215 then we do nothing else we move the value to dptr */
11216 if (AOP_TYPE (to) != AOP_STR) {
11217 /* if already in DPTR then we need to push */
11218 if (AOP_TYPE(to) == AOP_DPTR) {
11219 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11220 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11221 if (options.model == MODEL_FLAT24)
11222 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11223 emitcode ("pop", "dph");
11224 emitcode ("pop", "dpl");
11226 _startLazyDPSEvaluation ();
11227 /* if this is remateriazable */
11228 if (AOP_TYPE (to) == AOP_IMMD) {
11229 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11230 } else { /* we need to get it byte by byte */
11231 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11232 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11233 if (options.model == MODEL_FLAT24) {
11234 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11237 _endLazyDPSEvaluation ();
11240 freeAsmop (to, NULL, ic, FALSE);
11241 _G.dptrInUse = _G.dptr1InUse = 1;
11242 aopOp (count, ic->next->next, FALSE,FALSE);
11243 lbl =newiTempLabel(NULL);
11245 /* now for the actual copy */
11246 if (AOP_TYPE(count) == AOP_LIT &&
11247 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11248 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11250 emitcode ("lcall","__bi_memcpyc2x_s");
11252 emitcode ("lcall","__bi_memcpyx2x_s");
11254 freeAsmop (count, NULL, ic, FALSE);
11256 symbol *lbl1 = newiTempLabel(NULL);
11258 emitcode (";"," Auto increment but no djnz");
11259 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11260 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11261 freeAsmop (count, NULL, ic, FALSE);
11262 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11263 emitcode ("","!tlabeldef",lbl->key+100);
11265 emitcode ("clr","a");
11266 emitcode ("movc", "a,@a+dptr");
11268 emitcode ("movx", "a,@dptr");
11269 emitcode ("movx", "@dptr,a");
11270 emitcode ("inc", "dptr");
11271 emitcode ("inc", "dptr");
11272 emitcode ("mov","a,b");
11273 emitcode ("orl","a,_ap");
11274 emitcode ("jz","!tlabel",lbl1->key+100);
11275 emitcode ("mov","a,_ap");
11276 emitcode ("add","a,#!constbyte",0xFF);
11277 emitcode ("mov","_ap,a");
11278 emitcode ("mov","a,b");
11279 emitcode ("addc","a,#!constbyte",0xFF);
11280 emitcode ("mov","b,a");
11281 emitcode ("sjmp","!tlabel",lbl->key+100);
11282 emitcode ("","!tlabeldef",lbl1->key+100);
11284 emitcode ("mov", "dps,#0");
11285 _G.dptrInUse = _G.dptr1InUse = 0;
11286 unsavermask(rsave);
11290 /*-----------------------------------------------------------------*/
11291 /* genMemcmpX2X - gen code for memcmp xdata to xdata */
11292 /*-----------------------------------------------------------------*/
11293 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11295 operand *from , *to , *count;
11300 /* we know it has to be 3 parameters */
11301 assert (nparms == 3);
11303 rsave = newBitVect(16);
11304 /* save DPTR if it needs to be saved */
11305 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11306 if (bitVectBitValue(ic->rMask,i))
11307 rsave = bitVectSetBit(rsave,i);
11309 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11310 ds390_rUmaskForOp (IC_RESULT(ic))));
11317 aopOp (from, ic->next, FALSE, FALSE);
11319 /* get from into DPTR1 */
11320 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
11321 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
11322 if (options.model == MODEL_FLAT24) {
11323 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
11326 freeAsmop (from, NULL, ic, FALSE);
11327 aopOp (to, ic, FALSE, FALSE);
11328 /* get "to" into DPTR */
11329 /* if the operand is already in dptr
11330 then we do nothing else we move the value to dptr */
11331 if (AOP_TYPE (to) != AOP_STR) {
11332 /* if already in DPTR then we need to push */
11333 if (AOP_TYPE(to) == AOP_DPTR) {
11334 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11335 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11336 if (options.model == MODEL_FLAT24)
11337 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11338 emitcode ("pop", "dph");
11339 emitcode ("pop", "dpl");
11341 _startLazyDPSEvaluation ();
11342 /* if this is remateriazable */
11343 if (AOP_TYPE (to) == AOP_IMMD) {
11344 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11345 } else { /* we need to get it byte by byte */
11346 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11347 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11348 if (options.model == MODEL_FLAT24) {
11349 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11352 _endLazyDPSEvaluation ();
11355 freeAsmop (to, NULL, ic, FALSE);
11356 _G.dptrInUse = _G.dptr1InUse = 1;
11357 aopOp (count, ic->next->next, FALSE,FALSE);
11358 lbl =newiTempLabel(NULL);
11359 lbl2 =newiTempLabel(NULL);
11361 /* now for the actual compare */
11362 if (AOP_TYPE(count) == AOP_LIT &&
11363 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11364 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11366 emitcode("lcall","__bi_memcmpc2x_s");
11368 emitcode("lcall","__bi_memcmpx2x_s");
11369 freeAsmop (count, NULL, ic, FALSE);
11370 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11371 aopPut(AOP(IC_RESULT(ic)),"a",0);
11372 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11374 symbol *lbl1 = newiTempLabel(NULL);
11376 emitcode("push","ar0");
11377 emitcode (";"," Auto increment but no djnz");
11378 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11379 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11380 freeAsmop (count, NULL, ic, FALSE);
11381 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11382 emitcode ("","!tlabeldef",lbl->key+100);
11384 emitcode ("clr","a");
11385 emitcode ("movc", "a,@a+dptr");
11387 emitcode ("movx", "a,@dptr");
11388 emitcode ("mov","r0,a");
11389 emitcode ("movx", "a,@dptr");
11390 emitcode ("clr","c");
11391 emitcode ("subb","a,r0");
11392 emitcode ("jnz","!tlabel",lbl2->key+100);
11393 emitcode ("inc", "dptr");
11394 emitcode ("inc", "dptr");
11395 emitcode ("mov","a,b");
11396 emitcode ("orl","a,_ap");
11397 emitcode ("jz","!tlabel",lbl1->key+100);
11398 emitcode ("mov","a,_ap");
11399 emitcode ("add","a,#!constbyte",0xFF);
11400 emitcode ("mov","_ap,a");
11401 emitcode ("mov","a,b");
11402 emitcode ("addc","a,#!constbyte",0xFF);
11403 emitcode ("mov","b,a");
11404 emitcode ("sjmp","!tlabel",lbl->key+100);
11405 emitcode ("","!tlabeldef",lbl1->key+100);
11406 emitcode ("clr","a");
11407 emitcode ("","!tlabeldef",lbl2->key+100);
11408 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11409 aopPut(AOP(IC_RESULT(ic)),"a",0);
11410 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11411 emitcode("pop","ar0");
11412 emitcode ("mov", "dps,#0");
11414 _G.dptrInUse = _G.dptr1InUse = 0;
11415 unsavermask(rsave);
11419 /*-----------------------------------------------------------------*/
11420 /* genInp - gen code for __builtin_inp read data from a mem mapped */
11421 /* port, first parameter output area second parameter pointer to */
11422 /* port third parameter count */
11423 /*-----------------------------------------------------------------*/
11424 static void genInp( iCode *ic, int nparms, operand **parms)
11426 operand *from , *to , *count;
11431 /* we know it has to be 3 parameters */
11432 assert (nparms == 3);
11434 rsave = newBitVect(16);
11435 /* save DPTR if it needs to be saved */
11436 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11437 if (bitVectBitValue(ic->rMask,i))
11438 rsave = bitVectSetBit(rsave,i);
11440 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11441 ds390_rUmaskForOp (IC_RESULT(ic))));
11448 aopOp (from, ic->next, FALSE, FALSE);
11450 /* get from into DPTR1 */
11451 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
11452 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
11453 if (options.model == MODEL_FLAT24) {
11454 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
11457 freeAsmop (from, NULL, ic, FALSE);
11458 aopOp (to, ic, FALSE, FALSE);
11459 /* get "to" into DPTR */
11460 /* if the operand is already in dptr
11461 then we do nothing else we move the value to dptr */
11462 if (AOP_TYPE (to) != AOP_STR) {
11463 /* if already in DPTR then we need to push */
11464 if (AOP_TYPE(to) == AOP_DPTR) {
11465 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11466 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11467 if (options.model == MODEL_FLAT24)
11468 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11469 emitcode ("pop", "dph");
11470 emitcode ("pop", "dpl");
11472 _startLazyDPSEvaluation ();
11473 /* if this is remateriazable */
11474 if (AOP_TYPE (to) == AOP_IMMD) {
11475 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11476 } else { /* we need to get it byte by byte */
11477 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11478 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11479 if (options.model == MODEL_FLAT24) {
11480 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11483 _endLazyDPSEvaluation ();
11486 freeAsmop (to, NULL, ic, FALSE);
11488 _G.dptrInUse = _G.dptr1InUse = 1;
11489 aopOp (count, ic->next->next, FALSE,FALSE);
11490 lbl =newiTempLabel(NULL);
11492 /* now for the actual copy */
11493 if (AOP_TYPE(count) == AOP_LIT &&
11494 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11495 emitcode (";","OH JOY auto increment with djnz (very fast)");
11496 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11497 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11498 freeAsmop (count, NULL, ic, FALSE);
11499 emitcode ("","!tlabeldef",lbl->key+100);
11500 emitcode ("movx", "a,@dptr"); /* read data from port */
11501 emitcode ("dec","dps"); /* switch to DPTR */
11502 emitcode ("movx", "@dptr,a"); /* save into location */
11503 emitcode ("inc", "dptr"); /* point to next area */
11504 emitcode ("inc","dps"); /* switch to DPTR2 */
11505 emitcode ("djnz","b,!tlabel",lbl->key+100);
11507 symbol *lbl1 = newiTempLabel(NULL);
11509 emitcode (";"," Auto increment but no djnz");
11510 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11511 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11512 freeAsmop (count, NULL, ic, FALSE);
11513 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11514 emitcode ("","!tlabeldef",lbl->key+100);
11515 emitcode ("movx", "a,@dptr");
11516 emitcode ("dec","dps"); /* switch to DPTR */
11517 emitcode ("movx", "@dptr,a");
11518 emitcode ("inc", "dptr");
11519 emitcode ("inc","dps"); /* switch to DPTR2 */
11520 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
11521 /* emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
11522 emitcode ("mov","a,b");
11523 emitcode ("orl","a,_ap");
11524 emitcode ("jz","!tlabel",lbl1->key+100);
11525 emitcode ("mov","a,_ap");
11526 emitcode ("add","a,#!constbyte",0xFF);
11527 emitcode ("mov","_ap,a");
11528 emitcode ("mov","a,b");
11529 emitcode ("addc","a,#!constbyte",0xFF);
11530 emitcode ("mov","b,a");
11531 emitcode ("sjmp","!tlabel",lbl->key+100);
11532 emitcode ("","!tlabeldef",lbl1->key+100);
11534 emitcode ("mov", "dps,#0");
11535 _G.dptrInUse = _G.dptr1InUse = 0;
11536 unsavermask(rsave);
11540 /*-----------------------------------------------------------------*/
11541 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
11542 /* port, first parameter output area second parameter pointer to */
11543 /* port third parameter count */
11544 /*-----------------------------------------------------------------*/
11545 static void genOutp( iCode *ic, int nparms, operand **parms)
11547 operand *from , *to , *count;
11552 /* we know it has to be 3 parameters */
11553 assert (nparms == 3);
11555 rsave = newBitVect(16);
11556 /* save DPTR if it needs to be saved */
11557 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11558 if (bitVectBitValue(ic->rMask,i))
11559 rsave = bitVectSetBit(rsave,i);
11561 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11562 ds390_rUmaskForOp (IC_RESULT(ic))));
11569 aopOp (from, ic->next, FALSE, FALSE);
11571 /* get from into DPTR1 */
11572 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
11573 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
11574 if (options.model == MODEL_FLAT24) {
11575 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
11578 freeAsmop (from, NULL, ic, FALSE);
11579 aopOp (to, ic, FALSE, FALSE);
11580 /* get "to" into DPTR */
11581 /* if the operand is already in dptr
11582 then we do nothing else we move the value to dptr */
11583 if (AOP_TYPE (to) != AOP_STR) {
11584 /* if already in DPTR then we need to push */
11585 if (AOP_TYPE(to) == AOP_DPTR) {
11586 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11587 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11588 if (options.model == MODEL_FLAT24)
11589 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11590 emitcode ("pop", "dph");
11591 emitcode ("pop", "dpl");
11593 _startLazyDPSEvaluation ();
11594 /* if this is remateriazable */
11595 if (AOP_TYPE (to) == AOP_IMMD) {
11596 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11597 } else { /* we need to get it byte by byte */
11598 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11599 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11600 if (options.model == MODEL_FLAT24) {
11601 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11604 _endLazyDPSEvaluation ();
11607 freeAsmop (to, NULL, ic, FALSE);
11609 _G.dptrInUse = _G.dptr1InUse = 1;
11610 aopOp (count, ic->next->next, FALSE,FALSE);
11611 lbl =newiTempLabel(NULL);
11613 /* now for the actual copy */
11614 if (AOP_TYPE(count) == AOP_LIT &&
11615 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11616 emitcode (";","OH JOY auto increment with djnz (very fast)");
11617 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
11618 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11619 emitcode ("","!tlabeldef",lbl->key+100);
11620 emitcode ("movx", "a,@dptr"); /* read data from port */
11621 emitcode ("inc","dps"); /* switch to DPTR2 */
11622 emitcode ("movx", "@dptr,a"); /* save into location */
11623 emitcode ("inc", "dptr"); /* point to next area */
11624 emitcode ("dec","dps"); /* switch to DPTR */
11625 emitcode ("djnz","b,!tlabel",lbl->key+100);
11626 freeAsmop (count, NULL, ic, FALSE);
11628 symbol *lbl1 = newiTempLabel(NULL);
11630 emitcode (";"," Auto increment but no djnz");
11631 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11632 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11633 freeAsmop (count, NULL, ic, FALSE);
11634 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
11635 emitcode ("","!tlabeldef",lbl->key+100);
11636 emitcode ("movx", "a,@dptr");
11637 emitcode ("inc", "dptr");
11638 emitcode ("inc","dps"); /* switch to DPTR2 */
11639 emitcode ("movx", "@dptr,a");
11640 emitcode ("dec","dps"); /* switch to DPTR */
11641 emitcode ("mov","a,b");
11642 emitcode ("orl","a,_ap");
11643 emitcode ("jz","!tlabel",lbl1->key+100);
11644 emitcode ("mov","a,_ap");
11645 emitcode ("add","a,#!constbyte",0xFF);
11646 emitcode ("mov","_ap,a");
11647 emitcode ("mov","a,b");
11648 emitcode ("addc","a,#!constbyte",0xFF);
11649 emitcode ("mov","b,a");
11650 emitcode ("sjmp","!tlabel",lbl->key+100);
11651 emitcode ("","!tlabeldef",lbl1->key+100);
11653 emitcode ("mov", "dps,#0");
11654 _G.dptrInUse = _G.dptr1InUse = 0;
11655 unsavermask(rsave);
11659 /*-----------------------------------------------------------------*/
11660 /* genSwapW - swap lower & high order bytes */
11661 /*-----------------------------------------------------------------*/
11662 static void genSwapW(iCode *ic, int nparms, operand **parms)
11666 assert (nparms==1);
11669 dest=IC_RESULT(ic);
11671 assert(getSize(operandType(src))==2);
11673 aopOp (src, ic, FALSE, FALSE);
11674 emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,TRUE));
11676 emitcode ("mov","b,%s",aopGet(AOP(src),1,FALSE,FALSE,FALSE));
11678 freeAsmop (src, NULL, ic, FALSE);
11680 aopOp (dest,ic, FALSE, FALSE);
11681 aopPut(AOP(dest),"b",0);
11682 aopPut(AOP(dest),"a",1);
11683 freeAsmop (dest, NULL, ic, FALSE);
11686 /*-----------------------------------------------------------------*/
11687 /* genMemsetX - gencode for memSetX data */
11688 /*-----------------------------------------------------------------*/
11689 static void genMemsetX(iCode *ic, int nparms, operand **parms)
11691 operand *to , *val , *count;
11695 bitVect *rsave = NULL;
11697 /* we know it has to be 3 parameters */
11698 assert (nparms == 3);
11704 /* save DPTR if it needs to be saved */
11705 rsave = newBitVect(16);
11706 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11707 if (bitVectBitValue(ic->rMask,i))
11708 rsave = bitVectSetBit(rsave,i);
11710 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11711 ds390_rUmaskForOp (IC_RESULT(ic))));
11714 aopOp (to, ic, FALSE, FALSE);
11715 /* get "to" into DPTR */
11716 /* if the operand is already in dptr
11717 then we do nothing else we move the value to dptr */
11718 if (AOP_TYPE (to) != AOP_STR) {
11719 /* if already in DPTR then we need to push */
11720 if (AOP_TYPE(to) == AOP_DPTR) {
11721 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11722 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11723 if (options.model == MODEL_FLAT24)
11724 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11725 emitcode ("pop", "dph");
11726 emitcode ("pop", "dpl");
11728 _startLazyDPSEvaluation ();
11729 /* if this is remateriazable */
11730 if (AOP_TYPE (to) == AOP_IMMD) {
11731 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11732 } else { /* we need to get it byte by byte */
11733 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11734 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11735 if (options.model == MODEL_FLAT24) {
11736 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11739 _endLazyDPSEvaluation ();
11742 freeAsmop (to, NULL, ic, FALSE);
11744 aopOp (val, ic->next->next, FALSE,FALSE);
11745 aopOp (count, ic->next->next, FALSE,FALSE);
11746 lbl =newiTempLabel(NULL);
11747 /* now for the actual copy */
11748 if (AOP_TYPE(count) == AOP_LIT &&
11749 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11750 l = aopGet(AOP (val), 0, FALSE, FALSE, TRUE);
11751 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11753 emitcode ("","!tlabeldef",lbl->key+100);
11754 emitcode ("movx", "@dptr,a");
11755 emitcode ("inc", "dptr");
11756 emitcode ("djnz","b,!tlabel",lbl->key+100);
11758 symbol *lbl1 = newiTempLabel(NULL);
11760 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11761 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11762 emitcode ("","!tlabeldef",lbl->key+100);
11763 l = aopGet(AOP (val), 0, FALSE, FALSE, TRUE);
11765 emitcode ("movx", "@dptr,a");
11766 emitcode ("inc", "dptr");
11767 emitcode ("mov","a,b");
11768 emitcode ("orl","a,_ap");
11769 emitcode ("jz","!tlabel",lbl1->key+100);
11770 emitcode ("mov","a,_ap");
11771 emitcode ("add","a,#!constbyte",0xFF);
11772 emitcode ("mov","_ap,a");
11773 emitcode ("mov","a,b");
11774 emitcode ("addc","a,#!constbyte",0xFF);
11775 emitcode ("mov","b,a");
11776 emitcode ("sjmp","!tlabel",lbl->key+100);
11777 emitcode ("","!tlabeldef",lbl1->key+100);
11779 freeAsmop (count, NULL, ic, FALSE);
11780 unsavermask(rsave);
11783 /*-----------------------------------------------------------------*/
11784 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
11785 /*-----------------------------------------------------------------*/
11786 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
11789 operand *pnum, *result;
11792 assert (nparms==1);
11793 /* save registers that need to be saved */
11794 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11795 ds390_rUmaskForOp (IC_RESULT(ic))));
11798 aopOp (pnum, ic, FALSE, FALSE);
11799 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,FALSE));
11800 freeAsmop (pnum, NULL, ic, FALSE);
11801 emitcode ("lcall","NatLib_LoadPrimitive");
11802 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11803 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
11804 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
11805 for (i = (size-1) ; i >= 0 ; i-- ) {
11806 emitcode ("push","a%s",javaRet[i]);
11808 for (i=0; i < size ; i++ ) {
11809 emitcode ("pop","a%s",aopGet(AOP(result),i,FALSE,FALSE,FALSE));
11812 for (i = 0 ; i < size ; i++ ) {
11813 aopPut(AOP(result),javaRet[i],i);
11816 freeAsmop (result, NULL, ic, FALSE);
11817 unsavermask(rsave);
11820 /*-----------------------------------------------------------------*/
11821 /* genNatLibLoadPointer - calls TINI api function to load pointer */
11822 /*-----------------------------------------------------------------*/
11823 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
11826 operand *pnum, *result;
11830 assert (nparms==1);
11831 /* save registers that need to be saved */
11832 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11833 ds390_rUmaskForOp (IC_RESULT(ic))));
11836 aopOp (pnum, ic, FALSE, FALSE);
11837 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,FALSE));
11838 freeAsmop (pnum, NULL, ic, FALSE);
11839 emitcode ("lcall","NatLib_LoadPointer");
11840 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11841 if (AOP_TYPE(result)!=AOP_STR) {
11842 for (i = 0 ; i < size ; i++ ) {
11843 aopPut(AOP(result),fReturn[i],i);
11846 freeAsmop (result, NULL, ic, FALSE);
11847 unsavermask(rsave);
11850 /*-----------------------------------------------------------------*/
11851 /* genNatLibInstallStateBlock - */
11852 /*-----------------------------------------------------------------*/
11853 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
11854 operand **parms, const char *name)
11857 operand *psb, *handle;
11858 assert (nparms==2);
11860 /* save registers that need to be saved */
11861 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11862 ds390_rUmaskForOp (IC_RESULT(ic))));
11866 /* put pointer to state block into DPTR1 */
11867 aopOp (psb, ic, FALSE, FALSE);
11868 if (AOP_TYPE (psb) == AOP_IMMD) {
11869 emitcode ("mov","dps,#1");
11870 emitcode ("mov", "dptr,%s", aopGet (AOP (psb), 0, TRUE, FALSE, FALSE));
11871 emitcode ("mov","dps,#0");
11873 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,FALSE));
11874 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,FALSE));
11875 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,FALSE));
11877 freeAsmop (psb, NULL, ic, FALSE);
11879 /* put libraryID into DPTR */
11880 emitcode ("mov","dptr,#LibraryID");
11882 /* put handle into r3:r2 */
11883 aopOp (handle, ic, FALSE, FALSE);
11884 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11885 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11886 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11887 emitcode ("pop","ar3");
11888 emitcode ("pop","ar2");
11890 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11891 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11893 freeAsmop (psb, NULL, ic, FALSE);
11895 /* make the call */
11896 emitcode ("lcall","NatLib_Install%sStateBlock",name);
11898 /* put return value into place*/
11900 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
11902 aopPut(AOP(IC_RESULT(ic)),"a",0);
11903 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11904 unsavermask(rsave);
11907 /*-----------------------------------------------------------------*/
11908 /* genNatLibRemoveStateBlock - */
11909 /*-----------------------------------------------------------------*/
11910 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
11916 /* save registers that need to be saved */
11917 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11918 ds390_rUmaskForOp (IC_RESULT(ic))));
11920 /* put libraryID into DPTR */
11921 emitcode ("mov","dptr,#LibraryID");
11922 /* make the call */
11923 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
11924 unsavermask(rsave);
11927 /*-----------------------------------------------------------------*/
11928 /* genNatLibGetStateBlock - */
11929 /*-----------------------------------------------------------------*/
11930 static void genNatLibGetStateBlock(iCode *ic,int nparms,
11931 operand **parms,const char *name)
11934 symbol *lbl = newiTempLabel(NULL);
11937 /* save registers that need to be saved */
11938 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11939 ds390_rUmaskForOp (IC_RESULT(ic))));
11941 /* put libraryID into DPTR */
11942 emitcode ("mov","dptr,#LibraryID");
11943 /* make the call */
11944 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
11945 emitcode ("jnz","!tlabel",lbl->key+100);
11947 /* put return value into place */
11948 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
11949 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
11950 emitcode ("push","ar3");
11951 emitcode ("push","ar2");
11952 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,FALSE));
11953 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,FALSE));
11955 aopPut(AOP(IC_RESULT(ic)),"r2",0);
11956 aopPut(AOP(IC_RESULT(ic)),"r3",1);
11958 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11959 emitcode ("","!tlabeldef",lbl->key+100);
11960 unsavermask(rsave);
11963 /*-----------------------------------------------------------------*/
11964 /* genMMMalloc - */
11965 /*-----------------------------------------------------------------*/
11966 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
11967 int size, const char *name)
11972 symbol *lbl = newiTempLabel(NULL);
11974 assert (nparms == 1);
11975 /* save registers that need to be saved */
11976 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11977 ds390_rUmaskForOp (IC_RESULT(ic))));
11980 aopOp (bsize,ic,FALSE,FALSE);
11982 /* put the size in R4-R2 */
11983 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
11984 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,FALSE));
11985 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,FALSE));
11987 emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,FALSE));
11988 emitcode("pop","ar4");
11990 emitcode("pop","ar3");
11991 emitcode("pop","ar2");
11993 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,FALSE));
11994 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,FALSE));
11996 emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,FALSE));
11999 freeAsmop (bsize, NULL, ic, FALSE);
12001 /* make the call */
12002 emitcode ("lcall","MM_%s",name);
12003 emitcode ("jz","!tlabel",lbl->key+100);
12004 emitcode ("mov","r2,#!constbyte",0xff);
12005 emitcode ("mov","r3,#!constbyte",0xff);
12006 emitcode ("","!tlabeldef",lbl->key+100);
12007 /* we don't care about the pointer : we just save the handle */
12008 rsym = OP_SYMBOL(IC_RESULT(ic));
12009 if (rsym->liveFrom != rsym->liveTo) {
12010 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12011 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12012 emitcode ("push","ar3");
12013 emitcode ("push","ar2");
12014 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,FALSE));
12015 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,FALSE));
12017 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12018 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12020 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12022 unsavermask(rsave);
12025 /*-----------------------------------------------------------------*/
12027 /*-----------------------------------------------------------------*/
12028 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12033 assert (nparms == 1);
12034 /* save registers that need to be saved */
12035 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12036 ds390_rUmaskForOp (IC_RESULT(ic))));
12039 aopOp (handle,ic,FALSE,FALSE);
12041 /* put the size in R4-R2 */
12042 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12043 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
12044 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
12045 emitcode("pop","ar3");
12046 emitcode("pop","ar2");
12048 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
12049 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
12051 freeAsmop (handle, NULL, ic, FALSE);
12053 /* make the call */
12054 emitcode ("lcall","MM_Deref");
12057 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12058 if (rsym->liveFrom != rsym->liveTo) {
12059 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12060 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12061 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12062 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12063 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12067 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12068 unsavermask(rsave);
12071 /*-----------------------------------------------------------------*/
12072 /* genMMUnrestrictedPersist - */
12073 /*-----------------------------------------------------------------*/
12074 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12079 assert (nparms == 1);
12080 /* save registers that need to be saved */
12081 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12082 ds390_rUmaskForOp (IC_RESULT(ic))));
12085 aopOp (handle,ic,FALSE,FALSE);
12087 /* put the size in R3-R2 */
12088 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12089 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
12090 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
12091 emitcode("pop","ar3");
12092 emitcode("pop","ar2");
12094 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
12095 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
12097 freeAsmop (handle, NULL, ic, FALSE);
12099 /* make the call */
12100 emitcode ("lcall","MM_UnrestrictedPersist");
12103 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12104 if (rsym->liveFrom != rsym->liveTo) {
12105 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12106 aopPut(AOP(IC_RESULT(ic)),"a",0);
12107 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12110 unsavermask(rsave);
12113 /*-----------------------------------------------------------------*/
12114 /* genSystemExecJavaProcess - */
12115 /*-----------------------------------------------------------------*/
12116 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12119 operand *handle, *pp;
12121 assert (nparms==2);
12122 /* save registers that need to be saved */
12123 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12124 ds390_rUmaskForOp (IC_RESULT(ic))));
12129 /* put the handle in R3-R2 */
12130 aopOp (handle,ic,FALSE,FALSE);
12131 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12132 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
12133 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
12134 emitcode("pop","ar3");
12135 emitcode("pop","ar2");
12137 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
12138 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
12140 freeAsmop (handle, NULL, ic, FALSE);
12142 /* put pointer in DPTR */
12143 aopOp (pp,ic,FALSE,FALSE);
12144 if (AOP_TYPE(pp) == AOP_IMMD) {
12145 emitcode ("mov", "dptr,%s", aopGet (AOP (pp), 0, TRUE, FALSE, FALSE));
12146 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12147 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,FALSE));
12148 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,FALSE));
12149 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,FALSE));
12151 freeAsmop (handle, NULL, ic, FALSE);
12153 /* make the call */
12154 emitcode ("lcall","System_ExecJavaProcess");
12156 /* put result in place */
12158 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12159 if (rsym->liveFrom != rsym->liveTo) {
12160 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12161 aopPut(AOP(IC_RESULT(ic)),"a",0);
12162 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12166 unsavermask(rsave);
12169 /*-----------------------------------------------------------------*/
12170 /* genSystemRTCRegisters - */
12171 /*-----------------------------------------------------------------*/
12172 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12178 assert (nparms==1);
12179 /* save registers that need to be saved */
12180 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12181 ds390_rUmaskForOp (IC_RESULT(ic))));
12184 /* put pointer in DPTR */
12185 aopOp (pp,ic,FALSE,FALSE);
12186 if (AOP_TYPE (pp) == AOP_IMMD) {
12187 emitcode ("mov","dps,#1");
12188 emitcode ("mov", "dptr,%s", aopGet (AOP (pp), 0, TRUE, FALSE, FALSE));
12189 emitcode ("mov","dps,#0");
12191 emitcode ("mov","dpl1,%s",aopGet(AOP(pp),0,FALSE,FALSE,FALSE));
12192 emitcode ("mov","dph1,%s",aopGet(AOP(pp),1,FALSE,FALSE,FALSE));
12193 emitcode ("mov","dpx1,%s",aopGet(AOP(pp),2,FALSE,FALSE,FALSE));
12195 freeAsmop (pp, NULL, ic, FALSE);
12197 /* make the call */
12198 emitcode ("lcall","System_%sRTCRegisters",name);
12200 unsavermask(rsave);
12203 /*-----------------------------------------------------------------*/
12204 /* genSystemThreadSleep - */
12205 /*-----------------------------------------------------------------*/
12206 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12211 assert (nparms==1);
12212 /* save registers that need to be saved */
12213 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12214 ds390_rUmaskForOp (IC_RESULT(ic))));
12217 aopOp(to,ic,FALSE,FALSE);
12218 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12219 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12220 emitcode ("push","%s",aopGet(AOP(to),0,FALSE,TRUE,FALSE));
12221 emitcode ("push","%s",aopGet(AOP(to),1,FALSE,TRUE,FALSE));
12222 emitcode ("push","%s",aopGet(AOP(to),2,FALSE,TRUE,FALSE));
12223 emitcode ("push","%s",aopGet(AOP(to),3,FALSE,TRUE,FALSE));
12224 emitcode ("pop","ar3");
12225 emitcode ("pop","ar2");
12226 emitcode ("pop","ar1");
12227 emitcode ("pop","ar0");
12229 emitcode ("mov","r0,%s",aopGet(AOP(to),0,FALSE,TRUE,FALSE));
12230 emitcode ("mov","r1,%s",aopGet(AOP(to),1,FALSE,TRUE,FALSE));
12231 emitcode ("mov","r2,%s",aopGet(AOP(to),2,FALSE,TRUE,FALSE));
12232 emitcode ("mov","r3,%s",aopGet(AOP(to),3,FALSE,TRUE,FALSE));
12234 freeAsmop (to, NULL, ic, FALSE);
12236 /* suspend in acc */
12238 aopOp(s,ic,FALSE,FALSE);
12239 emitcode ("mov","a,%s",aopGet(AOP(s),0,FALSE,TRUE,FALSE));
12240 freeAsmop (s, NULL, ic, FALSE);
12242 /* make the call */
12243 emitcode ("lcall","System_%s",name);
12245 unsavermask(rsave);
12248 /*-----------------------------------------------------------------*/
12249 /* genSystemThreadResume - */
12250 /*-----------------------------------------------------------------*/
12251 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12256 assert (nparms==2);
12257 /* save registers that need to be saved */
12258 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12259 ds390_rUmaskForOp (IC_RESULT(ic))));
12265 aopOp(pid,ic,FALSE,FALSE);
12266 emitcode ("mov","r0,%s",aopGet(AOP(pid),0,FALSE,TRUE,FALSE));
12267 freeAsmop (pid, NULL, ic, FALSE);
12270 aopOp(tid,ic,FALSE,FALSE);
12271 emitcode ("mov","a,%s",aopGet(AOP(tid),0,FALSE,TRUE,FALSE));
12272 freeAsmop (tid, NULL, ic, FALSE);
12274 emitcode ("lcall","System_ThreadResume");
12276 /* put result into place */
12278 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12279 if (rsym->liveFrom != rsym->liveTo) {
12280 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12281 aopPut(AOP(IC_RESULT(ic)),"a",0);
12282 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12285 unsavermask(rsave);
12288 /*-----------------------------------------------------------------*/
12289 /* genSystemProcessResume - */
12290 /*-----------------------------------------------------------------*/
12291 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
12296 assert (nparms==1);
12297 /* save registers that need to be saved */
12298 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12299 ds390_rUmaskForOp (IC_RESULT(ic))));
12304 aopOp(pid,ic,FALSE,FALSE);
12305 emitcode ("mov","a,%s",aopGet(AOP(pid),0,FALSE,TRUE,FALSE));
12306 freeAsmop (pid, NULL, ic, FALSE);
12308 emitcode ("lcall","System_ProcessResume");
12310 unsavermask(rsave);
12313 /*-----------------------------------------------------------------*/
12315 /*-----------------------------------------------------------------*/
12316 static void genSystem (iCode *ic,int nparms,char *name)
12318 assert(nparms == 0);
12320 emitcode ("lcall","System_%s",name);
12323 /*-----------------------------------------------------------------*/
12324 /* genSystemPoll - */
12325 /*-----------------------------------------------------------------*/
12326 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
12331 assert (nparms==1);
12332 /* save registers that need to be saved */
12333 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12334 ds390_rUmaskForOp (IC_RESULT(ic))));
12337 aopOp (fp,ic,FALSE,FALSE);
12338 if (AOP_TYPE (fp) == AOP_IMMD) {
12339 emitcode ("mov", "dptr,%s", aopGet (AOP (fp), 0, TRUE, FALSE, FALSE));
12340 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
12341 emitcode ("mov","dpl,%s",aopGet(AOP(fp),0,FALSE,FALSE,FALSE));
12342 emitcode ("mov","dph,%s",aopGet(AOP(fp),1,FALSE,FALSE,FALSE));
12343 emitcode ("mov","dpx,%s",aopGet(AOP(fp),2,FALSE,FALSE,FALSE));
12345 freeAsmop (fp, NULL, ic, FALSE);
12347 emitcode ("lcall","System_%sPoll",name);
12349 /* put result into place */
12351 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12352 if (rsym->liveFrom != rsym->liveTo) {
12353 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12354 aopPut(AOP(IC_RESULT(ic)),"a",0);
12355 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12358 unsavermask(rsave);
12361 /*-----------------------------------------------------------------*/
12362 /* genSystemGetCurrentID - */
12363 /*-----------------------------------------------------------------*/
12364 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
12366 assert (nparms==0);
12368 emitcode ("lcall","System_GetCurrent%sId",name);
12369 /* put result into place */
12371 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12372 if (rsym->liveFrom != rsym->liveTo) {
12373 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12374 aopPut(AOP(IC_RESULT(ic)),"a",0);
12375 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12380 /*-----------------------------------------------------------------*/
12381 /* genBuiltIn - calls the appropriate function to generating code */
12382 /* for a built in function */
12383 /*-----------------------------------------------------------------*/
12384 static void genBuiltIn (iCode *ic)
12386 operand *bi_parms[MAX_BUILTIN_ARGS];
12391 /* get all the arguments for a built in function */
12392 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
12394 /* which function is it */
12395 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
12396 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
12397 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
12398 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
12399 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
12400 } else if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
12401 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
12402 } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
12403 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
12404 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
12405 genMemsetX(bi_iCode,nbi_parms,bi_parms);
12406 } else if (strcmp(bif->name,"__builtin_inp")==0) {
12407 genInp(bi_iCode,nbi_parms,bi_parms);
12408 } else if (strcmp(bif->name,"__builtin_outp")==0) {
12409 genOutp(bi_iCode,nbi_parms,bi_parms);
12410 } else if (strcmp(bif->name,"__builtin_swapw")==0) {
12411 genSwapW(bi_iCode,nbi_parms,bi_parms);
12412 /* JavaNative builtIns */
12413 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
12414 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
12415 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
12416 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
12417 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
12418 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
12419 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
12420 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
12421 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
12422 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12423 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
12424 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12425 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
12426 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
12427 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
12428 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
12429 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
12430 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12431 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
12432 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12433 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
12434 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
12435 } else if (strcmp(bif->name,"MM_Malloc")==0) {
12436 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
12437 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
12438 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
12439 } else if (strcmp(bif->name,"MM_Free")==0) {
12440 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
12441 } else if (strcmp(bif->name,"MM_Deref")==0) {
12442 genMMDeref(bi_iCode,nbi_parms,bi_parms);
12443 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
12444 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
12445 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
12446 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
12447 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
12448 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
12449 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
12450 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
12451 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
12452 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
12453 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
12454 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
12455 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
12456 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
12457 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
12458 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
12459 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12460 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12461 } else if (strcmp(bif->name,"System_SaveThread")==0) {
12462 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12463 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12464 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12465 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
12466 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
12467 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
12468 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
12469 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
12470 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
12471 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
12472 genSystem(bi_iCode,nbi_parms,"ProcessYield");
12473 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
12474 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
12475 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
12476 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
12477 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
12478 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
12479 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
12480 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
12481 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
12482 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
12484 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
12490 /*-----------------------------------------------------------------*/
12491 /* gen390Code - generate code for Dallas 390 based controllers */
12492 /*-----------------------------------------------------------------*/
12494 gen390Code (iCode * lic)
12499 lineHead = lineCurr = NULL;
12500 dptrn[1][0] = "dpl1";
12501 dptrn[1][1] = "dph1";
12502 dptrn[1][2] = "dpx1";
12504 if (options.model == MODEL_FLAT24) {
12505 fReturnSizeDS390 = 5;
12506 fReturn = fReturn24;
12508 fReturnSizeDS390 = 4;
12509 fReturn = fReturn16;
12510 options.stack10bit=0;
12513 /* print the allocation information */
12515 printAllocInfo (currFunc, codeOutFile);
12517 /* if debug information required */
12518 if (options.debug && currFunc)
12520 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
12522 if (IS_STATIC (currFunc->etype))
12523 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
12525 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
12528 /* stack pointer name */
12529 if (options.useXstack)
12535 for (ic = lic; ic; ic = ic->next)
12538 if (ic->lineno && cln != ic->lineno)
12543 emitcode ("", "C$%s$%d$%d$%d ==.",
12544 FileBaseName (ic->filename), ic->lineno,
12545 ic->level, ic->block);
12548 if (!options.noCcodeInAsm) {
12549 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
12550 printCLine(ic->filename, ic->lineno));
12554 if (options.iCodeInAsm) {
12555 emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
12557 /* if the result is marked as
12558 spilt and rematerializable or code for
12559 this has already been generated then
12561 if (resultRemat (ic) || ic->generated)
12564 /* depending on the operation */
12584 /* IPOP happens only when trying to restore a
12585 spilt live range, if there is an ifx statement
12586 following this pop then the if statement might
12587 be using some of the registers being popped which
12588 would destory the contents of the register so
12589 we need to check for this condition and handle it */
12591 ic->next->op == IFX &&
12592 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
12593 genIfx (ic->next, ic);
12611 genEndFunction (ic);
12631 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
12648 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
12652 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
12659 /* note these two are xlated by algebraic equivalence
12660 during parsing SDCC.y */
12661 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12662 "got '>=' or '<=' shouldn't have come here");
12666 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
12678 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
12682 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
12686 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
12710 genRightShift (ic);
12713 case GET_VALUE_AT_ADDRESS:
12714 genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
12718 if (POINTER_SET (ic))
12719 genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
12745 if (ic->builtinSEND) genBuiltIn(ic);
12746 else addSet (&_G.sendSet, ic);
12759 /* now we are ready to call the
12760 peep hole optimizer */
12761 if (!options.nopeep)
12762 peepHole (&lineHead);
12764 /* now do the actual printing */
12765 printLine (lineHead, codeOutFile);