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))
4165 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
4167 /* special cases :- */
4168 /* if both left & right are in bit space */
4169 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4170 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4176 /* if I can do an decrement instead
4177 of subtract then GOOD for ME */
4178 if (genMinusDec (ic) == TRUE)
4183 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4185 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4191 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4196 /* if literal, add a,#-lit, else normal subb */
4197 _startLazyDPSEvaluation ();
4199 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
4200 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4201 if (AOP_USESDPTR(IC_RIGHT(ic))) {
4202 emitcode ("mov","b,a");
4203 MOVA(aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
4204 emitcode ("xch","a,b");
4205 emitcode ("subb","a,b");
4207 emitcode ("subb", "a,%s",
4208 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
4211 /* first add without previous c */
4213 if (!size && lit==-1) {
4214 emitcode ("dec", "a");
4216 emitcode ("add", "a,#!constbyte",
4217 (unsigned int) (lit & 0x0FFL));
4220 emitcode ("addc", "a,#!constbyte",
4221 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4226 emitcode ("push", "acc");
4228 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4232 _endLazyDPSEvaluation ();
4236 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4238 size = getDataSize (IC_LEFT (ic));
4239 rSize = getDataSize (IC_RESULT (ic));
4241 ADJUST_PUSHED_RESULT(size, rSize);
4243 _startLazyDPSEvaluation ();
4246 emitcode ("pop", "acc");
4247 aopPut (AOP (IC_RESULT (ic)), "a", size);
4249 _endLazyDPSEvaluation ();
4252 adjustArithmeticResult (ic);
4255 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4256 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4257 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4261 /*-----------------------------------------------------------------*/
4262 /* genMultbits :- multiplication of bits */
4263 /*-----------------------------------------------------------------*/
4265 genMultbits (operand * left,
4270 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4271 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4272 aopOp(result, ic, TRUE, FALSE);
4277 /*-----------------------------------------------------------------*/
4278 /* genMultOneByte : 8*8=8/16 bit multiplication */
4279 /*-----------------------------------------------------------------*/
4281 genMultOneByte (operand * left,
4286 sym_link *opetype = operandType (result);
4290 /* (if two literals: the value is computed before) */
4291 /* if one literal, literal on the right */
4292 if (AOP_TYPE (left) == AOP_LIT)
4297 emitcode (";", "swapped left and right");
4300 if (SPEC_USIGN(opetype)
4301 // ignore the sign of left and right, what else can we do?
4302 || (SPEC_USIGN(operandType(left)) &&
4303 SPEC_USIGN(operandType(right)))) {
4304 // just an unsigned 8*8=8/16 multiply
4305 //emitcode (";","unsigned");
4306 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4307 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4308 emitcode ("mul", "ab");
4310 _G.accInUse++; _G.bInUse++;
4311 aopOp(result, ic, TRUE, FALSE);
4313 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4315 // this should never happen
4316 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4317 AOP_SIZE(result), __FILE__, lineno);
4321 aopPut (AOP (result), "a", 0);
4322 _G.accInUse--; _G.bInUse--;
4323 if (AOP_SIZE(result)==2)
4325 aopPut (AOP (result), "b", 1);
4330 // we have to do a signed multiply
4332 emitcode (";", "signed");
4333 emitcode ("clr", "F0"); // reset sign flag
4334 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4336 lbl=newiTempLabel(NULL);
4337 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4338 // left side is negative, 8-bit two's complement, this fails for -128
4339 emitcode ("setb", "F0"); // set sign flag
4340 emitcode ("cpl", "a");
4341 emitcode ("inc", "a");
4343 emitcode ("", "!tlabeldef", lbl->key+100);
4346 if (AOP_TYPE(right)==AOP_LIT) {
4347 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4348 /* AND literal negative */
4349 if ((int) val < 0) {
4350 emitcode ("cpl", "F0"); // complement sign flag
4351 emitcode ("mov", "b,#!constbyte", -val);
4353 emitcode ("mov", "b,#!constbyte", val);
4356 lbl=newiTempLabel(NULL);
4357 emitcode ("mov", "b,a");
4358 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4359 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4360 // right side is negative, 8-bit two's complement
4361 emitcode ("cpl", "F0"); // complement sign flag
4362 emitcode ("cpl", "a");
4363 emitcode ("inc", "a");
4364 emitcode ("", "!tlabeldef", lbl->key+100);
4366 emitcode ("mul", "ab");
4368 _G.accInUse++;_G.bInUse++;
4369 aopOp(result, ic, TRUE, FALSE);
4371 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4373 // this should never happen
4374 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4375 AOP_SIZE(result), __FILE__, lineno);
4379 lbl=newiTempLabel(NULL);
4380 emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4381 // only ONE op was negative, we have to do a 8/16-bit two's complement
4382 emitcode ("cpl", "a"); // lsb
4383 if (AOP_SIZE(result)==1) {
4384 emitcode ("inc", "a");
4386 emitcode ("add", "a,#1");
4387 emitcode ("xch", "a,b");
4388 emitcode ("cpl", "a"); // msb
4389 emitcode ("addc", "a,#0");
4390 emitcode ("xch", "a,b");
4393 emitcode ("", "!tlabeldef", lbl->key+100);
4394 aopPut (AOP (result), "a", 0);
4395 _G.accInUse--;_G.bInUse--;
4396 if (AOP_SIZE(result)==2) {
4397 aopPut (AOP (result), "b", 1);
4401 /*-----------------------------------------------------------------*/
4402 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
4403 /*-----------------------------------------------------------------*/
4404 static void genMultTwoByte (operand *left, operand *right,
4405 operand *result, iCode *ic)
4407 sym_link *retype = getSpec(operandType(right));
4408 sym_link *letype = getSpec(operandType(left));
4409 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4412 if (AOP_TYPE (left) == AOP_LIT) {
4417 /* save EA bit in F1 */
4418 lbl = newiTempLabel(NULL);
4419 emitcode ("setb","F1");
4420 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4421 emitcode ("clr","F1");
4422 emitcode("","!tlabeldef",lbl->key+100);
4424 /* load up MB with right */
4426 emitcode("clr","F0");
4427 if (AOP_TYPE(right) == AOP_LIT) {
4428 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4430 emitcode("setb","F0");
4433 emitcode ("mov","mb,#!constbyte",val & 0xff);
4434 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4436 lbl = newiTempLabel(NULL);
4437 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4438 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4439 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4440 emitcode ("xch", "a,b");
4441 emitcode ("cpl","a");
4442 emitcode ("add", "a,#1");
4443 emitcode ("xch", "a,b");
4444 emitcode ("cpl", "a"); // msb
4445 emitcode ("addc", "a,#0");
4446 emitcode ("setb","F0");
4447 emitcode ("","!tlabeldef",lbl->key+100);
4448 emitcode ("mov","mb,b");
4449 emitcode ("mov","mb,a");
4452 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4453 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4455 /* load up MA with left */
4457 lbl = newiTempLabel(NULL);
4458 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4459 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4460 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4461 emitcode ("xch", "a,b");
4462 emitcode ("cpl","a");
4463 emitcode ("add", "a,#1");
4464 emitcode ("xch", "a,b");
4465 emitcode ("cpl", "a"); // msb
4466 emitcode ("addc","a,#0");
4467 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4468 emitcode ("setb","F0");
4469 emitcode ("","!tlabeldef",lbl->key+100);
4470 emitcode ("mov","ma,b");
4471 emitcode ("mov","ma,a");
4473 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4474 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4476 /* wait for multiplication to finish */
4477 lbl = newiTempLabel(NULL);
4478 emitcode("","!tlabeldef", lbl->key+100);
4479 emitcode("mov","a,mcnt1");
4480 emitcode("anl","a,#!constbyte",0x80);
4481 emitcode("jnz","!tlabel",lbl->key+100);
4483 freeAsmop (left, NULL, ic, TRUE);
4484 freeAsmop (right, NULL, ic,TRUE);
4485 aopOp(result, ic, TRUE, FALSE);
4487 /* if unsigned then simple */
4489 emitcode ("mov","a,ma");
4490 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4491 emitcode ("mov","a,ma");
4492 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4493 aopPut(AOP(result),"ma",1);
4494 aopPut(AOP(result),"ma",0);
4496 emitcode("push","ma");
4497 emitcode("push","ma");
4498 emitcode("push","ma");
4500 /* negate result if needed */
4501 lbl = newiTempLabel(NULL);
4502 emitcode("jnb","F0,!tlabel",lbl->key+100);
4503 emitcode("cpl","a");
4504 emitcode("add","a,#1");
4505 emitcode("","!tlabeldef", lbl->key+100);
4506 if (AOP_TYPE(result) == AOP_ACC)
4508 D(emitcode(";", "ACC special case."););
4509 /* We know result is the only live aop, and
4510 * it's obviously not a DPTR2, so AP is available.
4512 emitcode("mov", "%s,acc", DP2_RESULT_REG);
4516 aopPut(AOP(result),"a",0);
4519 emitcode("pop","acc");
4520 lbl = newiTempLabel(NULL);
4521 emitcode("jnb","F0,!tlabel",lbl->key+100);
4522 emitcode("cpl","a");
4523 emitcode("addc","a,#0");
4524 emitcode("","!tlabeldef", lbl->key+100);
4525 aopPut(AOP(result),"a",1);
4526 emitcode("pop","acc");
4527 if (AOP_SIZE(result) >= 3) {
4528 lbl = newiTempLabel(NULL);
4529 emitcode("jnb","F0,!tlabel",lbl->key+100);
4530 emitcode("cpl","a");
4531 emitcode("addc","a,#0");
4532 emitcode("","!tlabeldef", lbl->key+100);
4533 aopPut(AOP(result),"a",2);
4535 emitcode("pop","acc");
4536 if (AOP_SIZE(result) >= 4) {
4537 lbl = newiTempLabel(NULL);
4538 emitcode("jnb","F0,!tlabel",lbl->key+100);
4539 emitcode("cpl","a");
4540 emitcode("addc","a,#0");
4541 emitcode("","!tlabeldef", lbl->key+100);
4542 aopPut(AOP(result),"a",3);
4544 if (AOP_TYPE(result) == AOP_ACC)
4546 /* We stashed the result away above. */
4547 emitcode("mov", "acc,%s", DP2_RESULT_REG);
4551 freeAsmop (result, NULL, ic, TRUE);
4553 /* restore EA bit in F1 */
4554 lbl = newiTempLabel(NULL);
4555 emitcode ("jnb","F1,!tlabel",lbl->key+100);
4556 emitcode ("setb","EA");
4557 emitcode("","!tlabeldef",lbl->key+100);
4561 /*-----------------------------------------------------------------*/
4562 /* genMult - generates code for multiplication */
4563 /*-----------------------------------------------------------------*/
4565 genMult (iCode * ic)
4567 operand *left = IC_LEFT (ic);
4568 operand *right = IC_RIGHT (ic);
4569 operand *result = IC_RESULT (ic);
4571 D (emitcode (";", "genMult "););
4573 /* assign the amsops */
4576 /* special cases first */
4578 if (AOP_TYPE (left) == AOP_CRY &&
4579 AOP_TYPE (right) == AOP_CRY)
4581 genMultbits (left, right, result, ic);
4585 /* if both are of size == 1 */
4586 if (AOP_SIZE (left) == 1 &&
4587 AOP_SIZE (right) == 1)
4589 genMultOneByte (left, right, result, ic);
4593 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4594 /* use the ds390 ARITHMETIC accel UNIT */
4595 genMultTwoByte (left, right, result, ic);
4598 /* should have been converted to function call */
4602 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4603 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4604 freeAsmop (result, NULL, ic, TRUE);
4607 /*-----------------------------------------------------------------*/
4608 /* genDivbits :- division of bits */
4609 /*-----------------------------------------------------------------*/
4611 genDivbits (operand * left,
4619 /* the result must be bit */
4620 LOAD_AB_FOR_DIV (left, right, l);
4621 emitcode ("div", "ab");
4622 emitcode ("rrc", "a");
4623 aopOp(result, ic, TRUE, FALSE);
4625 aopPut (AOP (result), "c", 0);
4628 /*-----------------------------------------------------------------*/
4629 /* genDivOneByte : 8 bit division */
4630 /*-----------------------------------------------------------------*/
4632 genDivOneByte (operand * left,
4637 sym_link *opetype = operandType (result);
4643 /* signed or unsigned */
4644 if (SPEC_USIGN (opetype))
4646 /* unsigned is easy */
4647 LOAD_AB_FOR_DIV (left, right, l);
4648 emitcode ("div", "ab");
4651 aopOp(result, ic, TRUE, FALSE);
4652 aopPut (AOP (result), "a", 0);
4655 size = AOP_SIZE (result) - 1;
4659 aopPut (AOP (result), zero, offset++);
4664 /* signed is a little bit more difficult */
4666 /* save the signs of the operands */
4667 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4669 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4670 emitcode ("push", "acc"); /* save it on the stack */
4672 /* now sign adjust for both left & right */
4673 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4675 lbl = newiTempLabel (NULL);
4676 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4677 emitcode ("cpl", "a");
4678 emitcode ("inc", "a");
4679 emitcode ("", "!tlabeldef", (lbl->key + 100));
4680 emitcode ("mov", "b,a");
4682 /* sign adjust left side */
4683 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4686 lbl = newiTempLabel (NULL);
4687 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4688 emitcode ("cpl", "a");
4689 emitcode ("inc", "a");
4690 emitcode ("", "!tlabeldef", (lbl->key + 100));
4692 /* now the division */
4693 emitcode ("nop", "; workaround for DS80C390 div bug.");
4694 emitcode ("div", "ab");
4695 /* we are interested in the lower order
4697 emitcode ("mov", "b,a");
4698 lbl = newiTempLabel (NULL);
4699 emitcode ("pop", "acc");
4700 /* if there was an over flow we don't
4701 adjust the sign of the result */
4702 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4703 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4705 emitcode ("clr", "a");
4706 emitcode ("subb", "a,b");
4707 emitcode ("mov", "b,a");
4708 emitcode ("", "!tlabeldef", (lbl->key + 100));
4710 /* now we are done */
4711 _G.accInUse++; _G.bInUse++;
4712 aopOp(result, ic, TRUE, FALSE);
4714 aopPut (AOP (result), "b", 0);
4716 size = AOP_SIZE (result) - 1;
4720 emitcode ("mov", "c,b.7");
4721 emitcode ("subb", "a,acc");
4725 aopPut (AOP (result), "a", offset++);
4727 _G.accInUse--; _G.bInUse--;
4731 /*-----------------------------------------------------------------*/
4732 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
4733 /*-----------------------------------------------------------------*/
4734 static void genDivTwoByte (operand *left, operand *right,
4735 operand *result, iCode *ic)
4737 sym_link *retype = getSpec(operandType(right));
4738 sym_link *letype = getSpec(operandType(left));
4739 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4742 /* save EA bit in F1 */
4743 lbl = newiTempLabel(NULL);
4744 emitcode ("setb","F1");
4745 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4746 emitcode ("clr","F1");
4747 emitcode("","!tlabeldef",lbl->key+100);
4749 /* load up MA with left */
4751 emitcode("clr","F0");
4752 lbl = newiTempLabel(NULL);
4753 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4754 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4755 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4756 emitcode ("xch", "a,b");
4757 emitcode ("cpl","a");
4758 emitcode ("add", "a,#1");
4759 emitcode ("xch", "a,b");
4760 emitcode ("cpl", "a"); // msb
4761 emitcode ("addc","a,#0");
4762 emitcode ("setb","F0");
4763 emitcode ("","!tlabeldef",lbl->key+100);
4764 emitcode ("mov","ma,b");
4765 emitcode ("mov","ma,a");
4767 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4768 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4771 /* load up MB with right */
4773 if (AOP_TYPE(right) == AOP_LIT) {
4774 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4776 lbl = newiTempLabel(NULL);
4777 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4778 emitcode("setb","F0");
4779 emitcode ("","!tlabeldef",lbl->key+100);
4782 emitcode ("mov","mb,#!constbyte",val & 0xff);
4783 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4785 lbl = newiTempLabel(NULL);
4786 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4787 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4788 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4789 emitcode ("xch", "a,b");
4790 emitcode ("cpl","a");
4791 emitcode ("add", "a,#1");
4792 emitcode ("xch", "a,b");
4793 emitcode ("cpl", "a"); // msb
4794 emitcode ("addc", "a,#0");
4795 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4796 emitcode ("setb","F0");
4797 emitcode ("","!tlabeldef",lbl->key+100);
4798 emitcode ("mov","mb,b");
4799 emitcode ("mov","mb,a");
4802 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4803 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4806 /* wait for multiplication to finish */
4807 lbl = newiTempLabel(NULL);
4808 emitcode("","!tlabeldef", lbl->key+100);
4809 emitcode("mov","a,mcnt1");
4810 emitcode("anl","a,#!constbyte",0x80);
4811 emitcode("jnz","!tlabel",lbl->key+100);
4813 freeAsmop (left, NULL, ic, TRUE);
4814 freeAsmop (right, NULL, ic,TRUE);
4815 aopOp(result, ic, TRUE, FALSE);
4817 /* if unsigned then simple */
4819 aopPut(AOP(result),"ma",1);
4820 aopPut(AOP(result),"ma",0);
4822 emitcode("push","ma");
4824 /* negate result if needed */
4825 lbl = newiTempLabel(NULL);
4826 emitcode("jnb","F0,!tlabel",lbl->key+100);
4827 emitcode("cpl","a");
4828 emitcode("add","a,#1");
4829 emitcode("","!tlabeldef", lbl->key+100);
4830 aopPut(AOP(result),"a",0);
4831 emitcode("pop","acc");
4832 lbl = newiTempLabel(NULL);
4833 emitcode("jnb","F0,!tlabel",lbl->key+100);
4834 emitcode("cpl","a");
4835 emitcode("addc","a,#0");
4836 emitcode("","!tlabeldef", lbl->key+100);
4837 aopPut(AOP(result),"a",1);
4839 freeAsmop (result, NULL, ic, TRUE);
4840 /* restore EA bit in F1 */
4841 lbl = newiTempLabel(NULL);
4842 emitcode ("jnb","F1,!tlabel",lbl->key+100);
4843 emitcode ("setb","EA");
4844 emitcode("","!tlabeldef",lbl->key+100);
4848 /*-----------------------------------------------------------------*/
4849 /* genDiv - generates code for division */
4850 /*-----------------------------------------------------------------*/
4854 operand *left = IC_LEFT (ic);
4855 operand *right = IC_RIGHT (ic);
4856 operand *result = IC_RESULT (ic);
4858 D (emitcode (";", "genDiv "););
4860 /* assign the amsops */
4863 /* special cases first */
4865 if (AOP_TYPE (left) == AOP_CRY &&
4866 AOP_TYPE (right) == AOP_CRY)
4868 genDivbits (left, right, result, ic);
4872 /* if both are of size == 1 */
4873 if (AOP_SIZE (left) == 1 &&
4874 AOP_SIZE (right) == 1)
4876 genDivOneByte (left, right, result, ic);
4880 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4881 /* use the ds390 ARITHMETIC accel UNIT */
4882 genDivTwoByte (left, right, result, ic);
4885 /* should have been converted to function call */
4888 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4889 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4890 freeAsmop (result, NULL, ic, TRUE);
4893 /*-----------------------------------------------------------------*/
4894 /* genModbits :- modulus of bits */
4895 /*-----------------------------------------------------------------*/
4897 genModbits (operand * left,
4905 /* the result must be bit */
4906 LOAD_AB_FOR_DIV (left, right, l);
4907 emitcode ("div", "ab");
4908 emitcode ("mov", "a,b");
4909 emitcode ("rrc", "a");
4910 aopOp(result, ic, TRUE, FALSE);
4911 aopPut (AOP (result), "c", 0);
4914 /*-----------------------------------------------------------------*/
4915 /* genModOneByte : 8 bit modulus */
4916 /*-----------------------------------------------------------------*/
4918 genModOneByte (operand * left,
4923 sym_link *opetype = operandType (result);
4927 /* signed or unsigned */
4928 if (SPEC_USIGN (opetype))
4930 /* unsigned is easy */
4931 LOAD_AB_FOR_DIV (left, right, l);
4932 emitcode ("div", "ab");
4933 aopOp(result, ic, TRUE, FALSE);
4934 aopPut (AOP (result), "b", 0);
4938 /* signed is a little bit more difficult */
4940 /* save the signs of the operands */
4941 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4944 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4945 emitcode ("push", "acc"); /* save it on the stack */
4947 /* now sign adjust for both left & right */
4948 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4951 lbl = newiTempLabel (NULL);
4952 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4953 emitcode ("cpl", "a");
4954 emitcode ("inc", "a");
4955 emitcode ("", "!tlabeldef", (lbl->key + 100));
4956 emitcode ("mov", "b,a");
4958 /* sign adjust left side */
4959 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4962 lbl = newiTempLabel (NULL);
4963 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4964 emitcode ("cpl", "a");
4965 emitcode ("inc", "a");
4966 emitcode ("", "!tlabeldef", (lbl->key + 100));
4968 /* now the multiplication */
4969 emitcode ("nop", "; workaround for DS80C390 div bug.");
4970 emitcode ("div", "ab");
4971 /* we are interested in the lower order
4973 lbl = newiTempLabel (NULL);
4974 emitcode ("pop", "acc");
4975 /* if there was an over flow we don't
4976 adjust the sign of the result */
4977 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4978 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4980 emitcode ("clr", "a");
4981 emitcode ("subb", "a,b");
4982 emitcode ("mov", "b,a");
4983 emitcode ("", "!tlabeldef", (lbl->key + 100));
4986 /* now we are done */
4987 aopOp(result, ic, TRUE, FALSE);
4988 aopPut (AOP (result), "b", 0);
4993 /*-----------------------------------------------------------------*/
4994 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
4995 /*-----------------------------------------------------------------*/
4996 static void genModTwoByte (operand *left, operand *right,
4997 operand *result, iCode *ic)
4999 sym_link *retype = getSpec(operandType(right));
5000 sym_link *letype = getSpec(operandType(left));
5001 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5004 /* load up MA with left */
5005 /* save EA bit in F1 */
5006 lbl = newiTempLabel(NULL);
5007 emitcode ("setb","F1");
5008 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5009 emitcode ("clr","F1");
5010 emitcode("","!tlabeldef",lbl->key+100);
5013 lbl = newiTempLabel(NULL);
5014 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
5015 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
5016 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5017 emitcode ("xch", "a,b");
5018 emitcode ("cpl","a");
5019 emitcode ("add", "a,#1");
5020 emitcode ("xch", "a,b");
5021 emitcode ("cpl", "a"); // msb
5022 emitcode ("addc","a,#0");
5023 emitcode ("","!tlabeldef",lbl->key+100);
5024 emitcode ("mov","ma,b");
5025 emitcode ("mov","ma,a");
5027 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
5028 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
5031 /* load up MB with right */
5033 if (AOP_TYPE(right) == AOP_LIT) {
5034 int val=floatFromVal (AOP (right)->aopu.aop_lit);
5038 emitcode ("mov","mb,#!constbyte",val & 0xff);
5039 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5041 lbl = newiTempLabel(NULL);
5042 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
5043 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
5044 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5045 emitcode ("xch", "a,b");
5046 emitcode ("cpl","a");
5047 emitcode ("add", "a,#1");
5048 emitcode ("xch", "a,b");
5049 emitcode ("cpl", "a"); // msb
5050 emitcode ("addc", "a,#0");
5051 emitcode ("","!tlabeldef",lbl->key+100);
5052 emitcode ("mov","mb,b");
5053 emitcode ("mov","mb,a");
5056 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
5057 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
5060 /* wait for multiplication to finish */
5061 lbl = newiTempLabel(NULL);
5062 emitcode("","!tlabeldef", lbl->key+100);
5063 emitcode("mov","a,mcnt1");
5064 emitcode("anl","a,#!constbyte",0x80);
5065 emitcode("jnz","!tlabel",lbl->key+100);
5067 freeAsmop (left, NULL, ic, TRUE);
5068 freeAsmop (right, NULL, ic,TRUE);
5069 aopOp(result, ic, TRUE, FALSE);
5071 aopPut(AOP(result),"mb",1);
5072 aopPut(AOP(result),"mb",0);
5073 freeAsmop (result, NULL, ic, TRUE);
5075 /* restore EA bit in F1 */
5076 lbl = newiTempLabel(NULL);
5077 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5078 emitcode ("setb","EA");
5079 emitcode("","!tlabeldef",lbl->key+100);
5083 /*-----------------------------------------------------------------*/
5084 /* genMod - generates code for division */
5085 /*-----------------------------------------------------------------*/
5089 operand *left = IC_LEFT (ic);
5090 operand *right = IC_RIGHT (ic);
5091 operand *result = IC_RESULT (ic);
5093 D (emitcode (";", "genMod "); );
5095 /* assign the amsops */
5098 /* special cases first */
5100 if (AOP_TYPE (left) == AOP_CRY &&
5101 AOP_TYPE (right) == AOP_CRY)
5103 genModbits (left, right, result, ic);
5107 /* if both are of size == 1 */
5108 if (AOP_SIZE (left) == 1 &&
5109 AOP_SIZE (right) == 1)
5111 genModOneByte (left, right, result, ic);
5115 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5116 /* use the ds390 ARITHMETIC accel UNIT */
5117 genModTwoByte (left, right, result, ic);
5121 /* should have been converted to function call */
5125 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5126 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5127 freeAsmop (result, NULL, ic, TRUE);
5130 /*-----------------------------------------------------------------*/
5131 /* genIfxJump :- will create a jump depending on the ifx */
5132 /*-----------------------------------------------------------------*/
5134 genIfxJump (iCode * ic, char *jval)
5137 symbol *tlbl = newiTempLabel (NULL);
5140 D (emitcode (";", "genIfxJump ");
5143 /* if true label then we jump if condition
5147 jlbl = IC_TRUE (ic);
5148 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5149 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5153 /* false label is present */
5154 jlbl = IC_FALSE (ic);
5155 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5156 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5158 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5159 emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5161 emitcode (inst, "!tlabel", tlbl->key + 100);
5162 emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5163 emitcode ("", "!tlabeldef", tlbl->key + 100);
5165 /* mark the icode as generated */
5169 /*-----------------------------------------------------------------*/
5170 /* genCmp :- greater or less than comparison */
5171 /*-----------------------------------------------------------------*/
5173 genCmp (operand * left, operand * right,
5174 iCode * ic, iCode * ifx, int sign)
5176 int size, offset = 0;
5177 unsigned long lit = 0L;
5180 D (emitcode (";", "genCmp");
5183 result = IC_RESULT (ic);
5185 /* if left & right are bit variables */
5186 if (AOP_TYPE (left) == AOP_CRY &&
5187 AOP_TYPE (right) == AOP_CRY)
5189 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5190 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
5194 /* subtract right from left if at the
5195 end the carry flag is set then we know that
5196 left is greater than right */
5197 size = max (AOP_SIZE (left), AOP_SIZE (right));
5199 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5200 if ((size == 1) && !sign &&
5201 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5203 symbol *lbl = newiTempLabel (NULL);
5204 emitcode ("cjne", "%s,%s,!tlabel",
5205 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5206 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5208 emitcode ("", "!tlabeldef", lbl->key + 100);
5212 if (AOP_TYPE (right) == AOP_LIT)
5214 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5215 /* optimize if(x < 0) or if(x >= 0) */
5224 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
5226 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5227 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5229 aopOp (result, ic, FALSE, FALSE);
5231 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5233 freeAsmop (result, NULL, ic, TRUE);
5234 genIfxJump (ifx, "acc.7");
5239 emitcode ("rlc", "a");
5241 goto release_freedLR;
5249 //emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5250 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5251 //emitcode (";", "genCmp #2");
5252 if (sign && (size == 0))
5254 //emitcode (";", "genCmp #3");
5255 emitcode ("xrl", "a,#!constbyte",0x80);
5256 if (AOP_TYPE (right) == AOP_LIT)
5258 unsigned long lit = (unsigned long)
5259 floatFromVal (AOP (right)->aopu.aop_lit);
5260 //emitcode (";", "genCmp #3.1");
5261 emitcode ("subb", "a,#!constbyte",
5262 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5266 //emitcode (";", "genCmp #3.2");
5267 if (AOP_NEEDSACC (right))
5269 emitcode ("push", "acc");
5271 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
5272 FALSE, FALSE, FALSE));
5273 emitcode ("xrl", "b,#!constbyte",0x80);
5274 if (AOP_NEEDSACC (right))
5276 emitcode ("pop", "acc");
5278 emitcode ("subb", "a,b");
5285 //emitcode (";", "genCmp #4");
5286 if (AOP_NEEDSACC (right))
5289 //emitcode (";", "genCmp #4.1");
5290 emitcode ("xch", "a, b");
5291 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
5292 emitcode ("xch", "a, b");
5297 //emitcode (";", "genCmp #4.2");
5298 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
5301 emitcode ("subb", "a,%s", s);
5308 /* Don't need the left & right operands any more; do need the result. */
5309 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5310 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5312 aopOp (result, ic, FALSE, FALSE);
5316 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5322 /* if the result is used in the next
5323 ifx conditional branch then generate
5324 code a little differently */
5327 genIfxJump (ifx, "c");
5333 /* leave the result in acc */
5335 freeAsmop (result, NULL, ic, TRUE);
5338 /*-----------------------------------------------------------------*/
5339 /* genCmpGt :- greater than comparison */
5340 /*-----------------------------------------------------------------*/
5342 genCmpGt (iCode * ic, iCode * ifx)
5344 operand *left, *right;
5345 sym_link *letype, *retype;
5348 D (emitcode (";", "genCmpGt ");
5351 left = IC_LEFT (ic);
5352 right = IC_RIGHT (ic);
5354 letype = getSpec (operandType (left));
5355 retype = getSpec (operandType (right));
5356 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5358 /* assign the left & right amsops */
5361 genCmp (right, left, ic, ifx, sign);
5364 /*-----------------------------------------------------------------*/
5365 /* genCmpLt - less than comparisons */
5366 /*-----------------------------------------------------------------*/
5368 genCmpLt (iCode * ic, iCode * ifx)
5370 operand *left, *right;
5371 sym_link *letype, *retype;
5374 D (emitcode (";", "genCmpLt "););
5376 left = IC_LEFT (ic);
5377 right = IC_RIGHT (ic);
5379 letype = getSpec (operandType (left));
5380 retype = getSpec (operandType (right));
5381 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5383 /* assign the left & right amsops */
5386 genCmp (left, right, ic, ifx, sign);
5389 /*-----------------------------------------------------------------*/
5390 /* gencjneshort - compare and jump if not equal */
5391 /*-----------------------------------------------------------------*/
5393 gencjneshort (operand * left, operand * right, symbol * lbl)
5395 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5397 unsigned long lit = 0L;
5399 D (emitcode (";", "gencjneshort");
5402 /* if the left side is a literal or
5403 if the right is in a pointer register and left
5405 if ((AOP_TYPE (left) == AOP_LIT) ||
5406 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5413 if (AOP_TYPE (right) == AOP_LIT)
5414 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5416 if (opIsGptr (left) || opIsGptr (right))
5418 /* We are comparing a generic pointer to something.
5419 * Exclude the generic type byte from the comparison.
5422 D (emitcode (";", "cjneshort: generic ptr special case.");
5427 /* if the right side is a literal then anything goes */
5428 if (AOP_TYPE (right) == AOP_LIT &&
5429 AOP_TYPE (left) != AOP_DIR)
5433 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5435 emitcode ("cjne", "a,%s,!tlabel",
5436 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5442 /* if the right side is in a register or in direct space or
5443 if the left is a pointer register & right is not */
5444 else if (AOP_TYPE (right) == AOP_REG ||
5445 AOP_TYPE (right) == AOP_DIR ||
5446 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5447 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5451 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5452 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5453 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5454 emitcode ("jnz", "!tlabel", lbl->key + 100);
5456 emitcode ("cjne", "a,%s,!tlabel",
5457 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
5464 /* right is a pointer reg need both a & b */
5467 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5468 if (strcmp (l, "b"))
5469 emitcode ("mov", "b,%s", l);
5470 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5471 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5477 /*-----------------------------------------------------------------*/
5478 /* gencjne - compare and jump if not equal */
5479 /*-----------------------------------------------------------------*/
5481 gencjne (operand * left, operand * right, symbol * lbl)
5483 symbol *tlbl = newiTempLabel (NULL);
5485 D (emitcode (";", "gencjne");
5488 gencjneshort (left, right, lbl);
5490 emitcode ("mov", "a,%s", one);
5491 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5492 emitcode ("", "!tlabeldef", lbl->key + 100);
5493 emitcode ("clr", "a");
5494 emitcode ("", "!tlabeldef", tlbl->key + 100);
5497 /*-----------------------------------------------------------------*/
5498 /* genCmpEq - generates code for equal to */
5499 /*-----------------------------------------------------------------*/
5501 genCmpEq (iCode * ic, iCode * ifx)
5503 operand *left, *right, *result;
5505 D (emitcode (";", "genCmpEq ");
5509 AOP_SET_LOCALS (ic);
5511 /* if literal, literal on the right or
5512 if the right is in a pointer register and left
5514 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5515 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5517 operand *t = IC_RIGHT (ic);
5518 IC_RIGHT (ic) = IC_LEFT (ic);
5522 if (ifx && /* !AOP_SIZE(result) */
5523 OP_SYMBOL (result) &&
5524 OP_SYMBOL (result)->regType == REG_CND)
5527 /* if they are both bit variables */
5528 if (AOP_TYPE (left) == AOP_CRY &&
5529 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5531 if (AOP_TYPE (right) == AOP_LIT)
5533 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5536 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5537 emitcode ("cpl", "c");
5541 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5545 emitcode ("clr", "c");
5547 /* AOP_TYPE(right) == AOP_CRY */
5551 symbol *lbl = newiTempLabel (NULL);
5552 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5553 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5554 emitcode ("cpl", "c");
5555 emitcode ("", "!tlabeldef", (lbl->key + 100));
5557 /* if true label then we jump if condition
5559 tlbl = newiTempLabel (NULL);
5562 emitcode ("jnc", "!tlabel", tlbl->key + 100);
5563 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5567 emitcode ("jc", "!tlabel", tlbl->key + 100);
5568 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5570 emitcode ("", "!tlabeldef", tlbl->key + 100);
5574 tlbl = newiTempLabel (NULL);
5575 gencjneshort (left, right, tlbl);
5578 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5579 emitcode ("", "!tlabeldef", tlbl->key + 100);
5583 symbol *lbl = newiTempLabel (NULL);
5584 emitcode ("sjmp", "!tlabel", lbl->key + 100);
5585 emitcode ("", "!tlabeldef", tlbl->key + 100);
5586 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5587 emitcode ("", "!tlabeldef", lbl->key + 100);
5590 /* mark the icode as generated */
5593 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5594 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5598 /* if they are both bit variables */
5599 if (AOP_TYPE (left) == AOP_CRY &&
5600 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5602 if (AOP_TYPE (right) == AOP_LIT)
5604 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5607 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5608 emitcode ("cpl", "c");
5612 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5616 emitcode ("clr", "c");
5618 /* AOP_TYPE(right) == AOP_CRY */
5622 symbol *lbl = newiTempLabel (NULL);
5623 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5624 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5625 emitcode ("cpl", "c");
5626 emitcode ("", "!tlabeldef", (lbl->key + 100));
5629 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5630 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5632 aopOp (result, ic, TRUE, FALSE);
5635 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5642 genIfxJump (ifx, "c");
5645 /* if the result is used in an arithmetic operation
5646 then put the result in place */
5651 gencjne (left, right, newiTempLabel (NULL));
5653 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5654 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5656 aopOp (result, ic, TRUE, FALSE);
5658 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5660 aopPut (AOP (result), "a", 0);
5665 genIfxJump (ifx, "a");
5668 /* if the result is used in an arithmetic operation
5669 then put the result in place */
5670 if (AOP_TYPE (result) != AOP_CRY)
5672 /* leave the result in acc */
5676 freeAsmop (result, NULL, ic, TRUE);
5679 /*-----------------------------------------------------------------*/
5680 /* ifxForOp - returns the icode containing the ifx for operand */
5681 /*-----------------------------------------------------------------*/
5683 ifxForOp (operand * op, iCode * ic)
5685 /* if true symbol then needs to be assigned */
5686 if (IS_TRUE_SYMOP (op))
5689 /* if this has register type condition and
5690 the next instruction is ifx with the same operand
5691 and live to of the operand is upto the ifx only then */
5693 ic->next->op == IFX &&
5694 IC_COND (ic->next)->key == op->key &&
5695 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5700 /*-----------------------------------------------------------------*/
5701 /* hasInc - operand is incremented before any other use */
5702 /*-----------------------------------------------------------------*/
5704 hasInc (operand *op, iCode *ic, int osize)
5706 sym_link *type = operandType(op);
5707 sym_link *retype = getSpec (type);
5708 iCode *lic = ic->next;
5711 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5712 if (!IS_SYMOP(op)) return NULL;
5714 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5715 if (IS_AGGREGATE(type->next)) return NULL;
5716 if (osize != (isize = getSize(type->next))) return NULL;
5719 /* if operand of the form op = op + <sizeof *op> */
5720 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5721 isOperandEqual(IC_RESULT(lic),op) &&
5722 isOperandLiteral(IC_RIGHT(lic)) &&
5723 operandLitValue(IC_RIGHT(lic)) == isize) {
5726 /* if the operand used or deffed */
5727 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5730 /* if GOTO or IFX */
5731 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5737 /*-----------------------------------------------------------------*/
5738 /* genAndOp - for && operation */
5739 /*-----------------------------------------------------------------*/
5741 genAndOp (iCode * ic)
5743 operand *left, *right, *result;
5746 D (emitcode (";", "genAndOp "););
5748 /* note here that && operations that are in an
5749 if statement are taken away by backPatchLabels
5750 only those used in arthmetic operations remain */
5752 AOP_SET_LOCALS (ic);
5754 /* if both are bit variables */
5755 if (AOP_TYPE (left) == AOP_CRY &&
5756 AOP_TYPE (right) == AOP_CRY)
5758 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5759 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5760 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5761 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5763 aopOp (result,ic,FALSE, FALSE);
5768 tlbl = newiTempLabel (NULL);
5770 emitcode ("jz", "!tlabel", tlbl->key + 100);
5772 emitcode ("", "!tlabeldef", tlbl->key + 100);
5773 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5774 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5776 aopOp (result,ic,FALSE, FALSE);
5779 freeAsmop (result, NULL, ic, TRUE);
5783 /*-----------------------------------------------------------------*/
5784 /* genOrOp - for || operation */
5785 /*-----------------------------------------------------------------*/
5787 genOrOp (iCode * ic)
5789 operand *left, *right, *result;
5792 D (emitcode (";", "genOrOp "););
5794 /* note here that || operations that are in an
5795 if statement are taken away by backPatchLabels
5796 only those used in arthmetic operations remain */
5798 AOP_SET_LOCALS (ic);
5800 /* if both are bit variables */
5801 if (AOP_TYPE (left) == AOP_CRY &&
5802 AOP_TYPE (right) == AOP_CRY)
5804 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5805 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5806 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5807 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5809 aopOp (result,ic,FALSE, FALSE);
5815 tlbl = newiTempLabel (NULL);
5817 emitcode ("jnz", "!tlabel", tlbl->key + 100);
5819 emitcode ("", "!tlabeldef", tlbl->key + 100);
5820 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5821 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5823 aopOp (result,ic,FALSE, FALSE);
5828 freeAsmop (result, NULL, ic, TRUE);
5831 /*-----------------------------------------------------------------*/
5832 /* isLiteralBit - test if lit == 2^n */
5833 /*-----------------------------------------------------------------*/
5835 isLiteralBit (unsigned long lit)
5837 unsigned long pw[32] =
5838 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5839 0x100L, 0x200L, 0x400L, 0x800L,
5840 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5841 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5842 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5843 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5844 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5847 for (idx = 0; idx < 32; idx++)
5853 /*-----------------------------------------------------------------*/
5854 /* continueIfTrue - */
5855 /*-----------------------------------------------------------------*/
5857 continueIfTrue (iCode * ic)
5860 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
5864 /*-----------------------------------------------------------------*/
5866 /*-----------------------------------------------------------------*/
5868 jumpIfTrue (iCode * ic)
5871 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
5875 /*-----------------------------------------------------------------*/
5876 /* jmpTrueOrFalse - */
5877 /*-----------------------------------------------------------------*/
5879 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5881 // ugly but optimized by peephole
5884 symbol *nlbl = newiTempLabel (NULL);
5885 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
5886 emitcode ("", "!tlabeldef", tlbl->key + 100);
5887 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
5888 emitcode ("", "!tlabeldef", nlbl->key + 100);
5892 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
5893 emitcode ("", "!tlabeldef", tlbl->key + 100);
5898 // Generate code to perform a bit-wise logic operation
5899 // on two operands in far space (assumed to already have been
5900 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5901 // in far space. This requires pushing the result on the stack
5902 // then popping it into the result.
5904 genFarFarLogicOp(iCode *ic, char *logicOp)
5906 int size, resultSize, compSize;
5910 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5911 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
5912 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5914 _startLazyDPSEvaluation();
5915 for (size = compSize; (size--); offset++)
5917 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5918 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5919 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5921 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5922 emitcode ("push", "acc");
5924 _endLazyDPSEvaluation();
5926 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5927 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5928 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5930 resultSize = AOP_SIZE(IC_RESULT(ic));
5932 ADJUST_PUSHED_RESULT(compSize, resultSize);
5934 _startLazyDPSEvaluation();
5937 emitcode ("pop", "acc");
5938 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5940 _endLazyDPSEvaluation();
5941 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5945 /*-----------------------------------------------------------------*/
5946 /* genAnd - code for and */
5947 /*-----------------------------------------------------------------*/
5949 genAnd (iCode * ic, iCode * ifx)
5951 operand *left, *right, *result;
5952 int size, offset = 0;
5953 unsigned long lit = 0L;
5958 D (emitcode (";", "genAnd "););
5960 AOP_OP_3_NOFATAL (ic, pushResult);
5961 AOP_SET_LOCALS (ic);
5965 genFarFarLogicOp(ic, "anl");
5970 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5972 AOP_TYPE (left), AOP_TYPE (right));
5973 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5975 AOP_SIZE (left), AOP_SIZE (right));
5978 /* if left is a literal & right is not then exchange them */
5979 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5980 #ifdef LOGIC_OPS_BROKEN
5981 || AOP_NEEDSACC (left)
5985 operand *tmp = right;
5990 /* if result = right then exchange them */
5991 if (sameRegs (AOP (result), AOP (right)))
5993 operand *tmp = right;
5998 /* if right is bit then exchange them */
5999 if (AOP_TYPE (right) == AOP_CRY &&
6000 AOP_TYPE (left) != AOP_CRY)
6002 operand *tmp = right;
6006 if (AOP_TYPE (right) == AOP_LIT)
6007 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6009 size = AOP_SIZE (result);
6012 // result = bit & yy;
6013 if (AOP_TYPE (left) == AOP_CRY)
6015 // c = bit & literal;
6016 if (AOP_TYPE (right) == AOP_LIT)
6020 if (size && sameRegs (AOP (result), AOP (left)))
6023 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6028 if (size && (AOP_TYPE (result) == AOP_CRY))
6030 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6033 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6038 emitcode ("clr", "c");
6043 if (AOP_TYPE (right) == AOP_CRY)
6046 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6047 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6052 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
6054 emitcode ("rrc", "a");
6055 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6063 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6064 genIfxJump (ifx, "c");
6068 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6069 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6070 if ((AOP_TYPE (right) == AOP_LIT) &&
6071 (AOP_TYPE (result) == AOP_CRY) &&
6072 (AOP_TYPE (left) != AOP_CRY))
6074 int posbit = isLiteralBit (lit);
6079 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
6082 emitcode ("mov", "c,acc.%d", posbit & 0x07);
6088 sprintf (buffer, "acc.%d", posbit & 0x07);
6089 genIfxJump (ifx, buffer);
6093 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6100 symbol *tlbl = newiTempLabel (NULL);
6101 int sizel = AOP_SIZE (left);
6103 emitcode ("setb", "c");
6106 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6108 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6110 if ((posbit = isLiteralBit (bytelit)) != 0)
6111 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6114 if (bytelit != 0x0FFL)
6115 emitcode ("anl", "a,%s",
6116 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
6117 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6122 // bit = left & literal
6125 emitcode ("clr", "c");
6126 emitcode ("", "!tlabeldef", tlbl->key + 100);
6128 // if(left & literal)
6132 jmpTrueOrFalse (ifx, tlbl);
6140 /* if left is same as result */
6141 if (sameRegs (AOP (result), AOP (left)))
6143 for (; size--; offset++)
6145 if (AOP_TYPE (right) == AOP_LIT)
6147 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6149 else if (bytelit == 0)
6150 aopPut (AOP (result), zero, offset);
6151 else if (IS_AOP_PREG (result))
6153 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6154 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6155 aopPut (AOP (result), "a", offset);
6158 emitcode ("anl", "%s,%s",
6159 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6160 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6164 if (AOP_TYPE (left) == AOP_ACC)
6165 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6168 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6169 if (IS_AOP_PREG (result))
6171 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6172 aopPut (AOP (result), "a", offset);
6176 emitcode ("anl", "%s,a",
6177 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6184 // left & result in different registers
6185 if (AOP_TYPE (result) == AOP_CRY)
6188 // if(size), result in bit
6189 // if(!size && ifx), conditional oper: if(left & right)
6190 symbol *tlbl = newiTempLabel (NULL);
6191 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6193 emitcode ("setb", "c");
6196 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6197 emitcode ("anl", "a,%s",
6198 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6200 if (AOP_TYPE(left)==AOP_ACC) {
6201 emitcode("mov", "b,a");
6202 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6203 emitcode("anl", "a,b");
6205 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6206 emitcode ("anl", "a,%s",
6207 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6210 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6216 emitcode ("", "!tlabeldef", tlbl->key + 100);
6220 jmpTrueOrFalse (ifx, tlbl);
6224 for (; (size--); offset++)
6227 // result = left & right
6228 if (AOP_TYPE (right) == AOP_LIT)
6230 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6232 aopPut (AOP (result),
6233 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6237 else if (bytelit == 0)
6239 aopPut (AOP (result), zero, offset);
6242 D (emitcode (";", "better literal AND."););
6243 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6244 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6245 FALSE, FALSE, FALSE));
6250 // faster than result <- left, anl result,right
6251 // and better if result is SFR
6252 if (AOP_TYPE (left) == AOP_ACC)
6254 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
6255 FALSE, FALSE, FALSE));
6259 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6260 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6262 emitcode("mov", "b,a");
6266 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6267 emitcode ("anl", "a,%s", rOp);
6270 aopPut (AOP (result), "a", offset);
6276 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6277 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6278 freeAsmop (result, NULL, ic, TRUE);
6282 /*-----------------------------------------------------------------*/
6283 /* genOr - code for or */
6284 /*-----------------------------------------------------------------*/
6286 genOr (iCode * ic, iCode * ifx)
6288 operand *left, *right, *result;
6289 int size, offset = 0;
6290 unsigned long lit = 0L;
6293 D (emitcode (";", "genOr "););
6295 AOP_OP_3_NOFATAL (ic, pushResult);
6296 AOP_SET_LOCALS (ic);
6300 genFarFarLogicOp(ic, "orl");
6306 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6308 AOP_TYPE (left), AOP_TYPE (right));
6309 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6311 AOP_SIZE (left), AOP_SIZE (right));
6314 /* if left is a literal & right is not then exchange them */
6315 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6316 #ifdef LOGIC_OPS_BROKEN
6317 || AOP_NEEDSACC (left) // I think this is a net loss now.
6321 operand *tmp = right;
6326 /* if result = right then exchange them */
6327 if (sameRegs (AOP (result), AOP (right)))
6329 operand *tmp = right;
6334 /* if right is bit then exchange them */
6335 if (AOP_TYPE (right) == AOP_CRY &&
6336 AOP_TYPE (left) != AOP_CRY)
6338 operand *tmp = right;
6342 if (AOP_TYPE (right) == AOP_LIT)
6343 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6345 size = AOP_SIZE (result);
6349 if (AOP_TYPE (left) == AOP_CRY)
6351 if (AOP_TYPE (right) == AOP_LIT)
6353 // c = bit & literal;
6356 // lit != 0 => result = 1
6357 if (AOP_TYPE (result) == AOP_CRY)
6360 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6362 continueIfTrue (ifx);
6365 emitcode ("setb", "c");
6369 // lit == 0 => result = left
6370 if (size && sameRegs (AOP (result), AOP (left)))
6372 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6377 if (AOP_TYPE (right) == AOP_CRY)
6380 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6381 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6386 symbol *tlbl = newiTempLabel (NULL);
6387 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6388 emitcode ("setb", "c");
6389 emitcode ("jb", "%s,!tlabel",
6390 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6392 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6393 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6395 jmpTrueOrFalse (ifx, tlbl);
6401 emitcode ("", "!tlabeldef", tlbl->key + 100);
6410 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6411 genIfxJump (ifx, "c");
6415 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6416 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6417 if ((AOP_TYPE (right) == AOP_LIT) &&
6418 (AOP_TYPE (result) == AOP_CRY) &&
6419 (AOP_TYPE (left) != AOP_CRY))
6425 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6427 continueIfTrue (ifx);
6432 // lit = 0, result = boolean(left)
6434 emitcode ("setb", "c");
6438 symbol *tlbl = newiTempLabel (NULL);
6439 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6441 emitcode ("", "!tlabeldef", tlbl->key + 100);
6445 genIfxJump (ifx, "a");
6453 /* if left is same as result */
6454 if (sameRegs (AOP (result), AOP (left)))
6456 for (; size--; offset++)
6458 if (AOP_TYPE (right) == AOP_LIT)
6460 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6466 if (IS_AOP_PREG (left))
6468 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6469 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6470 aopPut (AOP (result), "a", offset);
6474 emitcode ("orl", "%s,%s",
6475 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6476 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6482 if (AOP_TYPE (left) == AOP_ACC)
6484 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6488 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6489 if (IS_AOP_PREG (left))
6491 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6492 aopPut (AOP (result), "a", offset);
6496 emitcode ("orl", "%s,a",
6497 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6505 // left & result in different registers
6506 if (AOP_TYPE (result) == AOP_CRY)
6509 // if(size), result in bit
6510 // if(!size && ifx), conditional oper: if(left | right)
6511 symbol *tlbl = newiTempLabel (NULL);
6512 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6514 emitcode ("setb", "c");
6517 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6518 emitcode ("orl", "a,%s",
6519 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6521 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6522 emitcode ("orl", "a,%s",
6523 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6525 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6531 emitcode ("", "!tlabeldef", tlbl->key + 100);
6535 jmpTrueOrFalse (ifx, tlbl);
6539 _startLazyDPSEvaluation();
6540 for (; (size--); offset++)
6543 // result = left & right
6544 if (AOP_TYPE (right) == AOP_LIT)
6546 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6548 aopPut (AOP (result),
6549 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6553 D (emitcode (";", "better literal OR."););
6554 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6555 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
6556 FALSE, FALSE, FALSE));
6561 // faster than result <- left, anl result,right
6562 // and better if result is SFR
6563 if (AOP_TYPE (left) == AOP_ACC)
6565 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
6566 FALSE, FALSE, FALSE));
6570 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6572 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6574 emitcode("mov", "b,a");
6578 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6579 emitcode ("orl", "a,%s", rOp);
6582 aopPut (AOP (result), "a", offset);
6584 _endLazyDPSEvaluation();
6589 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6590 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6591 freeAsmop (result, NULL, ic, TRUE);
6594 /*-----------------------------------------------------------------*/
6595 /* genXor - code for xclusive or */
6596 /*-----------------------------------------------------------------*/
6598 genXor (iCode * ic, iCode * ifx)
6600 operand *left, *right, *result;
6601 int size, offset = 0;
6602 unsigned long lit = 0L;
6605 D (emitcode (";", "genXor "););
6607 AOP_OP_3_NOFATAL (ic, pushResult);
6608 AOP_SET_LOCALS (ic);
6612 genFarFarLogicOp(ic, "xrl");
6617 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6619 AOP_TYPE (left), AOP_TYPE (right));
6620 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6622 AOP_SIZE (left), AOP_SIZE (right));
6625 /* if left is a literal & right is not ||
6626 if left needs acc & right does not */
6627 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6628 #ifdef LOGIC_OPS_BROKEN
6629 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6633 operand *tmp = right;
6638 /* if result = right then exchange them */
6639 if (sameRegs (AOP (result), AOP (right)))
6641 operand *tmp = right;
6646 /* if right is bit then exchange them */
6647 if (AOP_TYPE (right) == AOP_CRY &&
6648 AOP_TYPE (left) != AOP_CRY)
6650 operand *tmp = right;
6654 if (AOP_TYPE (right) == AOP_LIT)
6655 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6657 size = AOP_SIZE (result);
6661 if (AOP_TYPE (left) == AOP_CRY)
6663 if (AOP_TYPE (right) == AOP_LIT)
6665 // c = bit & literal;
6668 // lit>>1 != 0 => result = 1
6669 if (AOP_TYPE (result) == AOP_CRY)
6672 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6674 continueIfTrue (ifx);
6677 emitcode ("setb", "c");
6684 // lit == 0, result = left
6685 if (size && sameRegs (AOP (result), AOP (left)))
6687 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6691 // lit == 1, result = not(left)
6692 if (size && sameRegs (AOP (result), AOP (left)))
6694 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6699 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6700 emitcode ("cpl", "c");
6709 symbol *tlbl = newiTempLabel (NULL);
6710 if (AOP_TYPE (right) == AOP_CRY)
6713 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6717 int sizer = AOP_SIZE (right);
6719 // if val>>1 != 0, result = 1
6720 emitcode ("setb", "c");
6723 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
6725 // test the msb of the lsb
6726 emitcode ("anl", "a,#!constbyte",0xfe);
6727 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6731 emitcode ("rrc", "a");
6733 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6734 emitcode ("cpl", "c");
6735 emitcode ("", "!tlabeldef", (tlbl->key + 100));
6742 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6743 genIfxJump (ifx, "c");
6747 if (sameRegs (AOP (result), AOP (left)))
6749 /* if left is same as result */
6750 for (; size--; offset++)
6752 if (AOP_TYPE (right) == AOP_LIT)
6754 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6756 else if (IS_AOP_PREG (left))
6758 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6759 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6760 aopPut (AOP (result), "a", offset);
6763 emitcode ("xrl", "%s,%s",
6764 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6765 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6769 if (AOP_TYPE (left) == AOP_ACC)
6770 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6773 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6774 if (IS_AOP_PREG (left))
6776 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6777 aopPut (AOP (result), "a", offset);
6780 emitcode ("xrl", "%s,a",
6781 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6788 // left & result in different registers
6789 if (AOP_TYPE (result) == AOP_CRY)
6792 // if(size), result in bit
6793 // if(!size && ifx), conditional oper: if(left ^ right)
6794 symbol *tlbl = newiTempLabel (NULL);
6795 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6798 emitcode ("setb", "c");
6801 if ((AOP_TYPE (right) == AOP_LIT) &&
6802 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6804 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6808 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6809 emitcode ("xrl", "a,%s",
6810 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6812 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6813 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6815 emitcode("mov", "b,a");
6819 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6820 emitcode ("xrl", "a,%s", rOp);
6823 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6829 emitcode ("", "!tlabeldef", tlbl->key + 100);
6833 jmpTrueOrFalse (ifx, tlbl);
6837 for (; (size--); offset++)
6840 // result = left & right
6841 if (AOP_TYPE (right) == AOP_LIT)
6843 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6845 aopPut (AOP (result),
6846 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6850 D (emitcode (";", "better literal XOR."););
6851 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6852 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
6853 FALSE, FALSE, FALSE));
6857 // faster than result <- left, anl result,right
6858 // and better if result is SFR
6859 if (AOP_TYPE (left) == AOP_ACC)
6861 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
6862 FALSE, FALSE, FALSE));
6866 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6867 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6869 emitcode("mov", "b,a");
6873 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6874 emitcode ("xrl", "a,%s", rOp);
6877 aopPut (AOP (result), "a", offset);
6884 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6885 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6886 freeAsmop (result, NULL, ic, TRUE);
6889 /*-----------------------------------------------------------------*/
6890 /* genInline - write the inline code out */
6891 /*-----------------------------------------------------------------*/
6893 genInline (iCode * ic)
6895 char *buffer, *bp, *bp1;
6897 D (emitcode (";", "genInline ");
6900 _G.inLine += (!options.asmpeep);
6902 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6903 strcpy (buffer, IC_INLINE (ic));
6905 /* emit each line as a code */
6930 /* emitcode("",buffer); */
6931 _G.inLine -= (!options.asmpeep);
6934 /*-----------------------------------------------------------------*/
6935 /* genRRC - rotate right with carry */
6936 /*-----------------------------------------------------------------*/
6940 operand *left, *result;
6941 int size, offset = 0;
6944 D (emitcode (";", "genRRC ");
6947 /* rotate right with carry */
6948 left = IC_LEFT (ic);
6949 result = IC_RESULT (ic);
6950 aopOp (left, ic, FALSE, FALSE);
6951 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6953 /* move it to the result */
6954 size = AOP_SIZE (result);
6958 _startLazyDPSEvaluation ();
6961 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6963 emitcode ("rrc", "a");
6964 if (AOP_SIZE (result) > 1)
6965 aopPut (AOP (result), "a", offset--);
6967 _endLazyDPSEvaluation ();
6969 /* now we need to put the carry into the
6970 highest order byte of the result */
6971 if (AOP_SIZE (result) > 1)
6973 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6976 emitcode ("mov", "acc.7,c");
6977 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6978 freeAsmop (left, NULL, ic, TRUE);
6979 freeAsmop (result, NULL, ic, TRUE);
6982 /*-----------------------------------------------------------------*/
6983 /* genRLC - generate code for rotate left with carry */
6984 /*-----------------------------------------------------------------*/
6988 operand *left, *result;
6989 int size, offset = 0;
6992 D (emitcode (";", "genRLC ");
6995 /* rotate right with carry */
6996 left = IC_LEFT (ic);
6997 result = IC_RESULT (ic);
6998 aopOp (left, ic, FALSE, FALSE);
6999 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7001 /* move it to the result */
7002 size = AOP_SIZE (result);
7006 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
7008 emitcode ("add", "a,acc");
7009 if (AOP_SIZE (result) > 1)
7011 aopPut (AOP (result), "a", offset++);
7014 _startLazyDPSEvaluation ();
7017 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
7019 emitcode ("rlc", "a");
7020 if (AOP_SIZE (result) > 1)
7021 aopPut (AOP (result), "a", offset++);
7023 _endLazyDPSEvaluation ();
7025 /* now we need to put the carry into the
7026 highest order byte of the result */
7027 if (AOP_SIZE (result) > 1)
7029 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
7032 emitcode ("mov", "acc.0,c");
7033 aopPut (AOP (result), "a", 0);
7034 freeAsmop (left, NULL, ic, TRUE);
7035 freeAsmop (result, NULL, ic, TRUE);
7038 /*-----------------------------------------------------------------*/
7039 /* genGetHbit - generates code get highest order bit */
7040 /*-----------------------------------------------------------------*/
7042 genGetHbit (iCode * ic)
7044 operand *left, *result;
7045 left = IC_LEFT (ic);
7046 result = IC_RESULT (ic);
7047 aopOp (left, ic, FALSE, FALSE);
7048 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7050 D (emitcode (";", "genGetHbit ");
7053 /* get the highest order byte into a */
7054 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
7055 if (AOP_TYPE (result) == AOP_CRY)
7057 emitcode ("rlc", "a");
7062 emitcode ("rl", "a");
7063 emitcode ("anl", "a,#1");
7068 freeAsmop (left, NULL, ic, TRUE);
7069 freeAsmop (result, NULL, ic, TRUE);
7072 /*-----------------------------------------------------------------*/
7073 /* AccRol - rotate left accumulator by known count */
7074 /*-----------------------------------------------------------------*/
7076 AccRol (int shCount)
7078 shCount &= 0x0007; // shCount : 0..7
7085 emitcode ("rl", "a");
7088 emitcode ("rl", "a");
7089 emitcode ("rl", "a");
7092 emitcode ("swap", "a");
7093 emitcode ("rr", "a");
7096 emitcode ("swap", "a");
7099 emitcode ("swap", "a");
7100 emitcode ("rl", "a");
7103 emitcode ("rr", "a");
7104 emitcode ("rr", "a");
7107 emitcode ("rr", "a");
7112 /*-----------------------------------------------------------------*/
7113 /* AccLsh - left shift accumulator by known count */
7114 /*-----------------------------------------------------------------*/
7116 AccLsh (int shCount)
7121 emitcode ("add", "a,acc");
7122 else if (shCount == 2)
7124 emitcode ("add", "a,acc");
7125 emitcode ("add", "a,acc");
7129 /* rotate left accumulator */
7131 /* and kill the lower order bits */
7132 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7137 /*-----------------------------------------------------------------*/
7138 /* AccRsh - right shift accumulator by known count */
7139 /*-----------------------------------------------------------------*/
7141 AccRsh (int shCount)
7148 emitcode ("rrc", "a");
7152 /* rotate right accumulator */
7153 AccRol (8 - shCount);
7154 /* and kill the higher order bits */
7155 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7160 #ifdef BETTER_LITERAL_SHIFT
7161 /*-----------------------------------------------------------------*/
7162 /* AccSRsh - signed right shift accumulator by known count */
7163 /*-----------------------------------------------------------------*/
7165 AccSRsh (int shCount)
7172 emitcode ("mov", "c,acc.7");
7173 emitcode ("rrc", "a");
7175 else if (shCount == 2)
7177 emitcode ("mov", "c,acc.7");
7178 emitcode ("rrc", "a");
7179 emitcode ("mov", "c,acc.7");
7180 emitcode ("rrc", "a");
7184 tlbl = newiTempLabel (NULL);
7185 /* rotate right accumulator */
7186 AccRol (8 - shCount);
7187 /* and kill the higher order bits */
7188 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7189 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7190 emitcode ("orl", "a,#!constbyte",
7191 (unsigned char) ~SRMask[shCount]);
7192 emitcode ("", "!tlabeldef", tlbl->key + 100);
7198 #ifdef BETTER_LITERAL_SHIFT
7199 /*-----------------------------------------------------------------*/
7200 /* shiftR1Left2Result - shift right one byte from left to result */
7201 /*-----------------------------------------------------------------*/
7203 shiftR1Left2Result (operand * left, int offl,
7204 operand * result, int offr,
7205 int shCount, int sign)
7207 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7208 /* shift right accumulator */
7213 aopPut (AOP (result), "a", offr);
7217 #ifdef BETTER_LITERAL_SHIFT
7218 /*-----------------------------------------------------------------*/
7219 /* shiftL1Left2Result - shift left one byte from left to result */
7220 /*-----------------------------------------------------------------*/
7222 shiftL1Left2Result (operand * left, int offl,
7223 operand * result, int offr, int shCount)
7225 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7226 /* shift left accumulator */
7228 aopPut (AOP (result), "a", offr);
7232 #ifdef BETTER_LITERAL_SHIFT
7233 /*-----------------------------------------------------------------*/
7234 /* movLeft2Result - move byte from left to result */
7235 /*-----------------------------------------------------------------*/
7237 movLeft2Result (operand * left, int offl,
7238 operand * result, int offr, int sign)
7241 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7243 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
7245 if (*l == '@' && (IS_AOP_PREG (result)))
7247 emitcode ("mov", "a,%s", l);
7248 aopPut (AOP (result), "a", offr);
7254 aopPut (AOP (result), l, offr);
7258 /* MSB sign in acc.7 ! */
7259 if (getDataSize (left) == offl + 1)
7261 emitcode ("mov", "a,%s", l);
7262 aopPut (AOP (result), "a", offr);
7270 #ifdef BETTER_LITERAL_SHIFT
7271 /*-----------------------------------------------------------------*/
7272 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7273 /*-----------------------------------------------------------------*/
7277 emitcode ("rrc", "a");
7278 emitcode ("xch", "a,%s", x);
7279 emitcode ("rrc", "a");
7280 emitcode ("xch", "a,%s", x);
7284 #ifdef BETTER_LITERAL_SHIFT
7286 /*-----------------------------------------------------------------*/
7287 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7288 /*-----------------------------------------------------------------*/
7292 emitcode ("xch", "a,%s", x);
7293 emitcode ("rlc", "a");
7294 emitcode ("xch", "a,%s", x);
7295 emitcode ("rlc", "a");
7299 #ifdef BETTER_LITERAL_SHIFT
7300 /*-----------------------------------------------------------------*/
7301 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7302 /*-----------------------------------------------------------------*/
7306 emitcode ("xch", "a,%s", x);
7307 emitcode ("add", "a,acc");
7308 emitcode ("xch", "a,%s", x);
7309 emitcode ("rlc", "a");
7313 #ifdef BETTER_LITERAL_SHIFT
7314 /*-----------------------------------------------------------------*/
7315 /* AccAXLsh - left shift a:x by known count (0..7) */
7316 /*-----------------------------------------------------------------*/
7318 AccAXLsh (char *x, int shCount)
7333 case 5: // AAAAABBB:CCCCCDDD
7335 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7337 emitcode ("anl", "a,#!constbyte",
7338 SLMask[shCount]); // BBB00000:CCCCCDDD
7340 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7342 AccRol (shCount); // DDDCCCCC:BBB00000
7344 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7346 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7348 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7350 emitcode ("anl", "a,#!constbyte",
7351 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7353 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7355 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7358 case 6: // AAAAAABB:CCCCCCDD
7359 emitcode ("anl", "a,#!constbyte",
7360 SRMask[shCount]); // 000000BB:CCCCCCDD
7361 emitcode ("mov", "c,acc.0"); // c = B
7362 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7364 AccAXRrl1 (x); // BCCCCCCD:D000000B
7365 AccAXRrl1 (x); // BBCCCCCC:DD000000
7367 emitcode("rrc","a");
7368 emitcode("xch","a,%s", x);
7369 emitcode("rrc","a");
7370 emitcode("mov","c,acc.0"); //<< get correct bit
7371 emitcode("xch","a,%s", x);
7373 emitcode("rrc","a");
7374 emitcode("xch","a,%s", x);
7375 emitcode("rrc","a");
7376 emitcode("xch","a,%s", x);
7379 case 7: // a:x <<= 7
7381 emitcode ("anl", "a,#!constbyte",
7382 SRMask[shCount]); // 0000000B:CCCCCCCD
7384 emitcode ("mov", "c,acc.0"); // c = B
7386 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7388 AccAXRrl1 (x); // BCCCCCCC:D0000000
7397 #ifdef BETTER_LITERAL_SHIFT
7399 /*-----------------------------------------------------------------*/
7400 /* AccAXRsh - right shift a:x known count (0..7) */
7401 /*-----------------------------------------------------------------*/
7403 AccAXRsh (char *x, int shCount)
7411 AccAXRrl1 (x); // 0->a:x
7416 AccAXRrl1 (x); // 0->a:x
7419 AccAXRrl1 (x); // 0->a:x
7424 case 5: // AAAAABBB:CCCCCDDD = a:x
7426 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7428 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7430 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7432 emitcode ("anl", "a,#!constbyte",
7433 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7435 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7437 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7439 emitcode ("anl", "a,#!constbyte",
7440 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7442 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7444 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7446 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7449 case 6: // AABBBBBB:CCDDDDDD
7451 emitcode ("mov", "c,acc.7");
7452 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7454 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7456 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7458 emitcode ("anl", "a,#!constbyte",
7459 SRMask[shCount]); // 000000AA:BBBBBBCC
7462 case 7: // ABBBBBBB:CDDDDDDD
7464 emitcode ("mov", "c,acc.7"); // c = A
7466 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7468 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7470 emitcode ("anl", "a,#!constbyte",
7471 SRMask[shCount]); // 0000000A:BBBBBBBC
7480 #ifdef BETTER_LITERAL_SHIFT
7481 /*-----------------------------------------------------------------*/
7482 /* AccAXRshS - right shift signed a:x known count (0..7) */
7483 /*-----------------------------------------------------------------*/
7485 AccAXRshS (char *x, int shCount)
7493 emitcode ("mov", "c,acc.7");
7494 AccAXRrl1 (x); // s->a:x
7498 emitcode ("mov", "c,acc.7");
7499 AccAXRrl1 (x); // s->a:x
7501 emitcode ("mov", "c,acc.7");
7502 AccAXRrl1 (x); // s->a:x
7507 case 5: // AAAAABBB:CCCCCDDD = a:x
7509 tlbl = newiTempLabel (NULL);
7510 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7512 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7514 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7516 emitcode ("anl", "a,#!constbyte",
7517 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7519 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7521 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7523 emitcode ("anl", "a,#!constbyte",
7524 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7526 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7528 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7530 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7532 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7533 emitcode ("orl", "a,#!constbyte",
7534 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7536 emitcode ("", "!tlabeldef", tlbl->key + 100);
7537 break; // SSSSAAAA:BBBCCCCC
7539 case 6: // AABBBBBB:CCDDDDDD
7541 tlbl = newiTempLabel (NULL);
7542 emitcode ("mov", "c,acc.7");
7543 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7545 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7547 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7549 emitcode ("anl", "a,#!constbyte",
7550 SRMask[shCount]); // 000000AA:BBBBBBCC
7552 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7553 emitcode ("orl", "a,#!constbyte",
7554 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7556 emitcode ("", "!tlabeldef", tlbl->key + 100);
7558 case 7: // ABBBBBBB:CDDDDDDD
7560 tlbl = newiTempLabel (NULL);
7561 emitcode ("mov", "c,acc.7"); // c = A
7563 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7565 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7567 emitcode ("anl", "a,#!constbyte",
7568 SRMask[shCount]); // 0000000A:BBBBBBBC
7570 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7571 emitcode ("orl", "a,#!constbyte",
7572 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7574 emitcode ("", "!tlabeldef", tlbl->key + 100);
7582 #ifdef BETTER_LITERAL_SHIFT
7584 _loadLeftIntoAx(char **lsb,
7590 // Get the initial value from left into a pair of registers.
7591 // MSB must be in A, LSB can be any register.
7593 // If the result is held in registers, it is an optimization
7594 // if the LSB can be held in the register which will hold the,
7595 // result LSB since this saves us from having to copy it into
7596 // the result following AccAXLsh.
7598 // If the result is addressed indirectly, this is not a gain.
7599 if (AOP_NEEDSACC(result))
7603 _startLazyDPSEvaluation();
7604 if (AOP_TYPE(left) == AOP_DPTR2)
7607 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
7608 // get LSB in DP2_RESULT_REG.
7609 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
7610 assert(!strcmp(leftByte, DP2_RESULT_REG));
7614 // get LSB into DP2_RESULT_REG
7615 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
7616 if (strcmp(leftByte, DP2_RESULT_REG))
7619 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7622 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
7623 assert(strcmp(leftByte, DP2_RESULT_REG));
7626 _endLazyDPSEvaluation();
7627 *lsb = DP2_RESULT_REG;
7631 if (sameRegs (AOP (result), AOP (left)) &&
7632 ((offl + MSB16) == offr))
7634 /* don't crash result[offr] */
7635 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
7636 emitcode ("xch", "a,%s",
7637 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
7641 movLeft2Result (left, offl, result, offr, 0);
7642 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
7644 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
7645 assert(strcmp(*lsb,"a"));
7650 _storeAxResults(char *lsb,
7654 _startLazyDPSEvaluation();
7655 if (AOP_NEEDSACC(result))
7657 /* We have to explicitly update the result LSB.
7659 emitcode("xch","a,%s", lsb);
7660 aopPut(AOP(result), "a", offr);
7661 emitcode("mov","a,%s", lsb);
7663 if (getDataSize (result) > 1)
7665 aopPut (AOP (result), "a", offr + MSB16);
7667 _endLazyDPSEvaluation();
7670 /*-----------------------------------------------------------------*/
7671 /* shiftL2Left2Result - shift left two bytes from left to result */
7672 /*-----------------------------------------------------------------*/
7674 shiftL2Left2Result (operand * left, int offl,
7675 operand * result, int offr, int shCount)
7679 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7681 AccAXLsh (lsb, shCount);
7683 _storeAxResults(lsb, result, offr);
7687 #ifdef BETTER_LITERAL_SHIFT
7688 /*-----------------------------------------------------------------*/
7689 /* shiftR2Left2Result - shift right two bytes from left to result */
7690 /*-----------------------------------------------------------------*/
7692 shiftR2Left2Result (operand * left, int offl,
7693 operand * result, int offr,
7694 int shCount, int sign)
7698 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7700 /* a:x >> shCount (x = lsb(result)) */
7703 AccAXRshS(lsb, shCount);
7707 AccAXRsh(lsb, shCount);
7710 _storeAxResults(lsb, result, offr);
7716 /*-----------------------------------------------------------------*/
7717 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7718 /*-----------------------------------------------------------------*/
7720 shiftLLeftOrResult (operand * left, int offl,
7721 operand * result, int offr, int shCount)
7723 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7724 /* shift left accumulator */
7726 /* or with result */
7727 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7728 /* back to result */
7729 aopPut (AOP (result), "a", offr);
7735 /*-----------------------------------------------------------------*/
7736 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7737 /*-----------------------------------------------------------------*/
7739 shiftRLeftOrResult (operand * left, int offl,
7740 operand * result, int offr, int shCount)
7742 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7743 /* shift right accumulator */
7745 /* or with result */
7746 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7747 /* back to result */
7748 aopPut (AOP (result), "a", offr);
7752 #ifdef BETTER_LITERAL_SHIFT
7753 /*-----------------------------------------------------------------*/
7754 /* genlshOne - left shift a one byte quantity by known count */
7755 /*-----------------------------------------------------------------*/
7757 genlshOne (operand * result, operand * left, int shCount)
7759 D (emitcode (";", "genlshOne "););
7760 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7764 #ifdef BETTER_LITERAL_SHIFT
7765 /*-----------------------------------------------------------------*/
7766 /* genlshTwo - left shift two bytes by known amount != 0 */
7767 /*-----------------------------------------------------------------*/
7769 genlshTwo (operand * result, operand * left, int shCount)
7773 D (emitcode (";", "genlshTwo "););
7775 size = getDataSize (result);
7777 /* if shCount >= 8 */
7782 _startLazyDPSEvaluation();
7788 _endLazyDPSEvaluation();
7789 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7790 aopPut (AOP (result), zero, LSB);
7794 movLeft2Result (left, LSB, result, MSB16, 0);
7795 aopPut (AOP (result), zero, LSB);
7796 _endLazyDPSEvaluation();
7801 aopPut (AOP (result), zero, LSB);
7802 _endLazyDPSEvaluation();
7806 /* 1 <= shCount <= 7 */
7811 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7815 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7823 /*-----------------------------------------------------------------*/
7824 /* shiftLLong - shift left one long from left to result */
7825 /* offl = LSB or MSB16 */
7826 /*-----------------------------------------------------------------*/
7828 shiftLLong (operand * left, operand * result, int offr)
7831 int size = AOP_SIZE (result);
7833 if (size >= LSB + offr)
7835 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
7837 emitcode ("add", "a,acc");
7838 if (sameRegs (AOP (left), AOP (result)) &&
7839 size >= MSB16 + offr && offr != LSB)
7840 emitcode ("xch", "a,%s",
7841 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
7843 aopPut (AOP (result), "a", LSB + offr);
7846 if (size >= MSB16 + offr)
7848 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7850 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
7853 emitcode ("rlc", "a");
7854 if (sameRegs (AOP (left), AOP (result)) &&
7855 size >= MSB24 + offr && offr != LSB)
7856 emitcode ("xch", "a,%s",
7857 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
7859 aopPut (AOP (result), "a", MSB16 + offr);
7862 if (size >= MSB24 + offr)
7864 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7866 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
7869 emitcode ("rlc", "a");
7870 if (sameRegs (AOP (left), AOP (result)) &&
7871 size >= MSB32 + offr && offr != LSB)
7872 emitcode ("xch", "a,%s",
7873 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
7875 aopPut (AOP (result), "a", MSB24 + offr);
7878 if (size > MSB32 + offr)
7880 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7882 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7885 emitcode ("rlc", "a");
7886 aopPut (AOP (result), "a", MSB32 + offr);
7889 aopPut (AOP (result), zero, LSB);
7895 /*-----------------------------------------------------------------*/
7896 /* genlshFour - shift four byte by a known amount != 0 */
7897 /*-----------------------------------------------------------------*/
7899 genlshFour (operand * result, operand * left, int shCount)
7903 D (emitcode (";", "genlshFour ");
7906 size = AOP_SIZE (result);
7908 /* if shifting more that 3 bytes */
7913 /* lowest order of left goes to the highest
7914 order of the destination */
7915 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7917 movLeft2Result (left, LSB, result, MSB32, 0);
7918 aopPut (AOP (result), zero, LSB);
7919 aopPut (AOP (result), zero, MSB16);
7920 aopPut (AOP (result), zero, MSB24);
7924 /* more than two bytes */
7925 else if (shCount >= 16)
7927 /* lower order two bytes goes to higher order two bytes */
7929 /* if some more remaining */
7931 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7934 movLeft2Result (left, MSB16, result, MSB32, 0);
7935 movLeft2Result (left, LSB, result, MSB24, 0);
7937 aopPut (AOP (result), zero, MSB16);
7938 aopPut (AOP (result), zero, LSB);
7942 /* if more than 1 byte */
7943 else if (shCount >= 8)
7945 /* lower order three bytes goes to higher order three bytes */
7950 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7952 movLeft2Result (left, LSB, result, MSB16, 0);
7958 movLeft2Result (left, MSB24, result, MSB32, 0);
7959 movLeft2Result (left, MSB16, result, MSB24, 0);
7960 movLeft2Result (left, LSB, result, MSB16, 0);
7961 aopPut (AOP (result), zero, LSB);
7963 else if (shCount == 1)
7964 shiftLLong (left, result, MSB16);
7967 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7968 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7969 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7970 aopPut (AOP (result), zero, LSB);
7975 /* 1 <= shCount <= 7 */
7976 else if (shCount <= 2)
7978 shiftLLong (left, result, LSB);
7980 shiftLLong (result, result, LSB);
7982 /* 3 <= shCount <= 7, optimize */
7985 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7986 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7987 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7992 #ifdef BETTER_LITERAL_SHIFT
7993 /*-----------------------------------------------------------------*/
7994 /* genLeftShiftLiteral - left shifting by known count */
7995 /*-----------------------------------------------------------------*/
7997 genLeftShiftLiteral (operand * left,
8002 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8005 size = getSize (operandType (result));
8007 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8009 /* We only handle certain easy cases so far. */
8011 && (shCount < (size * 8))
8015 D(emitcode (";", "genLeftShiftLiteral wimping out"););
8019 freeAsmop (right, NULL, ic, TRUE);
8021 aopOp(left, ic, FALSE, FALSE);
8022 aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
8025 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8027 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8028 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8030 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8033 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8035 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8036 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8038 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8044 emitcode ("; shift left ", "result %d, left %d", size,
8048 /* I suppose that the left size >= result size */
8051 _startLazyDPSEvaluation();
8054 movLeft2Result (left, size, result, size, 0);
8056 _endLazyDPSEvaluation();
8058 else if (shCount >= (size * 8))
8060 _startLazyDPSEvaluation();
8063 aopPut (AOP (result), zero, size);
8065 _endLazyDPSEvaluation();
8072 genlshOne (result, left, shCount);
8076 genlshTwo (result, left, shCount);
8080 genlshFour (result, left, shCount);
8084 fprintf(stderr, "*** ack! mystery literal shift!\n");
8088 freeAsmop (left, NULL, ic, TRUE);
8089 freeAsmop (result, NULL, ic, TRUE);
8094 /*-----------------------------------------------------------------*/
8095 /* genLeftShift - generates code for left shifting */
8096 /*-----------------------------------------------------------------*/
8098 genLeftShift (iCode * ic)
8100 operand *left, *right, *result;
8103 symbol *tlbl, *tlbl1;
8105 D (emitcode (";", "genLeftShift "););
8107 right = IC_RIGHT (ic);
8108 left = IC_LEFT (ic);
8109 result = IC_RESULT (ic);
8111 aopOp (right, ic, FALSE, FALSE);
8114 #ifdef BETTER_LITERAL_SHIFT
8115 /* if the shift count is known then do it
8116 as efficiently as possible */
8117 if (AOP_TYPE (right) == AOP_LIT)
8119 if (genLeftShiftLiteral (left, right, result, ic))
8126 /* shift count is unknown then we have to form
8127 a loop get the loop count in B : Note: we take
8128 only the lower order byte since shifting
8129 more that 32 bits make no sense anyway, ( the
8130 largest size of an object can be only 32 bits ) */
8132 if (AOP_TYPE (right) == AOP_LIT)
8134 /* Really should be handled by genLeftShiftLiteral,
8135 * but since I'm too lazy to fix that today, at least we can make
8136 * some small improvement.
8138 emitcode("mov", "b,#!constbyte",
8139 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8143 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8144 emitcode ("inc", "b");
8146 freeAsmop (right, NULL, ic, TRUE);
8147 aopOp (left, ic, FALSE, FALSE);
8148 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8150 /* now move the left to the result if they are not the
8152 if (!sameRegs (AOP (left), AOP (result)) &&
8153 AOP_SIZE (result) > 1)
8156 size = AOP_SIZE (result);
8158 _startLazyDPSEvaluation ();
8161 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8162 if (*l == '@' && (IS_AOP_PREG (result)))
8165 emitcode ("mov", "a,%s", l);
8166 aopPut (AOP (result), "a", offset);
8169 aopPut (AOP (result), l, offset);
8172 _endLazyDPSEvaluation ();
8175 tlbl = newiTempLabel (NULL);
8176 size = AOP_SIZE (result);
8178 tlbl1 = newiTempLabel (NULL);
8180 /* if it is only one byte then */
8183 symbol *tlbl1 = newiTempLabel (NULL);
8185 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8187 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8188 emitcode ("", "!tlabeldef", tlbl->key + 100);
8189 emitcode ("add", "a,acc");
8190 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8191 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8192 aopPut (AOP (result), "a", 0);
8196 reAdjustPreg (AOP (result));
8198 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8199 emitcode ("", "!tlabeldef", tlbl->key + 100);
8200 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8202 emitcode ("add", "a,acc");
8203 aopPut (AOP (result), "a", offset++);
8204 _startLazyDPSEvaluation ();
8207 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8209 emitcode ("rlc", "a");
8210 aopPut (AOP (result), "a", offset++);
8212 _endLazyDPSEvaluation ();
8213 reAdjustPreg (AOP (result));
8215 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8216 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8218 freeAsmop (left, NULL, ic, TRUE);
8219 freeAsmop (result, NULL, ic, TRUE);
8222 #ifdef BETTER_LITERAL_SHIFT
8223 /*-----------------------------------------------------------------*/
8224 /* genrshOne - right shift a one byte quantity by known count */
8225 /*-----------------------------------------------------------------*/
8227 genrshOne (operand * result, operand * left,
8228 int shCount, int sign)
8230 D (emitcode (";", "genrshOne"););
8231 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8235 #ifdef BETTER_LITERAL_SHIFT
8236 /*-----------------------------------------------------------------*/
8237 /* genrshTwo - right shift two bytes by known amount != 0 */
8238 /*-----------------------------------------------------------------*/
8240 genrshTwo (operand * result, operand * left,
8241 int shCount, int sign)
8243 D (emitcode (";", "genrshTwo"););
8245 /* if shCount >= 8 */
8249 _startLazyDPSEvaluation();
8252 shiftR1Left2Result (left, MSB16, result, LSB,
8257 movLeft2Result (left, MSB16, result, LSB, sign);
8259 addSign (result, MSB16, sign);
8260 _endLazyDPSEvaluation();
8263 /* 1 <= shCount <= 7 */
8266 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8273 /*-----------------------------------------------------------------*/
8274 /* shiftRLong - shift right one long from left to result */
8275 /* offl = LSB or MSB16 */
8276 /*-----------------------------------------------------------------*/
8278 shiftRLong (operand * left, int offl,
8279 operand * result, int sign)
8281 int isSameRegs=sameRegs(AOP(left),AOP(result));
8283 if (isSameRegs && offl>1) {
8284 // we are in big trouble, but this shouldn't happen
8285 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8288 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
8293 emitcode ("rlc", "a");
8294 emitcode ("subb", "a,acc");
8295 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
8297 aopPut (AOP(result), zero, MSB32);
8302 emitcode ("clr", "c");
8304 emitcode ("mov", "c,acc.7");
8307 emitcode ("rrc", "a");
8309 if (isSameRegs && offl==MSB16) {
8310 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
8312 aopPut (AOP (result), "a", MSB32);
8313 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
8316 emitcode ("rrc", "a");
8317 if (isSameRegs && offl==1) {
8318 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
8320 aopPut (AOP (result), "a", MSB24);
8321 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
8323 emitcode ("rrc", "a");
8324 aopPut (AOP (result), "a", MSB16 - offl);
8328 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
8329 emitcode ("rrc", "a");
8330 aopPut (AOP (result), "a", LSB);
8337 /*-----------------------------------------------------------------*/
8338 /* genrshFour - shift four byte by a known amount != 0 */
8339 /*-----------------------------------------------------------------*/
8341 genrshFour (operand * result, operand * left,
8342 int shCount, int sign)
8344 D (emitcode (";", "genrshFour");
8347 /* if shifting more that 3 bytes */
8352 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8354 movLeft2Result (left, MSB32, result, LSB, sign);
8355 addSign (result, MSB16, sign);
8357 else if (shCount >= 16)
8361 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8364 movLeft2Result (left, MSB24, result, LSB, 0);
8365 movLeft2Result (left, MSB32, result, MSB16, sign);
8367 addSign (result, MSB24, sign);
8369 else if (shCount >= 8)
8373 shiftRLong (left, MSB16, result, sign);
8374 else if (shCount == 0)
8376 movLeft2Result (left, MSB16, result, LSB, 0);
8377 movLeft2Result (left, MSB24, result, MSB16, 0);
8378 movLeft2Result (left, MSB32, result, MSB24, sign);
8379 addSign (result, MSB32, sign);
8383 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8384 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8385 /* the last shift is signed */
8386 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8387 addSign (result, MSB32, sign);
8391 { /* 1 <= shCount <= 7 */
8394 shiftRLong (left, LSB, result, sign);
8396 shiftRLong (result, LSB, result, sign);
8400 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8401 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8402 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8408 #ifdef BETTER_LITERAL_SHIFT
8409 /*-----------------------------------------------------------------*/
8410 /* genRightShiftLiteral - right shifting by known count */
8411 /*-----------------------------------------------------------------*/
8413 genRightShiftLiteral (operand * left,
8419 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8422 size = getSize (operandType (result));
8424 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8426 /* We only handle certain easy cases so far. */
8428 && (shCount < (size * 8))
8432 D(emitcode (";", "genRightShiftLiteral wimping out"););
8436 freeAsmop (right, NULL, ic, TRUE);
8438 aopOp (left, ic, FALSE, FALSE);
8439 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8442 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8446 /* test the LEFT size !!! */
8448 /* I suppose that the left size >= result size */
8451 size = getDataSize (result);
8452 _startLazyDPSEvaluation();
8455 movLeft2Result (left, size, result, size, 0);
8457 _endLazyDPSEvaluation();
8459 else if (shCount >= (size * 8))
8463 /* get sign in acc.7 */
8464 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
8466 addSign (result, LSB, sign);
8473 genrshOne (result, left, shCount, sign);
8477 genrshTwo (result, left, shCount, sign);
8481 genrshFour (result, left, shCount, sign);
8488 freeAsmop (left, NULL, ic, TRUE);
8489 freeAsmop (result, NULL, ic, TRUE);
8495 /*-----------------------------------------------------------------*/
8496 /* genSignedRightShift - right shift of signed number */
8497 /*-----------------------------------------------------------------*/
8499 genSignedRightShift (iCode * ic)
8501 operand *right, *left, *result;
8504 symbol *tlbl, *tlbl1;
8506 D (emitcode (";", "genSignedRightShift "););
8508 /* we do it the hard way put the shift count in b
8509 and loop thru preserving the sign */
8511 right = IC_RIGHT (ic);
8512 left = IC_LEFT (ic);
8513 result = IC_RESULT (ic);
8515 aopOp (right, ic, FALSE, FALSE);
8517 #ifdef BETTER_LITERAL_SHIFT
8518 if (AOP_TYPE (right) == AOP_LIT)
8520 if (genRightShiftLiteral (left, right, result, ic, 1))
8526 /* shift count is unknown then we have to form
8527 a loop get the loop count in B : Note: we take
8528 only the lower order byte since shifting
8529 more that 32 bits make no sense anyway, ( the
8530 largest size of an object can be only 32 bits ) */
8532 if (AOP_TYPE (right) == AOP_LIT)
8534 /* Really should be handled by genRightShiftLiteral,
8535 * but since I'm too lazy to fix that today, at least we can make
8536 * some small improvement.
8538 emitcode("mov", "b,#!constbyte",
8539 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8543 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8544 emitcode ("inc", "b");
8546 freeAsmop (right, NULL, ic, TRUE);
8547 aopOp (left, ic, FALSE, FALSE);
8548 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8550 /* now move the left to the result if they are not the
8552 if (!sameRegs (AOP (left), AOP (result)) &&
8553 AOP_SIZE (result) > 1)
8556 size = AOP_SIZE (result);
8558 _startLazyDPSEvaluation ();
8561 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8562 if (*l == '@' && IS_AOP_PREG (result))
8565 emitcode ("mov", "a,%s", l);
8566 aopPut (AOP (result), "a", offset);
8569 aopPut (AOP (result), l, offset);
8572 _endLazyDPSEvaluation ();
8575 /* mov the highest order bit to OVR */
8576 tlbl = newiTempLabel (NULL);
8577 tlbl1 = newiTempLabel (NULL);
8579 size = AOP_SIZE (result);
8581 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
8582 emitcode ("rlc", "a");
8583 emitcode ("mov", "ov,c");
8584 /* if it is only one byte then */
8587 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8589 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8590 emitcode ("", "!tlabeldef", tlbl->key + 100);
8591 emitcode ("mov", "c,ov");
8592 emitcode ("rrc", "a");
8593 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8594 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8595 aopPut (AOP (result), "a", 0);
8599 reAdjustPreg (AOP (result));
8600 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8601 emitcode ("", "!tlabeldef", tlbl->key + 100);
8602 emitcode ("mov", "c,ov");
8603 _startLazyDPSEvaluation ();
8606 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8608 emitcode ("rrc", "a");
8609 aopPut (AOP (result), "a", offset--);
8611 _endLazyDPSEvaluation ();
8612 reAdjustPreg (AOP (result));
8613 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8614 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8617 freeAsmop (left, NULL, ic, TRUE);
8618 freeAsmop (result, NULL, ic, TRUE);
8621 /*-----------------------------------------------------------------*/
8622 /* genRightShift - generate code for right shifting */
8623 /*-----------------------------------------------------------------*/
8625 genRightShift (iCode * ic)
8627 operand *right, *left, *result;
8631 symbol *tlbl, *tlbl1;
8633 D (emitcode (";", "genRightShift "););
8635 /* if signed then we do it the hard way preserve the
8636 sign bit moving it inwards */
8637 retype = getSpec (operandType (IC_RESULT (ic)));
8639 if (!SPEC_USIGN (retype))
8641 genSignedRightShift (ic);
8645 /* signed & unsigned types are treated the same : i.e. the
8646 signed is NOT propagated inwards : quoting from the
8647 ANSI - standard : "for E1 >> E2, is equivalent to division
8648 by 2**E2 if unsigned or if it has a non-negative value,
8649 otherwise the result is implementation defined ", MY definition
8650 is that the sign does not get propagated */
8652 right = IC_RIGHT (ic);
8653 left = IC_LEFT (ic);
8654 result = IC_RESULT (ic);
8656 aopOp (right, ic, FALSE, FALSE);
8658 #ifdef BETTER_LITERAL_SHIFT
8659 /* if the shift count is known then do it
8660 as efficiently as possible */
8661 if (AOP_TYPE (right) == AOP_LIT)
8663 if (genRightShiftLiteral (left, right, result, ic, 0))
8670 /* shift count is unknown then we have to form
8671 a loop get the loop count in B : Note: we take
8672 only the lower order byte since shifting
8673 more that 32 bits make no sense anyway, ( the
8674 largest size of an object can be only 32 bits ) */
8676 if (AOP_TYPE (right) == AOP_LIT)
8678 /* Really should be handled by genRightShiftLiteral,
8679 * but since I'm too lazy to fix that today, at least we can make
8680 * some small improvement.
8682 emitcode("mov", "b,#!constbyte",
8683 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8687 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8688 emitcode ("inc", "b");
8690 freeAsmop (right, NULL, ic, TRUE);
8691 aopOp (left, ic, FALSE, FALSE);
8692 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8694 /* now move the left to the result if they are not the
8696 if (!sameRegs (AOP (left), AOP (result)) &&
8697 AOP_SIZE (result) > 1)
8700 size = AOP_SIZE (result);
8702 _startLazyDPSEvaluation ();
8705 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8706 if (*l == '@' && IS_AOP_PREG (result))
8709 emitcode ("mov", "a,%s", l);
8710 aopPut (AOP (result), "a", offset);
8713 aopPut (AOP (result), l, offset);
8716 _endLazyDPSEvaluation ();
8719 tlbl = newiTempLabel (NULL);
8720 tlbl1 = newiTempLabel (NULL);
8721 size = AOP_SIZE (result);
8724 /* if it is only one byte then */
8727 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8729 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8730 emitcode ("", "!tlabeldef", tlbl->key + 100);
8732 emitcode ("rrc", "a");
8733 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8734 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8735 aopPut (AOP (result), "a", 0);
8739 reAdjustPreg (AOP (result));
8740 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8741 emitcode ("", "!tlabeldef", tlbl->key + 100);
8743 _startLazyDPSEvaluation ();
8746 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8748 emitcode ("rrc", "a");
8749 aopPut (AOP (result), "a", offset--);
8751 _endLazyDPSEvaluation ();
8752 reAdjustPreg (AOP (result));
8754 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8755 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8758 freeAsmop (left, NULL, ic, TRUE);
8759 freeAsmop (result, NULL, ic, TRUE);
8762 /*-----------------------------------------------------------------*/
8763 /* genUnpackBits - generates code for unpacking bits */
8764 /*-----------------------------------------------------------------*/
8766 genUnpackBits (operand * result, char *rname, int ptype)
8773 D (emitcode (";", "genUnpackBits ");
8776 etype = getSpec (operandType (result));
8778 /* read the first byte */
8784 emitcode ("mov", "a,@%s", rname);
8788 emitcode ("movx", "a,@%s", rname);
8792 emitcode ("movx", "a,@dptr");
8796 emitcode ("clr", "a");
8797 emitcode ("movc", "a,@a+dptr");
8801 emitcode ("lcall", "__gptrget");
8805 /* if we have bitdisplacement then it fits */
8806 /* into this byte completely or if length is */
8807 /* less than a byte */
8808 if ((shCnt = SPEC_BSTR (etype)) ||
8809 (SPEC_BLEN (etype) <= 8))
8812 /* shift right acc */
8815 emitcode ("anl", "a,#!constbyte",
8816 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8817 aopPut (AOP (result), "a", offset);
8821 /* bit field did not fit in a byte */
8822 rlen = SPEC_BLEN (etype) - 8;
8823 aopPut (AOP (result), "a", offset++);
8832 emitcode ("inc", "%s", rname);
8833 emitcode ("mov", "a,@%s", rname);
8837 emitcode ("inc", "%s", rname);
8838 emitcode ("movx", "a,@%s", rname);
8842 emitcode ("inc", "dptr");
8843 emitcode ("movx", "a,@dptr");
8847 emitcode ("clr", "a");
8848 emitcode ("inc", "dptr");
8849 emitcode ("movc", "a,@a+dptr");
8853 emitcode ("inc", "dptr");
8854 emitcode ("lcall", "__gptrget");
8859 /* if we are done */
8863 aopPut (AOP (result), "a", offset++);
8869 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (rlen));
8870 aopPut (AOP (result), "a", offset);
8877 /*-----------------------------------------------------------------*/
8878 /* genDataPointerGet - generates code when ptr offset is known */
8879 /*-----------------------------------------------------------------*/
8881 genDataPointerGet (operand * left,
8887 int size, offset = 0;
8888 aopOp (result, ic, TRUE, FALSE);
8890 /* get the string representation of the name */
8891 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8892 size = AOP_SIZE (result);
8893 _startLazyDPSEvaluation ();
8897 sprintf (buffer, "(%s + %d)", l + 1, offset);
8899 sprintf (buffer, "%s", l + 1);
8900 aopPut (AOP (result), buffer, offset++);
8902 _endLazyDPSEvaluation ();
8904 freeAsmop (left, NULL, ic, TRUE);
8905 freeAsmop (result, NULL, ic, TRUE);
8908 /*-----------------------------------------------------------------*/
8909 /* genNearPointerGet - emitcode for near pointer fetch */
8910 /*-----------------------------------------------------------------*/
8912 genNearPointerGet (operand * left,
8920 sym_link *rtype, *retype, *letype;
8921 sym_link *ltype = operandType (left);
8924 rtype = operandType (result);
8925 retype = getSpec (rtype);
8926 letype = getSpec (ltype);
8928 aopOp (left, ic, FALSE, FALSE);
8930 /* if left is rematerialisable and
8931 result is not bit variable type and
8932 the left is pointer to data space i.e
8933 lower 128 bytes of space */
8934 if (AOP_TYPE (left) == AOP_IMMD &&
8935 !IS_BITVAR (retype) &&
8936 !IS_BITVAR (letype) &&
8937 DCL_TYPE (ltype) == POINTER)
8939 genDataPointerGet (left, result, ic);
8943 /* if the value is already in a pointer register
8944 then don't need anything more */
8945 if (!AOP_INPREG (AOP (left)))
8947 /* otherwise get a free pointer register */
8949 preg = getFreePtr (ic, &aop, FALSE);
8950 emitcode ("mov", "%s,%s",
8952 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8956 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8958 freeAsmop (left, NULL, ic, TRUE);
8959 aopOp (result, ic, FALSE, FALSE);
8961 /* if bitfield then unpack the bits */
8962 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8963 genUnpackBits (result, rname, POINTER);
8966 /* we have can just get the values */
8967 int size = AOP_SIZE (result);
8972 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8975 emitcode ("mov", "a,@%s", rname);
8976 aopPut (AOP (result), "a", offset);
8980 sprintf (buffer, "@%s", rname);
8981 aopPut (AOP (result), buffer, offset);
8985 emitcode ("inc", "%s", rname);
8989 /* now some housekeeping stuff */
8992 /* we had to allocate for this iCode */
8993 if (pi) { /* post increment present */
8994 aopPut(AOP ( left ),rname,0);
8996 freeAsmop (NULL, aop, ic, TRUE);
9000 /* we did not allocate which means left
9001 already in a pointer register, then
9002 if size > 0 && this could be used again
9003 we have to point it back to where it
9005 if (AOP_SIZE (result) > 1 &&
9006 !OP_SYMBOL (left)->remat &&
9007 (OP_SYMBOL (left)->liveTo > ic->seq ||
9011 int size = AOP_SIZE (result) - 1;
9013 emitcode ("dec", "%s", rname);
9018 freeAsmop (result, NULL, ic, TRUE);
9019 if (pi) pi->generated = 1;
9022 /*-----------------------------------------------------------------*/
9023 /* genPagedPointerGet - emitcode for paged pointer fetch */
9024 /*-----------------------------------------------------------------*/
9026 genPagedPointerGet (operand * left,
9034 sym_link *rtype, *retype, *letype;
9036 rtype = operandType (result);
9037 retype = getSpec (rtype);
9038 letype = getSpec (operandType (left));
9039 aopOp (left, ic, FALSE, FALSE);
9041 /* if the value is already in a pointer register
9042 then don't need anything more */
9043 if (!AOP_INPREG (AOP (left)))
9045 /* otherwise get a free pointer register */
9047 preg = getFreePtr (ic, &aop, FALSE);
9048 emitcode ("mov", "%s,%s",
9050 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
9054 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
9056 freeAsmop (left, NULL, ic, TRUE);
9057 aopOp (result, ic, FALSE, FALSE);
9059 /* if bitfield then unpack the bits */
9060 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9061 genUnpackBits (result, rname, PPOINTER);
9064 /* we have can just get the values */
9065 int size = AOP_SIZE (result);
9071 emitcode ("movx", "a,@%s", rname);
9072 aopPut (AOP (result), "a", offset);
9077 emitcode ("inc", "%s", rname);
9081 /* now some housekeeping stuff */
9084 /* we had to allocate for this iCode */
9085 if (pi) aopPut ( AOP (left), rname, 0);
9086 freeAsmop (NULL, aop, ic, TRUE);
9090 /* we did not allocate which means left
9091 already in a pointer register, then
9092 if size > 0 && this could be used again
9093 we have to point it back to where it
9095 if (AOP_SIZE (result) > 1 &&
9096 !OP_SYMBOL (left)->remat &&
9097 (OP_SYMBOL (left)->liveTo > ic->seq ||
9101 int size = AOP_SIZE (result) - 1;
9103 emitcode ("dec", "%s", rname);
9108 freeAsmop (result, NULL, ic, TRUE);
9109 if (pi) pi->generated = 1;
9112 /*-----------------------------------------------------------------*/
9113 /* genFarPointerGet - gget value from far space */
9114 /*-----------------------------------------------------------------*/
9116 genFarPointerGet (operand * left,
9117 operand * result, iCode * ic, iCode *pi)
9119 int size, offset, dopi=1;
9120 sym_link *retype = getSpec (operandType (result));
9121 sym_link *letype = getSpec (operandType (left));
9122 D (emitcode (";", "genFarPointerGet");
9125 aopOp (left, ic, FALSE, FALSE);
9127 /* if the operand is already in dptr
9128 then we do nothing else we move the value to dptr */
9129 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9131 /* if this is remateriazable */
9132 if (AOP_TYPE (left) == AOP_IMMD)
9134 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9138 /* we need to get it byte by byte */
9139 _startLazyDPSEvaluation ();
9140 if (AOP_TYPE (left) != AOP_DPTR)
9142 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9143 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9144 if (options.model == MODEL_FLAT24)
9145 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9149 /* We need to generate a load to DPTR indirect through DPTR. */
9150 D (emitcode (";", "genFarPointerGet -- indirection special case.");
9152 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
9153 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
9154 if (options.model == MODEL_FLAT24)
9155 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9156 emitcode ("pop", "dph");
9157 emitcode ("pop", "dpl");
9160 _endLazyDPSEvaluation ();
9163 /* so dptr know contains the address */
9164 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9166 /* if bit then unpack */
9167 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9168 if (AOP_INDPTRn(left)) {
9169 genSetDPTR(AOP(left)->aopu.dptr);
9171 genUnpackBits (result, "dptr", FPOINTER);
9172 if (AOP_INDPTRn(left)) {
9177 size = AOP_SIZE (result);
9180 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9182 genSetDPTR(AOP(left)->aopu.dptr);
9183 emitcode ("movx", "a,@dptr");
9184 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9185 emitcode ("inc", "dptr");
9187 aopPut (AOP (result), "a", offset++);
9190 _startLazyDPSEvaluation ();
9192 if (AOP_INDPTRn(left)) {
9193 genSetDPTR(AOP(left)->aopu.dptr);
9199 emitcode ("movx", "a,@dptr");
9200 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9201 emitcode ("inc", "dptr");
9203 aopPut (AOP (result), "a", offset++);
9205 _endLazyDPSEvaluation ();
9208 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9209 if (!AOP_INDPTRn(left)) {
9210 aopPut ( AOP (left), "dpl", 0);
9211 aopPut ( AOP (left), "dph", 1);
9212 if (options.model == MODEL_FLAT24)
9213 aopPut ( AOP (left), "dpx", 2);
9216 } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
9217 AOP_SIZE(result) > 1 &&
9218 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9220 size = AOP_SIZE (result) - 1;
9221 if (AOP_INDPTRn(left)) {
9222 genSetDPTR(AOP(left)->aopu.dptr);
9224 while (size--) emitcode ("lcall","__decdptr");
9225 if (AOP_INDPTRn(left)) {
9230 freeAsmop (left, NULL, ic, TRUE);
9231 freeAsmop (result, NULL, ic, TRUE);
9234 /*-----------------------------------------------------------------*/
9235 /* genCodePointerGet - get value from code space */
9236 /*-----------------------------------------------------------------*/
9238 genCodePointerGet (operand * left,
9239 operand * result, iCode * ic, iCode *pi)
9241 int size, offset, dopi=1;
9242 sym_link *retype = getSpec (operandType (result));
9244 aopOp (left, ic, FALSE, FALSE);
9246 /* if the operand is already in dptr
9247 then we do nothing else we move the value to dptr */
9248 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
9250 /* if this is remateriazable */
9251 if (AOP_TYPE (left) == AOP_IMMD)
9253 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9256 { /* we need to get it byte by byte */
9257 _startLazyDPSEvaluation ();
9258 if (AOP_TYPE (left) != AOP_DPTR)
9260 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9261 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9262 if (options.model == MODEL_FLAT24)
9263 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9267 /* We need to generate a load to DPTR indirect through DPTR. */
9268 D (emitcode (";", "gencodePointerGet -- indirection special case.");
9270 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
9271 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
9272 if (options.model == MODEL_FLAT24)
9273 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9274 emitcode ("pop", "dph");
9275 emitcode ("pop", "dpl");
9278 _endLazyDPSEvaluation ();
9281 /* so dptr know contains the address */
9282 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9284 /* if bit then unpack */
9285 if (IS_BITVAR (retype)) {
9286 if (AOP_INDPTRn(left)) {
9287 genSetDPTR(AOP(left)->aopu.dptr);
9289 genUnpackBits (result, "dptr", CPOINTER);
9290 if (AOP_INDPTRn(left)) {
9295 size = AOP_SIZE (result);
9297 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9299 genSetDPTR(AOP(left)->aopu.dptr);
9300 emitcode ("clr", "a");
9301 emitcode ("movc", "a,@a+dptr");
9302 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9303 emitcode ("inc", "dptr");
9305 aopPut (AOP (result), "a", offset++);
9308 _startLazyDPSEvaluation ();
9311 if (AOP_INDPTRn(left)) {
9312 genSetDPTR(AOP(left)->aopu.dptr);
9318 emitcode ("clr", "a");
9319 emitcode ("movc", "a,@a+dptr");
9320 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9321 emitcode ("inc", "dptr");
9322 aopPut (AOP (result), "a", offset++);
9324 _endLazyDPSEvaluation ();
9327 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9328 if (!AOP_INDPTRn(left)) {
9329 aopPut ( AOP (left), "dpl", 0);
9330 aopPut ( AOP (left), "dph", 1);
9331 if (options.model == MODEL_FLAT24)
9332 aopPut ( AOP (left), "dpx", 2);
9335 } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
9336 AOP_SIZE(result) > 1 &&
9337 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9339 size = AOP_SIZE (result) - 1;
9340 if (AOP_INDPTRn(left)) {
9341 genSetDPTR(AOP(left)->aopu.dptr);
9343 while (size--) emitcode ("lcall","__decdptr");
9344 if (AOP_INDPTRn(left)) {
9349 freeAsmop (left, NULL, ic, TRUE);
9350 freeAsmop (result, NULL, ic, TRUE);
9353 /*-----------------------------------------------------------------*/
9354 /* genGenPointerGet - gget value from generic pointer space */
9355 /*-----------------------------------------------------------------*/
9357 genGenPointerGet (operand * left,
9358 operand * result, iCode * ic, iCode * pi)
9361 sym_link *retype = getSpec (operandType (result));
9362 sym_link *letype = getSpec (operandType (left));
9364 D (emitcode (";", "genGenPointerGet "); );
9366 aopOp (left, ic, FALSE, (OP_SYMBOL(left)->ruonly ? FALSE : TRUE));
9368 /* if the operand is already in dptr
9369 then we do nothing else we move the value to dptr */
9370 if (AOP_TYPE (left) != AOP_STR)
9372 /* if this is remateriazable */
9373 if (AOP_TYPE (left) == AOP_IMMD)
9375 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9376 if (AOP(left)->aopu.aop_immd.from_cast_remat)
9377 emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, FALSE));
9379 emitcode ("mov", "b,#%d", pointerCode (retype));
9382 { /* we need to get it byte by byte */
9383 _startLazyDPSEvaluation ();
9384 #if 1 // I see no point at all to this code and will likely yank it soon.
9385 if (AOP(left)->type==AOP_DPTR2) {
9387 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
9390 emitcode ("mov", "dpl,%s", l);
9391 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
9394 emitcode ("mov", "dph,%s", l);
9395 if (options.model == MODEL_FLAT24) {
9396 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
9399 emitcode ("mov", "dpx,%s", l);
9400 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9402 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9408 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
9409 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
9410 if (options.model == MODEL_FLAT24) {
9411 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9412 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9414 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9417 _endLazyDPSEvaluation ();
9420 /* so dptr know contains the address */
9421 aopOp (result, ic, FALSE, TRUE);
9423 /* if bit then unpack */
9424 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9425 genUnpackBits (result, "dptr", GPOINTER);
9428 size = AOP_SIZE (result);
9433 emitcode ("lcall", "__gptrget");
9434 aopPut (AOP (result), "a", offset++);
9435 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9436 emitcode ("inc", "dptr");
9440 if (pi && AOP_TYPE (left) != AOP_IMMD) {
9441 aopPut ( AOP (left), "dpl", 0);
9442 aopPut ( AOP (left), "dph", 1);
9443 if (options.model == MODEL_FLAT24) {
9444 aopPut ( AOP (left), "dpx", 2);
9445 aopPut ( AOP (left), "b", 3);
9446 } else aopPut ( AOP (left), "b", 2);
9448 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9449 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9451 size = AOP_SIZE (result) - 1;
9452 while (size--) emitcode ("lcall","__decdptr");
9455 freeAsmop (left, NULL, ic, TRUE);
9456 freeAsmop (result, NULL, ic, TRUE);
9459 /*-----------------------------------------------------------------*/
9460 /* genPointerGet - generate code for pointer get */
9461 /*-----------------------------------------------------------------*/
9463 genPointerGet (iCode * ic, iCode *pi)
9465 operand *left, *result;
9466 sym_link *type, *etype;
9469 D (emitcode (";", "genPointerGet ");
9472 left = IC_LEFT (ic);
9473 result = IC_RESULT (ic);
9475 /* depending on the type of pointer we need to
9476 move it to the correct pointer register */
9477 type = operandType (left);
9478 etype = getSpec (type);
9479 /* if left is of type of pointer then it is simple */
9480 if (IS_PTR (type) && !IS_FUNC (type->next))
9481 p_type = DCL_TYPE (type);
9484 /* we have to go by the storage class */
9485 p_type = PTR_TYPE (SPEC_OCLS (etype));
9487 /* special case when cast remat */
9488 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9489 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9490 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9491 type = type = operandType (left);
9492 p_type = DCL_TYPE (type);
9494 /* now that we have the pointer type we assign
9495 the pointer values */
9501 genNearPointerGet (left, result, ic, pi);
9505 genPagedPointerGet (left, result, ic, pi);
9509 genFarPointerGet (left, result, ic, pi);
9513 genCodePointerGet (left, result, ic, pi);
9517 genGenPointerGet (left, result, ic, pi);
9523 /*-----------------------------------------------------------------*/
9524 /* genPackBits - generates code for packed bit storage */
9525 /*-----------------------------------------------------------------*/
9527 genPackBits (sym_link * etype,
9529 char *rname, int p_type)
9537 blen = SPEC_BLEN (etype);
9538 bstr = SPEC_BSTR (etype);
9540 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9543 /* if the bit lenth is less than or */
9544 /* it exactly fits a byte then */
9545 if (SPEC_BLEN (etype) <= 8)
9547 shCount = SPEC_BSTR (etype);
9549 /* shift left acc */
9552 if (SPEC_BLEN (etype) < 8)
9553 { /* if smaller than a byte */
9559 emitcode ("mov", "b,a");
9560 emitcode ("mov", "a,@%s", rname);
9564 emitcode ("mov", "b,a");
9565 emitcode ("movx", "a,@dptr");
9569 emitcode ("push", "b");
9570 emitcode ("push", "acc");
9571 emitcode ("lcall", "__gptrget");
9572 emitcode ("pop", "b");
9576 emitcode ("anl", "a,#!constbyte", (unsigned char)
9577 ((unsigned char) (0xFF << (blen + bstr)) |
9578 (unsigned char) (0xFF >> (8 - bstr))));
9579 emitcode ("orl", "a,b");
9580 if (p_type == GPOINTER)
9581 emitcode ("pop", "b");
9588 emitcode ("mov", "@%s,a", rname);
9592 emitcode ("movx", "@dptr,a");
9596 emitcode ("lcall", "__gptrput");
9601 if (SPEC_BLEN (etype) <= 8)
9604 emitcode ("inc", "%s", rname);
9605 rLen = SPEC_BLEN (etype);
9607 /* now generate for lengths greater than one byte */
9611 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
9623 emitcode ("mov", "@%s,a", rname);
9626 emitcode ("mov", "@%s,%s", rname, l);
9631 emitcode ("movx", "@dptr,a");
9636 emitcode ("lcall", "__gptrput");
9639 emitcode ("inc", "%s", rname);
9644 /* last last was not complete */
9647 /* save the byte & read byte */
9651 emitcode ("mov", "b,a");
9652 emitcode ("mov", "a,@%s", rname);
9656 emitcode ("mov", "b,a");
9657 emitcode ("movx", "a,@dptr");
9661 emitcode ("push", "b");
9662 emitcode ("push", "acc");
9663 emitcode ("lcall", "__gptrget");
9664 emitcode ("pop", "b");
9668 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1 << rLen));
9669 emitcode ("orl", "a,b");
9672 if (p_type == GPOINTER)
9673 emitcode ("pop", "b");
9679 emitcode ("mov", "@%s,a", rname);
9683 emitcode ("movx", "@dptr,a");
9687 emitcode ("lcall", "__gptrput");
9691 /*-----------------------------------------------------------------*/
9692 /* genDataPointerSet - remat pointer to data space */
9693 /*-----------------------------------------------------------------*/
9695 genDataPointerSet (operand * right,
9699 int size, offset = 0;
9700 char *l, buffer[256];
9702 aopOp (right, ic, FALSE, FALSE);
9704 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
9705 size = AOP_SIZE (right);
9709 sprintf (buffer, "(%s + %d)", l + 1, offset);
9711 sprintf (buffer, "%s", l + 1);
9712 emitcode ("mov", "%s,%s", buffer,
9713 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
9716 freeAsmop (right, NULL, ic, TRUE);
9717 freeAsmop (result, NULL, ic, TRUE);
9720 /*-----------------------------------------------------------------*/
9721 /* genNearPointerSet - emitcode for near pointer put */
9722 /*-----------------------------------------------------------------*/
9724 genNearPointerSet (operand * right,
9732 sym_link *retype, *letype;
9733 sym_link *ptype = operandType (result);
9735 retype = getSpec (operandType (right));
9736 letype = getSpec (ptype);
9738 aopOp (result, ic, FALSE, FALSE);
9740 /* if the result is rematerializable &
9741 in data space & not a bit variable */
9742 if (AOP_TYPE (result) == AOP_IMMD &&
9743 DCL_TYPE (ptype) == POINTER &&
9744 !IS_BITVAR (retype) &&
9745 !IS_BITVAR (letype))
9747 genDataPointerSet (right, result, ic);
9751 /* if the value is already in a pointer register
9752 then don't need anything more */
9753 if (!AOP_INPREG (AOP (result)))
9755 /* otherwise get a free pointer register */
9757 preg = getFreePtr (ic, &aop, FALSE);
9758 emitcode ("mov", "%s,%s",
9760 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9764 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9766 aopOp (right, ic, FALSE, FALSE);
9768 /* if bitfield then unpack the bits */
9769 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9770 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9773 /* we have can just get the values */
9774 int size = AOP_SIZE (right);
9779 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
9783 emitcode ("mov", "@%s,a", rname);
9786 emitcode ("mov", "@%s,%s", rname, l);
9788 emitcode ("inc", "%s", rname);
9793 /* now some housekeeping stuff */
9796 /* we had to allocate for this iCode */
9797 if (pi) aopPut (AOP (result),rname,0);
9798 freeAsmop (NULL, aop, ic, TRUE);
9802 /* we did not allocate which means left
9803 already in a pointer register, then
9804 if size > 0 && this could be used again
9805 we have to point it back to where it
9807 if (AOP_SIZE (right) > 1 &&
9808 !OP_SYMBOL (result)->remat &&
9809 (OP_SYMBOL (result)->liveTo > ic->seq ||
9813 int size = AOP_SIZE (right) - 1;
9815 emitcode ("dec", "%s", rname);
9820 if (pi) pi->generated = 1;
9821 freeAsmop (result, NULL, ic, TRUE);
9822 freeAsmop (right, NULL, ic, TRUE);
9827 /*-----------------------------------------------------------------*/
9828 /* genPagedPointerSet - emitcode for Paged pointer put */
9829 /*-----------------------------------------------------------------*/
9831 genPagedPointerSet (operand * right,
9839 sym_link *retype, *letype;
9841 retype = getSpec (operandType (right));
9842 letype = getSpec (operandType (result));
9844 aopOp (result, ic, FALSE, FALSE);
9846 /* if the value is already in a pointer register
9847 then don't need anything more */
9848 if (!AOP_INPREG (AOP (result)))
9850 /* otherwise get a free pointer register */
9852 preg = getFreePtr (ic, &aop, FALSE);
9853 emitcode ("mov", "%s,%s",
9855 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9859 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9861 aopOp (right, ic, FALSE, FALSE);
9863 /* if bitfield then unpack the bits */
9864 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9865 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
9868 /* we have can just get the values */
9869 int size = AOP_SIZE (right);
9874 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
9877 emitcode ("movx", "@%s,a", rname);
9880 emitcode ("inc", "%s", rname);
9886 /* now some housekeeping stuff */
9889 if (pi) aopPut (AOP (result),rname,0);
9890 /* we had to allocate for this iCode */
9891 freeAsmop (NULL, aop, ic, TRUE);
9895 /* we did not allocate which means left
9896 already in a pointer register, then
9897 if size > 0 && this could be used again
9898 we have to point it back to where it
9900 if (AOP_SIZE (right) > 1 &&
9901 !OP_SYMBOL (result)->remat &&
9902 (OP_SYMBOL (result)->liveTo > ic->seq ||
9906 int size = AOP_SIZE (right) - 1;
9908 emitcode ("dec", "%s", rname);
9913 if (pi) pi->generated = 1;
9914 freeAsmop (result, NULL, ic, TRUE);
9915 freeAsmop (right, NULL, ic, TRUE);
9920 /*-----------------------------------------------------------------*/
9921 /* genFarPointerSet - set value from far space */
9922 /*-----------------------------------------------------------------*/
9924 genFarPointerSet (operand * right,
9925 operand * result, iCode * ic, iCode *pi)
9927 int size, offset, dopi=1;
9928 sym_link *retype = getSpec (operandType (right));
9929 sym_link *letype = getSpec (operandType (result));
9931 aopOp (result, ic, FALSE, FALSE);
9933 /* if the operand is already in dptr
9934 then we do nothing else we move the value to dptr */
9935 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
9937 /* if this is remateriazable */
9938 if (AOP_TYPE (result) == AOP_IMMD)
9939 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9942 /* we need to get it byte by byte */
9943 _startLazyDPSEvaluation ();
9944 if (AOP_TYPE (result) != AOP_DPTR)
9946 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9947 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9948 if (options.model == MODEL_FLAT24)
9949 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9953 /* We need to generate a load to DPTR indirect through DPTR. */
9954 D (emitcode (";", "genFarPointerSet -- indirection special case.");
9956 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
9957 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
9958 if (options.model == MODEL_FLAT24)
9959 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9960 emitcode ("pop", "dph");
9961 emitcode ("pop", "dpl");
9964 _endLazyDPSEvaluation ();
9967 /* so dptr know contains the address */
9968 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
9970 /* if bit then unpack */
9971 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9972 if (AOP_INDPTRn(result)) {
9973 genSetDPTR(AOP(result)->aopu.dptr);
9975 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
9976 if (AOP_INDPTRn(result)) {
9980 size = AOP_SIZE (right);
9982 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
9984 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9987 genSetDPTR(AOP(result)->aopu.dptr);
9988 emitcode ("movx", "@dptr,a");
9989 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
9990 emitcode ("inc", "dptr");
9994 _startLazyDPSEvaluation ();
9996 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9999 if (AOP_INDPTRn(result)) {
10000 genSetDPTR(AOP(result)->aopu.dptr);
10006 emitcode ("movx", "@dptr,a");
10007 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10008 emitcode ("inc", "dptr");
10010 _endLazyDPSEvaluation ();
10014 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10015 if (!AOP_INDPTRn(result)) {
10016 aopPut (AOP(result),"dpl",0);
10017 aopPut (AOP(result),"dph",1);
10018 if (options.model == MODEL_FLAT24)
10019 aopPut (AOP(result),"dpx",2);
10022 } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
10023 AOP_SIZE(right) > 1 &&
10024 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10026 size = AOP_SIZE (right) - 1;
10027 if (AOP_INDPTRn(result)) {
10028 genSetDPTR(AOP(result)->aopu.dptr);
10030 while (size--) emitcode ("lcall","__decdptr");
10031 if (AOP_INDPTRn(result)) {
10035 freeAsmop (result, NULL, ic, TRUE);
10036 freeAsmop (right, NULL, ic, TRUE);
10039 /*-----------------------------------------------------------------*/
10040 /* genGenPointerSet - set value from generic pointer space */
10041 /*-----------------------------------------------------------------*/
10043 genGenPointerSet (operand * right,
10044 operand * result, iCode * ic, iCode *pi)
10047 sym_link *retype = getSpec (operandType (right));
10048 sym_link *letype = getSpec (operandType (result));
10050 aopOp (result, ic, FALSE, OP_SYMBOL(result)->ruonly ? FALSE : TRUE);
10052 /* if the operand is already in dptr
10053 then we do nothing else we move the value to dptr */
10054 if (AOP_TYPE (result) != AOP_STR)
10056 _startLazyDPSEvaluation ();
10057 /* if this is remateriazable */
10058 if (AOP_TYPE (result) == AOP_IMMD)
10060 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
10061 if (AOP(result)->aopu.aop_immd.from_cast_remat)
10062 emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, FALSE));
10064 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
10067 { /* we need to get it byte by byte */
10068 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
10069 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
10070 if (options.model == MODEL_FLAT24) {
10071 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
10072 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
10074 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
10077 _endLazyDPSEvaluation ();
10079 /* so dptr know contains the address */
10080 aopOp (right, ic, FALSE, TRUE);
10082 /* if bit then unpack */
10083 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10084 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
10087 size = AOP_SIZE (right);
10090 _startLazyDPSEvaluation ();
10093 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
10099 emitcode ("lcall", "__gptrput");
10100 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10101 emitcode ("inc", "dptr");
10103 _endLazyDPSEvaluation ();
10106 if (pi && AOP_TYPE (result) != AOP_IMMD) {
10107 aopPut (AOP(result),"dpl",0);
10108 aopPut (AOP(result),"dph",1);
10109 if (options.model == MODEL_FLAT24) {
10110 aopPut (AOP(result),"dpx",2);
10111 aopPut (AOP(result),"b",3);
10113 aopPut (AOP(result),"b",2);
10116 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10117 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10119 size = AOP_SIZE (right) - 1;
10120 while (size--) emitcode ("lcall","__decdptr");
10122 freeAsmop (result, NULL, ic, TRUE);
10123 freeAsmop (right, NULL, ic, TRUE);
10126 /*-----------------------------------------------------------------*/
10127 /* genPointerSet - stores the value into a pointer location */
10128 /*-----------------------------------------------------------------*/
10130 genPointerSet (iCode * ic, iCode *pi)
10132 operand *right, *result;
10133 sym_link *type, *etype;
10136 D (emitcode (";", "genPointerSet ");
10139 right = IC_RIGHT (ic);
10140 result = IC_RESULT (ic);
10142 /* depending on the type of pointer we need to
10143 move it to the correct pointer register */
10144 type = operandType (result);
10145 etype = getSpec (type);
10146 /* if left is of type of pointer then it is simple */
10147 if (IS_PTR (type) && !IS_FUNC (type->next))
10149 p_type = DCL_TYPE (type);
10153 /* we have to go by the storage class */
10154 p_type = PTR_TYPE (SPEC_OCLS (etype));
10156 /* special case when cast remat */
10157 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10158 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10159 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10160 type = type = operandType (result);
10161 p_type = DCL_TYPE (type);
10164 /* now that we have the pointer type we assign
10165 the pointer values */
10171 genNearPointerSet (right, result, ic, pi);
10175 genPagedPointerSet (right, result, ic, pi);
10179 genFarPointerSet (right, result, ic, pi);
10183 genGenPointerSet (right, result, ic, pi);
10187 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10188 "genPointerSet: illegal pointer type");
10193 /*-----------------------------------------------------------------*/
10194 /* genIfx - generate code for Ifx statement */
10195 /*-----------------------------------------------------------------*/
10197 genIfx (iCode * ic, iCode * popIc)
10199 operand *cond = IC_COND (ic);
10202 D (emitcode (";", "genIfx "););
10204 aopOp (cond, ic, FALSE, FALSE);
10206 /* get the value into acc */
10207 if (AOP_TYPE (cond) != AOP_CRY)
10211 /* the result is now in the accumulator */
10212 freeAsmop (cond, NULL, ic, TRUE);
10214 /* if there was something to be popped then do it */
10218 /* if the condition is a bit variable */
10219 if (isbit && IS_ITEMP (cond) &&
10221 genIfxJump (ic, SPIL_LOC (cond)->rname);
10222 else if (isbit && !IS_ITEMP (cond))
10223 genIfxJump (ic, OP_SYMBOL (cond)->rname);
10225 genIfxJump (ic, "a");
10230 /*-----------------------------------------------------------------*/
10231 /* genAddrOf - generates code for address of */
10232 /*-----------------------------------------------------------------*/
10234 genAddrOf (iCode * ic)
10236 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10239 D (emitcode (";", "genAddrOf ");
10242 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10244 /* if the operand is on the stack then we
10245 need to get the stack offset of this
10247 if (sym->onStack) {
10249 /* if 10 bit stack */
10250 if (options.stack10bit) {
10252 tsprintf(buff,"#!constbyte",(options.stack_loc >> 16) & 0xff);
10253 /* if it has an offset then we need to compute it */
10254 /* emitcode ("subb", "a,#!constbyte", */
10255 /* -((sym->stack < 0) ? */
10256 /* ((short) (sym->stack - _G.nRegsSaved)) : */
10257 /* ((short) sym->stack)) & 0xff); */
10258 /* emitcode ("mov","b,a"); */
10259 /* emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
10260 /* ((short) (sym->stack - _G.nRegsSaved)) : */
10261 /* ((short) sym->stack)) >> 8) & 0xff); */
10263 emitcode ("mov", "a,_bpx");
10264 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
10265 ((char) (sym->stack - _G.nRegsSaved)) :
10266 ((char) sym->stack )) & 0xff);
10267 emitcode ("mov", "b,a");
10268 emitcode ("mov", "a,_bpx+1");
10269 emitcode ("addc","a,#!constbyte", (((sym->stack < 0) ?
10270 ((short) (sym->stack - _G.nRegsSaved)) :
10271 ((short) sym->stack )) >> 8) & 0xff);
10272 aopPut (AOP (IC_RESULT (ic)), "b", 0);
10273 aopPut (AOP (IC_RESULT (ic)), "a", 1);
10274 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10276 /* we can just move _bp */
10277 aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10278 aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10279 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10282 /* if it has an offset then we need to compute it */
10284 emitcode ("mov", "a,_bp");
10285 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10286 aopPut (AOP (IC_RESULT (ic)), "a", 0);
10288 /* we can just move _bp */
10289 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10291 /* fill the result with zero */
10292 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10295 if (options.stack10bit && size < (FPTRSIZE - 1)) {
10297 "*** warning: pointer to stack var truncated.\n");
10302 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10308 /* object not on stack then we need the name */
10309 size = AOP_SIZE (IC_RESULT (ic));
10314 char s[SDCC_NAME_MAX];
10318 tsprintf(s,"!his",sym->rname);
10321 tsprintf(s,"!hihis",sym->rname);
10324 tsprintf(s,"!hihihis",sym->rname);
10326 default: /* should not need this (just in case) */
10327 sprintf (s, "#(%s >> %d)",
10332 sprintf (s, "#%s", sym->rname);
10333 aopPut (AOP (IC_RESULT (ic)), s, offset++);
10337 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10341 /*-----------------------------------------------------------------*/
10342 /* genArrayInit - generates code for address of */
10343 /*-----------------------------------------------------------------*/
10345 genArrayInit (iCode * ic)
10347 literalList *iLoop;
10349 int elementSize = 0, eIndex;
10350 unsigned val, lastVal;
10352 operand *left=IC_LEFT(ic);
10354 D (emitcode (";", "genArrayInit "););
10356 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10358 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10360 // Load immediate value into DPTR.
10361 emitcode("mov", "dptr, %s",
10362 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
10364 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10367 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10368 "Unexpected operand to genArrayInit.\n");
10371 // a regression because of SDCCcse.c:1.52
10372 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
10373 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
10374 if (options.model == MODEL_FLAT24)
10375 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
10379 type = operandType(IC_LEFT(ic));
10381 if (type && type->next)
10383 elementSize = getSize(type->next);
10387 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10388 "can't determine element size in genArrayInit.\n");
10392 iLoop = IC_ARRAYILIST(ic);
10397 bool firstpass = TRUE;
10399 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
10400 iLoop->count, (int)iLoop->literalValue, elementSize);
10406 symbol *tlbl = NULL;
10408 count = ix > 256 ? 256 : ix;
10412 tlbl = newiTempLabel (NULL);
10413 if (firstpass || (count & 0xff))
10415 emitcode("mov", "b, #!constbyte", count & 0xff);
10418 emitcode ("", "!tlabeldef", tlbl->key + 100);
10423 for (eIndex = 0; eIndex < elementSize; eIndex++)
10425 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10426 if (val != lastVal)
10428 emitcode("mov", "a, #!constbyte", val);
10432 emitcode("movx", "@dptr, a");
10433 emitcode("inc", "dptr");
10438 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10444 iLoop = iLoop->next;
10447 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10450 /*-----------------------------------------------------------------*/
10451 /* genFarFarAssign - assignment when both are in far space */
10452 /*-----------------------------------------------------------------*/
10454 genFarFarAssign (operand * result, operand * right, iCode * ic)
10456 int size = AOP_SIZE (right);
10458 symbol *rSym = NULL;
10462 /* quick & easy case. */
10463 D(emitcode(";","genFarFarAssign (1 byte case)"););
10464 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
10465 freeAsmop (right, NULL, ic, FALSE);
10466 /* now assign DPTR to result */
10468 aopOp(result, ic, FALSE, FALSE);
10470 aopPut(AOP(result), "a", 0);
10471 freeAsmop(result, NULL, ic, FALSE);
10475 /* See if we've got an underlying symbol to abuse. */
10476 if (IS_SYMOP(result) && OP_SYMBOL(result))
10478 if (IS_TRUE_SYMOP(result))
10480 rSym = OP_SYMBOL(result);
10482 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10484 rSym = OP_SYMBOL(result)->usl.spillLoc;
10488 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10490 /* We can use the '390 auto-toggle feature to good effect here. */
10492 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10493 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
10494 emitcode ("mov", "dptr,#%s", rSym->rname);
10495 /* DP2 = result, DP1 = right, DP1 is current. */
10498 emitcode("movx", "a,@dptr");
10499 emitcode("movx", "@dptr,a");
10502 emitcode("inc", "dptr");
10503 emitcode("inc", "dptr");
10506 emitcode("mov", "dps,#0");
10507 freeAsmop (right, NULL, ic, FALSE);
10509 some alternative code for processors without auto-toggle
10510 no time to test now, so later well put in...kpb
10511 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10512 emitcode("mov", "dps,#1"); /* Select DPTR2. */
10513 emitcode ("mov", "dptr,#%s", rSym->rname);
10514 /* DP2 = result, DP1 = right, DP1 is current. */
10518 emitcode("movx", "a,@dptr");
10520 emitcode("inc", "dptr");
10521 emitcode("inc", "dps");
10522 emitcode("movx", "@dptr,a");
10524 emitcode("inc", "dptr");
10525 emitcode("inc", "dps");
10527 emitcode("mov", "dps,#0");
10528 freeAsmop (right, NULL, ic, FALSE);
10533 D (emitcode (";", "genFarFarAssign"););
10534 aopOp (result, ic, TRUE, TRUE);
10536 _startLazyDPSEvaluation ();
10540 aopPut (AOP (result),
10541 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
10544 _endLazyDPSEvaluation ();
10545 freeAsmop (result, NULL, ic, FALSE);
10546 freeAsmop (right, NULL, ic, FALSE);
10550 /*-----------------------------------------------------------------*/
10551 /* genAssign - generate code for assignment */
10552 /*-----------------------------------------------------------------*/
10554 genAssign (iCode * ic)
10556 operand *result, *right;
10558 unsigned long lit = 0L;
10560 D (emitcode (";", "genAssign ");
10563 result = IC_RESULT (ic);
10564 right = IC_RIGHT (ic);
10566 /* if they are the same */
10567 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10570 aopOp (right, ic, FALSE, FALSE);
10572 emitcode (";", "genAssign: resultIsFar = %s",
10573 isOperandInFarSpace (result) ?
10576 /* special case both in far space */
10577 if ((AOP_TYPE (right) == AOP_DPTR ||
10578 AOP_TYPE (right) == AOP_DPTR2) &&
10579 /* IS_TRUE_SYMOP(result) && */
10580 isOperandInFarSpace (result))
10582 genFarFarAssign (result, right, ic);
10586 aopOp (result, ic, TRUE, FALSE);
10588 /* if they are the same registers */
10589 if (sameRegs (AOP (right), AOP (result)))
10592 /* if the result is a bit */
10593 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10595 /* if the right size is a literal then
10596 we know what the value is */
10597 if (AOP_TYPE (right) == AOP_LIT)
10599 if (((int) operandLitValue (right)))
10600 aopPut (AOP (result), one, 0);
10602 aopPut (AOP (result), zero, 0);
10606 /* the right is also a bit variable */
10607 if (AOP_TYPE (right) == AOP_CRY)
10609 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10610 aopPut (AOP (result), "c", 0);
10614 /* we need to or */
10616 aopPut (AOP (result), "a", 0);
10620 /* bit variables done */
10622 size = AOP_SIZE (result);
10624 if (AOP_TYPE (right) == AOP_LIT)
10625 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10628 (AOP_TYPE (result) != AOP_REG) &&
10629 (AOP_TYPE (right) == AOP_LIT) &&
10630 !IS_FLOAT (operandType (right)))
10632 _startLazyDPSEvaluation ();
10633 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10635 aopPut (AOP (result),
10636 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
10641 /* And now fill the rest with zeros. */
10644 emitcode ("clr", "a");
10648 aopPut (AOP (result), "a", offset++);
10650 _endLazyDPSEvaluation ();
10654 _startLazyDPSEvaluation ();
10657 aopPut (AOP (result),
10658 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10662 _endLazyDPSEvaluation ();
10666 freeAsmop (right, NULL, ic, FALSE);
10667 freeAsmop (result, NULL, ic, TRUE);
10670 /*-----------------------------------------------------------------*/
10671 /* genJumpTab - generates code for jump table */
10672 /*-----------------------------------------------------------------*/
10674 genJumpTab (iCode * ic)
10679 D (emitcode (";", "genJumpTab ");
10682 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10683 /* get the condition into accumulator */
10684 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
10686 /* multiply by four! */
10687 emitcode ("add", "a,acc");
10688 emitcode ("add", "a,acc");
10689 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10691 jtab = newiTempLabel (NULL);
10692 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
10693 emitcode ("jmp", "@a+dptr");
10694 emitcode ("", "!tlabeldef", jtab->key + 100);
10695 /* now generate the jump labels */
10696 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10697 jtab = setNextItem (IC_JTLABELS (ic)))
10698 emitcode ("ljmp", "!tlabel", jtab->key + 100);
10702 /*-----------------------------------------------------------------*/
10703 /* genCast - gen code for casting */
10704 /*-----------------------------------------------------------------*/
10706 genCast (iCode * ic)
10708 operand *result = IC_RESULT (ic);
10709 sym_link *ctype = operandType (IC_LEFT (ic));
10710 sym_link *rtype = operandType (IC_RIGHT (ic));
10711 operand *right = IC_RIGHT (ic);
10714 D (emitcode (";", "genCast ");
10717 /* if they are equivalent then do nothing */
10718 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10721 aopOp (right, ic, FALSE, FALSE);
10722 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
10724 /* if the result is a bit */
10725 // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10726 if (IS_BITVAR(OP_SYMBOL(result)->type))
10728 /* if the right size is a literal then
10729 we know what the value is */
10730 if (AOP_TYPE (right) == AOP_LIT)
10732 if (((int) operandLitValue (right)))
10733 aopPut (AOP (result), one, 0);
10735 aopPut (AOP (result), zero, 0);
10740 /* the right is also a bit variable */
10741 if (AOP_TYPE (right) == AOP_CRY)
10743 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10744 aopPut (AOP (result), "c", 0);
10748 /* we need to or */
10750 aopPut (AOP (result), "a", 0);
10754 /* if they are the same size : or less */
10755 if (AOP_SIZE (result) <= AOP_SIZE (right))
10758 /* if they are in the same place */
10759 if (sameRegs (AOP (right), AOP (result)))
10762 /* if they in different places then copy */
10763 size = AOP_SIZE (result);
10765 _startLazyDPSEvaluation ();
10768 aopPut (AOP (result),
10769 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10773 _endLazyDPSEvaluation ();
10778 /* if the result is of type pointer */
10779 if (IS_PTR (ctype))
10783 sym_link *type = operandType (right);
10785 /* pointer to generic pointer */
10786 if (IS_GENPTR (ctype))
10790 p_type = DCL_TYPE (type);
10794 #if OLD_CAST_BEHAVIOR
10795 /* KV: we are converting a non-pointer type to
10796 * a generic pointer. This (ifdef'd out) code
10797 * says that the resulting generic pointer
10798 * should have the same class as the storage
10799 * location of the non-pointer variable.
10801 * For example, converting an int (which happens
10802 * to be stored in DATA space) to a pointer results
10803 * in a DATA generic pointer; if the original int
10804 * in XDATA space, so will be the resulting pointer.
10806 * I don't like that behavior, and thus this change:
10807 * all such conversions will be forced to XDATA and
10808 * throw a warning. If you want some non-XDATA
10809 * type, or you want to suppress the warning, you
10810 * must go through an intermediate cast, like so:
10812 * char _generic *gp = (char _xdata *)(intVar);
10814 sym_link *etype = getSpec (type);
10816 /* we have to go by the storage class */
10817 if (SPEC_OCLS (etype) != generic)
10819 p_type = PTR_TYPE (SPEC_OCLS (etype));
10824 /* Converting unknown class (i.e. register variable)
10825 * to generic pointer. This is not good, but
10826 * we'll make a guess (and throw a warning).
10829 werror (W_INT_TO_GEN_PTR_CAST);
10833 /* the first two bytes are known */
10834 size = GPTRSIZE - 1;
10836 _startLazyDPSEvaluation ();
10839 aopPut (AOP (result),
10840 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10844 _endLazyDPSEvaluation ();
10846 /* the last byte depending on type */
10848 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
10853 // pointerTypeToGPByte will have bitched.
10857 sprintf(gpValStr, "#0x%d", gpVal);
10858 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
10863 /* just copy the pointers */
10864 size = AOP_SIZE (result);
10866 _startLazyDPSEvaluation ();
10869 aopPut (AOP (result),
10870 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10874 _endLazyDPSEvaluation ();
10878 /* so we now know that the size of destination is greater
10879 than the size of the source */
10880 /* we move to result for the size of source */
10881 size = AOP_SIZE (right);
10883 _startLazyDPSEvaluation ();
10886 aopPut (AOP (result),
10887 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10891 _endLazyDPSEvaluation ();
10893 /* now depending on the sign of the source && destination */
10894 size = AOP_SIZE (result) - AOP_SIZE (right);
10895 /* if unsigned or not an integral type */
10896 /* also, if the source is a bit, we don't need to sign extend, because
10897 * it can't possibly have set the sign bit.
10899 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
10903 aopPut (AOP (result), zero, offset++);
10908 /* we need to extend the sign :{ */
10909 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
10910 FALSE, FALSE, TRUE);
10912 emitcode ("rlc", "a");
10913 emitcode ("subb", "a,acc");
10915 aopPut (AOP (result), "a", offset++);
10918 /* we are done hurray !!!! */
10921 freeAsmop (right, NULL, ic, TRUE);
10922 freeAsmop (result, NULL, ic, TRUE);
10926 /*-----------------------------------------------------------------*/
10927 /* genDjnz - generate decrement & jump if not zero instrucion */
10928 /*-----------------------------------------------------------------*/
10930 genDjnz (iCode * ic, iCode * ifx)
10932 symbol *lbl, *lbl1;
10936 /* if the if condition has a false label
10937 then we cannot save */
10938 if (IC_FALSE (ifx))
10941 /* if the minus is not of the form
10943 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10944 !IS_OP_LITERAL (IC_RIGHT (ic)))
10947 if (operandLitValue (IC_RIGHT (ic)) != 1)
10950 /* if the size of this greater than one then no
10952 if (getSize (operandType (IC_RESULT (ic))) > 1)
10955 /* otherwise we can save BIG */
10956 D(emitcode(";", "genDjnz"););
10958 lbl = newiTempLabel (NULL);
10959 lbl1 = newiTempLabel (NULL);
10961 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10963 if (AOP_NEEDSACC(IC_RESULT(ic)))
10965 /* If the result is accessed indirectly via
10966 * the accumulator, we must explicitly write
10967 * it back after the decrement.
10969 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
10971 if (strcmp(rByte, "a"))
10973 /* Something is hopelessly wrong */
10974 fprintf(stderr, "*** warning: internal error at %s:%d\n",
10975 __FILE__, __LINE__);
10976 /* We can just give up; the generated code will be inefficient,
10977 * but what the hey.
10979 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10982 emitcode ("dec", "%s", rByte);
10983 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
10984 emitcode ("jnz", "!tlabel", lbl->key + 100);
10986 else if (IS_AOP_PREG (IC_RESULT (ic)))
10988 emitcode ("dec", "%s",
10989 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10990 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10991 emitcode ("jnz", "!tlabel", lbl->key + 100);
10995 emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
10998 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
10999 emitcode ("", "!tlabeldef", lbl->key + 100);
11000 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11001 emitcode ("", "!tlabeldef", lbl1->key + 100);
11003 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11004 ifx->generated = 1;
11008 /*-----------------------------------------------------------------*/
11009 /* genReceive - generate code for a receive iCode */
11010 /*-----------------------------------------------------------------*/
11012 genReceive (iCode * ic)
11015 int size = getSize (operandType (IC_RESULT (ic)));
11019 D (emitcode (";", "genReceive ");
11022 if (ic->argreg == 1) { /* first parameter */
11023 if (isOperandInFarSpace (IC_RESULT (ic)) &&
11024 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11025 IS_TRUE_SYMOP (IC_RESULT (ic))))
11027 offset = fReturnSizeDS390 - size;
11030 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
11031 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
11034 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11035 size = AOP_SIZE (IC_RESULT (ic));
11039 emitcode ("pop", "acc");
11040 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
11045 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11047 assignResultValue (IC_RESULT (ic));
11049 } else { /* second receive onwards */
11050 /* this gets a little tricky since unused recevies will be
11051 eliminated, we have saved the reg in the type field . and
11052 we use that to figure out which register to use */
11053 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11054 rb1off = ic->argreg;
11056 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11060 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11063 /*-----------------------------------------------------------------*/
11064 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
11065 /*-----------------------------------------------------------------*/
11066 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11068 operand *from , *to , *count;
11073 /* we know it has to be 3 parameters */
11074 assert (nparms == 3);
11076 rsave = newBitVect(16);
11077 /* save DPTR if it needs to be saved */
11078 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11079 if (bitVectBitValue(ic->rMask,i))
11080 rsave = bitVectSetBit(rsave,i);
11082 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11083 ds390_rUmaskForOp (IC_RESULT(ic))));
11090 aopOp (from, ic->next, FALSE, FALSE);
11092 /* get from into DPTR1 */
11093 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
11094 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
11095 if (options.model == MODEL_FLAT24) {
11096 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
11099 freeAsmop (from, NULL, ic, FALSE);
11100 aopOp (to, ic, FALSE, FALSE);
11101 /* get "to" into DPTR */
11102 /* if the operand is already in dptr
11103 then we do nothing else we move the value to dptr */
11104 if (AOP_TYPE (to) != AOP_STR) {
11105 /* if already in DPTR then we need to push */
11106 if (AOP_TYPE(to) == AOP_DPTR) {
11107 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11108 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11109 if (options.model == MODEL_FLAT24)
11110 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11111 emitcode ("pop", "dph");
11112 emitcode ("pop", "dpl");
11114 _startLazyDPSEvaluation ();
11115 /* if this is remateriazable */
11116 if (AOP_TYPE (to) == AOP_IMMD) {
11117 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11118 } else { /* we need to get it byte by byte */
11119 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11120 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11121 if (options.model == MODEL_FLAT24) {
11122 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11125 _endLazyDPSEvaluation ();
11128 freeAsmop (to, NULL, ic, FALSE);
11129 _G.dptrInUse = _G.dptr1InUse = 1;
11130 aopOp (count, ic->next->next, FALSE,FALSE);
11131 lbl =newiTempLabel(NULL);
11133 /* now for the actual copy */
11134 if (AOP_TYPE(count) == AOP_LIT &&
11135 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11136 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11138 emitcode ("lcall","__bi_memcpyc2x_s");
11140 emitcode ("lcall","__bi_memcpyx2x_s");
11142 freeAsmop (count, NULL, ic, FALSE);
11144 symbol *lbl1 = newiTempLabel(NULL);
11146 emitcode (";"," Auto increment but no djnz");
11147 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11148 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11149 freeAsmop (count, NULL, ic, FALSE);
11150 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11151 emitcode ("","!tlabeldef",lbl->key+100);
11153 emitcode ("clr","a");
11154 emitcode ("movc", "a,@a+dptr");
11156 emitcode ("movx", "a,@dptr");
11157 emitcode ("movx", "@dptr,a");
11158 emitcode ("inc", "dptr");
11159 emitcode ("inc", "dptr");
11160 emitcode ("mov","a,b");
11161 emitcode ("orl","a,_ap");
11162 emitcode ("jz","!tlabel",lbl1->key+100);
11163 emitcode ("mov","a,_ap");
11164 emitcode ("add","a,#!constbyte",0xFF);
11165 emitcode ("mov","_ap,a");
11166 emitcode ("mov","a,b");
11167 emitcode ("addc","a,#!constbyte",0xFF);
11168 emitcode ("mov","b,a");
11169 emitcode ("sjmp","!tlabel",lbl->key+100);
11170 emitcode ("","!tlabeldef",lbl1->key+100);
11172 emitcode ("mov", "dps,#0");
11173 _G.dptrInUse = _G.dptr1InUse = 0;
11174 unsavermask(rsave);
11178 /*-----------------------------------------------------------------*/
11179 /* genMemcmpX2X - gen code for memcmp xdata to xdata */
11180 /*-----------------------------------------------------------------*/
11181 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11183 operand *from , *to , *count;
11188 /* we know it has to be 3 parameters */
11189 assert (nparms == 3);
11191 rsave = newBitVect(16);
11192 /* save DPTR if it needs to be saved */
11193 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11194 if (bitVectBitValue(ic->rMask,i))
11195 rsave = bitVectSetBit(rsave,i);
11197 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11198 ds390_rUmaskForOp (IC_RESULT(ic))));
11205 aopOp (from, ic->next, FALSE, FALSE);
11207 /* get from into DPTR1 */
11208 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
11209 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
11210 if (options.model == MODEL_FLAT24) {
11211 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
11214 freeAsmop (from, NULL, ic, FALSE);
11215 aopOp (to, ic, FALSE, FALSE);
11216 /* get "to" into DPTR */
11217 /* if the operand is already in dptr
11218 then we do nothing else we move the value to dptr */
11219 if (AOP_TYPE (to) != AOP_STR) {
11220 /* if already in DPTR then we need to push */
11221 if (AOP_TYPE(to) == AOP_DPTR) {
11222 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11223 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11224 if (options.model == MODEL_FLAT24)
11225 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11226 emitcode ("pop", "dph");
11227 emitcode ("pop", "dpl");
11229 _startLazyDPSEvaluation ();
11230 /* if this is remateriazable */
11231 if (AOP_TYPE (to) == AOP_IMMD) {
11232 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11233 } else { /* we need to get it byte by byte */
11234 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11235 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11236 if (options.model == MODEL_FLAT24) {
11237 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11240 _endLazyDPSEvaluation ();
11243 freeAsmop (to, NULL, ic, FALSE);
11244 _G.dptrInUse = _G.dptr1InUse = 1;
11245 aopOp (count, ic->next->next, FALSE,FALSE);
11246 lbl =newiTempLabel(NULL);
11247 lbl2 =newiTempLabel(NULL);
11249 /* now for the actual compare */
11250 if (AOP_TYPE(count) == AOP_LIT &&
11251 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11252 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11254 emitcode("lcall","__bi_memcmpc2x_s");
11256 emitcode("lcall","__bi_memcmpx2x_s");
11257 freeAsmop (count, NULL, ic, FALSE);
11258 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11259 aopPut(AOP(IC_RESULT(ic)),"a",0);
11260 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11262 symbol *lbl1 = newiTempLabel(NULL);
11264 emitcode("push","ar0");
11265 emitcode (";"," Auto increment but no djnz");
11266 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11267 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11268 freeAsmop (count, NULL, ic, FALSE);
11269 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11270 emitcode ("","!tlabeldef",lbl->key+100);
11272 emitcode ("clr","a");
11273 emitcode ("movc", "a,@a+dptr");
11275 emitcode ("movx", "a,@dptr");
11276 emitcode ("mov","r0,a");
11277 emitcode ("movx", "a,@dptr");
11278 emitcode ("clr","c");
11279 emitcode ("subb","a,r0");
11280 emitcode ("jnz","!tlabel",lbl2->key+100);
11281 emitcode ("inc", "dptr");
11282 emitcode ("inc", "dptr");
11283 emitcode ("mov","a,b");
11284 emitcode ("orl","a,_ap");
11285 emitcode ("jz","!tlabel",lbl1->key+100);
11286 emitcode ("mov","a,_ap");
11287 emitcode ("add","a,#!constbyte",0xFF);
11288 emitcode ("mov","_ap,a");
11289 emitcode ("mov","a,b");
11290 emitcode ("addc","a,#!constbyte",0xFF);
11291 emitcode ("mov","b,a");
11292 emitcode ("sjmp","!tlabel",lbl->key+100);
11293 emitcode ("","!tlabeldef",lbl1->key+100);
11294 emitcode ("clr","a");
11295 emitcode ("","!tlabeldef",lbl2->key+100);
11296 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11297 aopPut(AOP(IC_RESULT(ic)),"a",0);
11298 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11299 emitcode("pop","ar0");
11300 emitcode ("mov", "dps,#0");
11302 _G.dptrInUse = _G.dptr1InUse = 0;
11303 unsavermask(rsave);
11307 /*-----------------------------------------------------------------*/
11308 /* genInp - gen code for __builtin_inp read data from a mem mapped */
11309 /* port, first parameter output area second parameter pointer to */
11310 /* port third parameter count */
11311 /*-----------------------------------------------------------------*/
11312 static void genInp( iCode *ic, int nparms, operand **parms)
11314 operand *from , *to , *count;
11319 /* we know it has to be 3 parameters */
11320 assert (nparms == 3);
11322 rsave = newBitVect(16);
11323 /* save DPTR if it needs to be saved */
11324 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11325 if (bitVectBitValue(ic->rMask,i))
11326 rsave = bitVectSetBit(rsave,i);
11328 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11329 ds390_rUmaskForOp (IC_RESULT(ic))));
11336 aopOp (from, ic->next, FALSE, FALSE);
11338 /* get from into DPTR1 */
11339 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
11340 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
11341 if (options.model == MODEL_FLAT24) {
11342 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
11345 freeAsmop (from, NULL, ic, FALSE);
11346 aopOp (to, ic, FALSE, FALSE);
11347 /* get "to" into DPTR */
11348 /* if the operand is already in dptr
11349 then we do nothing else we move the value to dptr */
11350 if (AOP_TYPE (to) != AOP_STR) {
11351 /* if already in DPTR then we need to push */
11352 if (AOP_TYPE(to) == AOP_DPTR) {
11353 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11354 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11355 if (options.model == MODEL_FLAT24)
11356 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11357 emitcode ("pop", "dph");
11358 emitcode ("pop", "dpl");
11360 _startLazyDPSEvaluation ();
11361 /* if this is remateriazable */
11362 if (AOP_TYPE (to) == AOP_IMMD) {
11363 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11364 } else { /* we need to get it byte by byte */
11365 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11366 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11367 if (options.model == MODEL_FLAT24) {
11368 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11371 _endLazyDPSEvaluation ();
11374 freeAsmop (to, NULL, ic, FALSE);
11376 _G.dptrInUse = _G.dptr1InUse = 1;
11377 aopOp (count, ic->next->next, FALSE,FALSE);
11378 lbl =newiTempLabel(NULL);
11380 /* now for the actual copy */
11381 if (AOP_TYPE(count) == AOP_LIT &&
11382 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11383 emitcode (";","OH JOY auto increment with djnz (very fast)");
11384 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11385 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11386 freeAsmop (count, NULL, ic, FALSE);
11387 emitcode ("","!tlabeldef",lbl->key+100);
11388 emitcode ("movx", "a,@dptr"); /* read data from port */
11389 emitcode ("dec","dps"); /* switch to DPTR */
11390 emitcode ("movx", "@dptr,a"); /* save into location */
11391 emitcode ("inc", "dptr"); /* point to next area */
11392 emitcode ("inc","dps"); /* switch to DPTR2 */
11393 emitcode ("djnz","b,!tlabel",lbl->key+100);
11395 symbol *lbl1 = newiTempLabel(NULL);
11397 emitcode (";"," Auto increment but no djnz");
11398 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11399 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11400 freeAsmop (count, NULL, ic, FALSE);
11401 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11402 emitcode ("","!tlabeldef",lbl->key+100);
11403 emitcode ("movx", "a,@dptr");
11404 emitcode ("dec","dps"); /* switch to DPTR */
11405 emitcode ("movx", "@dptr,a");
11406 emitcode ("inc", "dptr");
11407 emitcode ("inc","dps"); /* switch to DPTR2 */
11408 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
11409 /* emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
11410 emitcode ("mov","a,b");
11411 emitcode ("orl","a,_ap");
11412 emitcode ("jz","!tlabel",lbl1->key+100);
11413 emitcode ("mov","a,_ap");
11414 emitcode ("add","a,#!constbyte",0xFF);
11415 emitcode ("mov","_ap,a");
11416 emitcode ("mov","a,b");
11417 emitcode ("addc","a,#!constbyte",0xFF);
11418 emitcode ("mov","b,a");
11419 emitcode ("sjmp","!tlabel",lbl->key+100);
11420 emitcode ("","!tlabeldef",lbl1->key+100);
11422 emitcode ("mov", "dps,#0");
11423 _G.dptrInUse = _G.dptr1InUse = 0;
11424 unsavermask(rsave);
11428 /*-----------------------------------------------------------------*/
11429 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
11430 /* port, first parameter output area second parameter pointer to */
11431 /* port third parameter count */
11432 /*-----------------------------------------------------------------*/
11433 static void genOutp( iCode *ic, int nparms, operand **parms)
11435 operand *from , *to , *count;
11440 /* we know it has to be 3 parameters */
11441 assert (nparms == 3);
11443 rsave = newBitVect(16);
11444 /* save DPTR if it needs to be saved */
11445 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11446 if (bitVectBitValue(ic->rMask,i))
11447 rsave = bitVectSetBit(rsave,i);
11449 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11450 ds390_rUmaskForOp (IC_RESULT(ic))));
11457 aopOp (from, ic->next, FALSE, FALSE);
11459 /* get from into DPTR1 */
11460 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
11461 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
11462 if (options.model == MODEL_FLAT24) {
11463 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
11466 freeAsmop (from, NULL, ic, FALSE);
11467 aopOp (to, ic, FALSE, FALSE);
11468 /* get "to" into DPTR */
11469 /* if the operand is already in dptr
11470 then we do nothing else we move the value to dptr */
11471 if (AOP_TYPE (to) != AOP_STR) {
11472 /* if already in DPTR then we need to push */
11473 if (AOP_TYPE(to) == AOP_DPTR) {
11474 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11475 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11476 if (options.model == MODEL_FLAT24)
11477 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11478 emitcode ("pop", "dph");
11479 emitcode ("pop", "dpl");
11481 _startLazyDPSEvaluation ();
11482 /* if this is remateriazable */
11483 if (AOP_TYPE (to) == AOP_IMMD) {
11484 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11485 } else { /* we need to get it byte by byte */
11486 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11487 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11488 if (options.model == MODEL_FLAT24) {
11489 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11492 _endLazyDPSEvaluation ();
11495 freeAsmop (to, NULL, ic, FALSE);
11497 _G.dptrInUse = _G.dptr1InUse = 1;
11498 aopOp (count, ic->next->next, FALSE,FALSE);
11499 lbl =newiTempLabel(NULL);
11501 /* now for the actual copy */
11502 if (AOP_TYPE(count) == AOP_LIT &&
11503 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11504 emitcode (";","OH JOY auto increment with djnz (very fast)");
11505 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
11506 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11507 emitcode ("","!tlabeldef",lbl->key+100);
11508 emitcode ("movx", "a,@dptr"); /* read data from port */
11509 emitcode ("inc","dps"); /* switch to DPTR2 */
11510 emitcode ("movx", "@dptr,a"); /* save into location */
11511 emitcode ("inc", "dptr"); /* point to next area */
11512 emitcode ("dec","dps"); /* switch to DPTR */
11513 emitcode ("djnz","b,!tlabel",lbl->key+100);
11514 freeAsmop (count, NULL, ic, FALSE);
11516 symbol *lbl1 = newiTempLabel(NULL);
11518 emitcode (";"," Auto increment but no djnz");
11519 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11520 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11521 freeAsmop (count, NULL, ic, FALSE);
11522 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
11523 emitcode ("","!tlabeldef",lbl->key+100);
11524 emitcode ("movx", "a,@dptr");
11525 emitcode ("inc", "dptr");
11526 emitcode ("inc","dps"); /* switch to DPTR2 */
11527 emitcode ("movx", "@dptr,a");
11528 emitcode ("dec","dps"); /* switch to DPTR */
11529 emitcode ("mov","a,b");
11530 emitcode ("orl","a,_ap");
11531 emitcode ("jz","!tlabel",lbl1->key+100);
11532 emitcode ("mov","a,_ap");
11533 emitcode ("add","a,#!constbyte",0xFF);
11534 emitcode ("mov","_ap,a");
11535 emitcode ("mov","a,b");
11536 emitcode ("addc","a,#!constbyte",0xFF);
11537 emitcode ("mov","b,a");
11538 emitcode ("sjmp","!tlabel",lbl->key+100);
11539 emitcode ("","!tlabeldef",lbl1->key+100);
11541 emitcode ("mov", "dps,#0");
11542 _G.dptrInUse = _G.dptr1InUse = 0;
11543 unsavermask(rsave);
11547 /*-----------------------------------------------------------------*/
11548 /* genSwapW - swap lower & high order bytes */
11549 /*-----------------------------------------------------------------*/
11550 static void genSwapW(iCode *ic, int nparms, operand **parms)
11554 assert (nparms==1);
11557 dest=IC_RESULT(ic);
11559 assert(getSize(operandType(src))==2);
11561 aopOp (src, ic, FALSE, FALSE);
11562 emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,TRUE));
11564 emitcode ("mov","b,%s",aopGet(AOP(src),1,FALSE,FALSE,FALSE));
11566 freeAsmop (src, NULL, ic, FALSE);
11568 aopOp (dest,ic, FALSE, FALSE);
11569 aopPut(AOP(dest),"b",0);
11570 aopPut(AOP(dest),"a",1);
11571 freeAsmop (dest, NULL, ic, FALSE);
11574 /*-----------------------------------------------------------------*/
11575 /* genMemsetX - gencode for memSetX data */
11576 /*-----------------------------------------------------------------*/
11577 static void genMemsetX(iCode *ic, int nparms, operand **parms)
11579 operand *to , *val , *count;
11583 bitVect *rsave = NULL;
11585 /* we know it has to be 3 parameters */
11586 assert (nparms == 3);
11592 /* save DPTR if it needs to be saved */
11593 rsave = newBitVect(16);
11594 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11595 if (bitVectBitValue(ic->rMask,i))
11596 rsave = bitVectSetBit(rsave,i);
11598 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11599 ds390_rUmaskForOp (IC_RESULT(ic))));
11602 aopOp (to, ic, FALSE, FALSE);
11603 /* get "to" into DPTR */
11604 /* if the operand is already in dptr
11605 then we do nothing else we move the value to dptr */
11606 if (AOP_TYPE (to) != AOP_STR) {
11607 /* if already in DPTR then we need to push */
11608 if (AOP_TYPE(to) == AOP_DPTR) {
11609 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11610 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11611 if (options.model == MODEL_FLAT24)
11612 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11613 emitcode ("pop", "dph");
11614 emitcode ("pop", "dpl");
11616 _startLazyDPSEvaluation ();
11617 /* if this is remateriazable */
11618 if (AOP_TYPE (to) == AOP_IMMD) {
11619 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11620 } else { /* we need to get it byte by byte */
11621 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11622 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11623 if (options.model == MODEL_FLAT24) {
11624 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11627 _endLazyDPSEvaluation ();
11630 freeAsmop (to, NULL, ic, FALSE);
11632 aopOp (val, ic->next->next, FALSE,FALSE);
11633 aopOp (count, ic->next->next, FALSE,FALSE);
11634 lbl =newiTempLabel(NULL);
11635 /* now for the actual copy */
11636 if (AOP_TYPE(count) == AOP_LIT &&
11637 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11638 l = aopGet(AOP (val), 0, FALSE, FALSE, TRUE);
11639 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11641 emitcode ("","!tlabeldef",lbl->key+100);
11642 emitcode ("movx", "@dptr,a");
11643 emitcode ("inc", "dptr");
11644 emitcode ("djnz","b,!tlabel",lbl->key+100);
11646 symbol *lbl1 = newiTempLabel(NULL);
11648 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11649 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11650 emitcode ("","!tlabeldef",lbl->key+100);
11651 l = aopGet(AOP (val), 0, FALSE, FALSE, TRUE);
11653 emitcode ("movx", "@dptr,a");
11654 emitcode ("inc", "dptr");
11655 emitcode ("mov","a,b");
11656 emitcode ("orl","a,_ap");
11657 emitcode ("jz","!tlabel",lbl1->key+100);
11658 emitcode ("mov","a,_ap");
11659 emitcode ("add","a,#!constbyte",0xFF);
11660 emitcode ("mov","_ap,a");
11661 emitcode ("mov","a,b");
11662 emitcode ("addc","a,#!constbyte",0xFF);
11663 emitcode ("mov","b,a");
11664 emitcode ("sjmp","!tlabel",lbl->key+100);
11665 emitcode ("","!tlabeldef",lbl1->key+100);
11667 freeAsmop (count, NULL, ic, FALSE);
11668 unsavermask(rsave);
11671 /*-----------------------------------------------------------------*/
11672 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
11673 /*-----------------------------------------------------------------*/
11674 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
11677 operand *pnum, *result;
11680 assert (nparms==1);
11681 /* save registers that need to be saved */
11682 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11683 ds390_rUmaskForOp (IC_RESULT(ic))));
11686 aopOp (pnum, ic, FALSE, FALSE);
11687 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,FALSE));
11688 freeAsmop (pnum, NULL, ic, FALSE);
11689 emitcode ("lcall","NatLib_LoadPrimitive");
11690 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11691 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
11692 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
11693 for (i = (size-1) ; i >= 0 ; i-- ) {
11694 emitcode ("push","a%s",javaRet[i]);
11696 for (i=0; i < size ; i++ ) {
11697 emitcode ("pop","a%s",aopGet(AOP(result),i,FALSE,FALSE,FALSE));
11700 for (i = 0 ; i < size ; i++ ) {
11701 aopPut(AOP(result),javaRet[i],i);
11704 freeAsmop (result, NULL, ic, FALSE);
11705 unsavermask(rsave);
11708 /*-----------------------------------------------------------------*/
11709 /* genNatLibLoadPointer - calls TINI api function to load pointer */
11710 /*-----------------------------------------------------------------*/
11711 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
11714 operand *pnum, *result;
11718 assert (nparms==1);
11719 /* save registers that need to be saved */
11720 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11721 ds390_rUmaskForOp (IC_RESULT(ic))));
11724 aopOp (pnum, ic, FALSE, FALSE);
11725 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,FALSE));
11726 freeAsmop (pnum, NULL, ic, FALSE);
11727 emitcode ("lcall","NatLib_LoadPointer");
11728 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11729 if (AOP_TYPE(result)!=AOP_STR) {
11730 for (i = 0 ; i < size ; i++ ) {
11731 aopPut(AOP(result),fReturn[i],i);
11734 freeAsmop (result, NULL, ic, FALSE);
11735 unsavermask(rsave);
11738 /*-----------------------------------------------------------------*/
11739 /* genNatLibInstallStateBlock - */
11740 /*-----------------------------------------------------------------*/
11741 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
11742 operand **parms, const char *name)
11745 operand *psb, *handle;
11746 assert (nparms==2);
11748 /* save registers that need to be saved */
11749 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11750 ds390_rUmaskForOp (IC_RESULT(ic))));
11754 /* put pointer to state block into DPTR1 */
11755 aopOp (psb, ic, FALSE, FALSE);
11756 if (AOP_TYPE (psb) == AOP_IMMD) {
11757 emitcode ("mov","dps,#1");
11758 emitcode ("mov", "dptr,%s", aopGet (AOP (psb), 0, TRUE, FALSE, FALSE));
11759 emitcode ("mov","dps,#0");
11761 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,FALSE));
11762 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,FALSE));
11763 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,FALSE));
11765 freeAsmop (psb, NULL, ic, FALSE);
11767 /* put libraryID into DPTR */
11768 emitcode ("mov","dptr,#LibraryID");
11770 /* put handle into r3:r2 */
11771 aopOp (handle, ic, FALSE, FALSE);
11772 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11773 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11774 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11775 emitcode ("pop","ar3");
11776 emitcode ("pop","ar2");
11778 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11779 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11781 freeAsmop (psb, NULL, ic, FALSE);
11783 /* make the call */
11784 emitcode ("lcall","NatLib_Install%sStateBlock",name);
11786 /* put return value into place*/
11788 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
11790 aopPut(AOP(IC_RESULT(ic)),"a",0);
11791 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11792 unsavermask(rsave);
11795 /*-----------------------------------------------------------------*/
11796 /* genNatLibRemoveStateBlock - */
11797 /*-----------------------------------------------------------------*/
11798 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
11804 /* save registers that need to be saved */
11805 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11806 ds390_rUmaskForOp (IC_RESULT(ic))));
11808 /* put libraryID into DPTR */
11809 emitcode ("mov","dptr,#LibraryID");
11810 /* make the call */
11811 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
11812 unsavermask(rsave);
11815 /*-----------------------------------------------------------------*/
11816 /* genNatLibGetStateBlock - */
11817 /*-----------------------------------------------------------------*/
11818 static void genNatLibGetStateBlock(iCode *ic,int nparms,
11819 operand **parms,const char *name)
11822 symbol *lbl = newiTempLabel(NULL);
11825 /* save registers that need to be saved */
11826 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11827 ds390_rUmaskForOp (IC_RESULT(ic))));
11829 /* put libraryID into DPTR */
11830 emitcode ("mov","dptr,#LibraryID");
11831 /* make the call */
11832 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
11833 emitcode ("jnz","!tlabel",lbl->key+100);
11835 /* put return value into place */
11836 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
11837 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
11838 emitcode ("push","ar3");
11839 emitcode ("push","ar2");
11840 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,FALSE));
11841 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,FALSE));
11843 aopPut(AOP(IC_RESULT(ic)),"r2",0);
11844 aopPut(AOP(IC_RESULT(ic)),"r3",1);
11846 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11847 emitcode ("","!tlabeldef",lbl->key+100);
11848 unsavermask(rsave);
11851 /*-----------------------------------------------------------------*/
11852 /* genMMMalloc - */
11853 /*-----------------------------------------------------------------*/
11854 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
11855 int size, const char *name)
11860 symbol *lbl = newiTempLabel(NULL);
11862 assert (nparms == 1);
11863 /* save registers that need to be saved */
11864 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11865 ds390_rUmaskForOp (IC_RESULT(ic))));
11868 aopOp (bsize,ic,FALSE,FALSE);
11870 /* put the size in R4-R2 */
11871 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
11872 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,FALSE));
11873 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,FALSE));
11875 emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,FALSE));
11876 emitcode("pop","ar4");
11878 emitcode("pop","ar3");
11879 emitcode("pop","ar2");
11881 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,FALSE));
11882 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,FALSE));
11884 emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,FALSE));
11887 freeAsmop (bsize, NULL, ic, FALSE);
11889 /* make the call */
11890 emitcode ("lcall","MM_%s",name);
11891 emitcode ("jz","!tlabel",lbl->key+100);
11892 emitcode ("mov","r2,#!constbyte",0xff);
11893 emitcode ("mov","r3,#!constbyte",0xff);
11894 emitcode ("","!tlabeldef",lbl->key+100);
11895 /* we don't care about the pointer : we just save the handle */
11896 rsym = OP_SYMBOL(IC_RESULT(ic));
11897 if (rsym->liveFrom != rsym->liveTo) {
11898 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
11899 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
11900 emitcode ("push","ar3");
11901 emitcode ("push","ar2");
11902 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,FALSE));
11903 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,FALSE));
11905 aopPut(AOP(IC_RESULT(ic)),"r2",0);
11906 aopPut(AOP(IC_RESULT(ic)),"r3",1);
11908 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11910 unsavermask(rsave);
11913 /*-----------------------------------------------------------------*/
11915 /*-----------------------------------------------------------------*/
11916 static void genMMDeref (iCode *ic,int nparms, operand **parms)
11921 assert (nparms == 1);
11922 /* save registers that need to be saved */
11923 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11924 ds390_rUmaskForOp (IC_RESULT(ic))));
11927 aopOp (handle,ic,FALSE,FALSE);
11929 /* put the size in R4-R2 */
11930 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11931 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11932 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11933 emitcode("pop","ar3");
11934 emitcode("pop","ar2");
11936 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11937 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11939 freeAsmop (handle, NULL, ic, FALSE);
11941 /* make the call */
11942 emitcode ("lcall","MM_Deref");
11945 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11946 if (rsym->liveFrom != rsym->liveTo) {
11947 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11948 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
11949 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
11950 aopPut(AOP(IC_RESULT(ic)),"dph",1);
11951 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
11955 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11956 unsavermask(rsave);
11959 /*-----------------------------------------------------------------*/
11960 /* genMMUnrestrictedPersist - */
11961 /*-----------------------------------------------------------------*/
11962 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
11967 assert (nparms == 1);
11968 /* save registers that need to be saved */
11969 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11970 ds390_rUmaskForOp (IC_RESULT(ic))));
11973 aopOp (handle,ic,FALSE,FALSE);
11975 /* put the size in R3-R2 */
11976 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11977 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11978 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11979 emitcode("pop","ar3");
11980 emitcode("pop","ar2");
11982 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11983 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11985 freeAsmop (handle, NULL, ic, FALSE);
11987 /* make the call */
11988 emitcode ("lcall","MM_UnrestrictedPersist");
11991 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11992 if (rsym->liveFrom != rsym->liveTo) {
11993 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11994 aopPut(AOP(IC_RESULT(ic)),"a",0);
11995 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11998 unsavermask(rsave);
12001 /*-----------------------------------------------------------------*/
12002 /* genSystemExecJavaProcess - */
12003 /*-----------------------------------------------------------------*/
12004 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12007 operand *handle, *pp;
12009 assert (nparms==2);
12010 /* save registers that need to be saved */
12011 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12012 ds390_rUmaskForOp (IC_RESULT(ic))));
12017 /* put the handle in R3-R2 */
12018 aopOp (handle,ic,FALSE,FALSE);
12019 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12020 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
12021 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
12022 emitcode("pop","ar3");
12023 emitcode("pop","ar2");
12025 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
12026 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
12028 freeAsmop (handle, NULL, ic, FALSE);
12030 /* put pointer in DPTR */
12031 aopOp (pp,ic,FALSE,FALSE);
12032 if (AOP_TYPE(pp) == AOP_IMMD) {
12033 emitcode ("mov", "dptr,%s", aopGet (AOP (pp), 0, TRUE, FALSE, FALSE));
12034 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12035 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,FALSE));
12036 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,FALSE));
12037 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,FALSE));
12039 freeAsmop (handle, NULL, ic, FALSE);
12041 /* make the call */
12042 emitcode ("lcall","System_ExecJavaProcess");
12044 /* put result in place */
12046 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12047 if (rsym->liveFrom != rsym->liveTo) {
12048 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12049 aopPut(AOP(IC_RESULT(ic)),"a",0);
12050 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12054 unsavermask(rsave);
12057 /*-----------------------------------------------------------------*/
12058 /* genSystemRTCRegisters - */
12059 /*-----------------------------------------------------------------*/
12060 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12066 assert (nparms==1);
12067 /* save registers that need to be saved */
12068 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12069 ds390_rUmaskForOp (IC_RESULT(ic))));
12072 /* put pointer in DPTR */
12073 aopOp (pp,ic,FALSE,FALSE);
12074 if (AOP_TYPE (pp) == AOP_IMMD) {
12075 emitcode ("mov","dps,#1");
12076 emitcode ("mov", "dptr,%s", aopGet (AOP (pp), 0, TRUE, FALSE, FALSE));
12077 emitcode ("mov","dps,#0");
12079 emitcode ("mov","dpl1,%s",aopGet(AOP(pp),0,FALSE,FALSE,FALSE));
12080 emitcode ("mov","dph1,%s",aopGet(AOP(pp),1,FALSE,FALSE,FALSE));
12081 emitcode ("mov","dpx1,%s",aopGet(AOP(pp),2,FALSE,FALSE,FALSE));
12083 freeAsmop (pp, NULL, ic, FALSE);
12085 /* make the call */
12086 emitcode ("lcall","System_%sRTCRegisters",name);
12088 unsavermask(rsave);
12091 /*-----------------------------------------------------------------*/
12092 /* genSystemThreadSleep - */
12093 /*-----------------------------------------------------------------*/
12094 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12099 assert (nparms==1);
12100 /* save registers that need to be saved */
12101 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12102 ds390_rUmaskForOp (IC_RESULT(ic))));
12105 aopOp(to,ic,FALSE,FALSE);
12106 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12107 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12108 emitcode ("push","%s",aopGet(AOP(to),0,FALSE,TRUE,FALSE));
12109 emitcode ("push","%s",aopGet(AOP(to),1,FALSE,TRUE,FALSE));
12110 emitcode ("push","%s",aopGet(AOP(to),2,FALSE,TRUE,FALSE));
12111 emitcode ("push","%s",aopGet(AOP(to),3,FALSE,TRUE,FALSE));
12112 emitcode ("pop","ar3");
12113 emitcode ("pop","ar2");
12114 emitcode ("pop","ar1");
12115 emitcode ("pop","ar0");
12117 emitcode ("mov","r0,%s",aopGet(AOP(to),0,FALSE,TRUE,FALSE));
12118 emitcode ("mov","r1,%s",aopGet(AOP(to),1,FALSE,TRUE,FALSE));
12119 emitcode ("mov","r2,%s",aopGet(AOP(to),2,FALSE,TRUE,FALSE));
12120 emitcode ("mov","r3,%s",aopGet(AOP(to),3,FALSE,TRUE,FALSE));
12122 freeAsmop (to, NULL, ic, FALSE);
12124 /* suspend in acc */
12126 aopOp(s,ic,FALSE,FALSE);
12127 emitcode ("mov","a,%s",aopGet(AOP(s),0,FALSE,TRUE,FALSE));
12128 freeAsmop (s, NULL, ic, FALSE);
12130 /* make the call */
12131 emitcode ("lcall","System_%s",name);
12133 unsavermask(rsave);
12136 /*-----------------------------------------------------------------*/
12137 /* genSystemThreadResume - */
12138 /*-----------------------------------------------------------------*/
12139 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12144 assert (nparms==2);
12145 /* save registers that need to be saved */
12146 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12147 ds390_rUmaskForOp (IC_RESULT(ic))));
12153 aopOp(pid,ic,FALSE,FALSE);
12154 emitcode ("mov","r0,%s",aopGet(AOP(pid),0,FALSE,TRUE,FALSE));
12155 freeAsmop (pid, NULL, ic, FALSE);
12158 aopOp(tid,ic,FALSE,FALSE);
12159 emitcode ("mov","a,%s",aopGet(AOP(tid),0,FALSE,TRUE,FALSE));
12160 freeAsmop (tid, NULL, ic, FALSE);
12162 emitcode ("lcall","System_ThreadResume");
12164 /* put result into place */
12166 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12167 if (rsym->liveFrom != rsym->liveTo) {
12168 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12169 aopPut(AOP(IC_RESULT(ic)),"a",0);
12170 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12173 unsavermask(rsave);
12176 /*-----------------------------------------------------------------*/
12177 /* genSystemProcessResume - */
12178 /*-----------------------------------------------------------------*/
12179 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
12184 assert (nparms==1);
12185 /* save registers that need to be saved */
12186 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12187 ds390_rUmaskForOp (IC_RESULT(ic))));
12192 aopOp(pid,ic,FALSE,FALSE);
12193 emitcode ("mov","a,%s",aopGet(AOP(pid),0,FALSE,TRUE,FALSE));
12194 freeAsmop (pid, NULL, ic, FALSE);
12196 emitcode ("lcall","System_ProcessResume");
12198 unsavermask(rsave);
12201 /*-----------------------------------------------------------------*/
12203 /*-----------------------------------------------------------------*/
12204 static void genSystem (iCode *ic,int nparms,char *name)
12206 assert(nparms == 0);
12208 emitcode ("lcall","System_%s",name);
12211 /*-----------------------------------------------------------------*/
12212 /* genSystemPoll - */
12213 /*-----------------------------------------------------------------*/
12214 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
12219 assert (nparms==1);
12220 /* save registers that need to be saved */
12221 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12222 ds390_rUmaskForOp (IC_RESULT(ic))));
12225 aopOp (fp,ic,FALSE,FALSE);
12226 if (AOP_TYPE (fp) == AOP_IMMD) {
12227 emitcode ("mov", "dptr,%s", aopGet (AOP (fp), 0, TRUE, FALSE, FALSE));
12228 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
12229 emitcode ("mov","dpl,%s",aopGet(AOP(fp),0,FALSE,FALSE,FALSE));
12230 emitcode ("mov","dph,%s",aopGet(AOP(fp),1,FALSE,FALSE,FALSE));
12231 emitcode ("mov","dpx,%s",aopGet(AOP(fp),2,FALSE,FALSE,FALSE));
12233 freeAsmop (fp, NULL, ic, FALSE);
12235 emitcode ("lcall","System_%sPoll",name);
12237 /* put result into place */
12239 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12240 if (rsym->liveFrom != rsym->liveTo) {
12241 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12242 aopPut(AOP(IC_RESULT(ic)),"a",0);
12243 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12246 unsavermask(rsave);
12249 /*-----------------------------------------------------------------*/
12250 /* genSystemGetCurrentID - */
12251 /*-----------------------------------------------------------------*/
12252 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
12254 assert (nparms==0);
12256 emitcode ("lcall","System_GetCurrent%sId",name);
12257 /* put result into place */
12259 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12260 if (rsym->liveFrom != rsym->liveTo) {
12261 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12262 aopPut(AOP(IC_RESULT(ic)),"a",0);
12263 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12268 /*-----------------------------------------------------------------*/
12269 /* genBuiltIn - calls the appropriate function to generating code */
12270 /* for a built in function */
12271 /*-----------------------------------------------------------------*/
12272 static void genBuiltIn (iCode *ic)
12274 operand *bi_parms[MAX_BUILTIN_ARGS];
12279 /* get all the arguments for a built in function */
12280 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
12282 /* which function is it */
12283 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
12284 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
12285 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
12286 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
12287 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
12288 } else if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
12289 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
12290 } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
12291 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
12292 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
12293 genMemsetX(bi_iCode,nbi_parms,bi_parms);
12294 } else if (strcmp(bif->name,"__builtin_inp")==0) {
12295 genInp(bi_iCode,nbi_parms,bi_parms);
12296 } else if (strcmp(bif->name,"__builtin_outp")==0) {
12297 genOutp(bi_iCode,nbi_parms,bi_parms);
12298 } else if (strcmp(bif->name,"__builtin_swapw")==0) {
12299 genSwapW(bi_iCode,nbi_parms,bi_parms);
12300 /* JavaNative builtIns */
12301 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
12302 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
12303 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
12304 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
12305 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
12306 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
12307 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
12308 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
12309 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
12310 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12311 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
12312 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12313 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
12314 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
12315 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
12316 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
12317 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
12318 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12319 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
12320 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12321 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
12322 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
12323 } else if (strcmp(bif->name,"MM_Malloc")==0) {
12324 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
12325 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
12326 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
12327 } else if (strcmp(bif->name,"MM_Free")==0) {
12328 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
12329 } else if (strcmp(bif->name,"MM_Deref")==0) {
12330 genMMDeref(bi_iCode,nbi_parms,bi_parms);
12331 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
12332 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
12333 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
12334 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
12335 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
12336 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
12337 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
12338 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
12339 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
12340 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
12341 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
12342 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
12343 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
12344 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
12345 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
12346 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
12347 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12348 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12349 } else if (strcmp(bif->name,"System_SaveThread")==0) {
12350 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12351 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12352 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12353 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
12354 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
12355 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
12356 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
12357 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
12358 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
12359 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
12360 genSystem(bi_iCode,nbi_parms,"ProcessYield");
12361 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
12362 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
12363 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
12364 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
12365 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
12366 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
12367 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
12368 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
12369 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
12370 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
12372 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
12378 /*-----------------------------------------------------------------*/
12379 /* gen390Code - generate code for Dallas 390 based controllers */
12380 /*-----------------------------------------------------------------*/
12382 gen390Code (iCode * lic)
12387 lineHead = lineCurr = NULL;
12388 dptrn[1][0] = "dpl1";
12389 dptrn[1][1] = "dph1";
12390 dptrn[1][2] = "dpx1";
12392 if (options.model == MODEL_FLAT24) {
12393 fReturnSizeDS390 = 5;
12394 fReturn = fReturn24;
12396 fReturnSizeDS390 = 4;
12397 fReturn = fReturn16;
12398 options.stack10bit=0;
12401 /* print the allocation information */
12403 printAllocInfo (currFunc, codeOutFile);
12405 /* if debug information required */
12406 if (options.debug && currFunc)
12408 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
12410 if (IS_STATIC (currFunc->etype))
12411 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
12413 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
12416 /* stack pointer name */
12417 if (options.useXstack)
12423 for (ic = lic; ic; ic = ic->next)
12426 if (ic->lineno && cln != ic->lineno)
12431 emitcode ("", "C$%s$%d$%d$%d ==.",
12432 FileBaseName (ic->filename), ic->lineno,
12433 ic->level, ic->block);
12436 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
12437 printCLine(ic->filename, ic->lineno));
12440 /* if the result is marked as
12441 spilt and rematerializable or code for
12442 this has already been generated then
12444 if (resultRemat (ic) || ic->generated)
12447 /* depending on the operation */
12467 /* IPOP happens only when trying to restore a
12468 spilt live range, if there is an ifx statement
12469 following this pop then the if statement might
12470 be using some of the registers being popped which
12471 would destory the contents of the register so
12472 we need to check for this condition and handle it */
12474 ic->next->op == IFX &&
12475 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
12476 genIfx (ic->next, ic);
12494 genEndFunction (ic);
12514 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
12531 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
12535 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
12542 /* note these two are xlated by algebraic equivalence
12543 during parsing SDCC.y */
12544 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12545 "got '>=' or '<=' shouldn't have come here");
12549 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
12561 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
12565 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
12569 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
12593 genRightShift (ic);
12596 case GET_VALUE_AT_ADDRESS:
12597 genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
12601 if (POINTER_SET (ic))
12602 genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
12628 if (ic->builtinSEND) genBuiltIn(ic);
12629 else addSet (&_G.sendSet, ic);
12642 /* now we are ready to call the
12643 peep hole optimizer */
12644 if (!options.nopeep)
12645 peepHole (&lineHead);
12647 /* now do the actual printing */
12648 printLine (lineHead, codeOutFile);