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 // Macro to aopOp all three operands of an ic. If this cannot be done,
3684 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3685 // will be set TRUE. The caller must then handle the case specially, noting
3686 // that the IC_RESULT operand is not aopOp'd.
3687 #define AOP_OP_3_NOFATAL(ic, rc) \
3688 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3689 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR) || \
3690 ((OP_SYMBOL(IC_RESULT(ic))->ruonly) && !isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)))); \
3691 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3692 (isOperandInFarSpace(IC_RESULT(ic)) || (OP_SYMBOL(IC_RESULT(ic))->ruonly && !isOperandEqual(IC_LEFT(ic),IC_RESULT(ic))))) \
3694 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3699 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3700 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3702 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3703 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3705 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3707 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3711 // aopOp the left & right operands of an ic.
3712 #define AOP_OP_2(ic) \
3713 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3714 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3716 // convienience macro.
3717 #define AOP_SET_LOCALS(ic) \
3718 left = IC_LEFT(ic); \
3719 right = IC_RIGHT(ic); \
3720 result = IC_RESULT(ic);
3723 // Given an integer value of pushedSize bytes on the stack,
3724 // adjust it to be resultSize bytes, either by discarding
3725 // the most significant bytes or by zero-padding.
3727 // On exit from this macro, pushedSize will have been adjusted to
3728 // equal resultSize, and ACC may be trashed.
3729 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3730 /* If the pushed data is bigger than the result, \
3731 * simply discard unused bytes. Icky, but works. \
3733 while (pushedSize > resultSize) \
3735 D (emitcode (";", "discarding unused result byte."););\
3736 emitcode ("pop", "acc"); \
3739 if (pushedSize < resultSize) \
3741 emitcode ("clr", "a"); \
3742 /* Conversly, we haven't pushed enough here. \
3743 * just zero-pad, and all is well. \
3745 while (pushedSize < resultSize) \
3747 emitcode("push", "acc"); \
3751 assert(pushedSize == resultSize);
3753 /*-----------------------------------------------------------------*/
3754 /* genPlus - generates code for addition */
3755 /*-----------------------------------------------------------------*/
3757 genPlus (iCode * ic)
3759 int size, offset = 0;
3760 bool pushResult = FALSE;
3763 D (emitcode (";", "genPlus "););
3765 /* special cases :- */
3766 if ( IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly &&
3767 isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
3768 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
3769 size = floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
3771 while (size--) emitcode ("inc","dptr");
3773 emitcode ("mov","a,dpl");
3774 emitcode ("add","a,#!constbyte",size & 0xff);
3775 emitcode ("mov","dpl,a");
3776 emitcode ("mov","a,dph");
3777 emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
3778 emitcode ("mov","dph,a");
3779 emitcode ("mov","a,dpx");
3780 emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
3781 emitcode ("mov","dpx,a");
3783 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
3786 if ( IS_SYMOP(IC_LEFT(ic)) &&
3787 OP_SYMBOL(IC_LEFT(ic))->remat &&
3788 isOperandInFarSpace(IC_RIGHT(ic))) {
3789 operand *op = IC_RIGHT(ic);
3790 IC_RIGHT(ic) = IC_LEFT(ic);
3794 AOP_OP_3_NOFATAL (ic, pushResult);
3797 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3802 /* if literal, literal on the right or
3803 if left requires ACC or right is already
3805 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3806 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3807 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3809 operand *t = IC_RIGHT (ic);
3810 IC_RIGHT (ic) = IC_LEFT (ic);
3812 emitcode (";", "Swapped plus args.");
3815 /* if both left & right are in bit
3817 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3818 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3824 /* if left in bit space & right literal */
3825 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3826 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3828 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3829 /* if result in bit space */
3830 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3832 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3833 emitcode ("cpl", "c");
3834 outBitC (IC_RESULT (ic));
3838 size = getDataSize (IC_RESULT (ic));
3839 _startLazyDPSEvaluation ();
3842 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3843 emitcode ("addc", "a,#0");
3844 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3846 _endLazyDPSEvaluation ();
3851 /* if I can do an increment instead
3852 of add then GOOD for ME */
3853 if (genPlusIncr (ic) == TRUE)
3855 emitcode (";", "did genPlusIncr");
3860 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3862 _startLazyDPSEvaluation ();
3865 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3867 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3869 emitcode ("add", "a,%s",
3870 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3872 emitcode ("addc", "a,%s",
3873 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3877 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3879 /* right is going to use ACC or we would have taken the
3882 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3884 D(emitcode(";", "+ AOP_ACC special case."););
3885 emitcode("xch", "a, %s", DP2_RESULT_REG);
3887 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3890 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3893 emitcode("add", "a, %s", DP2_RESULT_REG);
3897 emitcode ("add", "a,%s",
3898 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
3903 emitcode ("addc", "a,%s",
3904 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3909 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3913 emitcode ("push", "acc");
3917 _endLazyDPSEvaluation ();
3921 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3923 size = getDataSize (IC_LEFT (ic));
3924 rSize = getDataSize (IC_RESULT (ic));
3926 ADJUST_PUSHED_RESULT(size, rSize);
3928 _startLazyDPSEvaluation ();
3931 emitcode ("pop", "acc");
3932 aopPut (AOP (IC_RESULT (ic)), "a", size);
3934 _endLazyDPSEvaluation ();
3937 adjustArithmeticResult (ic);
3940 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3941 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3942 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3945 /*-----------------------------------------------------------------*/
3946 /* genMinusDec :- does subtraction with deccrement if possible */
3947 /*-----------------------------------------------------------------*/
3949 genMinusDec (iCode * ic)
3951 unsigned int icount;
3952 unsigned int size = getDataSize (IC_RESULT (ic));
3954 /* will try to generate an increment */
3955 /* if the right side is not a literal
3957 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3960 /* if the literal value of the right hand side
3961 is greater than 4 then it is not worth it */
3962 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3965 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3966 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3968 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
3972 /* if decrement 16 bits in register */
3973 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3974 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3975 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3983 /* If the next instruction is a goto and the goto target
3984 * is <= 5 instructions previous to this, we can generate
3985 * jumps straight to that target.
3987 if (ic->next && ic->next->op == GOTO
3988 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3991 emitcode (";", "tail decrement optimized (range %d)", labelRange);
3992 tlbl = IC_LABEL (ic->next);
3997 tlbl = newiTempLabel (NULL);
4001 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
4002 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4003 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4004 IS_AOP_PREG (IC_RESULT (ic)))
4005 emitcode ("cjne", "%s,#!constbyte,!tlabel"
4006 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE), 0xff
4010 emitcode ("mov", "a,#!constbyte",0xff);
4011 emitcode ("cjne", "a,%s,!tlabel"
4012 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
4015 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
4018 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4019 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4020 IS_AOP_PREG (IC_RESULT (ic)))
4021 emitcode ("cjne", "%s,#!constbyte,!tlabel"
4022 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE),0xff
4026 emitcode ("cjne", "a,%s,!tlabel"
4027 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
4030 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
4034 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4035 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4036 IS_AOP_PREG (IC_RESULT (ic)))
4037 emitcode ("cjne", "%s,#!constbyte,!tlabel"
4038 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE),0xff
4042 emitcode ("cjne", "a,%s,!tlabel"
4043 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
4046 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
4050 emitcode ("", "!tlabeldef", tlbl->key + 100);
4055 /* if the sizes are greater than 1 then we cannot */
4056 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4057 AOP_SIZE (IC_LEFT (ic)) > 1)
4060 /* we can if the aops of the left & result match or
4061 if they are in registers and the registers are the
4064 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4065 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4066 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4069 _startLazyDPSEvaluation ();
4072 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
4074 _endLazyDPSEvaluation ();
4082 /*-----------------------------------------------------------------*/
4083 /* addSign - complete with sign */
4084 /*-----------------------------------------------------------------*/
4086 addSign (operand * result, int offset, int sign)
4088 int size = (getDataSize (result) - offset);
4091 _startLazyDPSEvaluation();
4094 emitcode ("rlc", "a");
4095 emitcode ("subb", "a,acc");
4098 aopPut (AOP (result), "a", offset++);
4105 aopPut (AOP (result), zero, offset++);
4108 _endLazyDPSEvaluation();
4112 /*-----------------------------------------------------------------*/
4113 /* genMinusBits - generates code for subtraction of two bits */
4114 /*-----------------------------------------------------------------*/
4116 genMinusBits (iCode * ic)
4118 symbol *lbl = newiTempLabel (NULL);
4120 D (emitcode (";", "genMinusBits "););
4122 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4124 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4125 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4126 emitcode ("cpl", "c");
4127 emitcode ("", "!tlabeldef", (lbl->key + 100));
4128 outBitC (IC_RESULT (ic));
4132 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4133 emitcode ("subb", "a,acc");
4134 emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4135 emitcode ("inc", "a");
4136 emitcode ("", "!tlabeldef", (lbl->key + 100));
4137 aopPut (AOP (IC_RESULT (ic)), "a", 0);
4138 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4142 /*-----------------------------------------------------------------*/
4143 /* genMinus - generates code for subtraction */
4144 /*-----------------------------------------------------------------*/
4146 genMinus (iCode * ic)
4148 int size, offset = 0;
4150 unsigned long lit = 0L;
4151 bool pushResult = FALSE;
4153 D (emitcode (";", "genMinus "););
4155 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
4156 aopOp (IC_RIGHT (ic), ic, FALSE,
4157 (AOP_INDPTRn(IC_LEFT(ic)) ? FALSE : (AOP_USESDPTR(IC_LEFT(ic)) ? TRUE : FALSE)));
4158 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
4159 ((AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2)
4160 || OP_SYMBOL(IC_RESULT(ic))->ruonly))
4166 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
4168 /* special cases :- */
4169 /* if both left & right are in bit space */
4170 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4171 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4177 /* if I can do an decrement instead
4178 of subtract then GOOD for ME */
4179 if (genMinusDec (ic) == TRUE)
4184 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4186 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4192 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4197 /* if literal, add a,#-lit, else normal subb */
4198 _startLazyDPSEvaluation ();
4200 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
4201 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4202 if (AOP_USESDPTR(IC_RIGHT(ic))) {
4203 emitcode ("mov","b,a");
4204 MOVA(aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
4205 emitcode ("xch","a,b");
4206 emitcode ("subb","a,b");
4208 emitcode ("subb", "a,%s",
4209 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
4212 /* first add without previous c */
4214 if (!size && lit==-1) {
4215 emitcode ("dec", "a");
4217 emitcode ("add", "a,#!constbyte",
4218 (unsigned int) (lit & 0x0FFL));
4221 emitcode ("addc", "a,#!constbyte",
4222 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4227 emitcode ("push", "acc");
4229 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4233 _endLazyDPSEvaluation ();
4237 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4239 size = getDataSize (IC_LEFT (ic));
4240 rSize = getDataSize (IC_RESULT (ic));
4242 ADJUST_PUSHED_RESULT(size, rSize);
4244 _startLazyDPSEvaluation ();
4247 emitcode ("pop", "acc");
4248 aopPut (AOP (IC_RESULT (ic)), "a", size);
4250 _endLazyDPSEvaluation ();
4253 adjustArithmeticResult (ic);
4256 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4257 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4258 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4262 /*-----------------------------------------------------------------*/
4263 /* genMultbits :- multiplication of bits */
4264 /*-----------------------------------------------------------------*/
4266 genMultbits (operand * left,
4271 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4272 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4273 aopOp(result, ic, TRUE, FALSE);
4278 /*-----------------------------------------------------------------*/
4279 /* genMultOneByte : 8*8=8/16 bit multiplication */
4280 /*-----------------------------------------------------------------*/
4282 genMultOneByte (operand * left,
4287 sym_link *opetype = operandType (result);
4291 /* (if two literals: the value is computed before) */
4292 /* if one literal, literal on the right */
4293 if (AOP_TYPE (left) == AOP_LIT)
4298 emitcode (";", "swapped left and right");
4301 if (SPEC_USIGN(opetype)
4302 // ignore the sign of left and right, what else can we do?
4303 || (SPEC_USIGN(operandType(left)) &&
4304 SPEC_USIGN(operandType(right)))) {
4305 // just an unsigned 8*8=8/16 multiply
4306 //emitcode (";","unsigned");
4307 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4308 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4309 emitcode ("mul", "ab");
4311 _G.accInUse++; _G.bInUse++;
4312 aopOp(result, ic, TRUE, FALSE);
4314 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4316 // this should never happen
4317 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4318 AOP_SIZE(result), __FILE__, lineno);
4322 aopPut (AOP (result), "a", 0);
4323 _G.accInUse--; _G.bInUse--;
4324 if (AOP_SIZE(result)==2)
4326 aopPut (AOP (result), "b", 1);
4331 // we have to do a signed multiply
4333 emitcode (";", "signed");
4334 emitcode ("clr", "F0"); // reset sign flag
4335 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4337 lbl=newiTempLabel(NULL);
4338 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4339 // left side is negative, 8-bit two's complement, this fails for -128
4340 emitcode ("setb", "F0"); // set sign flag
4341 emitcode ("cpl", "a");
4342 emitcode ("inc", "a");
4344 emitcode ("", "!tlabeldef", lbl->key+100);
4347 if (AOP_TYPE(right)==AOP_LIT) {
4348 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4349 /* AND literal negative */
4350 if ((int) val < 0) {
4351 emitcode ("cpl", "F0"); // complement sign flag
4352 emitcode ("mov", "b,#!constbyte", -val);
4354 emitcode ("mov", "b,#!constbyte", val);
4357 lbl=newiTempLabel(NULL);
4358 emitcode ("mov", "b,a");
4359 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4360 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4361 // right side is negative, 8-bit two's complement
4362 emitcode ("cpl", "F0"); // complement sign flag
4363 emitcode ("cpl", "a");
4364 emitcode ("inc", "a");
4365 emitcode ("", "!tlabeldef", lbl->key+100);
4367 emitcode ("mul", "ab");
4369 _G.accInUse++;_G.bInUse++;
4370 aopOp(result, ic, TRUE, FALSE);
4372 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4374 // this should never happen
4375 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4376 AOP_SIZE(result), __FILE__, lineno);
4380 lbl=newiTempLabel(NULL);
4381 emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4382 // only ONE op was negative, we have to do a 8/16-bit two's complement
4383 emitcode ("cpl", "a"); // lsb
4384 if (AOP_SIZE(result)==1) {
4385 emitcode ("inc", "a");
4387 emitcode ("add", "a,#1");
4388 emitcode ("xch", "a,b");
4389 emitcode ("cpl", "a"); // msb
4390 emitcode ("addc", "a,#0");
4391 emitcode ("xch", "a,b");
4394 emitcode ("", "!tlabeldef", lbl->key+100);
4395 aopPut (AOP (result), "a", 0);
4396 _G.accInUse--;_G.bInUse--;
4397 if (AOP_SIZE(result)==2) {
4398 aopPut (AOP (result), "b", 1);
4402 /*-----------------------------------------------------------------*/
4403 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
4404 /*-----------------------------------------------------------------*/
4405 static void genMultTwoByte (operand *left, operand *right,
4406 operand *result, iCode *ic)
4408 sym_link *retype = getSpec(operandType(right));
4409 sym_link *letype = getSpec(operandType(left));
4410 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4413 if (AOP_TYPE (left) == AOP_LIT) {
4418 /* save EA bit in F1 */
4419 lbl = newiTempLabel(NULL);
4420 emitcode ("setb","F1");
4421 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4422 emitcode ("clr","F1");
4423 emitcode("","!tlabeldef",lbl->key+100);
4425 /* load up MB with right */
4427 emitcode("clr","F0");
4428 if (AOP_TYPE(right) == AOP_LIT) {
4429 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4431 emitcode("setb","F0");
4434 emitcode ("mov","mb,#!constbyte",val & 0xff);
4435 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4437 lbl = newiTempLabel(NULL);
4438 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4439 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4440 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4441 emitcode ("xch", "a,b");
4442 emitcode ("cpl","a");
4443 emitcode ("add", "a,#1");
4444 emitcode ("xch", "a,b");
4445 emitcode ("cpl", "a"); // msb
4446 emitcode ("addc", "a,#0");
4447 emitcode ("setb","F0");
4448 emitcode ("","!tlabeldef",lbl->key+100);
4449 emitcode ("mov","mb,b");
4450 emitcode ("mov","mb,a");
4453 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4454 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4456 /* load up MA with left */
4458 lbl = newiTempLabel(NULL);
4459 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4460 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4461 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4462 emitcode ("xch", "a,b");
4463 emitcode ("cpl","a");
4464 emitcode ("add", "a,#1");
4465 emitcode ("xch", "a,b");
4466 emitcode ("cpl", "a"); // msb
4467 emitcode ("addc","a,#0");
4468 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4469 emitcode ("setb","F0");
4470 emitcode ("","!tlabeldef",lbl->key+100);
4471 emitcode ("mov","ma,b");
4472 emitcode ("mov","ma,a");
4474 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4475 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4477 /* wait for multiplication to finish */
4478 lbl = newiTempLabel(NULL);
4479 emitcode("","!tlabeldef", lbl->key+100);
4480 emitcode("mov","a,mcnt1");
4481 emitcode("anl","a,#!constbyte",0x80);
4482 emitcode("jnz","!tlabel",lbl->key+100);
4484 freeAsmop (left, NULL, ic, TRUE);
4485 freeAsmop (right, NULL, ic,TRUE);
4486 aopOp(result, ic, TRUE, FALSE);
4488 /* if unsigned then simple */
4490 emitcode ("mov","a,ma");
4491 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4492 emitcode ("mov","a,ma");
4493 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4494 aopPut(AOP(result),"ma",1);
4495 aopPut(AOP(result),"ma",0);
4497 emitcode("push","ma");
4498 emitcode("push","ma");
4499 emitcode("push","ma");
4501 /* negate result if needed */
4502 lbl = newiTempLabel(NULL);
4503 emitcode("jnb","F0,!tlabel",lbl->key+100);
4504 emitcode("cpl","a");
4505 emitcode("add","a,#1");
4506 emitcode("","!tlabeldef", lbl->key+100);
4507 if (AOP_TYPE(result) == AOP_ACC)
4509 D(emitcode(";", "ACC special case."););
4510 /* We know result is the only live aop, and
4511 * it's obviously not a DPTR2, so AP is available.
4513 emitcode("mov", "%s,acc", DP2_RESULT_REG);
4517 aopPut(AOP(result),"a",0);
4520 emitcode("pop","acc");
4521 lbl = newiTempLabel(NULL);
4522 emitcode("jnb","F0,!tlabel",lbl->key+100);
4523 emitcode("cpl","a");
4524 emitcode("addc","a,#0");
4525 emitcode("","!tlabeldef", lbl->key+100);
4526 aopPut(AOP(result),"a",1);
4527 emitcode("pop","acc");
4528 if (AOP_SIZE(result) >= 3) {
4529 lbl = newiTempLabel(NULL);
4530 emitcode("jnb","F0,!tlabel",lbl->key+100);
4531 emitcode("cpl","a");
4532 emitcode("addc","a,#0");
4533 emitcode("","!tlabeldef", lbl->key+100);
4534 aopPut(AOP(result),"a",2);
4536 emitcode("pop","acc");
4537 if (AOP_SIZE(result) >= 4) {
4538 lbl = newiTempLabel(NULL);
4539 emitcode("jnb","F0,!tlabel",lbl->key+100);
4540 emitcode("cpl","a");
4541 emitcode("addc","a,#0");
4542 emitcode("","!tlabeldef", lbl->key+100);
4543 aopPut(AOP(result),"a",3);
4545 if (AOP_TYPE(result) == AOP_ACC)
4547 /* We stashed the result away above. */
4548 emitcode("mov", "acc,%s", DP2_RESULT_REG);
4552 freeAsmop (result, NULL, ic, TRUE);
4554 /* restore EA bit in F1 */
4555 lbl = newiTempLabel(NULL);
4556 emitcode ("jnb","F1,!tlabel",lbl->key+100);
4557 emitcode ("setb","EA");
4558 emitcode("","!tlabeldef",lbl->key+100);
4562 /*-----------------------------------------------------------------*/
4563 /* genMult - generates code for multiplication */
4564 /*-----------------------------------------------------------------*/
4566 genMult (iCode * ic)
4568 operand *left = IC_LEFT (ic);
4569 operand *right = IC_RIGHT (ic);
4570 operand *result = IC_RESULT (ic);
4572 D (emitcode (";", "genMult "););
4574 /* assign the amsops */
4577 /* special cases first */
4579 if (AOP_TYPE (left) == AOP_CRY &&
4580 AOP_TYPE (right) == AOP_CRY)
4582 genMultbits (left, right, result, ic);
4586 /* if both are of size == 1 */
4587 if (AOP_SIZE (left) == 1 &&
4588 AOP_SIZE (right) == 1)
4590 genMultOneByte (left, right, result, ic);
4594 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4595 /* use the ds390 ARITHMETIC accel UNIT */
4596 genMultTwoByte (left, right, result, ic);
4599 /* should have been converted to function call */
4603 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4604 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4605 freeAsmop (result, NULL, ic, TRUE);
4608 /*-----------------------------------------------------------------*/
4609 /* genDivbits :- division of bits */
4610 /*-----------------------------------------------------------------*/
4612 genDivbits (operand * left,
4620 /* the result must be bit */
4621 LOAD_AB_FOR_DIV (left, right, l);
4622 emitcode ("div", "ab");
4623 emitcode ("rrc", "a");
4624 aopOp(result, ic, TRUE, FALSE);
4626 aopPut (AOP (result), "c", 0);
4629 /*-----------------------------------------------------------------*/
4630 /* genDivOneByte : 8 bit division */
4631 /*-----------------------------------------------------------------*/
4633 genDivOneByte (operand * left,
4638 sym_link *opetype = operandType (result);
4644 /* signed or unsigned */
4645 if (SPEC_USIGN (opetype))
4647 /* unsigned is easy */
4648 LOAD_AB_FOR_DIV (left, right, l);
4649 emitcode ("div", "ab");
4652 aopOp(result, ic, TRUE, FALSE);
4653 aopPut (AOP (result), "a", 0);
4656 size = AOP_SIZE (result) - 1;
4660 aopPut (AOP (result), zero, offset++);
4665 /* signed is a little bit more difficult */
4667 /* save the signs of the operands */
4668 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4670 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4671 emitcode ("push", "acc"); /* save it on the stack */
4673 /* now sign adjust for both left & right */
4674 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4676 lbl = newiTempLabel (NULL);
4677 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4678 emitcode ("cpl", "a");
4679 emitcode ("inc", "a");
4680 emitcode ("", "!tlabeldef", (lbl->key + 100));
4681 emitcode ("mov", "b,a");
4683 /* sign adjust left side */
4684 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4687 lbl = newiTempLabel (NULL);
4688 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4689 emitcode ("cpl", "a");
4690 emitcode ("inc", "a");
4691 emitcode ("", "!tlabeldef", (lbl->key + 100));
4693 /* now the division */
4694 emitcode ("nop", "; workaround for DS80C390 div bug.");
4695 emitcode ("div", "ab");
4696 /* we are interested in the lower order
4698 emitcode ("mov", "b,a");
4699 lbl = newiTempLabel (NULL);
4700 emitcode ("pop", "acc");
4701 /* if there was an over flow we don't
4702 adjust the sign of the result */
4703 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4704 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4706 emitcode ("clr", "a");
4707 emitcode ("subb", "a,b");
4708 emitcode ("mov", "b,a");
4709 emitcode ("", "!tlabeldef", (lbl->key + 100));
4711 /* now we are done */
4712 _G.accInUse++; _G.bInUse++;
4713 aopOp(result, ic, TRUE, FALSE);
4715 aopPut (AOP (result), "b", 0);
4717 size = AOP_SIZE (result) - 1;
4721 emitcode ("mov", "c,b.7");
4722 emitcode ("subb", "a,acc");
4726 aopPut (AOP (result), "a", offset++);
4728 _G.accInUse--; _G.bInUse--;
4732 /*-----------------------------------------------------------------*/
4733 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
4734 /*-----------------------------------------------------------------*/
4735 static void genDivTwoByte (operand *left, operand *right,
4736 operand *result, iCode *ic)
4738 sym_link *retype = getSpec(operandType(right));
4739 sym_link *letype = getSpec(operandType(left));
4740 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4743 /* save EA bit in F1 */
4744 lbl = newiTempLabel(NULL);
4745 emitcode ("setb","F1");
4746 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4747 emitcode ("clr","F1");
4748 emitcode("","!tlabeldef",lbl->key+100);
4750 /* load up MA with left */
4752 emitcode("clr","F0");
4753 lbl = newiTempLabel(NULL);
4754 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4755 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4756 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4757 emitcode ("xch", "a,b");
4758 emitcode ("cpl","a");
4759 emitcode ("add", "a,#1");
4760 emitcode ("xch", "a,b");
4761 emitcode ("cpl", "a"); // msb
4762 emitcode ("addc","a,#0");
4763 emitcode ("setb","F0");
4764 emitcode ("","!tlabeldef",lbl->key+100);
4765 emitcode ("mov","ma,b");
4766 emitcode ("mov","ma,a");
4768 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4769 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4772 /* load up MB with right */
4774 if (AOP_TYPE(right) == AOP_LIT) {
4775 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4777 lbl = newiTempLabel(NULL);
4778 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4779 emitcode("setb","F0");
4780 emitcode ("","!tlabeldef",lbl->key+100);
4783 emitcode ("mov","mb,#!constbyte",val & 0xff);
4784 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4786 lbl = newiTempLabel(NULL);
4787 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4788 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4789 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4790 emitcode ("xch", "a,b");
4791 emitcode ("cpl","a");
4792 emitcode ("add", "a,#1");
4793 emitcode ("xch", "a,b");
4794 emitcode ("cpl", "a"); // msb
4795 emitcode ("addc", "a,#0");
4796 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4797 emitcode ("setb","F0");
4798 emitcode ("","!tlabeldef",lbl->key+100);
4799 emitcode ("mov","mb,b");
4800 emitcode ("mov","mb,a");
4803 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4804 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4807 /* wait for multiplication to finish */
4808 lbl = newiTempLabel(NULL);
4809 emitcode("","!tlabeldef", lbl->key+100);
4810 emitcode("mov","a,mcnt1");
4811 emitcode("anl","a,#!constbyte",0x80);
4812 emitcode("jnz","!tlabel",lbl->key+100);
4814 freeAsmop (left, NULL, ic, TRUE);
4815 freeAsmop (right, NULL, ic,TRUE);
4816 aopOp(result, ic, TRUE, FALSE);
4818 /* if unsigned then simple */
4820 aopPut(AOP(result),"ma",1);
4821 aopPut(AOP(result),"ma",0);
4823 emitcode("push","ma");
4825 /* negate result if needed */
4826 lbl = newiTempLabel(NULL);
4827 emitcode("jnb","F0,!tlabel",lbl->key+100);
4828 emitcode("cpl","a");
4829 emitcode("add","a,#1");
4830 emitcode("","!tlabeldef", lbl->key+100);
4831 aopPut(AOP(result),"a",0);
4832 emitcode("pop","acc");
4833 lbl = newiTempLabel(NULL);
4834 emitcode("jnb","F0,!tlabel",lbl->key+100);
4835 emitcode("cpl","a");
4836 emitcode("addc","a,#0");
4837 emitcode("","!tlabeldef", lbl->key+100);
4838 aopPut(AOP(result),"a",1);
4840 freeAsmop (result, NULL, ic, TRUE);
4841 /* restore EA bit in F1 */
4842 lbl = newiTempLabel(NULL);
4843 emitcode ("jnb","F1,!tlabel",lbl->key+100);
4844 emitcode ("setb","EA");
4845 emitcode("","!tlabeldef",lbl->key+100);
4849 /*-----------------------------------------------------------------*/
4850 /* genDiv - generates code for division */
4851 /*-----------------------------------------------------------------*/
4855 operand *left = IC_LEFT (ic);
4856 operand *right = IC_RIGHT (ic);
4857 operand *result = IC_RESULT (ic);
4859 D (emitcode (";", "genDiv "););
4861 /* assign the amsops */
4864 /* special cases first */
4866 if (AOP_TYPE (left) == AOP_CRY &&
4867 AOP_TYPE (right) == AOP_CRY)
4869 genDivbits (left, right, result, ic);
4873 /* if both are of size == 1 */
4874 if (AOP_SIZE (left) == 1 &&
4875 AOP_SIZE (right) == 1)
4877 genDivOneByte (left, right, result, ic);
4881 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4882 /* use the ds390 ARITHMETIC accel UNIT */
4883 genDivTwoByte (left, right, result, ic);
4886 /* should have been converted to function call */
4889 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4890 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4891 freeAsmop (result, NULL, ic, TRUE);
4894 /*-----------------------------------------------------------------*/
4895 /* genModbits :- modulus of bits */
4896 /*-----------------------------------------------------------------*/
4898 genModbits (operand * left,
4906 /* the result must be bit */
4907 LOAD_AB_FOR_DIV (left, right, l);
4908 emitcode ("div", "ab");
4909 emitcode ("mov", "a,b");
4910 emitcode ("rrc", "a");
4911 aopOp(result, ic, TRUE, FALSE);
4912 aopPut (AOP (result), "c", 0);
4915 /*-----------------------------------------------------------------*/
4916 /* genModOneByte : 8 bit modulus */
4917 /*-----------------------------------------------------------------*/
4919 genModOneByte (operand * left,
4924 sym_link *opetype = operandType (result);
4928 /* signed or unsigned */
4929 if (SPEC_USIGN (opetype))
4931 /* unsigned is easy */
4932 LOAD_AB_FOR_DIV (left, right, l);
4933 emitcode ("div", "ab");
4934 aopOp(result, ic, TRUE, FALSE);
4935 aopPut (AOP (result), "b", 0);
4939 /* signed is a little bit more difficult */
4941 /* save the signs of the operands */
4942 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4945 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4946 emitcode ("push", "acc"); /* save it on the stack */
4948 /* now sign adjust for both left & right */
4949 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4952 lbl = newiTempLabel (NULL);
4953 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4954 emitcode ("cpl", "a");
4955 emitcode ("inc", "a");
4956 emitcode ("", "!tlabeldef", (lbl->key + 100));
4957 emitcode ("mov", "b,a");
4959 /* sign adjust left side */
4960 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4963 lbl = newiTempLabel (NULL);
4964 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4965 emitcode ("cpl", "a");
4966 emitcode ("inc", "a");
4967 emitcode ("", "!tlabeldef", (lbl->key + 100));
4969 /* now the multiplication */
4970 emitcode ("nop", "; workaround for DS80C390 div bug.");
4971 emitcode ("div", "ab");
4972 /* we are interested in the lower order
4974 lbl = newiTempLabel (NULL);
4975 emitcode ("pop", "acc");
4976 /* if there was an over flow we don't
4977 adjust the sign of the result */
4978 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4979 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4981 emitcode ("clr", "a");
4982 emitcode ("subb", "a,b");
4983 emitcode ("mov", "b,a");
4984 emitcode ("", "!tlabeldef", (lbl->key + 100));
4987 /* now we are done */
4988 aopOp(result, ic, TRUE, FALSE);
4989 aopPut (AOP (result), "b", 0);
4994 /*-----------------------------------------------------------------*/
4995 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
4996 /*-----------------------------------------------------------------*/
4997 static void genModTwoByte (operand *left, operand *right,
4998 operand *result, iCode *ic)
5000 sym_link *retype = getSpec(operandType(right));
5001 sym_link *letype = getSpec(operandType(left));
5002 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5005 /* load up MA with left */
5006 /* save EA bit in F1 */
5007 lbl = newiTempLabel(NULL);
5008 emitcode ("setb","F1");
5009 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5010 emitcode ("clr","F1");
5011 emitcode("","!tlabeldef",lbl->key+100);
5014 lbl = newiTempLabel(NULL);
5015 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
5016 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
5017 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5018 emitcode ("xch", "a,b");
5019 emitcode ("cpl","a");
5020 emitcode ("add", "a,#1");
5021 emitcode ("xch", "a,b");
5022 emitcode ("cpl", "a"); // msb
5023 emitcode ("addc","a,#0");
5024 emitcode ("","!tlabeldef",lbl->key+100);
5025 emitcode ("mov","ma,b");
5026 emitcode ("mov","ma,a");
5028 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
5029 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
5032 /* load up MB with right */
5034 if (AOP_TYPE(right) == AOP_LIT) {
5035 int val=floatFromVal (AOP (right)->aopu.aop_lit);
5039 emitcode ("mov","mb,#!constbyte",val & 0xff);
5040 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5042 lbl = newiTempLabel(NULL);
5043 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
5044 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
5045 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5046 emitcode ("xch", "a,b");
5047 emitcode ("cpl","a");
5048 emitcode ("add", "a,#1");
5049 emitcode ("xch", "a,b");
5050 emitcode ("cpl", "a"); // msb
5051 emitcode ("addc", "a,#0");
5052 emitcode ("","!tlabeldef",lbl->key+100);
5053 emitcode ("mov","mb,b");
5054 emitcode ("mov","mb,a");
5057 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
5058 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
5061 /* wait for multiplication to finish */
5062 lbl = newiTempLabel(NULL);
5063 emitcode("","!tlabeldef", lbl->key+100);
5064 emitcode("mov","a,mcnt1");
5065 emitcode("anl","a,#!constbyte",0x80);
5066 emitcode("jnz","!tlabel",lbl->key+100);
5068 freeAsmop (left, NULL, ic, TRUE);
5069 freeAsmop (right, NULL, ic,TRUE);
5070 aopOp(result, ic, TRUE, FALSE);
5072 aopPut(AOP(result),"mb",1);
5073 aopPut(AOP(result),"mb",0);
5074 freeAsmop (result, NULL, ic, TRUE);
5076 /* restore EA bit in F1 */
5077 lbl = newiTempLabel(NULL);
5078 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5079 emitcode ("setb","EA");
5080 emitcode("","!tlabeldef",lbl->key+100);
5084 /*-----------------------------------------------------------------*/
5085 /* genMod - generates code for division */
5086 /*-----------------------------------------------------------------*/
5090 operand *left = IC_LEFT (ic);
5091 operand *right = IC_RIGHT (ic);
5092 operand *result = IC_RESULT (ic);
5094 D (emitcode (";", "genMod "); );
5096 /* assign the amsops */
5099 /* special cases first */
5101 if (AOP_TYPE (left) == AOP_CRY &&
5102 AOP_TYPE (right) == AOP_CRY)
5104 genModbits (left, right, result, ic);
5108 /* if both are of size == 1 */
5109 if (AOP_SIZE (left) == 1 &&
5110 AOP_SIZE (right) == 1)
5112 genModOneByte (left, right, result, ic);
5116 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5117 /* use the ds390 ARITHMETIC accel UNIT */
5118 genModTwoByte (left, right, result, ic);
5122 /* should have been converted to function call */
5126 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5127 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5128 freeAsmop (result, NULL, ic, TRUE);
5131 /*-----------------------------------------------------------------*/
5132 /* genIfxJump :- will create a jump depending on the ifx */
5133 /*-----------------------------------------------------------------*/
5135 genIfxJump (iCode * ic, char *jval)
5138 symbol *tlbl = newiTempLabel (NULL);
5141 D (emitcode (";", "genIfxJump ");
5144 /* if true label then we jump if condition
5148 jlbl = IC_TRUE (ic);
5149 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5150 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5154 /* false label is present */
5155 jlbl = IC_FALSE (ic);
5156 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5157 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5159 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5160 emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5162 emitcode (inst, "!tlabel", tlbl->key + 100);
5163 emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5164 emitcode ("", "!tlabeldef", tlbl->key + 100);
5166 /* mark the icode as generated */
5170 /*-----------------------------------------------------------------*/
5171 /* genCmp :- greater or less than comparison */
5172 /*-----------------------------------------------------------------*/
5174 genCmp (operand * left, operand * right,
5175 iCode * ic, iCode * ifx, int sign)
5177 int size, offset = 0;
5178 unsigned long lit = 0L;
5181 D (emitcode (";", "genCmp");
5184 result = IC_RESULT (ic);
5186 /* if left & right are bit variables */
5187 if (AOP_TYPE (left) == AOP_CRY &&
5188 AOP_TYPE (right) == AOP_CRY)
5190 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5191 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
5195 /* subtract right from left if at the
5196 end the carry flag is set then we know that
5197 left is greater than right */
5198 size = max (AOP_SIZE (left), AOP_SIZE (right));
5200 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5201 if ((size == 1) && !sign &&
5202 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5204 symbol *lbl = newiTempLabel (NULL);
5205 emitcode ("cjne", "%s,%s,!tlabel",
5206 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5207 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5209 emitcode ("", "!tlabeldef", lbl->key + 100);
5213 if (AOP_TYPE (right) == AOP_LIT)
5215 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5216 /* optimize if(x < 0) or if(x >= 0) */
5225 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
5227 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5228 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5230 aopOp (result, ic, FALSE, FALSE);
5232 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5234 freeAsmop (result, NULL, ic, TRUE);
5235 genIfxJump (ifx, "acc.7");
5240 emitcode ("rlc", "a");
5242 goto release_freedLR;
5250 //emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5251 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5252 //emitcode (";", "genCmp #2");
5253 if (sign && (size == 0))
5255 //emitcode (";", "genCmp #3");
5256 emitcode ("xrl", "a,#!constbyte",0x80);
5257 if (AOP_TYPE (right) == AOP_LIT)
5259 unsigned long lit = (unsigned long)
5260 floatFromVal (AOP (right)->aopu.aop_lit);
5261 //emitcode (";", "genCmp #3.1");
5262 emitcode ("subb", "a,#!constbyte",
5263 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5267 //emitcode (";", "genCmp #3.2");
5268 if (AOP_NEEDSACC (right))
5270 emitcode ("push", "acc");
5272 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
5273 FALSE, FALSE, FALSE));
5274 emitcode ("xrl", "b,#!constbyte",0x80);
5275 if (AOP_NEEDSACC (right))
5277 emitcode ("pop", "acc");
5279 emitcode ("subb", "a,b");
5286 //emitcode (";", "genCmp #4");
5287 if (AOP_NEEDSACC (right))
5290 //emitcode (";", "genCmp #4.1");
5291 emitcode ("xch", "a, b");
5292 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
5293 emitcode ("xch", "a, b");
5298 //emitcode (";", "genCmp #4.2");
5299 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
5302 emitcode ("subb", "a,%s", s);
5309 /* Don't need the left & right operands any more; do need the result. */
5310 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5311 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5313 aopOp (result, ic, FALSE, FALSE);
5317 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5323 /* if the result is used in the next
5324 ifx conditional branch then generate
5325 code a little differently */
5328 genIfxJump (ifx, "c");
5334 /* leave the result in acc */
5336 freeAsmop (result, NULL, ic, TRUE);
5339 /*-----------------------------------------------------------------*/
5340 /* genCmpGt :- greater than comparison */
5341 /*-----------------------------------------------------------------*/
5343 genCmpGt (iCode * ic, iCode * ifx)
5345 operand *left, *right;
5346 sym_link *letype, *retype;
5349 D (emitcode (";", "genCmpGt ");
5352 left = IC_LEFT (ic);
5353 right = IC_RIGHT (ic);
5355 letype = getSpec (operandType (left));
5356 retype = getSpec (operandType (right));
5357 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5359 /* assign the left & right amsops */
5362 genCmp (right, left, ic, ifx, sign);
5365 /*-----------------------------------------------------------------*/
5366 /* genCmpLt - less than comparisons */
5367 /*-----------------------------------------------------------------*/
5369 genCmpLt (iCode * ic, iCode * ifx)
5371 operand *left, *right;
5372 sym_link *letype, *retype;
5375 D (emitcode (";", "genCmpLt "););
5377 left = IC_LEFT (ic);
5378 right = IC_RIGHT (ic);
5380 letype = getSpec (operandType (left));
5381 retype = getSpec (operandType (right));
5382 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5384 /* assign the left & right amsops */
5387 genCmp (left, right, ic, ifx, sign);
5390 /*-----------------------------------------------------------------*/
5391 /* gencjneshort - compare and jump if not equal */
5392 /*-----------------------------------------------------------------*/
5394 gencjneshort (operand * left, operand * right, symbol * lbl)
5396 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5398 unsigned long lit = 0L;
5400 D (emitcode (";", "gencjneshort");
5403 /* if the left side is a literal or
5404 if the right is in a pointer register and left
5406 if ((AOP_TYPE (left) == AOP_LIT) ||
5407 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5414 if (AOP_TYPE (right) == AOP_LIT)
5415 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5417 if (opIsGptr (left) || opIsGptr (right))
5419 /* We are comparing a generic pointer to something.
5420 * Exclude the generic type byte from the comparison.
5423 D (emitcode (";", "cjneshort: generic ptr special case.");
5428 /* if the right side is a literal then anything goes */
5429 if (AOP_TYPE (right) == AOP_LIT &&
5430 AOP_TYPE (left) != AOP_DIR)
5434 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5436 emitcode ("cjne", "a,%s,!tlabel",
5437 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5443 /* if the right side is in a register or in direct space or
5444 if the left is a pointer register & right is not */
5445 else if (AOP_TYPE (right) == AOP_REG ||
5446 AOP_TYPE (right) == AOP_DIR ||
5447 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5448 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5452 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5453 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5454 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5455 emitcode ("jnz", "!tlabel", lbl->key + 100);
5457 emitcode ("cjne", "a,%s,!tlabel",
5458 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
5465 /* right is a pointer reg need both a & b */
5468 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5469 if (strcmp (l, "b"))
5470 emitcode ("mov", "b,%s", l);
5471 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5472 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5478 /*-----------------------------------------------------------------*/
5479 /* gencjne - compare and jump if not equal */
5480 /*-----------------------------------------------------------------*/
5482 gencjne (operand * left, operand * right, symbol * lbl)
5484 symbol *tlbl = newiTempLabel (NULL);
5486 D (emitcode (";", "gencjne");
5489 gencjneshort (left, right, lbl);
5491 emitcode ("mov", "a,%s", one);
5492 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5493 emitcode ("", "!tlabeldef", lbl->key + 100);
5494 emitcode ("clr", "a");
5495 emitcode ("", "!tlabeldef", tlbl->key + 100);
5498 /*-----------------------------------------------------------------*/
5499 /* genCmpEq - generates code for equal to */
5500 /*-----------------------------------------------------------------*/
5502 genCmpEq (iCode * ic, iCode * ifx)
5504 operand *left, *right, *result;
5506 D (emitcode (";", "genCmpEq ");
5510 AOP_SET_LOCALS (ic);
5512 /* if literal, literal on the right or
5513 if the right is in a pointer register and left
5515 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5516 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5518 operand *t = IC_RIGHT (ic);
5519 IC_RIGHT (ic) = IC_LEFT (ic);
5523 if (ifx && /* !AOP_SIZE(result) */
5524 OP_SYMBOL (result) &&
5525 OP_SYMBOL (result)->regType == REG_CND)
5528 /* if they are both bit variables */
5529 if (AOP_TYPE (left) == AOP_CRY &&
5530 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5532 if (AOP_TYPE (right) == AOP_LIT)
5534 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5537 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5538 emitcode ("cpl", "c");
5542 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5546 emitcode ("clr", "c");
5548 /* AOP_TYPE(right) == AOP_CRY */
5552 symbol *lbl = newiTempLabel (NULL);
5553 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5554 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5555 emitcode ("cpl", "c");
5556 emitcode ("", "!tlabeldef", (lbl->key + 100));
5558 /* if true label then we jump if condition
5560 tlbl = newiTempLabel (NULL);
5563 emitcode ("jnc", "!tlabel", tlbl->key + 100);
5564 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5568 emitcode ("jc", "!tlabel", tlbl->key + 100);
5569 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5571 emitcode ("", "!tlabeldef", tlbl->key + 100);
5575 tlbl = newiTempLabel (NULL);
5576 gencjneshort (left, right, tlbl);
5579 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5580 emitcode ("", "!tlabeldef", tlbl->key + 100);
5584 symbol *lbl = newiTempLabel (NULL);
5585 emitcode ("sjmp", "!tlabel", lbl->key + 100);
5586 emitcode ("", "!tlabeldef", tlbl->key + 100);
5587 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5588 emitcode ("", "!tlabeldef", lbl->key + 100);
5591 /* mark the icode as generated */
5594 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5595 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5599 /* if they are both bit variables */
5600 if (AOP_TYPE (left) == AOP_CRY &&
5601 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5603 if (AOP_TYPE (right) == AOP_LIT)
5605 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5608 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5609 emitcode ("cpl", "c");
5613 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5617 emitcode ("clr", "c");
5619 /* AOP_TYPE(right) == AOP_CRY */
5623 symbol *lbl = newiTempLabel (NULL);
5624 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5625 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5626 emitcode ("cpl", "c");
5627 emitcode ("", "!tlabeldef", (lbl->key + 100));
5630 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5631 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5633 aopOp (result, ic, TRUE, FALSE);
5636 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5643 genIfxJump (ifx, "c");
5646 /* if the result is used in an arithmetic operation
5647 then put the result in place */
5652 gencjne (left, right, newiTempLabel (NULL));
5654 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5655 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5657 aopOp (result, ic, TRUE, FALSE);
5659 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5661 aopPut (AOP (result), "a", 0);
5666 genIfxJump (ifx, "a");
5669 /* if the result is used in an arithmetic operation
5670 then put the result in place */
5671 if (AOP_TYPE (result) != AOP_CRY)
5673 /* leave the result in acc */
5677 freeAsmop (result, NULL, ic, TRUE);
5680 /*-----------------------------------------------------------------*/
5681 /* ifxForOp - returns the icode containing the ifx for operand */
5682 /*-----------------------------------------------------------------*/
5684 ifxForOp (operand * op, iCode * ic)
5686 /* if true symbol then needs to be assigned */
5687 if (IS_TRUE_SYMOP (op))
5690 /* if this has register type condition and
5691 the next instruction is ifx with the same operand
5692 and live to of the operand is upto the ifx only then */
5694 ic->next->op == IFX &&
5695 IC_COND (ic->next)->key == op->key &&
5696 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5701 /*-----------------------------------------------------------------*/
5702 /* hasInc - operand is incremented before any other use */
5703 /*-----------------------------------------------------------------*/
5705 hasInc (operand *op, iCode *ic, int osize)
5707 sym_link *type = operandType(op);
5708 sym_link *retype = getSpec (type);
5709 iCode *lic = ic->next;
5712 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5713 if (!IS_SYMOP(op)) return NULL;
5715 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5716 if (IS_AGGREGATE(type->next)) return NULL;
5717 if (osize != (isize = getSize(type->next))) return NULL;
5720 /* if operand of the form op = op + <sizeof *op> */
5721 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5722 isOperandEqual(IC_RESULT(lic),op) &&
5723 isOperandLiteral(IC_RIGHT(lic)) &&
5724 operandLitValue(IC_RIGHT(lic)) == isize) {
5727 /* if the operand used or deffed */
5728 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5731 /* if GOTO or IFX */
5732 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5738 /*-----------------------------------------------------------------*/
5739 /* genAndOp - for && operation */
5740 /*-----------------------------------------------------------------*/
5742 genAndOp (iCode * ic)
5744 operand *left, *right, *result;
5747 D (emitcode (";", "genAndOp "););
5749 /* note here that && operations that are in an
5750 if statement are taken away by backPatchLabels
5751 only those used in arthmetic operations remain */
5753 AOP_SET_LOCALS (ic);
5755 /* if both are bit variables */
5756 if (AOP_TYPE (left) == AOP_CRY &&
5757 AOP_TYPE (right) == AOP_CRY)
5759 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5760 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5761 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5762 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5764 aopOp (result,ic,FALSE, FALSE);
5769 tlbl = newiTempLabel (NULL);
5771 emitcode ("jz", "!tlabel", tlbl->key + 100);
5773 emitcode ("", "!tlabeldef", tlbl->key + 100);
5774 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5775 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5777 aopOp (result,ic,FALSE, FALSE);
5780 freeAsmop (result, NULL, ic, TRUE);
5784 /*-----------------------------------------------------------------*/
5785 /* genOrOp - for || operation */
5786 /*-----------------------------------------------------------------*/
5788 genOrOp (iCode * ic)
5790 operand *left, *right, *result;
5793 D (emitcode (";", "genOrOp "););
5795 /* note here that || operations that are in an
5796 if statement are taken away by backPatchLabels
5797 only those used in arthmetic operations remain */
5799 AOP_SET_LOCALS (ic);
5801 /* if both are bit variables */
5802 if (AOP_TYPE (left) == AOP_CRY &&
5803 AOP_TYPE (right) == AOP_CRY)
5805 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5806 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5807 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5808 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5810 aopOp (result,ic,FALSE, FALSE);
5816 tlbl = newiTempLabel (NULL);
5818 emitcode ("jnz", "!tlabel", tlbl->key + 100);
5820 emitcode ("", "!tlabeldef", tlbl->key + 100);
5821 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5822 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5824 aopOp (result,ic,FALSE, FALSE);
5829 freeAsmop (result, NULL, ic, TRUE);
5832 /*-----------------------------------------------------------------*/
5833 /* isLiteralBit - test if lit == 2^n */
5834 /*-----------------------------------------------------------------*/
5836 isLiteralBit (unsigned long lit)
5838 unsigned long pw[32] =
5839 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5840 0x100L, 0x200L, 0x400L, 0x800L,
5841 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5842 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5843 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5844 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5845 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5848 for (idx = 0; idx < 32; idx++)
5854 /*-----------------------------------------------------------------*/
5855 /* continueIfTrue - */
5856 /*-----------------------------------------------------------------*/
5858 continueIfTrue (iCode * ic)
5861 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
5865 /*-----------------------------------------------------------------*/
5867 /*-----------------------------------------------------------------*/
5869 jumpIfTrue (iCode * ic)
5872 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
5876 /*-----------------------------------------------------------------*/
5877 /* jmpTrueOrFalse - */
5878 /*-----------------------------------------------------------------*/
5880 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5882 // ugly but optimized by peephole
5885 symbol *nlbl = newiTempLabel (NULL);
5886 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
5887 emitcode ("", "!tlabeldef", tlbl->key + 100);
5888 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
5889 emitcode ("", "!tlabeldef", nlbl->key + 100);
5893 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
5894 emitcode ("", "!tlabeldef", tlbl->key + 100);
5899 // Generate code to perform a bit-wise logic operation
5900 // on two operands in far space (assumed to already have been
5901 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5902 // in far space. This requires pushing the result on the stack
5903 // then popping it into the result.
5905 genFarFarLogicOp(iCode *ic, char *logicOp)
5907 int size, resultSize, compSize;
5911 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5912 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
5913 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5915 _startLazyDPSEvaluation();
5916 for (size = compSize; (size--); offset++)
5918 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5919 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5920 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5922 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5923 emitcode ("push", "acc");
5925 _endLazyDPSEvaluation();
5927 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5928 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5929 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5931 resultSize = AOP_SIZE(IC_RESULT(ic));
5933 ADJUST_PUSHED_RESULT(compSize, resultSize);
5935 _startLazyDPSEvaluation();
5938 emitcode ("pop", "acc");
5939 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5941 _endLazyDPSEvaluation();
5942 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5946 /*-----------------------------------------------------------------*/
5947 /* genAnd - code for and */
5948 /*-----------------------------------------------------------------*/
5950 genAnd (iCode * ic, iCode * ifx)
5952 operand *left, *right, *result;
5953 int size, offset = 0;
5954 unsigned long lit = 0L;
5959 D (emitcode (";", "genAnd "););
5961 AOP_OP_3_NOFATAL (ic, pushResult);
5962 AOP_SET_LOCALS (ic);
5966 genFarFarLogicOp(ic, "anl");
5971 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5973 AOP_TYPE (left), AOP_TYPE (right));
5974 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5976 AOP_SIZE (left), AOP_SIZE (right));
5979 /* if left is a literal & right is not then exchange them */
5980 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5981 #ifdef LOGIC_OPS_BROKEN
5982 || AOP_NEEDSACC (left)
5986 operand *tmp = right;
5991 /* if result = right then exchange them */
5992 if (sameRegs (AOP (result), AOP (right)))
5994 operand *tmp = right;
5999 /* if right is bit then exchange them */
6000 if (AOP_TYPE (right) == AOP_CRY &&
6001 AOP_TYPE (left) != AOP_CRY)
6003 operand *tmp = right;
6007 if (AOP_TYPE (right) == AOP_LIT)
6008 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6010 size = AOP_SIZE (result);
6013 // result = bit & yy;
6014 if (AOP_TYPE (left) == AOP_CRY)
6016 // c = bit & literal;
6017 if (AOP_TYPE (right) == AOP_LIT)
6021 if (size && sameRegs (AOP (result), AOP (left)))
6024 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6029 if (size && (AOP_TYPE (result) == AOP_CRY))
6031 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6034 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6039 emitcode ("clr", "c");
6044 if (AOP_TYPE (right) == AOP_CRY)
6047 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6048 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6053 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
6055 emitcode ("rrc", "a");
6056 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6064 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6065 genIfxJump (ifx, "c");
6069 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6070 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6071 if ((AOP_TYPE (right) == AOP_LIT) &&
6072 (AOP_TYPE (result) == AOP_CRY) &&
6073 (AOP_TYPE (left) != AOP_CRY))
6075 int posbit = isLiteralBit (lit);
6080 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
6083 emitcode ("mov", "c,acc.%d", posbit & 0x07);
6089 sprintf (buffer, "acc.%d", posbit & 0x07);
6090 genIfxJump (ifx, buffer);
6094 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6101 symbol *tlbl = newiTempLabel (NULL);
6102 int sizel = AOP_SIZE (left);
6104 emitcode ("setb", "c");
6107 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6109 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6111 if ((posbit = isLiteralBit (bytelit)) != 0)
6112 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6115 if (bytelit != 0x0FFL)
6116 emitcode ("anl", "a,%s",
6117 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
6118 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6123 // bit = left & literal
6126 emitcode ("clr", "c");
6127 emitcode ("", "!tlabeldef", tlbl->key + 100);
6129 // if(left & literal)
6133 jmpTrueOrFalse (ifx, tlbl);
6141 /* if left is same as result */
6142 if (sameRegs (AOP (result), AOP (left)))
6144 for (; size--; offset++)
6146 if (AOP_TYPE (right) == AOP_LIT)
6148 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6150 else if (bytelit == 0)
6151 aopPut (AOP (result), zero, offset);
6152 else if (IS_AOP_PREG (result))
6154 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6155 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6156 aopPut (AOP (result), "a", offset);
6159 emitcode ("anl", "%s,%s",
6160 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6161 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6165 if (AOP_TYPE (left) == AOP_ACC)
6166 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6169 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6170 if (IS_AOP_PREG (result))
6172 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6173 aopPut (AOP (result), "a", offset);
6177 emitcode ("anl", "%s,a",
6178 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6185 // left & result in different registers
6186 if (AOP_TYPE (result) == AOP_CRY)
6189 // if(size), result in bit
6190 // if(!size && ifx), conditional oper: if(left & right)
6191 symbol *tlbl = newiTempLabel (NULL);
6192 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6194 emitcode ("setb", "c");
6197 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6198 emitcode ("anl", "a,%s",
6199 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6201 if (AOP_TYPE(left)==AOP_ACC) {
6202 emitcode("mov", "b,a");
6203 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6204 emitcode("anl", "a,b");
6206 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6207 emitcode ("anl", "a,%s",
6208 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6211 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6217 emitcode ("", "!tlabeldef", tlbl->key + 100);
6221 jmpTrueOrFalse (ifx, tlbl);
6225 for (; (size--); offset++)
6228 // result = left & right
6229 if (AOP_TYPE (right) == AOP_LIT)
6231 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6233 aopPut (AOP (result),
6234 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6238 else if (bytelit == 0)
6240 aopPut (AOP (result), zero, offset);
6243 D (emitcode (";", "better literal AND."););
6244 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6245 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6246 FALSE, FALSE, FALSE));
6251 // faster than result <- left, anl result,right
6252 // and better if result is SFR
6253 if (AOP_TYPE (left) == AOP_ACC)
6255 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
6256 FALSE, FALSE, FALSE));
6260 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6261 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6263 emitcode("mov", "b,a");
6267 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6268 emitcode ("anl", "a,%s", rOp);
6271 aopPut (AOP (result), "a", offset);
6277 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6278 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6279 freeAsmop (result, NULL, ic, TRUE);
6283 /*-----------------------------------------------------------------*/
6284 /* genOr - code for or */
6285 /*-----------------------------------------------------------------*/
6287 genOr (iCode * ic, iCode * ifx)
6289 operand *left, *right, *result;
6290 int size, offset = 0;
6291 unsigned long lit = 0L;
6294 D (emitcode (";", "genOr "););
6296 AOP_OP_3_NOFATAL (ic, pushResult);
6297 AOP_SET_LOCALS (ic);
6301 genFarFarLogicOp(ic, "orl");
6307 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6309 AOP_TYPE (left), AOP_TYPE (right));
6310 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6312 AOP_SIZE (left), AOP_SIZE (right));
6315 /* if left is a literal & right is not then exchange them */
6316 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6317 #ifdef LOGIC_OPS_BROKEN
6318 || AOP_NEEDSACC (left) // I think this is a net loss now.
6322 operand *tmp = right;
6327 /* if result = right then exchange them */
6328 if (sameRegs (AOP (result), AOP (right)))
6330 operand *tmp = right;
6335 /* if right is bit then exchange them */
6336 if (AOP_TYPE (right) == AOP_CRY &&
6337 AOP_TYPE (left) != AOP_CRY)
6339 operand *tmp = right;
6343 if (AOP_TYPE (right) == AOP_LIT)
6344 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6346 size = AOP_SIZE (result);
6350 if (AOP_TYPE (left) == AOP_CRY)
6352 if (AOP_TYPE (right) == AOP_LIT)
6354 // c = bit & literal;
6357 // lit != 0 => result = 1
6358 if (AOP_TYPE (result) == AOP_CRY)
6361 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6363 continueIfTrue (ifx);
6366 emitcode ("setb", "c");
6370 // lit == 0 => result = left
6371 if (size && sameRegs (AOP (result), AOP (left)))
6373 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6378 if (AOP_TYPE (right) == AOP_CRY)
6381 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6382 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6387 symbol *tlbl = newiTempLabel (NULL);
6388 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6389 emitcode ("setb", "c");
6390 emitcode ("jb", "%s,!tlabel",
6391 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6393 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6394 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6396 jmpTrueOrFalse (ifx, tlbl);
6402 emitcode ("", "!tlabeldef", tlbl->key + 100);
6411 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6412 genIfxJump (ifx, "c");
6416 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6417 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6418 if ((AOP_TYPE (right) == AOP_LIT) &&
6419 (AOP_TYPE (result) == AOP_CRY) &&
6420 (AOP_TYPE (left) != AOP_CRY))
6426 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6428 continueIfTrue (ifx);
6433 // lit = 0, result = boolean(left)
6435 emitcode ("setb", "c");
6439 symbol *tlbl = newiTempLabel (NULL);
6440 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6442 emitcode ("", "!tlabeldef", tlbl->key + 100);
6446 genIfxJump (ifx, "a");
6454 /* if left is same as result */
6455 if (sameRegs (AOP (result), AOP (left)))
6457 for (; size--; offset++)
6459 if (AOP_TYPE (right) == AOP_LIT)
6461 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6467 if (IS_AOP_PREG (left))
6469 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6470 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6471 aopPut (AOP (result), "a", offset);
6475 emitcode ("orl", "%s,%s",
6476 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6477 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6483 if (AOP_TYPE (left) == AOP_ACC)
6485 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6489 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6490 if (IS_AOP_PREG (left))
6492 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6493 aopPut (AOP (result), "a", offset);
6497 emitcode ("orl", "%s,a",
6498 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6506 // left & result in different registers
6507 if (AOP_TYPE (result) == AOP_CRY)
6510 // if(size), result in bit
6511 // if(!size && ifx), conditional oper: if(left | right)
6512 symbol *tlbl = newiTempLabel (NULL);
6513 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6515 emitcode ("setb", "c");
6518 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6519 emitcode ("orl", "a,%s",
6520 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6522 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6523 emitcode ("orl", "a,%s",
6524 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6526 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6532 emitcode ("", "!tlabeldef", tlbl->key + 100);
6536 jmpTrueOrFalse (ifx, tlbl);
6540 _startLazyDPSEvaluation();
6541 for (; (size--); offset++)
6544 // result = left & right
6545 if (AOP_TYPE (right) == AOP_LIT)
6547 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6549 aopPut (AOP (result),
6550 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6554 D (emitcode (";", "better literal OR."););
6555 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6556 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
6557 FALSE, FALSE, FALSE));
6562 // faster than result <- left, anl result,right
6563 // and better if result is SFR
6564 if (AOP_TYPE (left) == AOP_ACC)
6566 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
6567 FALSE, FALSE, FALSE));
6571 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6573 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6575 emitcode("mov", "b,a");
6579 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6580 emitcode ("orl", "a,%s", rOp);
6583 aopPut (AOP (result), "a", offset);
6585 _endLazyDPSEvaluation();
6590 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6591 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6592 freeAsmop (result, NULL, ic, TRUE);
6595 /*-----------------------------------------------------------------*/
6596 /* genXor - code for xclusive or */
6597 /*-----------------------------------------------------------------*/
6599 genXor (iCode * ic, iCode * ifx)
6601 operand *left, *right, *result;
6602 int size, offset = 0;
6603 unsigned long lit = 0L;
6606 D (emitcode (";", "genXor "););
6608 AOP_OP_3_NOFATAL (ic, pushResult);
6609 AOP_SET_LOCALS (ic);
6613 genFarFarLogicOp(ic, "xrl");
6618 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6620 AOP_TYPE (left), AOP_TYPE (right));
6621 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6623 AOP_SIZE (left), AOP_SIZE (right));
6626 /* if left is a literal & right is not ||
6627 if left needs acc & right does not */
6628 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6629 #ifdef LOGIC_OPS_BROKEN
6630 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6634 operand *tmp = right;
6639 /* if result = right then exchange them */
6640 if (sameRegs (AOP (result), AOP (right)))
6642 operand *tmp = right;
6647 /* if right is bit then exchange them */
6648 if (AOP_TYPE (right) == AOP_CRY &&
6649 AOP_TYPE (left) != AOP_CRY)
6651 operand *tmp = right;
6655 if (AOP_TYPE (right) == AOP_LIT)
6656 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6658 size = AOP_SIZE (result);
6662 if (AOP_TYPE (left) == AOP_CRY)
6664 if (AOP_TYPE (right) == AOP_LIT)
6666 // c = bit & literal;
6669 // lit>>1 != 0 => result = 1
6670 if (AOP_TYPE (result) == AOP_CRY)
6673 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6675 continueIfTrue (ifx);
6678 emitcode ("setb", "c");
6685 // lit == 0, result = left
6686 if (size && sameRegs (AOP (result), AOP (left)))
6688 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6692 // lit == 1, result = not(left)
6693 if (size && sameRegs (AOP (result), AOP (left)))
6695 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6700 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6701 emitcode ("cpl", "c");
6710 symbol *tlbl = newiTempLabel (NULL);
6711 if (AOP_TYPE (right) == AOP_CRY)
6714 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6718 int sizer = AOP_SIZE (right);
6720 // if val>>1 != 0, result = 1
6721 emitcode ("setb", "c");
6724 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
6726 // test the msb of the lsb
6727 emitcode ("anl", "a,#!constbyte",0xfe);
6728 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6732 emitcode ("rrc", "a");
6734 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6735 emitcode ("cpl", "c");
6736 emitcode ("", "!tlabeldef", (tlbl->key + 100));
6743 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6744 genIfxJump (ifx, "c");
6748 if (sameRegs (AOP (result), AOP (left)))
6750 /* if left is same as result */
6751 for (; size--; offset++)
6753 if (AOP_TYPE (right) == AOP_LIT)
6755 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6757 else if (IS_AOP_PREG (left))
6759 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6760 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6761 aopPut (AOP (result), "a", offset);
6764 emitcode ("xrl", "%s,%s",
6765 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6766 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6770 if (AOP_TYPE (left) == AOP_ACC)
6771 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6774 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6775 if (IS_AOP_PREG (left))
6777 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6778 aopPut (AOP (result), "a", offset);
6781 emitcode ("xrl", "%s,a",
6782 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6789 // left & result in different registers
6790 if (AOP_TYPE (result) == AOP_CRY)
6793 // if(size), result in bit
6794 // if(!size && ifx), conditional oper: if(left ^ right)
6795 symbol *tlbl = newiTempLabel (NULL);
6796 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6799 emitcode ("setb", "c");
6802 if ((AOP_TYPE (right) == AOP_LIT) &&
6803 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6805 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6809 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6810 emitcode ("xrl", "a,%s",
6811 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6813 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6814 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6816 emitcode("mov", "b,a");
6820 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6821 emitcode ("xrl", "a,%s", rOp);
6824 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6830 emitcode ("", "!tlabeldef", tlbl->key + 100);
6834 jmpTrueOrFalse (ifx, tlbl);
6838 for (; (size--); offset++)
6841 // result = left & right
6842 if (AOP_TYPE (right) == AOP_LIT)
6844 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6846 aopPut (AOP (result),
6847 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6851 D (emitcode (";", "better literal XOR."););
6852 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6853 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
6854 FALSE, FALSE, FALSE));
6858 // faster than result <- left, anl result,right
6859 // and better if result is SFR
6860 if (AOP_TYPE (left) == AOP_ACC)
6862 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
6863 FALSE, FALSE, FALSE));
6867 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6868 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6870 emitcode("mov", "b,a");
6874 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6875 emitcode ("xrl", "a,%s", rOp);
6878 aopPut (AOP (result), "a", offset);
6885 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6886 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6887 freeAsmop (result, NULL, ic, TRUE);
6890 /*-----------------------------------------------------------------*/
6891 /* genInline - write the inline code out */
6892 /*-----------------------------------------------------------------*/
6894 genInline (iCode * ic)
6896 char *buffer, *bp, *bp1;
6898 D (emitcode (";", "genInline ");
6901 _G.inLine += (!options.asmpeep);
6903 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6904 strcpy (buffer, IC_INLINE (ic));
6906 /* emit each line as a code */
6931 /* emitcode("",buffer); */
6932 _G.inLine -= (!options.asmpeep);
6935 /*-----------------------------------------------------------------*/
6936 /* genRRC - rotate right with carry */
6937 /*-----------------------------------------------------------------*/
6941 operand *left, *result;
6942 int size, offset = 0;
6945 D (emitcode (";", "genRRC ");
6948 /* rotate right with carry */
6949 left = IC_LEFT (ic);
6950 result = IC_RESULT (ic);
6951 aopOp (left, ic, FALSE, FALSE);
6952 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6954 /* move it to the result */
6955 size = AOP_SIZE (result);
6959 _startLazyDPSEvaluation ();
6962 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6964 emitcode ("rrc", "a");
6965 if (AOP_SIZE (result) > 1)
6966 aopPut (AOP (result), "a", offset--);
6968 _endLazyDPSEvaluation ();
6970 /* now we need to put the carry into the
6971 highest order byte of the result */
6972 if (AOP_SIZE (result) > 1)
6974 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6977 emitcode ("mov", "acc.7,c");
6978 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6979 freeAsmop (left, NULL, ic, TRUE);
6980 freeAsmop (result, NULL, ic, TRUE);
6983 /*-----------------------------------------------------------------*/
6984 /* genRLC - generate code for rotate left with carry */
6985 /*-----------------------------------------------------------------*/
6989 operand *left, *result;
6990 int size, offset = 0;
6993 D (emitcode (";", "genRLC ");
6996 /* rotate right with carry */
6997 left = IC_LEFT (ic);
6998 result = IC_RESULT (ic);
6999 aopOp (left, ic, FALSE, FALSE);
7000 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7002 /* move it to the result */
7003 size = AOP_SIZE (result);
7007 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
7009 emitcode ("add", "a,acc");
7010 if (AOP_SIZE (result) > 1)
7012 aopPut (AOP (result), "a", offset++);
7015 _startLazyDPSEvaluation ();
7018 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
7020 emitcode ("rlc", "a");
7021 if (AOP_SIZE (result) > 1)
7022 aopPut (AOP (result), "a", offset++);
7024 _endLazyDPSEvaluation ();
7026 /* now we need to put the carry into the
7027 highest order byte of the result */
7028 if (AOP_SIZE (result) > 1)
7030 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
7033 emitcode ("mov", "acc.0,c");
7034 aopPut (AOP (result), "a", 0);
7035 freeAsmop (left, NULL, ic, TRUE);
7036 freeAsmop (result, NULL, ic, TRUE);
7039 /*-----------------------------------------------------------------*/
7040 /* genGetHbit - generates code get highest order bit */
7041 /*-----------------------------------------------------------------*/
7043 genGetHbit (iCode * ic)
7045 operand *left, *result;
7046 left = IC_LEFT (ic);
7047 result = IC_RESULT (ic);
7048 aopOp (left, ic, FALSE, FALSE);
7049 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7051 D (emitcode (";", "genGetHbit ");
7054 /* get the highest order byte into a */
7055 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
7056 if (AOP_TYPE (result) == AOP_CRY)
7058 emitcode ("rlc", "a");
7063 emitcode ("rl", "a");
7064 emitcode ("anl", "a,#1");
7069 freeAsmop (left, NULL, ic, TRUE);
7070 freeAsmop (result, NULL, ic, TRUE);
7073 /*-----------------------------------------------------------------*/
7074 /* AccRol - rotate left accumulator by known count */
7075 /*-----------------------------------------------------------------*/
7077 AccRol (int shCount)
7079 shCount &= 0x0007; // shCount : 0..7
7086 emitcode ("rl", "a");
7089 emitcode ("rl", "a");
7090 emitcode ("rl", "a");
7093 emitcode ("swap", "a");
7094 emitcode ("rr", "a");
7097 emitcode ("swap", "a");
7100 emitcode ("swap", "a");
7101 emitcode ("rl", "a");
7104 emitcode ("rr", "a");
7105 emitcode ("rr", "a");
7108 emitcode ("rr", "a");
7113 /*-----------------------------------------------------------------*/
7114 /* AccLsh - left shift accumulator by known count */
7115 /*-----------------------------------------------------------------*/
7117 AccLsh (int shCount)
7122 emitcode ("add", "a,acc");
7123 else if (shCount == 2)
7125 emitcode ("add", "a,acc");
7126 emitcode ("add", "a,acc");
7130 /* rotate left accumulator */
7132 /* and kill the lower order bits */
7133 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7138 /*-----------------------------------------------------------------*/
7139 /* AccRsh - right shift accumulator by known count */
7140 /*-----------------------------------------------------------------*/
7142 AccRsh (int shCount)
7149 emitcode ("rrc", "a");
7153 /* rotate right accumulator */
7154 AccRol (8 - shCount);
7155 /* and kill the higher order bits */
7156 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7161 #ifdef BETTER_LITERAL_SHIFT
7162 /*-----------------------------------------------------------------*/
7163 /* AccSRsh - signed right shift accumulator by known count */
7164 /*-----------------------------------------------------------------*/
7166 AccSRsh (int shCount)
7173 emitcode ("mov", "c,acc.7");
7174 emitcode ("rrc", "a");
7176 else if (shCount == 2)
7178 emitcode ("mov", "c,acc.7");
7179 emitcode ("rrc", "a");
7180 emitcode ("mov", "c,acc.7");
7181 emitcode ("rrc", "a");
7185 tlbl = newiTempLabel (NULL);
7186 /* rotate right accumulator */
7187 AccRol (8 - shCount);
7188 /* and kill the higher order bits */
7189 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7190 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7191 emitcode ("orl", "a,#!constbyte",
7192 (unsigned char) ~SRMask[shCount]);
7193 emitcode ("", "!tlabeldef", tlbl->key + 100);
7199 #ifdef BETTER_LITERAL_SHIFT
7200 /*-----------------------------------------------------------------*/
7201 /* shiftR1Left2Result - shift right one byte from left to result */
7202 /*-----------------------------------------------------------------*/
7204 shiftR1Left2Result (operand * left, int offl,
7205 operand * result, int offr,
7206 int shCount, int sign)
7208 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7209 /* shift right accumulator */
7214 aopPut (AOP (result), "a", offr);
7218 #ifdef BETTER_LITERAL_SHIFT
7219 /*-----------------------------------------------------------------*/
7220 /* shiftL1Left2Result - shift left one byte from left to result */
7221 /*-----------------------------------------------------------------*/
7223 shiftL1Left2Result (operand * left, int offl,
7224 operand * result, int offr, int shCount)
7226 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7227 /* shift left accumulator */
7229 aopPut (AOP (result), "a", offr);
7233 #ifdef BETTER_LITERAL_SHIFT
7234 /*-----------------------------------------------------------------*/
7235 /* movLeft2Result - move byte from left to result */
7236 /*-----------------------------------------------------------------*/
7238 movLeft2Result (operand * left, int offl,
7239 operand * result, int offr, int sign)
7242 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7244 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
7246 if (*l == '@' && (IS_AOP_PREG (result)))
7248 emitcode ("mov", "a,%s", l);
7249 aopPut (AOP (result), "a", offr);
7255 aopPut (AOP (result), l, offr);
7259 /* MSB sign in acc.7 ! */
7260 if (getDataSize (left) == offl + 1)
7262 emitcode ("mov", "a,%s", l);
7263 aopPut (AOP (result), "a", offr);
7271 #ifdef BETTER_LITERAL_SHIFT
7272 /*-----------------------------------------------------------------*/
7273 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7274 /*-----------------------------------------------------------------*/
7278 emitcode ("rrc", "a");
7279 emitcode ("xch", "a,%s", x);
7280 emitcode ("rrc", "a");
7281 emitcode ("xch", "a,%s", x);
7285 #ifdef BETTER_LITERAL_SHIFT
7287 /*-----------------------------------------------------------------*/
7288 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7289 /*-----------------------------------------------------------------*/
7293 emitcode ("xch", "a,%s", x);
7294 emitcode ("rlc", "a");
7295 emitcode ("xch", "a,%s", x);
7296 emitcode ("rlc", "a");
7300 #ifdef BETTER_LITERAL_SHIFT
7301 /*-----------------------------------------------------------------*/
7302 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7303 /*-----------------------------------------------------------------*/
7307 emitcode ("xch", "a,%s", x);
7308 emitcode ("add", "a,acc");
7309 emitcode ("xch", "a,%s", x);
7310 emitcode ("rlc", "a");
7314 #ifdef BETTER_LITERAL_SHIFT
7315 /*-----------------------------------------------------------------*/
7316 /* AccAXLsh - left shift a:x by known count (0..7) */
7317 /*-----------------------------------------------------------------*/
7319 AccAXLsh (char *x, int shCount)
7334 case 5: // AAAAABBB:CCCCCDDD
7336 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7338 emitcode ("anl", "a,#!constbyte",
7339 SLMask[shCount]); // BBB00000:CCCCCDDD
7341 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7343 AccRol (shCount); // DDDCCCCC:BBB00000
7345 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7347 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7349 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7351 emitcode ("anl", "a,#!constbyte",
7352 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7354 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7356 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7359 case 6: // AAAAAABB:CCCCCCDD
7360 emitcode ("anl", "a,#!constbyte",
7361 SRMask[shCount]); // 000000BB:CCCCCCDD
7362 emitcode ("mov", "c,acc.0"); // c = B
7363 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7365 AccAXRrl1 (x); // BCCCCCCD:D000000B
7366 AccAXRrl1 (x); // BBCCCCCC:DD000000
7368 emitcode("rrc","a");
7369 emitcode("xch","a,%s", x);
7370 emitcode("rrc","a");
7371 emitcode("mov","c,acc.0"); //<< get correct bit
7372 emitcode("xch","a,%s", x);
7374 emitcode("rrc","a");
7375 emitcode("xch","a,%s", x);
7376 emitcode("rrc","a");
7377 emitcode("xch","a,%s", x);
7380 case 7: // a:x <<= 7
7382 emitcode ("anl", "a,#!constbyte",
7383 SRMask[shCount]); // 0000000B:CCCCCCCD
7385 emitcode ("mov", "c,acc.0"); // c = B
7387 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7389 AccAXRrl1 (x); // BCCCCCCC:D0000000
7398 #ifdef BETTER_LITERAL_SHIFT
7400 /*-----------------------------------------------------------------*/
7401 /* AccAXRsh - right shift a:x known count (0..7) */
7402 /*-----------------------------------------------------------------*/
7404 AccAXRsh (char *x, int shCount)
7412 AccAXRrl1 (x); // 0->a:x
7417 AccAXRrl1 (x); // 0->a:x
7420 AccAXRrl1 (x); // 0->a:x
7425 case 5: // AAAAABBB:CCCCCDDD = a:x
7427 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7429 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7431 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7433 emitcode ("anl", "a,#!constbyte",
7434 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7436 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7438 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7440 emitcode ("anl", "a,#!constbyte",
7441 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7443 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7445 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7447 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7450 case 6: // AABBBBBB:CCDDDDDD
7452 emitcode ("mov", "c,acc.7");
7453 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7455 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7457 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7459 emitcode ("anl", "a,#!constbyte",
7460 SRMask[shCount]); // 000000AA:BBBBBBCC
7463 case 7: // ABBBBBBB:CDDDDDDD
7465 emitcode ("mov", "c,acc.7"); // c = A
7467 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7469 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7471 emitcode ("anl", "a,#!constbyte",
7472 SRMask[shCount]); // 0000000A:BBBBBBBC
7481 #ifdef BETTER_LITERAL_SHIFT
7482 /*-----------------------------------------------------------------*/
7483 /* AccAXRshS - right shift signed a:x known count (0..7) */
7484 /*-----------------------------------------------------------------*/
7486 AccAXRshS (char *x, int shCount)
7494 emitcode ("mov", "c,acc.7");
7495 AccAXRrl1 (x); // s->a:x
7499 emitcode ("mov", "c,acc.7");
7500 AccAXRrl1 (x); // s->a:x
7502 emitcode ("mov", "c,acc.7");
7503 AccAXRrl1 (x); // s->a:x
7508 case 5: // AAAAABBB:CCCCCDDD = a:x
7510 tlbl = newiTempLabel (NULL);
7511 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7513 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7515 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7517 emitcode ("anl", "a,#!constbyte",
7518 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7520 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7522 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7524 emitcode ("anl", "a,#!constbyte",
7525 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7527 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7529 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7531 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7533 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7534 emitcode ("orl", "a,#!constbyte",
7535 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7537 emitcode ("", "!tlabeldef", tlbl->key + 100);
7538 break; // SSSSAAAA:BBBCCCCC
7540 case 6: // AABBBBBB:CCDDDDDD
7542 tlbl = newiTempLabel (NULL);
7543 emitcode ("mov", "c,acc.7");
7544 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7546 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7548 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7550 emitcode ("anl", "a,#!constbyte",
7551 SRMask[shCount]); // 000000AA:BBBBBBCC
7553 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7554 emitcode ("orl", "a,#!constbyte",
7555 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7557 emitcode ("", "!tlabeldef", tlbl->key + 100);
7559 case 7: // ABBBBBBB:CDDDDDDD
7561 tlbl = newiTempLabel (NULL);
7562 emitcode ("mov", "c,acc.7"); // c = A
7564 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7566 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7568 emitcode ("anl", "a,#!constbyte",
7569 SRMask[shCount]); // 0000000A:BBBBBBBC
7571 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7572 emitcode ("orl", "a,#!constbyte",
7573 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7575 emitcode ("", "!tlabeldef", tlbl->key + 100);
7583 #ifdef BETTER_LITERAL_SHIFT
7585 _loadLeftIntoAx(char **lsb,
7591 // Get the initial value from left into a pair of registers.
7592 // MSB must be in A, LSB can be any register.
7594 // If the result is held in registers, it is an optimization
7595 // if the LSB can be held in the register which will hold the,
7596 // result LSB since this saves us from having to copy it into
7597 // the result following AccAXLsh.
7599 // If the result is addressed indirectly, this is not a gain.
7600 if (AOP_NEEDSACC(result))
7604 _startLazyDPSEvaluation();
7605 if (AOP_TYPE(left) == AOP_DPTR2)
7608 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
7609 // get LSB in DP2_RESULT_REG.
7610 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
7611 assert(!strcmp(leftByte, DP2_RESULT_REG));
7615 // get LSB into DP2_RESULT_REG
7616 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
7617 if (strcmp(leftByte, DP2_RESULT_REG))
7620 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7623 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
7624 assert(strcmp(leftByte, DP2_RESULT_REG));
7627 _endLazyDPSEvaluation();
7628 *lsb = DP2_RESULT_REG;
7632 if (sameRegs (AOP (result), AOP (left)) &&
7633 ((offl + MSB16) == offr))
7635 /* don't crash result[offr] */
7636 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
7637 emitcode ("xch", "a,%s",
7638 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
7642 movLeft2Result (left, offl, result, offr, 0);
7643 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
7645 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
7646 assert(strcmp(*lsb,"a"));
7651 _storeAxResults(char *lsb,
7655 _startLazyDPSEvaluation();
7656 if (AOP_NEEDSACC(result))
7658 /* We have to explicitly update the result LSB.
7660 emitcode("xch","a,%s", lsb);
7661 aopPut(AOP(result), "a", offr);
7662 emitcode("mov","a,%s", lsb);
7664 if (getDataSize (result) > 1)
7666 aopPut (AOP (result), "a", offr + MSB16);
7668 _endLazyDPSEvaluation();
7671 /*-----------------------------------------------------------------*/
7672 /* shiftL2Left2Result - shift left two bytes from left to result */
7673 /*-----------------------------------------------------------------*/
7675 shiftL2Left2Result (operand * left, int offl,
7676 operand * result, int offr, int shCount)
7680 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7682 AccAXLsh (lsb, shCount);
7684 _storeAxResults(lsb, result, offr);
7688 #ifdef BETTER_LITERAL_SHIFT
7689 /*-----------------------------------------------------------------*/
7690 /* shiftR2Left2Result - shift right two bytes from left to result */
7691 /*-----------------------------------------------------------------*/
7693 shiftR2Left2Result (operand * left, int offl,
7694 operand * result, int offr,
7695 int shCount, int sign)
7699 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7701 /* a:x >> shCount (x = lsb(result)) */
7704 AccAXRshS(lsb, shCount);
7708 AccAXRsh(lsb, shCount);
7711 _storeAxResults(lsb, result, offr);
7717 /*-----------------------------------------------------------------*/
7718 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7719 /*-----------------------------------------------------------------*/
7721 shiftLLeftOrResult (operand * left, int offl,
7722 operand * result, int offr, int shCount)
7724 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7725 /* shift left accumulator */
7727 /* or with result */
7728 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7729 /* back to result */
7730 aopPut (AOP (result), "a", offr);
7736 /*-----------------------------------------------------------------*/
7737 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7738 /*-----------------------------------------------------------------*/
7740 shiftRLeftOrResult (operand * left, int offl,
7741 operand * result, int offr, int shCount)
7743 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7744 /* shift right accumulator */
7746 /* or with result */
7747 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7748 /* back to result */
7749 aopPut (AOP (result), "a", offr);
7753 #ifdef BETTER_LITERAL_SHIFT
7754 /*-----------------------------------------------------------------*/
7755 /* genlshOne - left shift a one byte quantity by known count */
7756 /*-----------------------------------------------------------------*/
7758 genlshOne (operand * result, operand * left, int shCount)
7760 D (emitcode (";", "genlshOne "););
7761 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7765 #ifdef BETTER_LITERAL_SHIFT
7766 /*-----------------------------------------------------------------*/
7767 /* genlshTwo - left shift two bytes by known amount != 0 */
7768 /*-----------------------------------------------------------------*/
7770 genlshTwo (operand * result, operand * left, int shCount)
7774 D (emitcode (";", "genlshTwo "););
7776 size = getDataSize (result);
7778 /* if shCount >= 8 */
7783 _startLazyDPSEvaluation();
7789 _endLazyDPSEvaluation();
7790 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7791 aopPut (AOP (result), zero, LSB);
7795 movLeft2Result (left, LSB, result, MSB16, 0);
7796 aopPut (AOP (result), zero, LSB);
7797 _endLazyDPSEvaluation();
7802 aopPut (AOP (result), zero, LSB);
7803 _endLazyDPSEvaluation();
7807 /* 1 <= shCount <= 7 */
7812 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7816 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7824 /*-----------------------------------------------------------------*/
7825 /* shiftLLong - shift left one long from left to result */
7826 /* offl = LSB or MSB16 */
7827 /*-----------------------------------------------------------------*/
7829 shiftLLong (operand * left, operand * result, int offr)
7832 int size = AOP_SIZE (result);
7834 if (size >= LSB + offr)
7836 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
7838 emitcode ("add", "a,acc");
7839 if (sameRegs (AOP (left), AOP (result)) &&
7840 size >= MSB16 + offr && offr != LSB)
7841 emitcode ("xch", "a,%s",
7842 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
7844 aopPut (AOP (result), "a", LSB + offr);
7847 if (size >= MSB16 + offr)
7849 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7851 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
7854 emitcode ("rlc", "a");
7855 if (sameRegs (AOP (left), AOP (result)) &&
7856 size >= MSB24 + offr && offr != LSB)
7857 emitcode ("xch", "a,%s",
7858 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
7860 aopPut (AOP (result), "a", MSB16 + offr);
7863 if (size >= MSB24 + offr)
7865 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7867 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
7870 emitcode ("rlc", "a");
7871 if (sameRegs (AOP (left), AOP (result)) &&
7872 size >= MSB32 + offr && offr != LSB)
7873 emitcode ("xch", "a,%s",
7874 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
7876 aopPut (AOP (result), "a", MSB24 + offr);
7879 if (size > MSB32 + offr)
7881 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7883 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7886 emitcode ("rlc", "a");
7887 aopPut (AOP (result), "a", MSB32 + offr);
7890 aopPut (AOP (result), zero, LSB);
7896 /*-----------------------------------------------------------------*/
7897 /* genlshFour - shift four byte by a known amount != 0 */
7898 /*-----------------------------------------------------------------*/
7900 genlshFour (operand * result, operand * left, int shCount)
7904 D (emitcode (";", "genlshFour ");
7907 size = AOP_SIZE (result);
7909 /* if shifting more that 3 bytes */
7914 /* lowest order of left goes to the highest
7915 order of the destination */
7916 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7918 movLeft2Result (left, LSB, result, MSB32, 0);
7919 aopPut (AOP (result), zero, LSB);
7920 aopPut (AOP (result), zero, MSB16);
7921 aopPut (AOP (result), zero, MSB24);
7925 /* more than two bytes */
7926 else if (shCount >= 16)
7928 /* lower order two bytes goes to higher order two bytes */
7930 /* if some more remaining */
7932 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7935 movLeft2Result (left, MSB16, result, MSB32, 0);
7936 movLeft2Result (left, LSB, result, MSB24, 0);
7938 aopPut (AOP (result), zero, MSB16);
7939 aopPut (AOP (result), zero, LSB);
7943 /* if more than 1 byte */
7944 else if (shCount >= 8)
7946 /* lower order three bytes goes to higher order three bytes */
7951 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7953 movLeft2Result (left, LSB, result, MSB16, 0);
7959 movLeft2Result (left, MSB24, result, MSB32, 0);
7960 movLeft2Result (left, MSB16, result, MSB24, 0);
7961 movLeft2Result (left, LSB, result, MSB16, 0);
7962 aopPut (AOP (result), zero, LSB);
7964 else if (shCount == 1)
7965 shiftLLong (left, result, MSB16);
7968 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7969 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7970 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7971 aopPut (AOP (result), zero, LSB);
7976 /* 1 <= shCount <= 7 */
7977 else if (shCount <= 2)
7979 shiftLLong (left, result, LSB);
7981 shiftLLong (result, result, LSB);
7983 /* 3 <= shCount <= 7, optimize */
7986 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7987 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7988 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7993 #ifdef BETTER_LITERAL_SHIFT
7994 /*-----------------------------------------------------------------*/
7995 /* genLeftShiftLiteral - left shifting by known count */
7996 /*-----------------------------------------------------------------*/
7998 genLeftShiftLiteral (operand * left,
8003 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8006 size = getSize (operandType (result));
8008 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8010 /* We only handle certain easy cases so far. */
8012 && (shCount < (size * 8))
8016 D(emitcode (";", "genLeftShiftLiteral wimping out"););
8020 freeAsmop (right, NULL, ic, TRUE);
8022 aopOp(left, ic, FALSE, FALSE);
8023 aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
8026 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8028 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8029 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8031 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8034 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8036 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8037 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8039 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8045 emitcode ("; shift left ", "result %d, left %d", size,
8049 /* I suppose that the left size >= result size */
8052 _startLazyDPSEvaluation();
8055 movLeft2Result (left, size, result, size, 0);
8057 _endLazyDPSEvaluation();
8059 else if (shCount >= (size * 8))
8061 _startLazyDPSEvaluation();
8064 aopPut (AOP (result), zero, size);
8066 _endLazyDPSEvaluation();
8073 genlshOne (result, left, shCount);
8077 genlshTwo (result, left, shCount);
8081 genlshFour (result, left, shCount);
8085 fprintf(stderr, "*** ack! mystery literal shift!\n");
8089 freeAsmop (left, NULL, ic, TRUE);
8090 freeAsmop (result, NULL, ic, TRUE);
8095 /*-----------------------------------------------------------------*/
8096 /* genLeftShift - generates code for left shifting */
8097 /*-----------------------------------------------------------------*/
8099 genLeftShift (iCode * ic)
8101 operand *left, *right, *result;
8104 symbol *tlbl, *tlbl1;
8106 D (emitcode (";", "genLeftShift "););
8108 right = IC_RIGHT (ic);
8109 left = IC_LEFT (ic);
8110 result = IC_RESULT (ic);
8112 aopOp (right, ic, FALSE, FALSE);
8115 #ifdef BETTER_LITERAL_SHIFT
8116 /* if the shift count is known then do it
8117 as efficiently as possible */
8118 if (AOP_TYPE (right) == AOP_LIT)
8120 if (genLeftShiftLiteral (left, right, result, ic))
8127 /* shift count is unknown then we have to form
8128 a loop get the loop count in B : Note: we take
8129 only the lower order byte since shifting
8130 more that 32 bits make no sense anyway, ( the
8131 largest size of an object can be only 32 bits ) */
8133 if (AOP_TYPE (right) == AOP_LIT)
8135 /* Really should be handled by genLeftShiftLiteral,
8136 * but since I'm too lazy to fix that today, at least we can make
8137 * some small improvement.
8139 emitcode("mov", "b,#!constbyte",
8140 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8144 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8145 emitcode ("inc", "b");
8147 freeAsmop (right, NULL, ic, TRUE);
8148 aopOp (left, ic, FALSE, FALSE);
8149 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8151 /* now move the left to the result if they are not the
8153 if (!sameRegs (AOP (left), AOP (result)) &&
8154 AOP_SIZE (result) > 1)
8157 size = AOP_SIZE (result);
8159 _startLazyDPSEvaluation ();
8162 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8163 if (*l == '@' && (IS_AOP_PREG (result)))
8166 emitcode ("mov", "a,%s", l);
8167 aopPut (AOP (result), "a", offset);
8170 aopPut (AOP (result), l, offset);
8173 _endLazyDPSEvaluation ();
8176 tlbl = newiTempLabel (NULL);
8177 size = AOP_SIZE (result);
8179 tlbl1 = newiTempLabel (NULL);
8181 /* if it is only one byte then */
8184 symbol *tlbl1 = newiTempLabel (NULL);
8186 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8188 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8189 emitcode ("", "!tlabeldef", tlbl->key + 100);
8190 emitcode ("add", "a,acc");
8191 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8192 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8193 aopPut (AOP (result), "a", 0);
8197 reAdjustPreg (AOP (result));
8199 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8200 emitcode ("", "!tlabeldef", tlbl->key + 100);
8201 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8203 emitcode ("add", "a,acc");
8204 aopPut (AOP (result), "a", offset++);
8205 _startLazyDPSEvaluation ();
8208 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8210 emitcode ("rlc", "a");
8211 aopPut (AOP (result), "a", offset++);
8213 _endLazyDPSEvaluation ();
8214 reAdjustPreg (AOP (result));
8216 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8217 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8219 freeAsmop (left, NULL, ic, TRUE);
8220 freeAsmop (result, NULL, ic, TRUE);
8223 #ifdef BETTER_LITERAL_SHIFT
8224 /*-----------------------------------------------------------------*/
8225 /* genrshOne - right shift a one byte quantity by known count */
8226 /*-----------------------------------------------------------------*/
8228 genrshOne (operand * result, operand * left,
8229 int shCount, int sign)
8231 D (emitcode (";", "genrshOne"););
8232 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8236 #ifdef BETTER_LITERAL_SHIFT
8237 /*-----------------------------------------------------------------*/
8238 /* genrshTwo - right shift two bytes by known amount != 0 */
8239 /*-----------------------------------------------------------------*/
8241 genrshTwo (operand * result, operand * left,
8242 int shCount, int sign)
8244 D (emitcode (";", "genrshTwo"););
8246 /* if shCount >= 8 */
8250 _startLazyDPSEvaluation();
8253 shiftR1Left2Result (left, MSB16, result, LSB,
8258 movLeft2Result (left, MSB16, result, LSB, sign);
8260 addSign (result, MSB16, sign);
8261 _endLazyDPSEvaluation();
8264 /* 1 <= shCount <= 7 */
8267 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8274 /*-----------------------------------------------------------------*/
8275 /* shiftRLong - shift right one long from left to result */
8276 /* offl = LSB or MSB16 */
8277 /*-----------------------------------------------------------------*/
8279 shiftRLong (operand * left, int offl,
8280 operand * result, int sign)
8282 int isSameRegs=sameRegs(AOP(left),AOP(result));
8284 if (isSameRegs && offl>1) {
8285 // we are in big trouble, but this shouldn't happen
8286 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8289 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
8294 emitcode ("rlc", "a");
8295 emitcode ("subb", "a,acc");
8296 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
8298 aopPut (AOP(result), zero, MSB32);
8303 emitcode ("clr", "c");
8305 emitcode ("mov", "c,acc.7");
8308 emitcode ("rrc", "a");
8310 if (isSameRegs && offl==MSB16) {
8311 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
8313 aopPut (AOP (result), "a", MSB32);
8314 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
8317 emitcode ("rrc", "a");
8318 if (isSameRegs && offl==1) {
8319 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
8321 aopPut (AOP (result), "a", MSB24);
8322 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
8324 emitcode ("rrc", "a");
8325 aopPut (AOP (result), "a", MSB16 - offl);
8329 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
8330 emitcode ("rrc", "a");
8331 aopPut (AOP (result), "a", LSB);
8338 /*-----------------------------------------------------------------*/
8339 /* genrshFour - shift four byte by a known amount != 0 */
8340 /*-----------------------------------------------------------------*/
8342 genrshFour (operand * result, operand * left,
8343 int shCount, int sign)
8345 D (emitcode (";", "genrshFour");
8348 /* if shifting more that 3 bytes */
8353 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8355 movLeft2Result (left, MSB32, result, LSB, sign);
8356 addSign (result, MSB16, sign);
8358 else if (shCount >= 16)
8362 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8365 movLeft2Result (left, MSB24, result, LSB, 0);
8366 movLeft2Result (left, MSB32, result, MSB16, sign);
8368 addSign (result, MSB24, sign);
8370 else if (shCount >= 8)
8374 shiftRLong (left, MSB16, result, sign);
8375 else if (shCount == 0)
8377 movLeft2Result (left, MSB16, result, LSB, 0);
8378 movLeft2Result (left, MSB24, result, MSB16, 0);
8379 movLeft2Result (left, MSB32, result, MSB24, sign);
8380 addSign (result, MSB32, sign);
8384 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8385 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8386 /* the last shift is signed */
8387 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8388 addSign (result, MSB32, sign);
8392 { /* 1 <= shCount <= 7 */
8395 shiftRLong (left, LSB, result, sign);
8397 shiftRLong (result, LSB, result, sign);
8401 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8402 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8403 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8409 #ifdef BETTER_LITERAL_SHIFT
8410 /*-----------------------------------------------------------------*/
8411 /* genRightShiftLiteral - right shifting by known count */
8412 /*-----------------------------------------------------------------*/
8414 genRightShiftLiteral (operand * left,
8420 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8423 size = getSize (operandType (result));
8425 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8427 /* We only handle certain easy cases so far. */
8429 && (shCount < (size * 8))
8433 D(emitcode (";", "genRightShiftLiteral wimping out"););
8437 freeAsmop (right, NULL, ic, TRUE);
8439 aopOp (left, ic, FALSE, FALSE);
8440 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8443 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8447 /* test the LEFT size !!! */
8449 /* I suppose that the left size >= result size */
8452 size = getDataSize (result);
8453 _startLazyDPSEvaluation();
8456 movLeft2Result (left, size, result, size, 0);
8458 _endLazyDPSEvaluation();
8460 else if (shCount >= (size * 8))
8464 /* get sign in acc.7 */
8465 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
8467 addSign (result, LSB, sign);
8474 genrshOne (result, left, shCount, sign);
8478 genrshTwo (result, left, shCount, sign);
8482 genrshFour (result, left, shCount, sign);
8489 freeAsmop (left, NULL, ic, TRUE);
8490 freeAsmop (result, NULL, ic, TRUE);
8496 /*-----------------------------------------------------------------*/
8497 /* genSignedRightShift - right shift of signed number */
8498 /*-----------------------------------------------------------------*/
8500 genSignedRightShift (iCode * ic)
8502 operand *right, *left, *result;
8505 symbol *tlbl, *tlbl1;
8507 D (emitcode (";", "genSignedRightShift "););
8509 /* we do it the hard way put the shift count in b
8510 and loop thru preserving the sign */
8512 right = IC_RIGHT (ic);
8513 left = IC_LEFT (ic);
8514 result = IC_RESULT (ic);
8516 aopOp (right, ic, FALSE, FALSE);
8518 #ifdef BETTER_LITERAL_SHIFT
8519 if (AOP_TYPE (right) == AOP_LIT)
8521 if (genRightShiftLiteral (left, right, result, ic, 1))
8527 /* shift count is unknown then we have to form
8528 a loop get the loop count in B : Note: we take
8529 only the lower order byte since shifting
8530 more that 32 bits make no sense anyway, ( the
8531 largest size of an object can be only 32 bits ) */
8533 if (AOP_TYPE (right) == AOP_LIT)
8535 /* Really should be handled by genRightShiftLiteral,
8536 * but since I'm too lazy to fix that today, at least we can make
8537 * some small improvement.
8539 emitcode("mov", "b,#!constbyte",
8540 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8544 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8545 emitcode ("inc", "b");
8547 freeAsmop (right, NULL, ic, TRUE);
8548 aopOp (left, ic, FALSE, FALSE);
8549 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8551 /* now move the left to the result if they are not the
8553 if (!sameRegs (AOP (left), AOP (result)) &&
8554 AOP_SIZE (result) > 1)
8557 size = AOP_SIZE (result);
8559 _startLazyDPSEvaluation ();
8562 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8563 if (*l == '@' && IS_AOP_PREG (result))
8566 emitcode ("mov", "a,%s", l);
8567 aopPut (AOP (result), "a", offset);
8570 aopPut (AOP (result), l, offset);
8573 _endLazyDPSEvaluation ();
8576 /* mov the highest order bit to OVR */
8577 tlbl = newiTempLabel (NULL);
8578 tlbl1 = newiTempLabel (NULL);
8580 size = AOP_SIZE (result);
8582 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
8583 emitcode ("rlc", "a");
8584 emitcode ("mov", "ov,c");
8585 /* if it is only one byte then */
8588 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8590 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8591 emitcode ("", "!tlabeldef", tlbl->key + 100);
8592 emitcode ("mov", "c,ov");
8593 emitcode ("rrc", "a");
8594 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8595 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8596 aopPut (AOP (result), "a", 0);
8600 reAdjustPreg (AOP (result));
8601 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8602 emitcode ("", "!tlabeldef", tlbl->key + 100);
8603 emitcode ("mov", "c,ov");
8604 _startLazyDPSEvaluation ();
8607 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8609 emitcode ("rrc", "a");
8610 aopPut (AOP (result), "a", offset--);
8612 _endLazyDPSEvaluation ();
8613 reAdjustPreg (AOP (result));
8614 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8615 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8618 freeAsmop (left, NULL, ic, TRUE);
8619 freeAsmop (result, NULL, ic, TRUE);
8622 /*-----------------------------------------------------------------*/
8623 /* genRightShift - generate code for right shifting */
8624 /*-----------------------------------------------------------------*/
8626 genRightShift (iCode * ic)
8628 operand *right, *left, *result;
8632 symbol *tlbl, *tlbl1;
8634 D (emitcode (";", "genRightShift "););
8636 /* if signed then we do it the hard way preserve the
8637 sign bit moving it inwards */
8638 retype = getSpec (operandType (IC_RESULT (ic)));
8640 if (!SPEC_USIGN (retype))
8642 genSignedRightShift (ic);
8646 /* signed & unsigned types are treated the same : i.e. the
8647 signed is NOT propagated inwards : quoting from the
8648 ANSI - standard : "for E1 >> E2, is equivalent to division
8649 by 2**E2 if unsigned or if it has a non-negative value,
8650 otherwise the result is implementation defined ", MY definition
8651 is that the sign does not get propagated */
8653 right = IC_RIGHT (ic);
8654 left = IC_LEFT (ic);
8655 result = IC_RESULT (ic);
8657 aopOp (right, ic, FALSE, FALSE);
8659 #ifdef BETTER_LITERAL_SHIFT
8660 /* if the shift count is known then do it
8661 as efficiently as possible */
8662 if (AOP_TYPE (right) == AOP_LIT)
8664 if (genRightShiftLiteral (left, right, result, ic, 0))
8671 /* shift count is unknown then we have to form
8672 a loop get the loop count in B : Note: we take
8673 only the lower order byte since shifting
8674 more that 32 bits make no sense anyway, ( the
8675 largest size of an object can be only 32 bits ) */
8677 if (AOP_TYPE (right) == AOP_LIT)
8679 /* Really should be handled by genRightShiftLiteral,
8680 * but since I'm too lazy to fix that today, at least we can make
8681 * some small improvement.
8683 emitcode("mov", "b,#!constbyte",
8684 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8688 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8689 emitcode ("inc", "b");
8691 freeAsmop (right, NULL, ic, TRUE);
8692 aopOp (left, ic, FALSE, FALSE);
8693 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8695 /* now move the left to the result if they are not the
8697 if (!sameRegs (AOP (left), AOP (result)) &&
8698 AOP_SIZE (result) > 1)
8701 size = AOP_SIZE (result);
8703 _startLazyDPSEvaluation ();
8706 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8707 if (*l == '@' && IS_AOP_PREG (result))
8710 emitcode ("mov", "a,%s", l);
8711 aopPut (AOP (result), "a", offset);
8714 aopPut (AOP (result), l, offset);
8717 _endLazyDPSEvaluation ();
8720 tlbl = newiTempLabel (NULL);
8721 tlbl1 = newiTempLabel (NULL);
8722 size = AOP_SIZE (result);
8725 /* if it is only one byte then */
8728 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8730 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8731 emitcode ("", "!tlabeldef", tlbl->key + 100);
8733 emitcode ("rrc", "a");
8734 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8735 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8736 aopPut (AOP (result), "a", 0);
8740 reAdjustPreg (AOP (result));
8741 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8742 emitcode ("", "!tlabeldef", tlbl->key + 100);
8744 _startLazyDPSEvaluation ();
8747 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8749 emitcode ("rrc", "a");
8750 aopPut (AOP (result), "a", offset--);
8752 _endLazyDPSEvaluation ();
8753 reAdjustPreg (AOP (result));
8755 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8756 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8759 freeAsmop (left, NULL, ic, TRUE);
8760 freeAsmop (result, NULL, ic, TRUE);
8763 /*-----------------------------------------------------------------*/
8764 /* genUnpackBits - generates code for unpacking bits */
8765 /*-----------------------------------------------------------------*/
8767 genUnpackBits (operand * result, char *rname, int ptype)
8774 D (emitcode (";", "genUnpackBits ");
8777 etype = getSpec (operandType (result));
8779 /* read the first byte */
8785 emitcode ("mov", "a,@%s", rname);
8789 emitcode ("movx", "a,@%s", rname);
8793 emitcode ("movx", "a,@dptr");
8797 emitcode ("clr", "a");
8798 emitcode ("movc", "a,@a+dptr");
8802 emitcode ("lcall", "__gptrget");
8806 /* if we have bitdisplacement then it fits */
8807 /* into this byte completely or if length is */
8808 /* less than a byte */
8809 if ((shCnt = SPEC_BSTR (etype)) ||
8810 (SPEC_BLEN (etype) <= 8))
8813 /* shift right acc */
8816 emitcode ("anl", "a,#!constbyte",
8817 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8818 aopPut (AOP (result), "a", offset);
8822 /* bit field did not fit in a byte */
8823 rlen = SPEC_BLEN (etype) - 8;
8824 aopPut (AOP (result), "a", offset++);
8833 emitcode ("inc", "%s", rname);
8834 emitcode ("mov", "a,@%s", rname);
8838 emitcode ("inc", "%s", rname);
8839 emitcode ("movx", "a,@%s", rname);
8843 emitcode ("inc", "dptr");
8844 emitcode ("movx", "a,@dptr");
8848 emitcode ("clr", "a");
8849 emitcode ("inc", "dptr");
8850 emitcode ("movc", "a,@a+dptr");
8854 emitcode ("inc", "dptr");
8855 emitcode ("lcall", "__gptrget");
8860 /* if we are done */
8864 aopPut (AOP (result), "a", offset++);
8870 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (rlen));
8871 aopPut (AOP (result), "a", offset);
8878 /*-----------------------------------------------------------------*/
8879 /* genDataPointerGet - generates code when ptr offset is known */
8880 /*-----------------------------------------------------------------*/
8882 genDataPointerGet (operand * left,
8888 int size, offset = 0;
8889 aopOp (result, ic, TRUE, FALSE);
8891 /* get the string representation of the name */
8892 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8893 size = AOP_SIZE (result);
8894 _startLazyDPSEvaluation ();
8898 sprintf (buffer, "(%s + %d)", l + 1, offset);
8900 sprintf (buffer, "%s", l + 1);
8901 aopPut (AOP (result), buffer, offset++);
8903 _endLazyDPSEvaluation ();
8905 freeAsmop (left, NULL, ic, TRUE);
8906 freeAsmop (result, NULL, ic, TRUE);
8909 /*-----------------------------------------------------------------*/
8910 /* genNearPointerGet - emitcode for near pointer fetch */
8911 /*-----------------------------------------------------------------*/
8913 genNearPointerGet (operand * left,
8921 sym_link *rtype, *retype, *letype;
8922 sym_link *ltype = operandType (left);
8925 rtype = operandType (result);
8926 retype = getSpec (rtype);
8927 letype = getSpec (ltype);
8929 aopOp (left, ic, FALSE, FALSE);
8931 /* if left is rematerialisable and
8932 result is not bit variable type and
8933 the left is pointer to data space i.e
8934 lower 128 bytes of space */
8935 if (AOP_TYPE (left) == AOP_IMMD &&
8936 !IS_BITVAR (retype) &&
8937 !IS_BITVAR (letype) &&
8938 DCL_TYPE (ltype) == POINTER)
8940 genDataPointerGet (left, result, ic);
8944 /* if the value is already in a pointer register
8945 then don't need anything more */
8946 if (!AOP_INPREG (AOP (left)))
8948 /* otherwise get a free pointer register */
8950 preg = getFreePtr (ic, &aop, FALSE);
8951 emitcode ("mov", "%s,%s",
8953 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8957 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8959 freeAsmop (left, NULL, ic, TRUE);
8960 aopOp (result, ic, FALSE, FALSE);
8962 /* if bitfield then unpack the bits */
8963 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8964 genUnpackBits (result, rname, POINTER);
8967 /* we have can just get the values */
8968 int size = AOP_SIZE (result);
8973 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8976 emitcode ("mov", "a,@%s", rname);
8977 aopPut (AOP (result), "a", offset);
8981 sprintf (buffer, "@%s", rname);
8982 aopPut (AOP (result), buffer, offset);
8986 emitcode ("inc", "%s", rname);
8990 /* now some housekeeping stuff */
8993 /* we had to allocate for this iCode */
8994 if (pi) { /* post increment present */
8995 aopPut(AOP ( left ),rname,0);
8997 freeAsmop (NULL, aop, ic, TRUE);
9001 /* we did not allocate which means left
9002 already in a pointer register, then
9003 if size > 0 && this could be used again
9004 we have to point it back to where it
9006 if (AOP_SIZE (result) > 1 &&
9007 !OP_SYMBOL (left)->remat &&
9008 (OP_SYMBOL (left)->liveTo > ic->seq ||
9012 int size = AOP_SIZE (result) - 1;
9014 emitcode ("dec", "%s", rname);
9019 freeAsmop (result, NULL, ic, TRUE);
9020 if (pi) pi->generated = 1;
9023 /*-----------------------------------------------------------------*/
9024 /* genPagedPointerGet - emitcode for paged pointer fetch */
9025 /*-----------------------------------------------------------------*/
9027 genPagedPointerGet (operand * left,
9035 sym_link *rtype, *retype, *letype;
9037 rtype = operandType (result);
9038 retype = getSpec (rtype);
9039 letype = getSpec (operandType (left));
9040 aopOp (left, ic, FALSE, FALSE);
9042 /* if the value is already in a pointer register
9043 then don't need anything more */
9044 if (!AOP_INPREG (AOP (left)))
9046 /* otherwise get a free pointer register */
9048 preg = getFreePtr (ic, &aop, FALSE);
9049 emitcode ("mov", "%s,%s",
9051 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
9055 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
9057 freeAsmop (left, NULL, ic, TRUE);
9058 aopOp (result, ic, FALSE, FALSE);
9060 /* if bitfield then unpack the bits */
9061 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9062 genUnpackBits (result, rname, PPOINTER);
9065 /* we have can just get the values */
9066 int size = AOP_SIZE (result);
9072 emitcode ("movx", "a,@%s", rname);
9073 aopPut (AOP (result), "a", offset);
9078 emitcode ("inc", "%s", rname);
9082 /* now some housekeeping stuff */
9085 /* we had to allocate for this iCode */
9086 if (pi) aopPut ( AOP (left), rname, 0);
9087 freeAsmop (NULL, aop, ic, TRUE);
9091 /* we did not allocate which means left
9092 already in a pointer register, then
9093 if size > 0 && this could be used again
9094 we have to point it back to where it
9096 if (AOP_SIZE (result) > 1 &&
9097 !OP_SYMBOL (left)->remat &&
9098 (OP_SYMBOL (left)->liveTo > ic->seq ||
9102 int size = AOP_SIZE (result) - 1;
9104 emitcode ("dec", "%s", rname);
9109 freeAsmop (result, NULL, ic, TRUE);
9110 if (pi) pi->generated = 1;
9113 /*-----------------------------------------------------------------*/
9114 /* genFarPointerGet - gget value from far space */
9115 /*-----------------------------------------------------------------*/
9117 genFarPointerGet (operand * left,
9118 operand * result, iCode * ic, iCode *pi)
9120 int size, offset, dopi=1;
9121 sym_link *retype = getSpec (operandType (result));
9122 sym_link *letype = getSpec (operandType (left));
9123 D (emitcode (";", "genFarPointerGet");
9126 aopOp (left, ic, FALSE, FALSE);
9128 /* if the operand is already in dptr
9129 then we do nothing else we move the value to dptr */
9130 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9132 /* if this is remateriazable */
9133 if (AOP_TYPE (left) == AOP_IMMD)
9135 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9139 /* we need to get it byte by byte */
9140 _startLazyDPSEvaluation ();
9141 if (AOP_TYPE (left) != AOP_DPTR)
9143 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9144 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9145 if (options.model == MODEL_FLAT24)
9146 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9150 /* We need to generate a load to DPTR indirect through DPTR. */
9151 D (emitcode (";", "genFarPointerGet -- indirection special case.");
9153 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
9154 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
9155 if (options.model == MODEL_FLAT24)
9156 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9157 emitcode ("pop", "dph");
9158 emitcode ("pop", "dpl");
9161 _endLazyDPSEvaluation ();
9164 /* so dptr know contains the address */
9165 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9167 /* if bit then unpack */
9168 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9169 if (AOP_INDPTRn(left)) {
9170 genSetDPTR(AOP(left)->aopu.dptr);
9172 genUnpackBits (result, "dptr", FPOINTER);
9173 if (AOP_INDPTRn(left)) {
9178 size = AOP_SIZE (result);
9181 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9183 genSetDPTR(AOP(left)->aopu.dptr);
9184 emitcode ("movx", "a,@dptr");
9185 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9186 emitcode ("inc", "dptr");
9188 aopPut (AOP (result), "a", offset++);
9191 _startLazyDPSEvaluation ();
9193 if (AOP_INDPTRn(left)) {
9194 genSetDPTR(AOP(left)->aopu.dptr);
9200 emitcode ("movx", "a,@dptr");
9201 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9202 emitcode ("inc", "dptr");
9204 aopPut (AOP (result), "a", offset++);
9206 _endLazyDPSEvaluation ();
9209 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9210 if (!AOP_INDPTRn(left)) {
9211 aopPut ( AOP (left), "dpl", 0);
9212 aopPut ( AOP (left), "dph", 1);
9213 if (options.model == MODEL_FLAT24)
9214 aopPut ( AOP (left), "dpx", 2);
9217 } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
9218 AOP_SIZE(result) > 1 &&
9219 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9221 size = AOP_SIZE (result) - 1;
9222 if (AOP_INDPTRn(left)) {
9223 genSetDPTR(AOP(left)->aopu.dptr);
9225 while (size--) emitcode ("lcall","__decdptr");
9226 if (AOP_INDPTRn(left)) {
9231 freeAsmop (left, NULL, ic, TRUE);
9232 freeAsmop (result, NULL, ic, TRUE);
9235 /*-----------------------------------------------------------------*/
9236 /* genCodePointerGet - get value from code space */
9237 /*-----------------------------------------------------------------*/
9239 genCodePointerGet (operand * left,
9240 operand * result, iCode * ic, iCode *pi)
9242 int size, offset, dopi=1;
9243 sym_link *retype = getSpec (operandType (result));
9245 aopOp (left, ic, FALSE, FALSE);
9247 /* if the operand is already in dptr
9248 then we do nothing else we move the value to dptr */
9249 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
9251 /* if this is remateriazable */
9252 if (AOP_TYPE (left) == AOP_IMMD)
9254 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9257 { /* we need to get it byte by byte */
9258 _startLazyDPSEvaluation ();
9259 if (AOP_TYPE (left) != AOP_DPTR)
9261 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9262 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9263 if (options.model == MODEL_FLAT24)
9264 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9268 /* We need to generate a load to DPTR indirect through DPTR. */
9269 D (emitcode (";", "gencodePointerGet -- indirection special case.");
9271 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
9272 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
9273 if (options.model == MODEL_FLAT24)
9274 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9275 emitcode ("pop", "dph");
9276 emitcode ("pop", "dpl");
9279 _endLazyDPSEvaluation ();
9282 /* so dptr know contains the address */
9283 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9285 /* if bit then unpack */
9286 if (IS_BITVAR (retype)) {
9287 if (AOP_INDPTRn(left)) {
9288 genSetDPTR(AOP(left)->aopu.dptr);
9290 genUnpackBits (result, "dptr", CPOINTER);
9291 if (AOP_INDPTRn(left)) {
9296 size = AOP_SIZE (result);
9298 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9300 genSetDPTR(AOP(left)->aopu.dptr);
9301 emitcode ("clr", "a");
9302 emitcode ("movc", "a,@a+dptr");
9303 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9304 emitcode ("inc", "dptr");
9306 aopPut (AOP (result), "a", offset++);
9309 _startLazyDPSEvaluation ();
9312 if (AOP_INDPTRn(left)) {
9313 genSetDPTR(AOP(left)->aopu.dptr);
9319 emitcode ("clr", "a");
9320 emitcode ("movc", "a,@a+dptr");
9321 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9322 emitcode ("inc", "dptr");
9323 aopPut (AOP (result), "a", offset++);
9325 _endLazyDPSEvaluation ();
9328 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9329 if (!AOP_INDPTRn(left)) {
9330 aopPut ( AOP (left), "dpl", 0);
9331 aopPut ( AOP (left), "dph", 1);
9332 if (options.model == MODEL_FLAT24)
9333 aopPut ( AOP (left), "dpx", 2);
9336 } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
9337 AOP_SIZE(result) > 1 &&
9338 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9340 size = AOP_SIZE (result) - 1;
9341 if (AOP_INDPTRn(left)) {
9342 genSetDPTR(AOP(left)->aopu.dptr);
9344 while (size--) emitcode ("lcall","__decdptr");
9345 if (AOP_INDPTRn(left)) {
9350 freeAsmop (left, NULL, ic, TRUE);
9351 freeAsmop (result, NULL, ic, TRUE);
9354 /*-----------------------------------------------------------------*/
9355 /* genGenPointerGet - gget value from generic pointer space */
9356 /*-----------------------------------------------------------------*/
9358 genGenPointerGet (operand * left,
9359 operand * result, iCode * ic, iCode * pi)
9362 sym_link *retype = getSpec (operandType (result));
9363 sym_link *letype = getSpec (operandType (left));
9365 D (emitcode (";", "genGenPointerGet "); );
9367 aopOp (left, ic, FALSE, (OP_SYMBOL(left)->ruonly ? FALSE : TRUE));
9369 /* if the operand is already in dptr
9370 then we do nothing else we move the value to dptr */
9371 if (AOP_TYPE (left) != AOP_STR)
9373 /* if this is remateriazable */
9374 if (AOP_TYPE (left) == AOP_IMMD)
9376 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9377 if (AOP(left)->aopu.aop_immd.from_cast_remat)
9378 emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, FALSE));
9380 emitcode ("mov", "b,#%d", pointerCode (retype));
9383 { /* we need to get it byte by byte */
9384 _startLazyDPSEvaluation ();
9385 #if 1 // I see no point at all to this code and will likely yank it soon.
9386 if (AOP(left)->type==AOP_DPTR2) {
9388 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
9391 emitcode ("mov", "dpl,%s", l);
9392 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
9395 emitcode ("mov", "dph,%s", l);
9396 if (options.model == MODEL_FLAT24) {
9397 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
9400 emitcode ("mov", "dpx,%s", l);
9401 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9403 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9409 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
9410 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
9411 if (options.model == MODEL_FLAT24) {
9412 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9413 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9415 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9418 _endLazyDPSEvaluation ();
9421 /* so dptr know contains the address */
9422 aopOp (result, ic, FALSE, TRUE);
9424 /* if bit then unpack */
9425 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9426 genUnpackBits (result, "dptr", GPOINTER);
9429 size = AOP_SIZE (result);
9434 emitcode ("lcall", "__gptrget");
9435 aopPut (AOP (result), "a", offset++);
9436 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9437 emitcode ("inc", "dptr");
9441 if (pi && AOP_TYPE (left) != AOP_IMMD) {
9442 aopPut ( AOP (left), "dpl", 0);
9443 aopPut ( AOP (left), "dph", 1);
9444 if (options.model == MODEL_FLAT24) {
9445 aopPut ( AOP (left), "dpx", 2);
9446 aopPut ( AOP (left), "b", 3);
9447 } else aopPut ( AOP (left), "b", 2);
9449 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9450 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9452 size = AOP_SIZE (result) - 1;
9453 while (size--) emitcode ("lcall","__decdptr");
9456 freeAsmop (left, NULL, ic, TRUE);
9457 freeAsmop (result, NULL, ic, TRUE);
9460 /*-----------------------------------------------------------------*/
9461 /* genPointerGet - generate code for pointer get */
9462 /*-----------------------------------------------------------------*/
9464 genPointerGet (iCode * ic, iCode *pi)
9466 operand *left, *result;
9467 sym_link *type, *etype;
9470 D (emitcode (";", "genPointerGet ");
9473 left = IC_LEFT (ic);
9474 result = IC_RESULT (ic);
9476 /* depending on the type of pointer we need to
9477 move it to the correct pointer register */
9478 type = operandType (left);
9479 etype = getSpec (type);
9480 /* if left is of type of pointer then it is simple */
9481 if (IS_PTR (type) && !IS_FUNC (type->next))
9482 p_type = DCL_TYPE (type);
9485 /* we have to go by the storage class */
9486 p_type = PTR_TYPE (SPEC_OCLS (etype));
9488 /* special case when cast remat */
9489 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9490 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9491 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9492 type = operandType (left);
9493 p_type = DCL_TYPE (type);
9495 /* now that we have the pointer type we assign
9496 the pointer values */
9502 genNearPointerGet (left, result, ic, pi);
9506 genPagedPointerGet (left, result, ic, pi);
9510 genFarPointerGet (left, result, ic, pi);
9514 genCodePointerGet (left, result, ic, pi);
9518 genGenPointerGet (left, result, ic, pi);
9524 /*-----------------------------------------------------------------*/
9525 /* genPackBits - generates code for packed bit storage */
9526 /*-----------------------------------------------------------------*/
9528 genPackBits (sym_link * etype,
9530 char *rname, int p_type)
9538 blen = SPEC_BLEN (etype);
9539 bstr = SPEC_BSTR (etype);
9541 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9544 /* if the bit lenth is less than or */
9545 /* it exactly fits a byte then */
9546 if (SPEC_BLEN (etype) <= 8)
9548 shCount = SPEC_BSTR (etype);
9550 /* shift left acc */
9553 if (SPEC_BLEN (etype) < 8)
9554 { /* if smaller than a byte */
9560 emitcode ("mov", "b,a");
9561 emitcode ("mov", "a,@%s", rname);
9565 emitcode ("mov", "b,a");
9566 emitcode ("movx", "a,@dptr");
9570 emitcode ("push", "b");
9571 emitcode ("push", "acc");
9572 emitcode ("lcall", "__gptrget");
9573 emitcode ("pop", "b");
9577 emitcode ("anl", "a,#!constbyte", (unsigned char)
9578 ((unsigned char) (0xFF << (blen + bstr)) |
9579 (unsigned char) (0xFF >> (8 - bstr))));
9580 emitcode ("orl", "a,b");
9581 if (p_type == GPOINTER)
9582 emitcode ("pop", "b");
9589 emitcode ("mov", "@%s,a", rname);
9593 emitcode ("movx", "@dptr,a");
9597 emitcode ("lcall", "__gptrput");
9602 if (SPEC_BLEN (etype) <= 8)
9605 emitcode ("inc", "%s", rname);
9606 rLen = SPEC_BLEN (etype);
9608 /* now generate for lengths greater than one byte */
9612 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
9624 emitcode ("mov", "@%s,a", rname);
9627 emitcode ("mov", "@%s,%s", rname, l);
9632 emitcode ("movx", "@dptr,a");
9637 emitcode ("lcall", "__gptrput");
9640 emitcode ("inc", "%s", rname);
9645 /* last last was not complete */
9648 /* save the byte & read byte */
9652 emitcode ("mov", "b,a");
9653 emitcode ("mov", "a,@%s", rname);
9657 emitcode ("mov", "b,a");
9658 emitcode ("movx", "a,@dptr");
9662 emitcode ("push", "b");
9663 emitcode ("push", "acc");
9664 emitcode ("lcall", "__gptrget");
9665 emitcode ("pop", "b");
9669 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1 << rLen));
9670 emitcode ("orl", "a,b");
9673 if (p_type == GPOINTER)
9674 emitcode ("pop", "b");
9680 emitcode ("mov", "@%s,a", rname);
9684 emitcode ("movx", "@dptr,a");
9688 emitcode ("lcall", "__gptrput");
9692 /*-----------------------------------------------------------------*/
9693 /* genDataPointerSet - remat pointer to data space */
9694 /*-----------------------------------------------------------------*/
9696 genDataPointerSet (operand * right,
9700 int size, offset = 0;
9701 char *l, buffer[256];
9703 aopOp (right, ic, FALSE, FALSE);
9705 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
9706 size = AOP_SIZE (right);
9710 sprintf (buffer, "(%s + %d)", l + 1, offset);
9712 sprintf (buffer, "%s", l + 1);
9713 emitcode ("mov", "%s,%s", buffer,
9714 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
9717 freeAsmop (right, NULL, ic, TRUE);
9718 freeAsmop (result, NULL, ic, TRUE);
9721 /*-----------------------------------------------------------------*/
9722 /* genNearPointerSet - emitcode for near pointer put */
9723 /*-----------------------------------------------------------------*/
9725 genNearPointerSet (operand * right,
9733 sym_link *retype, *letype;
9734 sym_link *ptype = operandType (result);
9736 retype = getSpec (operandType (right));
9737 letype = getSpec (ptype);
9739 aopOp (result, ic, FALSE, FALSE);
9741 /* if the result is rematerializable &
9742 in data space & not a bit variable */
9743 if (AOP_TYPE (result) == AOP_IMMD &&
9744 DCL_TYPE (ptype) == POINTER &&
9745 !IS_BITVAR (retype) &&
9746 !IS_BITVAR (letype))
9748 genDataPointerSet (right, result, ic);
9752 /* if the value is already in a pointer register
9753 then don't need anything more */
9754 if (!AOP_INPREG (AOP (result)))
9756 /* otherwise get a free pointer register */
9758 preg = getFreePtr (ic, &aop, FALSE);
9759 emitcode ("mov", "%s,%s",
9761 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9765 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9767 aopOp (right, ic, FALSE, FALSE);
9769 /* if bitfield then unpack the bits */
9770 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9771 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9774 /* we have can just get the values */
9775 int size = AOP_SIZE (right);
9780 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
9784 emitcode ("mov", "@%s,a", rname);
9787 emitcode ("mov", "@%s,%s", rname, l);
9789 emitcode ("inc", "%s", rname);
9794 /* now some housekeeping stuff */
9797 /* we had to allocate for this iCode */
9798 if (pi) aopPut (AOP (result),rname,0);
9799 freeAsmop (NULL, aop, ic, TRUE);
9803 /* we did not allocate which means left
9804 already in a pointer register, then
9805 if size > 0 && this could be used again
9806 we have to point it back to where it
9808 if (AOP_SIZE (right) > 1 &&
9809 !OP_SYMBOL (result)->remat &&
9810 (OP_SYMBOL (result)->liveTo > ic->seq ||
9814 int size = AOP_SIZE (right) - 1;
9816 emitcode ("dec", "%s", rname);
9821 if (pi) pi->generated = 1;
9822 freeAsmop (result, NULL, ic, TRUE);
9823 freeAsmop (right, NULL, ic, TRUE);
9828 /*-----------------------------------------------------------------*/
9829 /* genPagedPointerSet - emitcode for Paged pointer put */
9830 /*-----------------------------------------------------------------*/
9832 genPagedPointerSet (operand * right,
9840 sym_link *retype, *letype;
9842 retype = getSpec (operandType (right));
9843 letype = getSpec (operandType (result));
9845 aopOp (result, ic, FALSE, FALSE);
9847 /* if the value is already in a pointer register
9848 then don't need anything more */
9849 if (!AOP_INPREG (AOP (result)))
9851 /* otherwise get a free pointer register */
9853 preg = getFreePtr (ic, &aop, FALSE);
9854 emitcode ("mov", "%s,%s",
9856 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9860 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9862 aopOp (right, ic, FALSE, FALSE);
9864 /* if bitfield then unpack the bits */
9865 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9866 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
9869 /* we have can just get the values */
9870 int size = AOP_SIZE (right);
9875 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
9878 emitcode ("movx", "@%s,a", rname);
9881 emitcode ("inc", "%s", rname);
9887 /* now some housekeeping stuff */
9890 if (pi) aopPut (AOP (result),rname,0);
9891 /* we had to allocate for this iCode */
9892 freeAsmop (NULL, aop, ic, TRUE);
9896 /* we did not allocate which means left
9897 already in a pointer register, then
9898 if size > 0 && this could be used again
9899 we have to point it back to where it
9901 if (AOP_SIZE (right) > 1 &&
9902 !OP_SYMBOL (result)->remat &&
9903 (OP_SYMBOL (result)->liveTo > ic->seq ||
9907 int size = AOP_SIZE (right) - 1;
9909 emitcode ("dec", "%s", rname);
9914 if (pi) pi->generated = 1;
9915 freeAsmop (result, NULL, ic, TRUE);
9916 freeAsmop (right, NULL, ic, TRUE);
9921 /*-----------------------------------------------------------------*/
9922 /* genFarPointerSet - set value from far space */
9923 /*-----------------------------------------------------------------*/
9925 genFarPointerSet (operand * right,
9926 operand * result, iCode * ic, iCode *pi)
9928 int size, offset, dopi=1;
9929 sym_link *retype = getSpec (operandType (right));
9930 sym_link *letype = getSpec (operandType (result));
9932 aopOp (result, ic, FALSE, FALSE);
9934 /* if the operand is already in dptr
9935 then we do nothing else we move the value to dptr */
9936 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
9938 /* if this is remateriazable */
9939 if (AOP_TYPE (result) == AOP_IMMD)
9940 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9943 /* we need to get it byte by byte */
9944 _startLazyDPSEvaluation ();
9945 if (AOP_TYPE (result) != AOP_DPTR)
9947 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9948 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9949 if (options.model == MODEL_FLAT24)
9950 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9954 /* We need to generate a load to DPTR indirect through DPTR. */
9955 D (emitcode (";", "genFarPointerSet -- indirection special case.");
9957 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
9958 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
9959 if (options.model == MODEL_FLAT24)
9960 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9961 emitcode ("pop", "dph");
9962 emitcode ("pop", "dpl");
9965 _endLazyDPSEvaluation ();
9968 /* so dptr know contains the address */
9969 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
9971 /* if bit then unpack */
9972 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9973 if (AOP_INDPTRn(result)) {
9974 genSetDPTR(AOP(result)->aopu.dptr);
9976 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
9977 if (AOP_INDPTRn(result)) {
9981 size = AOP_SIZE (right);
9983 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
9985 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9988 genSetDPTR(AOP(result)->aopu.dptr);
9989 emitcode ("movx", "@dptr,a");
9990 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
9991 emitcode ("inc", "dptr");
9995 _startLazyDPSEvaluation ();
9997 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
10000 if (AOP_INDPTRn(result)) {
10001 genSetDPTR(AOP(result)->aopu.dptr);
10007 emitcode ("movx", "@dptr,a");
10008 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10009 emitcode ("inc", "dptr");
10011 _endLazyDPSEvaluation ();
10015 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10016 if (!AOP_INDPTRn(result)) {
10017 aopPut (AOP(result),"dpl",0);
10018 aopPut (AOP(result),"dph",1);
10019 if (options.model == MODEL_FLAT24)
10020 aopPut (AOP(result),"dpx",2);
10023 } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
10024 AOP_SIZE(right) > 1 &&
10025 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10027 size = AOP_SIZE (right) - 1;
10028 if (AOP_INDPTRn(result)) {
10029 genSetDPTR(AOP(result)->aopu.dptr);
10031 while (size--) emitcode ("lcall","__decdptr");
10032 if (AOP_INDPTRn(result)) {
10036 freeAsmop (result, NULL, ic, TRUE);
10037 freeAsmop (right, NULL, ic, TRUE);
10040 /*-----------------------------------------------------------------*/
10041 /* genGenPointerSet - set value from generic pointer space */
10042 /*-----------------------------------------------------------------*/
10044 genGenPointerSet (operand * right,
10045 operand * result, iCode * ic, iCode *pi)
10048 sym_link *retype = getSpec (operandType (right));
10049 sym_link *letype = getSpec (operandType (result));
10051 aopOp (result, ic, FALSE, OP_SYMBOL(result)->ruonly ? FALSE : TRUE);
10053 /* if the operand is already in dptr
10054 then we do nothing else we move the value to dptr */
10055 if (AOP_TYPE (result) != AOP_STR)
10057 _startLazyDPSEvaluation ();
10058 /* if this is remateriazable */
10059 if (AOP_TYPE (result) == AOP_IMMD)
10061 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
10062 if (AOP(result)->aopu.aop_immd.from_cast_remat)
10063 emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, FALSE));
10065 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
10068 { /* we need to get it byte by byte */
10069 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
10070 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
10071 if (options.model == MODEL_FLAT24) {
10072 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
10073 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
10075 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
10078 _endLazyDPSEvaluation ();
10080 /* so dptr know contains the address */
10081 aopOp (right, ic, FALSE, TRUE);
10083 /* if bit then unpack */
10084 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10085 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
10088 size = AOP_SIZE (right);
10091 _startLazyDPSEvaluation ();
10094 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
10100 emitcode ("lcall", "__gptrput");
10101 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10102 emitcode ("inc", "dptr");
10104 _endLazyDPSEvaluation ();
10107 if (pi && AOP_TYPE (result) != AOP_IMMD) {
10108 aopPut (AOP(result),"dpl",0);
10109 aopPut (AOP(result),"dph",1);
10110 if (options.model == MODEL_FLAT24) {
10111 aopPut (AOP(result),"dpx",2);
10112 aopPut (AOP(result),"b",3);
10114 aopPut (AOP(result),"b",2);
10117 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10118 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10120 size = AOP_SIZE (right) - 1;
10121 while (size--) emitcode ("lcall","__decdptr");
10123 freeAsmop (result, NULL, ic, TRUE);
10124 freeAsmop (right, NULL, ic, TRUE);
10127 /*-----------------------------------------------------------------*/
10128 /* genPointerSet - stores the value into a pointer location */
10129 /*-----------------------------------------------------------------*/
10131 genPointerSet (iCode * ic, iCode *pi)
10133 operand *right, *result;
10134 sym_link *type, *etype;
10137 D (emitcode (";", "genPointerSet ");
10140 right = IC_RIGHT (ic);
10141 result = IC_RESULT (ic);
10143 /* depending on the type of pointer we need to
10144 move it to the correct pointer register */
10145 type = operandType (result);
10146 etype = getSpec (type);
10147 /* if left is of type of pointer then it is simple */
10148 if (IS_PTR (type) && !IS_FUNC (type->next))
10150 p_type = DCL_TYPE (type);
10154 /* we have to go by the storage class */
10155 p_type = PTR_TYPE (SPEC_OCLS (etype));
10157 /* special case when cast remat */
10158 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10159 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10160 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10161 type = operandType (result);
10162 p_type = DCL_TYPE (type);
10165 /* now that we have the pointer type we assign
10166 the pointer values */
10172 genNearPointerSet (right, result, ic, pi);
10176 genPagedPointerSet (right, result, ic, pi);
10180 genFarPointerSet (right, result, ic, pi);
10184 genGenPointerSet (right, result, ic, pi);
10188 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10189 "genPointerSet: illegal pointer type");
10194 /*-----------------------------------------------------------------*/
10195 /* genIfx - generate code for Ifx statement */
10196 /*-----------------------------------------------------------------*/
10198 genIfx (iCode * ic, iCode * popIc)
10200 operand *cond = IC_COND (ic);
10203 D (emitcode (";", "genIfx "););
10205 aopOp (cond, ic, FALSE, FALSE);
10207 /* get the value into acc */
10208 if (AOP_TYPE (cond) != AOP_CRY)
10212 /* the result is now in the accumulator */
10213 freeAsmop (cond, NULL, ic, TRUE);
10215 /* if there was something to be popped then do it */
10219 /* if the condition is a bit variable */
10220 if (isbit && IS_ITEMP (cond) &&
10222 genIfxJump (ic, SPIL_LOC (cond)->rname);
10223 else if (isbit && !IS_ITEMP (cond))
10224 genIfxJump (ic, OP_SYMBOL (cond)->rname);
10226 genIfxJump (ic, "a");
10231 /*-----------------------------------------------------------------*/
10232 /* genAddrOf - generates code for address of */
10233 /*-----------------------------------------------------------------*/
10235 genAddrOf (iCode * ic)
10237 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10240 D (emitcode (";", "genAddrOf ");
10243 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10245 /* if the operand is on the stack then we
10246 need to get the stack offset of this
10248 if (sym->onStack) {
10250 /* if 10 bit stack */
10251 if (options.stack10bit) {
10253 tsprintf(buff,"#!constbyte",(options.stack_loc >> 16) & 0xff);
10254 /* if it has an offset then we need to compute it */
10255 /* emitcode ("subb", "a,#!constbyte", */
10256 /* -((sym->stack < 0) ? */
10257 /* ((short) (sym->stack - _G.nRegsSaved)) : */
10258 /* ((short) sym->stack)) & 0xff); */
10259 /* emitcode ("mov","b,a"); */
10260 /* emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
10261 /* ((short) (sym->stack - _G.nRegsSaved)) : */
10262 /* ((short) sym->stack)) >> 8) & 0xff); */
10264 emitcode ("mov", "a,_bpx");
10265 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
10266 ((char) (sym->stack - _G.nRegsSaved)) :
10267 ((char) sym->stack )) & 0xff);
10268 emitcode ("mov", "b,a");
10269 emitcode ("mov", "a,_bpx+1");
10270 emitcode ("addc","a,#!constbyte", (((sym->stack < 0) ?
10271 ((short) (sym->stack - _G.nRegsSaved)) :
10272 ((short) sym->stack )) >> 8) & 0xff);
10273 aopPut (AOP (IC_RESULT (ic)), "b", 0);
10274 aopPut (AOP (IC_RESULT (ic)), "a", 1);
10275 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10277 /* we can just move _bp */
10278 aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10279 aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10280 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10283 /* if it has an offset then we need to compute it */
10285 emitcode ("mov", "a,_bp");
10286 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10287 aopPut (AOP (IC_RESULT (ic)), "a", 0);
10289 /* we can just move _bp */
10290 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10292 /* fill the result with zero */
10293 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10296 if (options.stack10bit && size < (FPTRSIZE - 1)) {
10298 "*** warning: pointer to stack var truncated.\n");
10303 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10309 /* object not on stack then we need the name */
10310 size = AOP_SIZE (IC_RESULT (ic));
10315 char s[SDCC_NAME_MAX];
10319 tsprintf(s,"!his",sym->rname);
10322 tsprintf(s,"!hihis",sym->rname);
10325 tsprintf(s,"!hihihis",sym->rname);
10327 default: /* should not need this (just in case) */
10328 sprintf (s, "#(%s >> %d)",
10333 sprintf (s, "#%s", sym->rname);
10334 aopPut (AOP (IC_RESULT (ic)), s, offset++);
10338 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10342 /*-----------------------------------------------------------------*/
10343 /* genArrayInit - generates code for address of */
10344 /*-----------------------------------------------------------------*/
10346 genArrayInit (iCode * ic)
10348 literalList *iLoop;
10350 int elementSize = 0, eIndex;
10351 unsigned val, lastVal;
10353 operand *left=IC_LEFT(ic);
10355 D (emitcode (";", "genArrayInit "););
10357 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10359 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10361 // Load immediate value into DPTR.
10362 emitcode("mov", "dptr, %s",
10363 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
10365 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10368 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10369 "Unexpected operand to genArrayInit.\n");
10372 // a regression because of SDCCcse.c:1.52
10373 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
10374 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
10375 if (options.model == MODEL_FLAT24)
10376 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
10380 type = operandType(IC_LEFT(ic));
10382 if (type && type->next)
10384 elementSize = getSize(type->next);
10388 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10389 "can't determine element size in genArrayInit.\n");
10393 iLoop = IC_ARRAYILIST(ic);
10398 bool firstpass = TRUE;
10400 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
10401 iLoop->count, (int)iLoop->literalValue, elementSize);
10407 symbol *tlbl = NULL;
10409 count = ix > 256 ? 256 : ix;
10413 tlbl = newiTempLabel (NULL);
10414 if (firstpass || (count & 0xff))
10416 emitcode("mov", "b, #!constbyte", count & 0xff);
10419 emitcode ("", "!tlabeldef", tlbl->key + 100);
10424 for (eIndex = 0; eIndex < elementSize; eIndex++)
10426 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10427 if (val != lastVal)
10429 emitcode("mov", "a, #!constbyte", val);
10433 emitcode("movx", "@dptr, a");
10434 emitcode("inc", "dptr");
10439 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10445 iLoop = iLoop->next;
10448 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10451 /*-----------------------------------------------------------------*/
10452 /* genFarFarAssign - assignment when both are in far space */
10453 /*-----------------------------------------------------------------*/
10455 genFarFarAssign (operand * result, operand * right, iCode * ic)
10457 int size = AOP_SIZE (right);
10459 symbol *rSym = NULL;
10463 /* quick & easy case. */
10464 D(emitcode(";","genFarFarAssign (1 byte case)"););
10465 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
10466 freeAsmop (right, NULL, ic, FALSE);
10467 /* now assign DPTR to result */
10469 aopOp(result, ic, FALSE, FALSE);
10471 aopPut(AOP(result), "a", 0);
10472 freeAsmop(result, NULL, ic, FALSE);
10476 /* See if we've got an underlying symbol to abuse. */
10477 if (IS_SYMOP(result) && OP_SYMBOL(result))
10479 if (IS_TRUE_SYMOP(result))
10481 rSym = OP_SYMBOL(result);
10483 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10485 rSym = OP_SYMBOL(result)->usl.spillLoc;
10489 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10491 /* We can use the '390 auto-toggle feature to good effect here. */
10493 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10494 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
10495 emitcode ("mov", "dptr,#%s", rSym->rname);
10496 /* DP2 = result, DP1 = right, DP1 is current. */
10499 emitcode("movx", "a,@dptr");
10500 emitcode("movx", "@dptr,a");
10503 emitcode("inc", "dptr");
10504 emitcode("inc", "dptr");
10507 emitcode("mov", "dps,#0");
10508 freeAsmop (right, NULL, ic, FALSE);
10510 some alternative code for processors without auto-toggle
10511 no time to test now, so later well put in...kpb
10512 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10513 emitcode("mov", "dps,#1"); /* Select DPTR2. */
10514 emitcode ("mov", "dptr,#%s", rSym->rname);
10515 /* DP2 = result, DP1 = right, DP1 is current. */
10519 emitcode("movx", "a,@dptr");
10521 emitcode("inc", "dptr");
10522 emitcode("inc", "dps");
10523 emitcode("movx", "@dptr,a");
10525 emitcode("inc", "dptr");
10526 emitcode("inc", "dps");
10528 emitcode("mov", "dps,#0");
10529 freeAsmop (right, NULL, ic, FALSE);
10534 D (emitcode (";", "genFarFarAssign"););
10535 aopOp (result, ic, TRUE, TRUE);
10537 _startLazyDPSEvaluation ();
10541 aopPut (AOP (result),
10542 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
10545 _endLazyDPSEvaluation ();
10546 freeAsmop (result, NULL, ic, FALSE);
10547 freeAsmop (right, NULL, ic, FALSE);
10551 /*-----------------------------------------------------------------*/
10552 /* genAssign - generate code for assignment */
10553 /*-----------------------------------------------------------------*/
10555 genAssign (iCode * ic)
10557 operand *result, *right;
10559 unsigned long lit = 0L;
10561 D (emitcode (";", "genAssign ");
10564 result = IC_RESULT (ic);
10565 right = IC_RIGHT (ic);
10567 /* if they are the same */
10568 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10571 aopOp (right, ic, FALSE, FALSE);
10573 emitcode (";", "genAssign: resultIsFar = %s",
10574 isOperandInFarSpace (result) ?
10577 /* special case both in far space */
10578 if ((AOP_TYPE (right) == AOP_DPTR ||
10579 AOP_TYPE (right) == AOP_DPTR2) &&
10580 /* IS_TRUE_SYMOP(result) && */
10581 isOperandInFarSpace (result))
10583 genFarFarAssign (result, right, ic);
10587 aopOp (result, ic, TRUE, FALSE);
10589 /* if they are the same registers */
10590 if (sameRegs (AOP (right), AOP (result)))
10593 /* if the result is a bit */
10594 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10596 /* if the right size is a literal then
10597 we know what the value is */
10598 if (AOP_TYPE (right) == AOP_LIT)
10600 if (((int) operandLitValue (right)))
10601 aopPut (AOP (result), one, 0);
10603 aopPut (AOP (result), zero, 0);
10607 /* the right is also a bit variable */
10608 if (AOP_TYPE (right) == AOP_CRY)
10610 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10611 aopPut (AOP (result), "c", 0);
10615 /* we need to or */
10617 aopPut (AOP (result), "a", 0);
10621 /* bit variables done */
10623 size = AOP_SIZE (result);
10625 if (AOP_TYPE (right) == AOP_LIT)
10626 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10629 (AOP_TYPE (result) != AOP_REG) &&
10630 (AOP_TYPE (right) == AOP_LIT) &&
10631 !IS_FLOAT (operandType (right)))
10633 _startLazyDPSEvaluation ();
10634 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10636 aopPut (AOP (result),
10637 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
10642 /* And now fill the rest with zeros. */
10645 emitcode ("clr", "a");
10649 aopPut (AOP (result), "a", offset++);
10651 _endLazyDPSEvaluation ();
10655 _startLazyDPSEvaluation ();
10658 aopPut (AOP (result),
10659 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10663 _endLazyDPSEvaluation ();
10667 freeAsmop (right, NULL, ic, FALSE);
10668 freeAsmop (result, NULL, ic, TRUE);
10671 /*-----------------------------------------------------------------*/
10672 /* genJumpTab - generates code for jump table */
10673 /*-----------------------------------------------------------------*/
10675 genJumpTab (iCode * ic)
10680 D (emitcode (";", "genJumpTab ");
10683 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10684 /* get the condition into accumulator */
10685 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
10687 /* multiply by four! */
10688 emitcode ("add", "a,acc");
10689 emitcode ("add", "a,acc");
10690 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10692 jtab = newiTempLabel (NULL);
10693 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
10694 emitcode ("jmp", "@a+dptr");
10695 emitcode ("", "!tlabeldef", jtab->key + 100);
10696 /* now generate the jump labels */
10697 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10698 jtab = setNextItem (IC_JTLABELS (ic)))
10699 emitcode ("ljmp", "!tlabel", jtab->key + 100);
10703 /*-----------------------------------------------------------------*/
10704 /* genCast - gen code for casting */
10705 /*-----------------------------------------------------------------*/
10707 genCast (iCode * ic)
10709 operand *result = IC_RESULT (ic);
10710 sym_link *ctype = operandType (IC_LEFT (ic));
10711 sym_link *rtype = operandType (IC_RIGHT (ic));
10712 operand *right = IC_RIGHT (ic);
10715 D (emitcode (";", "genCast ");
10718 /* if they are equivalent then do nothing */
10719 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10722 aopOp (right, ic, FALSE, FALSE);
10723 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
10725 /* if the result is a bit */
10726 // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10727 if (IS_BITVAR(OP_SYMBOL(result)->type))
10729 /* if the right size is a literal then
10730 we know what the value is */
10731 if (AOP_TYPE (right) == AOP_LIT)
10733 if (((int) operandLitValue (right)))
10734 aopPut (AOP (result), one, 0);
10736 aopPut (AOP (result), zero, 0);
10741 /* the right is also a bit variable */
10742 if (AOP_TYPE (right) == AOP_CRY)
10744 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10745 aopPut (AOP (result), "c", 0);
10749 /* we need to or */
10751 aopPut (AOP (result), "a", 0);
10755 /* if they are the same size : or less */
10756 if (AOP_SIZE (result) <= AOP_SIZE (right))
10759 /* if they are in the same place */
10760 if (sameRegs (AOP (right), AOP (result)))
10763 /* if they in different places then copy */
10764 size = AOP_SIZE (result);
10766 _startLazyDPSEvaluation ();
10769 aopPut (AOP (result),
10770 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10774 _endLazyDPSEvaluation ();
10779 /* if the result is of type pointer */
10780 if (IS_PTR (ctype))
10784 sym_link *type = operandType (right);
10786 /* pointer to generic pointer */
10787 if (IS_GENPTR (ctype))
10791 p_type = DCL_TYPE (type);
10795 #if OLD_CAST_BEHAVIOR
10796 /* KV: we are converting a non-pointer type to
10797 * a generic pointer. This (ifdef'd out) code
10798 * says that the resulting generic pointer
10799 * should have the same class as the storage
10800 * location of the non-pointer variable.
10802 * For example, converting an int (which happens
10803 * to be stored in DATA space) to a pointer results
10804 * in a DATA generic pointer; if the original int
10805 * in XDATA space, so will be the resulting pointer.
10807 * I don't like that behavior, and thus this change:
10808 * all such conversions will be forced to XDATA and
10809 * throw a warning. If you want some non-XDATA
10810 * type, or you want to suppress the warning, you
10811 * must go through an intermediate cast, like so:
10813 * char _generic *gp = (char _xdata *)(intVar);
10815 sym_link *etype = getSpec (type);
10817 /* we have to go by the storage class */
10818 if (SPEC_OCLS (etype) != generic)
10820 p_type = PTR_TYPE (SPEC_OCLS (etype));
10825 /* Converting unknown class (i.e. register variable)
10826 * to generic pointer. This is not good, but
10827 * we'll make a guess (and throw a warning).
10830 werror (W_INT_TO_GEN_PTR_CAST);
10834 /* the first two bytes are known */
10835 size = GPTRSIZE - 1;
10837 _startLazyDPSEvaluation ();
10840 aopPut (AOP (result),
10841 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10845 _endLazyDPSEvaluation ();
10847 /* the last byte depending on type */
10849 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
10854 // pointerTypeToGPByte will have bitched.
10858 sprintf(gpValStr, "#0x%d", gpVal);
10859 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
10864 /* just copy the pointers */
10865 size = AOP_SIZE (result);
10867 _startLazyDPSEvaluation ();
10870 aopPut (AOP (result),
10871 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10875 _endLazyDPSEvaluation ();
10879 /* so we now know that the size of destination is greater
10880 than the size of the source */
10881 /* we move to result for the size of source */
10882 size = AOP_SIZE (right);
10884 _startLazyDPSEvaluation ();
10887 aopPut (AOP (result),
10888 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10892 _endLazyDPSEvaluation ();
10894 /* now depending on the sign of the source && destination */
10895 size = AOP_SIZE (result) - AOP_SIZE (right);
10896 /* if unsigned or not an integral type */
10897 /* also, if the source is a bit, we don't need to sign extend, because
10898 * it can't possibly have set the sign bit.
10900 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
10904 aopPut (AOP (result), zero, offset++);
10909 /* we need to extend the sign :{ */
10910 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
10911 FALSE, FALSE, TRUE);
10913 emitcode ("rlc", "a");
10914 emitcode ("subb", "a,acc");
10916 aopPut (AOP (result), "a", offset++);
10919 /* we are done hurray !!!! */
10922 freeAsmop (right, NULL, ic, TRUE);
10923 freeAsmop (result, NULL, ic, TRUE);
10927 /*-----------------------------------------------------------------*/
10928 /* genDjnz - generate decrement & jump if not zero instrucion */
10929 /*-----------------------------------------------------------------*/
10931 genDjnz (iCode * ic, iCode * ifx)
10933 symbol *lbl, *lbl1;
10937 /* if the if condition has a false label
10938 then we cannot save */
10939 if (IC_FALSE (ifx))
10942 /* if the minus is not of the form
10944 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10945 !IS_OP_LITERAL (IC_RIGHT (ic)))
10948 if (operandLitValue (IC_RIGHT (ic)) != 1)
10951 /* if the size of this greater than one then no
10953 if (getSize (operandType (IC_RESULT (ic))) > 1)
10956 /* otherwise we can save BIG */
10957 D(emitcode(";", "genDjnz"););
10959 lbl = newiTempLabel (NULL);
10960 lbl1 = newiTempLabel (NULL);
10962 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10964 if (AOP_NEEDSACC(IC_RESULT(ic)))
10966 /* If the result is accessed indirectly via
10967 * the accumulator, we must explicitly write
10968 * it back after the decrement.
10970 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
10972 if (strcmp(rByte, "a"))
10974 /* Something is hopelessly wrong */
10975 fprintf(stderr, "*** warning: internal error at %s:%d\n",
10976 __FILE__, __LINE__);
10977 /* We can just give up; the generated code will be inefficient,
10978 * but what the hey.
10980 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10983 emitcode ("dec", "%s", rByte);
10984 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
10985 emitcode ("jnz", "!tlabel", lbl->key + 100);
10987 else if (IS_AOP_PREG (IC_RESULT (ic)))
10989 emitcode ("dec", "%s",
10990 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10991 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10992 emitcode ("jnz", "!tlabel", lbl->key + 100);
10996 emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
10999 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11000 emitcode ("", "!tlabeldef", lbl->key + 100);
11001 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11002 emitcode ("", "!tlabeldef", lbl1->key + 100);
11004 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11005 ifx->generated = 1;
11009 /*-----------------------------------------------------------------*/
11010 /* genReceive - generate code for a receive iCode */
11011 /*-----------------------------------------------------------------*/
11013 genReceive (iCode * ic)
11016 int size = getSize (operandType (IC_RESULT (ic)));
11020 D (emitcode (";", "genReceive ");
11023 if (ic->argreg == 1) { /* first parameter */
11024 if (isOperandInFarSpace (IC_RESULT (ic)) &&
11025 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11026 IS_TRUE_SYMOP (IC_RESULT (ic))))
11028 offset = fReturnSizeDS390 - size;
11031 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
11032 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
11035 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11036 size = AOP_SIZE (IC_RESULT (ic));
11040 emitcode ("pop", "acc");
11041 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
11046 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11048 assignResultValue (IC_RESULT (ic));
11050 } else { /* second receive onwards */
11051 /* this gets a little tricky since unused recevies will be
11052 eliminated, we have saved the reg in the type field . and
11053 we use that to figure out which register to use */
11054 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11055 rb1off = ic->argreg;
11057 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11061 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11064 /*-----------------------------------------------------------------*/
11065 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
11066 /*-----------------------------------------------------------------*/
11067 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11069 operand *from , *to , *count;
11074 /* we know it has to be 3 parameters */
11075 assert (nparms == 3);
11077 rsave = newBitVect(16);
11078 /* save DPTR if it needs to be saved */
11079 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11080 if (bitVectBitValue(ic->rMask,i))
11081 rsave = bitVectSetBit(rsave,i);
11083 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11084 ds390_rUmaskForOp (IC_RESULT(ic))));
11091 aopOp (from, ic->next, FALSE, FALSE);
11093 /* get from into DPTR1 */
11094 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
11095 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
11096 if (options.model == MODEL_FLAT24) {
11097 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
11100 freeAsmop (from, NULL, ic, FALSE);
11101 aopOp (to, ic, FALSE, FALSE);
11102 /* get "to" into DPTR */
11103 /* if the operand is already in dptr
11104 then we do nothing else we move the value to dptr */
11105 if (AOP_TYPE (to) != AOP_STR) {
11106 /* if already in DPTR then we need to push */
11107 if (AOP_TYPE(to) == AOP_DPTR) {
11108 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11109 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11110 if (options.model == MODEL_FLAT24)
11111 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11112 emitcode ("pop", "dph");
11113 emitcode ("pop", "dpl");
11115 _startLazyDPSEvaluation ();
11116 /* if this is remateriazable */
11117 if (AOP_TYPE (to) == AOP_IMMD) {
11118 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11119 } else { /* we need to get it byte by byte */
11120 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11121 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11122 if (options.model == MODEL_FLAT24) {
11123 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11126 _endLazyDPSEvaluation ();
11129 freeAsmop (to, NULL, ic, FALSE);
11130 _G.dptrInUse = _G.dptr1InUse = 1;
11131 aopOp (count, ic->next->next, FALSE,FALSE);
11132 lbl =newiTempLabel(NULL);
11134 /* now for the actual copy */
11135 if (AOP_TYPE(count) == AOP_LIT &&
11136 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11137 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11139 emitcode ("lcall","__bi_memcpyc2x_s");
11141 emitcode ("lcall","__bi_memcpyx2x_s");
11143 freeAsmop (count, NULL, ic, FALSE);
11145 symbol *lbl1 = newiTempLabel(NULL);
11147 emitcode (";"," Auto increment but no djnz");
11148 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11149 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11150 freeAsmop (count, NULL, ic, FALSE);
11151 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11152 emitcode ("","!tlabeldef",lbl->key+100);
11154 emitcode ("clr","a");
11155 emitcode ("movc", "a,@a+dptr");
11157 emitcode ("movx", "a,@dptr");
11158 emitcode ("movx", "@dptr,a");
11159 emitcode ("inc", "dptr");
11160 emitcode ("inc", "dptr");
11161 emitcode ("mov","a,b");
11162 emitcode ("orl","a,_ap");
11163 emitcode ("jz","!tlabel",lbl1->key+100);
11164 emitcode ("mov","a,_ap");
11165 emitcode ("add","a,#!constbyte",0xFF);
11166 emitcode ("mov","_ap,a");
11167 emitcode ("mov","a,b");
11168 emitcode ("addc","a,#!constbyte",0xFF);
11169 emitcode ("mov","b,a");
11170 emitcode ("sjmp","!tlabel",lbl->key+100);
11171 emitcode ("","!tlabeldef",lbl1->key+100);
11173 emitcode ("mov", "dps,#0");
11174 _G.dptrInUse = _G.dptr1InUse = 0;
11175 unsavermask(rsave);
11179 /*-----------------------------------------------------------------*/
11180 /* genMemcmpX2X - gen code for memcmp xdata to xdata */
11181 /*-----------------------------------------------------------------*/
11182 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11184 operand *from , *to , *count;
11189 /* we know it has to be 3 parameters */
11190 assert (nparms == 3);
11192 rsave = newBitVect(16);
11193 /* save DPTR if it needs to be saved */
11194 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11195 if (bitVectBitValue(ic->rMask,i))
11196 rsave = bitVectSetBit(rsave,i);
11198 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11199 ds390_rUmaskForOp (IC_RESULT(ic))));
11206 aopOp (from, ic->next, FALSE, FALSE);
11208 /* get from into DPTR1 */
11209 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
11210 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
11211 if (options.model == MODEL_FLAT24) {
11212 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
11215 freeAsmop (from, NULL, ic, FALSE);
11216 aopOp (to, ic, FALSE, FALSE);
11217 /* get "to" into DPTR */
11218 /* if the operand is already in dptr
11219 then we do nothing else we move the value to dptr */
11220 if (AOP_TYPE (to) != AOP_STR) {
11221 /* if already in DPTR then we need to push */
11222 if (AOP_TYPE(to) == AOP_DPTR) {
11223 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11224 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11225 if (options.model == MODEL_FLAT24)
11226 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11227 emitcode ("pop", "dph");
11228 emitcode ("pop", "dpl");
11230 _startLazyDPSEvaluation ();
11231 /* if this is remateriazable */
11232 if (AOP_TYPE (to) == AOP_IMMD) {
11233 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11234 } else { /* we need to get it byte by byte */
11235 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11236 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11237 if (options.model == MODEL_FLAT24) {
11238 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11241 _endLazyDPSEvaluation ();
11244 freeAsmop (to, NULL, ic, FALSE);
11245 _G.dptrInUse = _G.dptr1InUse = 1;
11246 aopOp (count, ic->next->next, FALSE,FALSE);
11247 lbl =newiTempLabel(NULL);
11248 lbl2 =newiTempLabel(NULL);
11250 /* now for the actual compare */
11251 if (AOP_TYPE(count) == AOP_LIT &&
11252 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11253 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11255 emitcode("lcall","__bi_memcmpc2x_s");
11257 emitcode("lcall","__bi_memcmpx2x_s");
11258 freeAsmop (count, NULL, ic, FALSE);
11259 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11260 aopPut(AOP(IC_RESULT(ic)),"a",0);
11261 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11263 symbol *lbl1 = newiTempLabel(NULL);
11265 emitcode("push","ar0");
11266 emitcode (";"," Auto increment but no djnz");
11267 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11268 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11269 freeAsmop (count, NULL, ic, FALSE);
11270 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11271 emitcode ("","!tlabeldef",lbl->key+100);
11273 emitcode ("clr","a");
11274 emitcode ("movc", "a,@a+dptr");
11276 emitcode ("movx", "a,@dptr");
11277 emitcode ("mov","r0,a");
11278 emitcode ("movx", "a,@dptr");
11279 emitcode ("clr","c");
11280 emitcode ("subb","a,r0");
11281 emitcode ("jnz","!tlabel",lbl2->key+100);
11282 emitcode ("inc", "dptr");
11283 emitcode ("inc", "dptr");
11284 emitcode ("mov","a,b");
11285 emitcode ("orl","a,_ap");
11286 emitcode ("jz","!tlabel",lbl1->key+100);
11287 emitcode ("mov","a,_ap");
11288 emitcode ("add","a,#!constbyte",0xFF);
11289 emitcode ("mov","_ap,a");
11290 emitcode ("mov","a,b");
11291 emitcode ("addc","a,#!constbyte",0xFF);
11292 emitcode ("mov","b,a");
11293 emitcode ("sjmp","!tlabel",lbl->key+100);
11294 emitcode ("","!tlabeldef",lbl1->key+100);
11295 emitcode ("clr","a");
11296 emitcode ("","!tlabeldef",lbl2->key+100);
11297 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11298 aopPut(AOP(IC_RESULT(ic)),"a",0);
11299 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11300 emitcode("pop","ar0");
11301 emitcode ("mov", "dps,#0");
11303 _G.dptrInUse = _G.dptr1InUse = 0;
11304 unsavermask(rsave);
11308 /*-----------------------------------------------------------------*/
11309 /* genInp - gen code for __builtin_inp read data from a mem mapped */
11310 /* port, first parameter output area second parameter pointer to */
11311 /* port third parameter count */
11312 /*-----------------------------------------------------------------*/
11313 static void genInp( iCode *ic, int nparms, operand **parms)
11315 operand *from , *to , *count;
11320 /* we know it has to be 3 parameters */
11321 assert (nparms == 3);
11323 rsave = newBitVect(16);
11324 /* save DPTR if it needs to be saved */
11325 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11326 if (bitVectBitValue(ic->rMask,i))
11327 rsave = bitVectSetBit(rsave,i);
11329 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11330 ds390_rUmaskForOp (IC_RESULT(ic))));
11337 aopOp (from, ic->next, FALSE, FALSE);
11339 /* get from into DPTR1 */
11340 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
11341 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
11342 if (options.model == MODEL_FLAT24) {
11343 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
11346 freeAsmop (from, NULL, ic, FALSE);
11347 aopOp (to, ic, FALSE, FALSE);
11348 /* get "to" into DPTR */
11349 /* if the operand is already in dptr
11350 then we do nothing else we move the value to dptr */
11351 if (AOP_TYPE (to) != AOP_STR) {
11352 /* if already in DPTR then we need to push */
11353 if (AOP_TYPE(to) == AOP_DPTR) {
11354 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11355 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11356 if (options.model == MODEL_FLAT24)
11357 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11358 emitcode ("pop", "dph");
11359 emitcode ("pop", "dpl");
11361 _startLazyDPSEvaluation ();
11362 /* if this is remateriazable */
11363 if (AOP_TYPE (to) == AOP_IMMD) {
11364 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11365 } else { /* we need to get it byte by byte */
11366 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11367 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11368 if (options.model == MODEL_FLAT24) {
11369 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11372 _endLazyDPSEvaluation ();
11375 freeAsmop (to, NULL, ic, FALSE);
11377 _G.dptrInUse = _G.dptr1InUse = 1;
11378 aopOp (count, ic->next->next, FALSE,FALSE);
11379 lbl =newiTempLabel(NULL);
11381 /* now for the actual copy */
11382 if (AOP_TYPE(count) == AOP_LIT &&
11383 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11384 emitcode (";","OH JOY auto increment with djnz (very fast)");
11385 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11386 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11387 freeAsmop (count, NULL, ic, FALSE);
11388 emitcode ("","!tlabeldef",lbl->key+100);
11389 emitcode ("movx", "a,@dptr"); /* read data from port */
11390 emitcode ("dec","dps"); /* switch to DPTR */
11391 emitcode ("movx", "@dptr,a"); /* save into location */
11392 emitcode ("inc", "dptr"); /* point to next area */
11393 emitcode ("inc","dps"); /* switch to DPTR2 */
11394 emitcode ("djnz","b,!tlabel",lbl->key+100);
11396 symbol *lbl1 = newiTempLabel(NULL);
11398 emitcode (";"," Auto increment but no djnz");
11399 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11400 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11401 freeAsmop (count, NULL, ic, FALSE);
11402 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11403 emitcode ("","!tlabeldef",lbl->key+100);
11404 emitcode ("movx", "a,@dptr");
11405 emitcode ("dec","dps"); /* switch to DPTR */
11406 emitcode ("movx", "@dptr,a");
11407 emitcode ("inc", "dptr");
11408 emitcode ("inc","dps"); /* switch to DPTR2 */
11409 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
11410 /* emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
11411 emitcode ("mov","a,b");
11412 emitcode ("orl","a,_ap");
11413 emitcode ("jz","!tlabel",lbl1->key+100);
11414 emitcode ("mov","a,_ap");
11415 emitcode ("add","a,#!constbyte",0xFF);
11416 emitcode ("mov","_ap,a");
11417 emitcode ("mov","a,b");
11418 emitcode ("addc","a,#!constbyte",0xFF);
11419 emitcode ("mov","b,a");
11420 emitcode ("sjmp","!tlabel",lbl->key+100);
11421 emitcode ("","!tlabeldef",lbl1->key+100);
11423 emitcode ("mov", "dps,#0");
11424 _G.dptrInUse = _G.dptr1InUse = 0;
11425 unsavermask(rsave);
11429 /*-----------------------------------------------------------------*/
11430 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
11431 /* port, first parameter output area second parameter pointer to */
11432 /* port third parameter count */
11433 /*-----------------------------------------------------------------*/
11434 static void genOutp( iCode *ic, int nparms, operand **parms)
11436 operand *from , *to , *count;
11441 /* we know it has to be 3 parameters */
11442 assert (nparms == 3);
11444 rsave = newBitVect(16);
11445 /* save DPTR if it needs to be saved */
11446 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11447 if (bitVectBitValue(ic->rMask,i))
11448 rsave = bitVectSetBit(rsave,i);
11450 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11451 ds390_rUmaskForOp (IC_RESULT(ic))));
11458 aopOp (from, ic->next, FALSE, FALSE);
11460 /* get from into DPTR1 */
11461 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
11462 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
11463 if (options.model == MODEL_FLAT24) {
11464 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
11467 freeAsmop (from, NULL, ic, FALSE);
11468 aopOp (to, ic, FALSE, FALSE);
11469 /* get "to" into DPTR */
11470 /* if the operand is already in dptr
11471 then we do nothing else we move the value to dptr */
11472 if (AOP_TYPE (to) != AOP_STR) {
11473 /* if already in DPTR then we need to push */
11474 if (AOP_TYPE(to) == AOP_DPTR) {
11475 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11476 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11477 if (options.model == MODEL_FLAT24)
11478 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11479 emitcode ("pop", "dph");
11480 emitcode ("pop", "dpl");
11482 _startLazyDPSEvaluation ();
11483 /* if this is remateriazable */
11484 if (AOP_TYPE (to) == AOP_IMMD) {
11485 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11486 } else { /* we need to get it byte by byte */
11487 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11488 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11489 if (options.model == MODEL_FLAT24) {
11490 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11493 _endLazyDPSEvaluation ();
11496 freeAsmop (to, NULL, ic, FALSE);
11498 _G.dptrInUse = _G.dptr1InUse = 1;
11499 aopOp (count, ic->next->next, FALSE,FALSE);
11500 lbl =newiTempLabel(NULL);
11502 /* now for the actual copy */
11503 if (AOP_TYPE(count) == AOP_LIT &&
11504 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11505 emitcode (";","OH JOY auto increment with djnz (very fast)");
11506 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
11507 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11508 emitcode ("","!tlabeldef",lbl->key+100);
11509 emitcode ("movx", "a,@dptr"); /* read data from port */
11510 emitcode ("inc","dps"); /* switch to DPTR2 */
11511 emitcode ("movx", "@dptr,a"); /* save into location */
11512 emitcode ("inc", "dptr"); /* point to next area */
11513 emitcode ("dec","dps"); /* switch to DPTR */
11514 emitcode ("djnz","b,!tlabel",lbl->key+100);
11515 freeAsmop (count, NULL, ic, FALSE);
11517 symbol *lbl1 = newiTempLabel(NULL);
11519 emitcode (";"," Auto increment but no djnz");
11520 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11521 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11522 freeAsmop (count, NULL, ic, FALSE);
11523 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
11524 emitcode ("","!tlabeldef",lbl->key+100);
11525 emitcode ("movx", "a,@dptr");
11526 emitcode ("inc", "dptr");
11527 emitcode ("inc","dps"); /* switch to DPTR2 */
11528 emitcode ("movx", "@dptr,a");
11529 emitcode ("dec","dps"); /* switch to DPTR */
11530 emitcode ("mov","a,b");
11531 emitcode ("orl","a,_ap");
11532 emitcode ("jz","!tlabel",lbl1->key+100);
11533 emitcode ("mov","a,_ap");
11534 emitcode ("add","a,#!constbyte",0xFF);
11535 emitcode ("mov","_ap,a");
11536 emitcode ("mov","a,b");
11537 emitcode ("addc","a,#!constbyte",0xFF);
11538 emitcode ("mov","b,a");
11539 emitcode ("sjmp","!tlabel",lbl->key+100);
11540 emitcode ("","!tlabeldef",lbl1->key+100);
11542 emitcode ("mov", "dps,#0");
11543 _G.dptrInUse = _G.dptr1InUse = 0;
11544 unsavermask(rsave);
11548 /*-----------------------------------------------------------------*/
11549 /* genSwapW - swap lower & high order bytes */
11550 /*-----------------------------------------------------------------*/
11551 static void genSwapW(iCode *ic, int nparms, operand **parms)
11555 assert (nparms==1);
11558 dest=IC_RESULT(ic);
11560 assert(getSize(operandType(src))==2);
11562 aopOp (src, ic, FALSE, FALSE);
11563 emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,TRUE));
11565 emitcode ("mov","b,%s",aopGet(AOP(src),1,FALSE,FALSE,FALSE));
11567 freeAsmop (src, NULL, ic, FALSE);
11569 aopOp (dest,ic, FALSE, FALSE);
11570 aopPut(AOP(dest),"b",0);
11571 aopPut(AOP(dest),"a",1);
11572 freeAsmop (dest, NULL, ic, FALSE);
11575 /*-----------------------------------------------------------------*/
11576 /* genMemsetX - gencode for memSetX data */
11577 /*-----------------------------------------------------------------*/
11578 static void genMemsetX(iCode *ic, int nparms, operand **parms)
11580 operand *to , *val , *count;
11584 bitVect *rsave = NULL;
11586 /* we know it has to be 3 parameters */
11587 assert (nparms == 3);
11593 /* save DPTR if it needs to be saved */
11594 rsave = newBitVect(16);
11595 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11596 if (bitVectBitValue(ic->rMask,i))
11597 rsave = bitVectSetBit(rsave,i);
11599 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11600 ds390_rUmaskForOp (IC_RESULT(ic))));
11603 aopOp (to, ic, FALSE, FALSE);
11604 /* get "to" into DPTR */
11605 /* if the operand is already in dptr
11606 then we do nothing else we move the value to dptr */
11607 if (AOP_TYPE (to) != AOP_STR) {
11608 /* if already in DPTR then we need to push */
11609 if (AOP_TYPE(to) == AOP_DPTR) {
11610 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11611 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11612 if (options.model == MODEL_FLAT24)
11613 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11614 emitcode ("pop", "dph");
11615 emitcode ("pop", "dpl");
11617 _startLazyDPSEvaluation ();
11618 /* if this is remateriazable */
11619 if (AOP_TYPE (to) == AOP_IMMD) {
11620 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11621 } else { /* we need to get it byte by byte */
11622 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11623 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11624 if (options.model == MODEL_FLAT24) {
11625 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11628 _endLazyDPSEvaluation ();
11631 freeAsmop (to, NULL, ic, FALSE);
11633 aopOp (val, ic->next->next, FALSE,FALSE);
11634 aopOp (count, ic->next->next, FALSE,FALSE);
11635 lbl =newiTempLabel(NULL);
11636 /* now for the actual copy */
11637 if (AOP_TYPE(count) == AOP_LIT &&
11638 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11639 l = aopGet(AOP (val), 0, FALSE, FALSE, TRUE);
11640 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11642 emitcode ("","!tlabeldef",lbl->key+100);
11643 emitcode ("movx", "@dptr,a");
11644 emitcode ("inc", "dptr");
11645 emitcode ("djnz","b,!tlabel",lbl->key+100);
11647 symbol *lbl1 = newiTempLabel(NULL);
11649 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11650 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11651 emitcode ("","!tlabeldef",lbl->key+100);
11652 l = aopGet(AOP (val), 0, FALSE, FALSE, TRUE);
11654 emitcode ("movx", "@dptr,a");
11655 emitcode ("inc", "dptr");
11656 emitcode ("mov","a,b");
11657 emitcode ("orl","a,_ap");
11658 emitcode ("jz","!tlabel",lbl1->key+100);
11659 emitcode ("mov","a,_ap");
11660 emitcode ("add","a,#!constbyte",0xFF);
11661 emitcode ("mov","_ap,a");
11662 emitcode ("mov","a,b");
11663 emitcode ("addc","a,#!constbyte",0xFF);
11664 emitcode ("mov","b,a");
11665 emitcode ("sjmp","!tlabel",lbl->key+100);
11666 emitcode ("","!tlabeldef",lbl1->key+100);
11668 freeAsmop (count, NULL, ic, FALSE);
11669 unsavermask(rsave);
11672 /*-----------------------------------------------------------------*/
11673 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
11674 /*-----------------------------------------------------------------*/
11675 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
11678 operand *pnum, *result;
11681 assert (nparms==1);
11682 /* save registers that need to be saved */
11683 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11684 ds390_rUmaskForOp (IC_RESULT(ic))));
11687 aopOp (pnum, ic, FALSE, FALSE);
11688 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,FALSE));
11689 freeAsmop (pnum, NULL, ic, FALSE);
11690 emitcode ("lcall","NatLib_LoadPrimitive");
11691 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11692 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
11693 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
11694 for (i = (size-1) ; i >= 0 ; i-- ) {
11695 emitcode ("push","a%s",javaRet[i]);
11697 for (i=0; i < size ; i++ ) {
11698 emitcode ("pop","a%s",aopGet(AOP(result),i,FALSE,FALSE,FALSE));
11701 for (i = 0 ; i < size ; i++ ) {
11702 aopPut(AOP(result),javaRet[i],i);
11705 freeAsmop (result, NULL, ic, FALSE);
11706 unsavermask(rsave);
11709 /*-----------------------------------------------------------------*/
11710 /* genNatLibLoadPointer - calls TINI api function to load pointer */
11711 /*-----------------------------------------------------------------*/
11712 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
11715 operand *pnum, *result;
11719 assert (nparms==1);
11720 /* save registers that need to be saved */
11721 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11722 ds390_rUmaskForOp (IC_RESULT(ic))));
11725 aopOp (pnum, ic, FALSE, FALSE);
11726 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,FALSE));
11727 freeAsmop (pnum, NULL, ic, FALSE);
11728 emitcode ("lcall","NatLib_LoadPointer");
11729 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11730 if (AOP_TYPE(result)!=AOP_STR) {
11731 for (i = 0 ; i < size ; i++ ) {
11732 aopPut(AOP(result),fReturn[i],i);
11735 freeAsmop (result, NULL, ic, FALSE);
11736 unsavermask(rsave);
11739 /*-----------------------------------------------------------------*/
11740 /* genNatLibInstallStateBlock - */
11741 /*-----------------------------------------------------------------*/
11742 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
11743 operand **parms, const char *name)
11746 operand *psb, *handle;
11747 assert (nparms==2);
11749 /* save registers that need to be saved */
11750 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11751 ds390_rUmaskForOp (IC_RESULT(ic))));
11755 /* put pointer to state block into DPTR1 */
11756 aopOp (psb, ic, FALSE, FALSE);
11757 if (AOP_TYPE (psb) == AOP_IMMD) {
11758 emitcode ("mov","dps,#1");
11759 emitcode ("mov", "dptr,%s", aopGet (AOP (psb), 0, TRUE, FALSE, FALSE));
11760 emitcode ("mov","dps,#0");
11762 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,FALSE));
11763 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,FALSE));
11764 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,FALSE));
11766 freeAsmop (psb, NULL, ic, FALSE);
11768 /* put libraryID into DPTR */
11769 emitcode ("mov","dptr,#LibraryID");
11771 /* put handle into r3:r2 */
11772 aopOp (handle, ic, FALSE, FALSE);
11773 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11774 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11775 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11776 emitcode ("pop","ar3");
11777 emitcode ("pop","ar2");
11779 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11780 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11782 freeAsmop (psb, NULL, ic, FALSE);
11784 /* make the call */
11785 emitcode ("lcall","NatLib_Install%sStateBlock",name);
11787 /* put return value into place*/
11789 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
11791 aopPut(AOP(IC_RESULT(ic)),"a",0);
11792 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11793 unsavermask(rsave);
11796 /*-----------------------------------------------------------------*/
11797 /* genNatLibRemoveStateBlock - */
11798 /*-----------------------------------------------------------------*/
11799 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
11805 /* save registers that need to be saved */
11806 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11807 ds390_rUmaskForOp (IC_RESULT(ic))));
11809 /* put libraryID into DPTR */
11810 emitcode ("mov","dptr,#LibraryID");
11811 /* make the call */
11812 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
11813 unsavermask(rsave);
11816 /*-----------------------------------------------------------------*/
11817 /* genNatLibGetStateBlock - */
11818 /*-----------------------------------------------------------------*/
11819 static void genNatLibGetStateBlock(iCode *ic,int nparms,
11820 operand **parms,const char *name)
11823 symbol *lbl = newiTempLabel(NULL);
11826 /* save registers that need to be saved */
11827 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11828 ds390_rUmaskForOp (IC_RESULT(ic))));
11830 /* put libraryID into DPTR */
11831 emitcode ("mov","dptr,#LibraryID");
11832 /* make the call */
11833 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
11834 emitcode ("jnz","!tlabel",lbl->key+100);
11836 /* put return value into place */
11837 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
11838 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
11839 emitcode ("push","ar3");
11840 emitcode ("push","ar2");
11841 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,FALSE));
11842 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,FALSE));
11844 aopPut(AOP(IC_RESULT(ic)),"r2",0);
11845 aopPut(AOP(IC_RESULT(ic)),"r3",1);
11847 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11848 emitcode ("","!tlabeldef",lbl->key+100);
11849 unsavermask(rsave);
11852 /*-----------------------------------------------------------------*/
11853 /* genMMMalloc - */
11854 /*-----------------------------------------------------------------*/
11855 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
11856 int size, const char *name)
11861 symbol *lbl = newiTempLabel(NULL);
11863 assert (nparms == 1);
11864 /* save registers that need to be saved */
11865 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11866 ds390_rUmaskForOp (IC_RESULT(ic))));
11869 aopOp (bsize,ic,FALSE,FALSE);
11871 /* put the size in R4-R2 */
11872 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
11873 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,FALSE));
11874 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,FALSE));
11876 emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,FALSE));
11877 emitcode("pop","ar4");
11879 emitcode("pop","ar3");
11880 emitcode("pop","ar2");
11882 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,FALSE));
11883 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,FALSE));
11885 emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,FALSE));
11888 freeAsmop (bsize, NULL, ic, FALSE);
11890 /* make the call */
11891 emitcode ("lcall","MM_%s",name);
11892 emitcode ("jz","!tlabel",lbl->key+100);
11893 emitcode ("mov","r2,#!constbyte",0xff);
11894 emitcode ("mov","r3,#!constbyte",0xff);
11895 emitcode ("","!tlabeldef",lbl->key+100);
11896 /* we don't care about the pointer : we just save the handle */
11897 rsym = OP_SYMBOL(IC_RESULT(ic));
11898 if (rsym->liveFrom != rsym->liveTo) {
11899 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
11900 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
11901 emitcode ("push","ar3");
11902 emitcode ("push","ar2");
11903 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,FALSE));
11904 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,FALSE));
11906 aopPut(AOP(IC_RESULT(ic)),"r2",0);
11907 aopPut(AOP(IC_RESULT(ic)),"r3",1);
11909 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11911 unsavermask(rsave);
11914 /*-----------------------------------------------------------------*/
11916 /*-----------------------------------------------------------------*/
11917 static void genMMDeref (iCode *ic,int nparms, operand **parms)
11922 assert (nparms == 1);
11923 /* save registers that need to be saved */
11924 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11925 ds390_rUmaskForOp (IC_RESULT(ic))));
11928 aopOp (handle,ic,FALSE,FALSE);
11930 /* put the size in R4-R2 */
11931 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11932 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11933 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11934 emitcode("pop","ar3");
11935 emitcode("pop","ar2");
11937 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11938 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11940 freeAsmop (handle, NULL, ic, FALSE);
11942 /* make the call */
11943 emitcode ("lcall","MM_Deref");
11946 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11947 if (rsym->liveFrom != rsym->liveTo) {
11948 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11949 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
11950 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
11951 aopPut(AOP(IC_RESULT(ic)),"dph",1);
11952 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
11956 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11957 unsavermask(rsave);
11960 /*-----------------------------------------------------------------*/
11961 /* genMMUnrestrictedPersist - */
11962 /*-----------------------------------------------------------------*/
11963 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
11968 assert (nparms == 1);
11969 /* save registers that need to be saved */
11970 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11971 ds390_rUmaskForOp (IC_RESULT(ic))));
11974 aopOp (handle,ic,FALSE,FALSE);
11976 /* put the size in R3-R2 */
11977 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11978 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11979 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11980 emitcode("pop","ar3");
11981 emitcode("pop","ar2");
11983 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11984 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11986 freeAsmop (handle, NULL, ic, FALSE);
11988 /* make the call */
11989 emitcode ("lcall","MM_UnrestrictedPersist");
11992 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11993 if (rsym->liveFrom != rsym->liveTo) {
11994 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11995 aopPut(AOP(IC_RESULT(ic)),"a",0);
11996 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11999 unsavermask(rsave);
12002 /*-----------------------------------------------------------------*/
12003 /* genSystemExecJavaProcess - */
12004 /*-----------------------------------------------------------------*/
12005 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12008 operand *handle, *pp;
12010 assert (nparms==2);
12011 /* save registers that need to be saved */
12012 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12013 ds390_rUmaskForOp (IC_RESULT(ic))));
12018 /* put the handle in R3-R2 */
12019 aopOp (handle,ic,FALSE,FALSE);
12020 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12021 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
12022 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
12023 emitcode("pop","ar3");
12024 emitcode("pop","ar2");
12026 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
12027 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
12029 freeAsmop (handle, NULL, ic, FALSE);
12031 /* put pointer in DPTR */
12032 aopOp (pp,ic,FALSE,FALSE);
12033 if (AOP_TYPE(pp) == AOP_IMMD) {
12034 emitcode ("mov", "dptr,%s", aopGet (AOP (pp), 0, TRUE, FALSE, FALSE));
12035 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12036 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,FALSE));
12037 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,FALSE));
12038 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,FALSE));
12040 freeAsmop (handle, NULL, ic, FALSE);
12042 /* make the call */
12043 emitcode ("lcall","System_ExecJavaProcess");
12045 /* put result in place */
12047 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12048 if (rsym->liveFrom != rsym->liveTo) {
12049 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12050 aopPut(AOP(IC_RESULT(ic)),"a",0);
12051 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12055 unsavermask(rsave);
12058 /*-----------------------------------------------------------------*/
12059 /* genSystemRTCRegisters - */
12060 /*-----------------------------------------------------------------*/
12061 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12067 assert (nparms==1);
12068 /* save registers that need to be saved */
12069 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12070 ds390_rUmaskForOp (IC_RESULT(ic))));
12073 /* put pointer in DPTR */
12074 aopOp (pp,ic,FALSE,FALSE);
12075 if (AOP_TYPE (pp) == AOP_IMMD) {
12076 emitcode ("mov","dps,#1");
12077 emitcode ("mov", "dptr,%s", aopGet (AOP (pp), 0, TRUE, FALSE, FALSE));
12078 emitcode ("mov","dps,#0");
12080 emitcode ("mov","dpl1,%s",aopGet(AOP(pp),0,FALSE,FALSE,FALSE));
12081 emitcode ("mov","dph1,%s",aopGet(AOP(pp),1,FALSE,FALSE,FALSE));
12082 emitcode ("mov","dpx1,%s",aopGet(AOP(pp),2,FALSE,FALSE,FALSE));
12084 freeAsmop (pp, NULL, ic, FALSE);
12086 /* make the call */
12087 emitcode ("lcall","System_%sRTCRegisters",name);
12089 unsavermask(rsave);
12092 /*-----------------------------------------------------------------*/
12093 /* genSystemThreadSleep - */
12094 /*-----------------------------------------------------------------*/
12095 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12100 assert (nparms==1);
12101 /* save registers that need to be saved */
12102 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12103 ds390_rUmaskForOp (IC_RESULT(ic))));
12106 aopOp(to,ic,FALSE,FALSE);
12107 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12108 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12109 emitcode ("push","%s",aopGet(AOP(to),0,FALSE,TRUE,FALSE));
12110 emitcode ("push","%s",aopGet(AOP(to),1,FALSE,TRUE,FALSE));
12111 emitcode ("push","%s",aopGet(AOP(to),2,FALSE,TRUE,FALSE));
12112 emitcode ("push","%s",aopGet(AOP(to),3,FALSE,TRUE,FALSE));
12113 emitcode ("pop","ar3");
12114 emitcode ("pop","ar2");
12115 emitcode ("pop","ar1");
12116 emitcode ("pop","ar0");
12118 emitcode ("mov","r0,%s",aopGet(AOP(to),0,FALSE,TRUE,FALSE));
12119 emitcode ("mov","r1,%s",aopGet(AOP(to),1,FALSE,TRUE,FALSE));
12120 emitcode ("mov","r2,%s",aopGet(AOP(to),2,FALSE,TRUE,FALSE));
12121 emitcode ("mov","r3,%s",aopGet(AOP(to),3,FALSE,TRUE,FALSE));
12123 freeAsmop (to, NULL, ic, FALSE);
12125 /* suspend in acc */
12127 aopOp(s,ic,FALSE,FALSE);
12128 emitcode ("mov","a,%s",aopGet(AOP(s),0,FALSE,TRUE,FALSE));
12129 freeAsmop (s, NULL, ic, FALSE);
12131 /* make the call */
12132 emitcode ("lcall","System_%s",name);
12134 unsavermask(rsave);
12137 /*-----------------------------------------------------------------*/
12138 /* genSystemThreadResume - */
12139 /*-----------------------------------------------------------------*/
12140 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12145 assert (nparms==2);
12146 /* save registers that need to be saved */
12147 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12148 ds390_rUmaskForOp (IC_RESULT(ic))));
12154 aopOp(pid,ic,FALSE,FALSE);
12155 emitcode ("mov","r0,%s",aopGet(AOP(pid),0,FALSE,TRUE,FALSE));
12156 freeAsmop (pid, NULL, ic, FALSE);
12159 aopOp(tid,ic,FALSE,FALSE);
12160 emitcode ("mov","a,%s",aopGet(AOP(tid),0,FALSE,TRUE,FALSE));
12161 freeAsmop (tid, NULL, ic, FALSE);
12163 emitcode ("lcall","System_ThreadResume");
12165 /* put result into place */
12167 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12168 if (rsym->liveFrom != rsym->liveTo) {
12169 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12170 aopPut(AOP(IC_RESULT(ic)),"a",0);
12171 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12174 unsavermask(rsave);
12177 /*-----------------------------------------------------------------*/
12178 /* genSystemProcessResume - */
12179 /*-----------------------------------------------------------------*/
12180 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
12185 assert (nparms==1);
12186 /* save registers that need to be saved */
12187 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12188 ds390_rUmaskForOp (IC_RESULT(ic))));
12193 aopOp(pid,ic,FALSE,FALSE);
12194 emitcode ("mov","a,%s",aopGet(AOP(pid),0,FALSE,TRUE,FALSE));
12195 freeAsmop (pid, NULL, ic, FALSE);
12197 emitcode ("lcall","System_ProcessResume");
12199 unsavermask(rsave);
12202 /*-----------------------------------------------------------------*/
12204 /*-----------------------------------------------------------------*/
12205 static void genSystem (iCode *ic,int nparms,char *name)
12207 assert(nparms == 0);
12209 emitcode ("lcall","System_%s",name);
12212 /*-----------------------------------------------------------------*/
12213 /* genSystemPoll - */
12214 /*-----------------------------------------------------------------*/
12215 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
12220 assert (nparms==1);
12221 /* save registers that need to be saved */
12222 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12223 ds390_rUmaskForOp (IC_RESULT(ic))));
12226 aopOp (fp,ic,FALSE,FALSE);
12227 if (AOP_TYPE (fp) == AOP_IMMD) {
12228 emitcode ("mov", "dptr,%s", aopGet (AOP (fp), 0, TRUE, FALSE, FALSE));
12229 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
12230 emitcode ("mov","dpl,%s",aopGet(AOP(fp),0,FALSE,FALSE,FALSE));
12231 emitcode ("mov","dph,%s",aopGet(AOP(fp),1,FALSE,FALSE,FALSE));
12232 emitcode ("mov","dpx,%s",aopGet(AOP(fp),2,FALSE,FALSE,FALSE));
12234 freeAsmop (fp, NULL, ic, FALSE);
12236 emitcode ("lcall","System_%sPoll",name);
12238 /* put result into place */
12240 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12241 if (rsym->liveFrom != rsym->liveTo) {
12242 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12243 aopPut(AOP(IC_RESULT(ic)),"a",0);
12244 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12247 unsavermask(rsave);
12250 /*-----------------------------------------------------------------*/
12251 /* genSystemGetCurrentID - */
12252 /*-----------------------------------------------------------------*/
12253 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
12255 assert (nparms==0);
12257 emitcode ("lcall","System_GetCurrent%sId",name);
12258 /* put result into place */
12260 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12261 if (rsym->liveFrom != rsym->liveTo) {
12262 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12263 aopPut(AOP(IC_RESULT(ic)),"a",0);
12264 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12269 /*-----------------------------------------------------------------*/
12270 /* genBuiltIn - calls the appropriate function to generating code */
12271 /* for a built in function */
12272 /*-----------------------------------------------------------------*/
12273 static void genBuiltIn (iCode *ic)
12275 operand *bi_parms[MAX_BUILTIN_ARGS];
12280 /* get all the arguments for a built in function */
12281 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
12283 /* which function is it */
12284 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
12285 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
12286 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
12287 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
12288 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
12289 } else if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
12290 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
12291 } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
12292 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
12293 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
12294 genMemsetX(bi_iCode,nbi_parms,bi_parms);
12295 } else if (strcmp(bif->name,"__builtin_inp")==0) {
12296 genInp(bi_iCode,nbi_parms,bi_parms);
12297 } else if (strcmp(bif->name,"__builtin_outp")==0) {
12298 genOutp(bi_iCode,nbi_parms,bi_parms);
12299 } else if (strcmp(bif->name,"__builtin_swapw")==0) {
12300 genSwapW(bi_iCode,nbi_parms,bi_parms);
12301 /* JavaNative builtIns */
12302 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
12303 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
12304 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
12305 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
12306 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
12307 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
12308 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
12309 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
12310 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
12311 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12312 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
12313 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12314 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
12315 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
12316 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
12317 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
12318 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
12319 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12320 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
12321 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12322 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
12323 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
12324 } else if (strcmp(bif->name,"MM_Malloc")==0) {
12325 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
12326 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
12327 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
12328 } else if (strcmp(bif->name,"MM_Free")==0) {
12329 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
12330 } else if (strcmp(bif->name,"MM_Deref")==0) {
12331 genMMDeref(bi_iCode,nbi_parms,bi_parms);
12332 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
12333 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
12334 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
12335 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
12336 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
12337 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
12338 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
12339 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
12340 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
12341 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
12342 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
12343 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
12344 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
12345 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
12346 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
12347 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
12348 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12349 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12350 } else if (strcmp(bif->name,"System_SaveThread")==0) {
12351 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12352 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12353 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12354 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
12355 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
12356 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
12357 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
12358 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
12359 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
12360 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
12361 genSystem(bi_iCode,nbi_parms,"ProcessYield");
12362 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
12363 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
12364 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
12365 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
12366 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
12367 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
12368 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
12369 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
12370 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
12371 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
12373 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
12379 /*-----------------------------------------------------------------*/
12380 /* gen390Code - generate code for Dallas 390 based controllers */
12381 /*-----------------------------------------------------------------*/
12383 gen390Code (iCode * lic)
12388 lineHead = lineCurr = NULL;
12389 dptrn[1][0] = "dpl1";
12390 dptrn[1][1] = "dph1";
12391 dptrn[1][2] = "dpx1";
12393 if (options.model == MODEL_FLAT24) {
12394 fReturnSizeDS390 = 5;
12395 fReturn = fReturn24;
12397 fReturnSizeDS390 = 4;
12398 fReturn = fReturn16;
12399 options.stack10bit=0;
12402 /* print the allocation information */
12404 printAllocInfo (currFunc, codeOutFile);
12406 /* if debug information required */
12407 if (options.debug && currFunc)
12409 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
12411 if (IS_STATIC (currFunc->etype))
12412 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
12414 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
12417 /* stack pointer name */
12418 if (options.useXstack)
12424 for (ic = lic; ic; ic = ic->next)
12427 if (ic->lineno && cln != ic->lineno)
12432 emitcode ("", "C$%s$%d$%d$%d ==.",
12433 FileBaseName (ic->filename), ic->lineno,
12434 ic->level, ic->block);
12437 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
12438 printCLine(ic->filename, ic->lineno));
12441 /* if the result is marked as
12442 spilt and rematerializable or code for
12443 this has already been generated then
12445 if (resultRemat (ic) || ic->generated)
12448 /* depending on the operation */
12468 /* IPOP happens only when trying to restore a
12469 spilt live range, if there is an ifx statement
12470 following this pop then the if statement might
12471 be using some of the registers being popped which
12472 would destory the contents of the register so
12473 we need to check for this condition and handle it */
12475 ic->next->op == IFX &&
12476 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
12477 genIfx (ic->next, ic);
12495 genEndFunction (ic);
12515 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
12532 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
12536 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
12543 /* note these two are xlated by algebraic equivalence
12544 during parsing SDCC.y */
12545 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12546 "got '>=' or '<=' shouldn't have come here");
12550 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
12562 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
12566 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
12570 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
12594 genRightShift (ic);
12597 case GET_VALUE_AT_ADDRESS:
12598 genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
12602 if (POINTER_SET (ic))
12603 genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
12629 if (ic->builtinSEND) genBuiltIn(ic);
12630 else addSet (&_G.sendSet, ic);
12643 /* now we are ready to call the
12644 peep hole optimizer */
12645 if (!options.nopeep)
12646 peepHole (&lineHead);
12648 /* now do the actual printing */
12649 printLine (lineHead, codeOutFile);