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 #define BETTER_LITERAL_SHIFT
41 char *aopLiteral (value * val, int offset);
44 /* this is the down and dirty file with all kinds of
45 kludgy & hacky stuff. This is what it is all about
46 CODE GENERATION for a specific MCU . some of the
47 routines may be reusable, will have to see */
49 static char *zero = "#0";
50 static char *one = "#1";
55 #define TR_DPTR(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_DPTR1 %s ", s); }
56 #define TR_AP(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_AP %s ", s); }
58 unsigned fReturnSizeDS390 = 5; /* shared with ralloc.c */
59 static char *fReturn24[] =
60 {"dpl", "dph", "dpx", "b", "a"};
61 static char *fReturn16[] =
62 {"dpl", "dph", "b", "a"};
63 static char **fReturn = fReturn24;
64 static char *accUse[] =
66 static char *dptrn[2][3];
67 static char *javaRet[] = { "r0","r1","r2","r3"};
68 static short rbank = -1;
85 static char *rb1regs[] = {
86 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
89 static void saveRBank (int, iCode *, bool);
91 #define RESULTONSTACK(x) \
92 (IC_RESULT(x) && IC_RESULT(x)->aop && \
93 IC_RESULT(x)->aop->type == AOP_STK )
95 #define MOVA(x) _movA(x)
96 #define MOVB(x) _movB(x)
98 #define CLRC emitcode("clr","c")
99 #define SETC emitcode("setb","c")
101 // A scratch register which will be used to hold
102 // result bytes from operands in far space via DPTR2.
103 #define DP2_RESULT_REG "_ap"
105 static lineNode *lineHead = NULL;
106 static lineNode *lineCurr = NULL;
108 static unsigned char SLMask[] =
109 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
110 0xE0, 0xC0, 0x80, 0x00};
111 static unsigned char SRMask[] =
112 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
113 0x07, 0x03, 0x01, 0x00};
119 #define PROTECT_SP {if (options.protect_sp_update) { \
120 symbol *lbl = newiTempLabel(NULL); \
121 emitcode ("setb","F1"); \
122 emitcode ("jbc","EA,!tlabel",lbl->key+100); \
123 emitcode ("clr","F1"); \
124 emitcode ("","!tlabeldef",lbl->key+100); \
126 #define UNPROTECT_SP { if (options.protect_sp_update) { \
127 symbol *lbl = newiTempLabel(NULL); \
128 emitcode ("jnb","F1,!tlabel",lbl->key+100); \
129 emitcode ("setb","EA"); \
130 emitcode ("","!tlabeldef",lbl->key+100); \
134 /*-----------------------------------------------------------------*/
135 /* emitcode - writes the code into a file : for now it is simple */
136 /*-----------------------------------------------------------------*/
138 emitcode (char *inst, char *fmt,...)
141 char lb[INITIAL_INLINEASM];
150 SNPRINTF (lb, sizeof(lb), "%s\t", inst);
154 SNPRINTF (lb, sizeof(lb), "%s", inst);
157 tvsprintf (lb + strlen(lb), sizeof(lb) - strlen(lb),
162 tvsprintf (lb, sizeof(lb), fmt, ap);
166 while (isspace (*lbp))
173 lineCurr = (lineCurr ?
174 connectLine (lineCurr, newLineNode (lb)) :
175 (lineHead = newLineNode (lb)));
178 lineCurr->isInline = _G.inLine;
179 lineCurr->isDebug = _G.debugLine;
184 // Move the passed value into A unless it is already there.
189 if (strcmp(s,"a") && strcmp(s,"acc"))
191 emitcode("mov","a,%s",s);
196 // Move the passed value into B unless it is already there.
203 emitcode("mov","b,%s",s);
207 /*-----------------------------------------------------------------*/
208 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
209 /*-----------------------------------------------------------------*/
211 getFreePtr (iCode * ic, asmop ** aopp, bool result)
216 /* the logic: if r0 & r1 used in the instruction
217 then we are in trouble otherwise */
219 /* first check if r0 & r1 are used by this
220 instruction, in which case we are in trouble */
221 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
222 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
227 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
228 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
230 /* if no usage of r0 then return it */
233 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
234 (*aopp)->type = AOP_R0;
236 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
239 /* if no usage of r1 then return it */
242 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
243 (*aopp)->type = AOP_R1;
245 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
248 /* now we know they both have usage */
249 /* if r0 not used in this instruction */
252 /* push it if not already pushed */
255 emitcode ("push", "%s",
256 ds390_regWithIdx (R0_IDX)->dname);
260 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
261 (*aopp)->type = AOP_R0;
263 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
266 /* if r1 not used then */
270 /* push it if not already pushed */
273 emitcode ("push", "%s",
274 ds390_regWithIdx (R1_IDX)->dname);
278 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
279 (*aopp)->type = AOP_R1;
280 return ds390_regWithIdx (R1_IDX);
284 /* I said end of world but not quite end of world yet */
285 /* if this is a result then we can push it on the stack */
288 (*aopp)->type = AOP_STK;
292 /* other wise this is true end of the world */
293 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
294 "getFreePtr should never reach here");
297 return NULL; // notreached, but makes compiler happy.
300 /*-----------------------------------------------------------------*/
301 /* newAsmop - creates a new asmOp */
302 /*-----------------------------------------------------------------*/
304 newAsmop (short type)
308 aop = Safe_calloc (1, sizeof (asmop));
313 static int _currentDPS; /* Current processor DPS. */
314 static int _desiredDPS; /* DPS value compiler thinks we should be using. */
315 static int _lazyDPS = 0; /* if non-zero, we are doing lazy evaluation of DPS changes. */
317 /*-----------------------------------------------------------------*/
318 /* genSetDPTR: generate code to select which DPTR is in use (zero */
319 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390 */
320 /* alternate DPTR (DPL1/DPH1/DPX1). */
321 /*-----------------------------------------------------------------*/
326 /* If we are doing lazy evaluation, simply note the desired
327 * change, but don't emit any code yet.
337 emitcode ("mov", "dps,#0");
342 emitcode ("mov", "dps,#1");
346 /*-----------------------------------------------------------------*/
347 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
349 /* Any code that operates on DPTR (NB: not on the individual */
350 /* components, like DPH) *must* call _flushLazyDPS() before using */
351 /* DPTR within a lazy DPS evaluation block. */
353 /* Note that aopPut and aopGet already contain the proper calls to */
354 /* _flushLazyDPS, so it is safe to use these calls within a lazy */
355 /* DPS evaluation block. */
357 /* Also, _flushLazyDPS must be called before any flow control */
358 /* operations that could potentially branch out of the block. */
360 /* Lazy DPS evaluation is simply an optimization (though an */
361 /* important one), so if in doubt, leave it out. */
362 /*-----------------------------------------------------------------*/
364 _startLazyDPSEvaluation (void)
368 #ifdef BETTER_LITERAL_SHIFT
375 /*-----------------------------------------------------------------*/
376 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
377 /* desired one. Call before using DPTR within a lazy DPS evaluation */
379 /*-----------------------------------------------------------------*/
389 if (_desiredDPS != _currentDPS)
393 emitcode ("inc", "dps");
397 emitcode ("dec", "dps");
399 _currentDPS = _desiredDPS;
403 /*-----------------------------------------------------------------*/
404 /* _endLazyDPSEvaluation: end lazy DPS evaluation block. */
406 /* Forces us back to the safe state (standard DPTR selected). */
407 /*-----------------------------------------------------------------*/
409 _endLazyDPSEvaluation (void)
411 #ifdef BETTER_LITERAL_SHIFT
430 /*-----------------------------------------------------------------*/
431 /* pointerCode - returns the code for a pointer type */
432 /*-----------------------------------------------------------------*/
434 pointerCode (sym_link * etype)
437 return PTR_TYPE (SPEC_OCLS (etype));
441 /*-----------------------------------------------------------------*/
442 /* leftRightUseAcc - returns size of accumulator use by operands */
443 /*-----------------------------------------------------------------*/
445 leftRightUseAcc(iCode *ic)
449 if (ic && IC_LEFT (ic) && IS_SYMOP (IC_LEFT (ic))
450 && OP_SYMBOL (IC_LEFT (ic)) && OP_SYMBOL (IC_LEFT (ic))->accuse)
451 accuse = (accuse < OP_SYMBOL (IC_LEFT (ic))->nRegs)
452 ? OP_SYMBOL (IC_LEFT (ic))->nRegs : accuse;
454 if (ic && IC_RIGHT (ic) && IS_SYMOP (IC_RIGHT (ic))
455 && OP_SYMBOL (IC_RIGHT (ic)) && OP_SYMBOL (IC_RIGHT (ic))->accuse)
456 accuse = (accuse < OP_SYMBOL (IC_RIGHT (ic))->nRegs)
457 ? OP_SYMBOL (IC_RIGHT (ic))->nRegs : accuse;
462 /*-----------------------------------------------------------------*/
463 /* aopForSym - for a true symbol */
464 /*-----------------------------------------------------------------*/
466 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
469 memmap *space = SPEC_OCLS (sym->etype);
470 int accuse = leftRightUseAcc (ic);
472 /* if already has one */
476 /* assign depending on the storage class */
477 /* if it is on the stack or indirectly addressable */
478 /* space we need to assign either r0 or r1 to it */
479 if ((sym->onStack && !options.stack10bit) || sym->iaccess)
481 sym->aop = aop = newAsmop (0);
482 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
483 aop->size = getSize (sym->type);
485 /* now assign the address of the variable to
486 the pointer register */
487 if (aop->type != AOP_STK)
492 if (_G.accInUse || accuse)
493 emitcode ("push", "acc");
495 if (_G.bInUse || (accuse>1))
496 emitcode ("push", "b");
498 emitcode ("mov", "a,_bp");
499 emitcode ("add", "a,#!constbyte",
501 ((char) (sym->stack - _G.nRegsSaved)) :
502 ((char) sym->stack)) & 0xff);
503 emitcode ("mov", "%s,a",
504 aop->aopu.aop_ptr->name);
506 if (_G.bInUse || (accuse>1))
507 emitcode ("pop", "b");
509 if (_G.accInUse || accuse)
510 emitcode ("pop", "acc");
513 emitcode ("mov", "%s,#%s",
514 aop->aopu.aop_ptr->name,
516 aop->paged = space->paged;
519 aop->aopu.aop_stk = sym->stack;
523 if (sym->onStack && options.stack10bit)
525 short stack_val = -((sym->stack < 0) ?
526 ((short) (sym->stack - _G.nRegsSaved)) :
527 ((short) sym->stack)) ;
528 if (useDP2 && _G.dptr1InUse) {
529 emitcode ("push","dpl1");
530 emitcode ("push","dph1");
531 emitcode ("push","dpx1");
532 } else if (_G.dptrInUse ) {
533 emitcode ("push","dpl");
534 emitcode ("push","dph");
535 emitcode ("push","dpx");
537 /* It's on the 10 bit stack, which is located in
540 if (stack_val < 0 && stack_val > -5) { /* between -5 & -1 */
542 if (options.model == MODEL_FLAT24)
544 emitcode ("mov", "dpx1,#!constbyte",
545 (options.stack_loc >> 16) & 0xff);
547 emitcode ("mov", "dph1,_bpx+1");
549 emitcode ("mov", "dpl1,_bpx");
550 emitcode ("mov","dps,#1");
552 if (options.model == MODEL_FLAT24)
554 emitcode ("mov", "dpx,#!constbyte",
555 (options.stack_loc >> 16) & 0xff);
557 emitcode ("mov", "dph,_bpx+1");
558 emitcode ("mov", "dpl,_bpx");
560 stack_val = -stack_val;
561 while (stack_val--) {
562 emitcode ("inc","dptr");
565 emitcode("mov","dps,#0");
568 if (_G.accInUse || accuse)
569 emitcode ("push", "acc");
571 if (_G.bInUse || (accuse>1))
572 emitcode ("push", "b");
574 emitcode ("mov", "a,_bpx");
575 emitcode ("clr","c");
576 emitcode ("subb", "a,#!constbyte", stack_val & 0xff);
577 emitcode ("mov","b,a");
578 emitcode ("mov","a,_bpx+1");
579 emitcode ("subb","a,#!constbyte",(stack_val >> 8) & 0xff);
581 if (options.model == MODEL_FLAT24)
583 emitcode ("mov", "dpx1,#!constbyte",
584 (options.stack_loc >> 16) & 0xff);
586 emitcode ("mov", "dph1,a");
587 emitcode ("mov", "dpl1,b");
589 if (options.model == MODEL_FLAT24)
591 emitcode ("mov", "dpx,#!constbyte",
592 (options.stack_loc >> 16) & 0xff);
594 emitcode ("mov", "dph,a");
595 emitcode ("mov", "dpl,b");
598 if (_G.bInUse || (accuse>1))
599 emitcode ("pop", "b");
601 if (_G.accInUse || accuse)
602 emitcode ("pop", "acc");
604 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
605 aop->size = getSize (sym->type);
609 /* if in bit space */
610 if (IN_BITSPACE (space))
612 sym->aop = aop = newAsmop (AOP_CRY);
613 aop->aopu.aop_dir = sym->rname;
614 aop->size = getSize (sym->type);
617 /* if it is in direct space */
618 if (IN_DIRSPACE (space))
620 sym->aop = aop = newAsmop (AOP_DIR);
621 aop->aopu.aop_dir = sym->rname;
622 aop->size = getSize (sym->type);
626 /* special case for a function */
627 if (IS_FUNC (sym->type) && !(sym->isitmp))
629 sym->aop = aop = newAsmop (AOP_IMMD);
630 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
631 aop->size = FPTRSIZE;
635 /* only remaining is far space */
636 /* in which case DPTR gets the address */
637 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
642 emitcode ("mov", "dptr,#%s", sym->rname);
647 emitcode ("mov", "dptr,#%s", sym->rname);
649 aop->size = getSize (sym->type);
651 /* if it is in code space */
652 if (IN_CODESPACE (space))
658 /*-----------------------------------------------------------------*/
659 /* aopForRemat - rematerialzes an object */
660 /*-----------------------------------------------------------------*/
662 aopForRemat (symbol * sym)
664 iCode *ic = sym->rematiCode;
665 asmop *aop = newAsmop (AOP_IMMD);
672 val += (int) operandLitValue (IC_RIGHT (ic));
673 else if (ic->op == '-')
674 val -= (int) operandLitValue (IC_RIGHT (ic));
675 else if (IS_CAST_ICODE(ic)) {
676 sym_link *from_type = operandType(IC_RIGHT(ic));
677 aop->aopu.aop_immd.from_cast_remat = 1;
678 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
679 ptr_type = DCL_TYPE(from_type);
680 if (ptr_type == IPOINTER) {
687 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
692 SNPRINTF (buffer, sizeof(buffer),
694 OP_SYMBOL (IC_LEFT (ic))->rname,
695 val >= 0 ? '+' : '-',
696 abs (val) & 0xffffff);
700 if (IS_ASSIGN_ICODE(ic) && isOperandLiteral(IC_RIGHT(ic)))
702 SNPRINTF(buffer, sizeof(buffer),
703 "0x%x",(int) operandLitValue (IC_RIGHT (ic)));
707 strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
711 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);
712 /* set immd2 field if required */
713 if (aop->aopu.aop_immd.from_cast_remat)
715 tsprintf(buffer, sizeof(buffer), "#!constbyte",ptr_type);
716 aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
722 /*-----------------------------------------------------------------*/
723 /* aopHasRegs - returns true if aop has regs between from-to */
724 /*-----------------------------------------------------------------*/
725 static int aopHasRegs(asmop *aop, int from, int to)
729 if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
731 for (; size < aop->size ; size++) {
733 for (reg = from ; reg <= to ; reg++)
734 if (aop->aopu.aop_reg[size] == ds390_regWithIdx(reg)) return 1;
739 /*-----------------------------------------------------------------*/
740 /* regsInCommon - two operands have some registers in common */
741 /*-----------------------------------------------------------------*/
743 regsInCommon (operand * op1, operand * op2)
748 /* if they have registers in common */
749 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
752 sym1 = OP_SYMBOL (op1);
753 sym2 = OP_SYMBOL (op2);
755 if (sym1->nRegs == 0 || sym2->nRegs == 0)
758 for (i = 0; i < sym1->nRegs; i++)
764 for (j = 0; j < sym2->nRegs; j++)
769 if (sym2->regs[j] == sym1->regs[i])
777 /*-----------------------------------------------------------------*/
778 /* operandsEqu - equivalent */
779 /*-----------------------------------------------------------------*/
781 operandsEqu (operand * op1, operand * op2)
785 /* if they not symbols */
786 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
789 sym1 = OP_SYMBOL (op1);
790 sym2 = OP_SYMBOL (op2);
792 /* if both are itemps & one is spilt
793 and the other is not then false */
794 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
795 sym1->isspilt != sym2->isspilt)
798 /* if they are the same */
802 if (strcmp (sym1->rname, sym2->rname) == 0)
806 /* if left is a tmp & right is not */
807 if (IS_ITEMP (op1) &&
810 (sym1->usl.spillLoc == sym2))
813 if (IS_ITEMP (op2) &&
817 (sym2->usl.spillLoc == sym1))
823 /*-----------------------------------------------------------------*/
824 /* sameRegs - two asmops have the same registers */
825 /*-----------------------------------------------------------------*/
827 sameRegs (asmop * aop1, asmop * aop2)
833 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
840 if (aop1->type != AOP_REG ||
841 aop2->type != AOP_REG)
844 if (aop1->size != aop2->size)
847 for (i = 0; i < aop1->size; i++)
848 if (aop1->aopu.aop_reg[i] !=
849 aop2->aopu.aop_reg[i])
855 /*-----------------------------------------------------------------*/
856 /* aopOp - allocates an asmop for an operand : */
857 /*-----------------------------------------------------------------*/
859 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
868 /* if this a literal */
869 if (IS_OP_LITERAL (op))
871 op->aop = aop = newAsmop (AOP_LIT);
872 aop->aopu.aop_lit = op->operand.valOperand;
873 aop->size = getSize (operandType (op));
877 /* if already has a asmop then continue */
881 /* if the underlying symbol has a aop */
882 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
884 op->aop = OP_SYMBOL (op)->aop;
888 /* if this is a true symbol */
889 if (IS_TRUE_SYMOP (op))
891 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
895 /* this is a temporary : this has
901 e) can be a return use only */
903 sym = OP_SYMBOL (op);
906 /* if the type is a conditional */
907 if (sym->regType == REG_CND)
909 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
914 /* if it is spilt then two situations
916 b) has a spill location */
917 if (sym->isspilt || sym->nRegs == 0)
920 /* rematerialize it NOW */
923 sym->aop = op->aop = aop =
925 aop->size = getSize (sym->type);
932 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
933 aop->size = getSize (sym->type);
934 for (i = 0; i < 2; i++)
935 aop->aopu.aop_str[i] = accUse[i];
945 /* a AOP_STR uses DPTR, but DPTR is already in use;
948 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"AOP_STR with DPTR in use!");
951 aop = op->aop = sym->aop = newAsmop (AOP_STR);
952 aop->size = getSize (sym->type);
953 for (i = 0; i < (int) fReturnSizeDS390; i++)
954 aop->aopu.aop_str[i] = fReturn[i];
958 if (sym->dptr) { /* has been allocated to a DPTRn */
959 aop = op->aop = sym->aop = newAsmop (AOP_DPTRn);
960 aop->size = getSize (sym->type);
961 aop->aopu.dptr = sym->dptr;
964 /* else spill location */
965 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
966 /* force a new aop if sizes differ */
967 sym->usl.spillLoc->aop = NULL;
969 sym->aop = op->aop = aop =
970 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
971 aop->size = getSize (sym->type);
975 /* must be in a register */
976 sym->aop = op->aop = aop = newAsmop (AOP_REG);
977 aop->size = sym->nRegs;
978 for (i = 0; i < sym->nRegs; i++)
979 aop->aopu.aop_reg[i] = sym->regs[i];
982 /*-----------------------------------------------------------------*/
983 /* freeAsmop - free up the asmop given to an operand */
984 /*----------------------------------------------------------------*/
986 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1003 /* depending on the asmop type only three cases need work AOP_RO
1004 , AOP_R1 && AOP_STK */
1012 emitcode ("pop", "ar0");
1016 bitVectUnSetBit (ic->rUsed, R0_IDX);
1024 emitcode ("pop", "ar1");
1028 bitVectUnSetBit (ic->rUsed, R1_IDX);
1034 int stk = aop->aopu.aop_stk + aop->size;
1035 bitVectUnSetBit (ic->rUsed, R0_IDX);
1036 bitVectUnSetBit (ic->rUsed, R1_IDX);
1038 getFreePtr (ic, &aop, FALSE);
1040 if (options.stack10bit)
1042 /* I'm not sure what to do here yet... */
1045 "*** Warning: probably generating bad code for "
1046 "10 bit stack mode.\n");
1051 emitcode ("mov", "a,_bp");
1052 emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
1053 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1057 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1062 emitcode ("pop", "acc");
1063 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1066 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1069 freeAsmop (op, NULL, ic, TRUE);
1072 emitcode ("pop", "ar0");
1078 emitcode ("pop", "ar1");
1083 if (_G.dptr1InUse) {
1084 emitcode ("pop","dpx1");
1085 emitcode ("pop","dph1");
1086 emitcode ("pop","dpl1");
1091 emitcode ("pop","dpx");
1092 emitcode ("pop","dph");
1093 emitcode ("pop","dpl");
1098 /* all other cases just dealloc */
1104 OP_SYMBOL (op)->aop = NULL;
1105 /* if the symbol has a spill */
1107 SPIL_LOC (op)->aop = NULL;
1112 #define DEFAULT_ACC_WARNING 0
1113 static int saveAccWarn = DEFAULT_ACC_WARNING;
1115 /*-------------------------------------------------------------------*/
1116 /* aopGet - for fetching value of the aop */
1118 /* Set saveAcc to NULL if you are sure it is OK to clobber the value */
1119 /* in the accumulator. Set it to the name of a free register */
1120 /* if acc must be preserved; the register will be used to preserve */
1121 /* acc temporarily and to return the result byte. */
1122 /*-------------------------------------------------------------------*/
1131 /* offset is greater than
1133 if (offset > (aop->size - 1) &&
1134 aop->type != AOP_LIT)
1137 /* depending on type */
1143 /* if we need to increment it */
1144 while (offset > aop->coff)
1146 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1150 while (offset < aop->coff)
1152 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1159 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1160 return (dname ? "acc" : "a");
1162 SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1163 return Safe_strdup(buffer);
1166 assert(offset <= 3);
1167 return dptrn[aop->aopu.dptr][offset];
1172 if (aop->type == AOP_DPTR2)
1180 // if (aop->type != AOP_DPTR2)
1182 // if (saveAccWarn) { fprintf(stderr, "saveAcc for DPTR...\n"); }
1183 // emitcode(";", "spanky: saveAcc for DPTR");
1186 emitcode ("xch", "a, %s", saveAcc);
1191 while (offset > aop->coff)
1193 emitcode ("inc", "dptr");
1197 while (offset < aop->coff)
1199 emitcode ("lcall", "__decdptr");
1206 emitcode ("clr", "a");
1207 emitcode ("movc", "a,@a+dptr");
1211 emitcode ("movx", "a,@dptr");
1214 if (aop->type == AOP_DPTR2)
1222 emitcode ("xch", "a, %s", saveAcc);
1223 // if (strcmp(saveAcc, "_ap"))
1225 // emitcode(";", "spiffy: non _ap return from aopGet.");
1230 return (dname ? "acc" : "a");
1233 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1235 SNPRINTF(buffer, sizeof(buffer),
1236 "%s",aop->aopu.aop_immd.aop_immd2);
1240 SNPRINTF(buffer, sizeof(buffer),
1241 "#%s", aop->aopu.aop_immd.aop_immd1);
1247 tsprintf(buffer, sizeof(buffer),
1248 "#!his",aop->aopu.aop_immd.aop_immd1);
1251 tsprintf(buffer, sizeof(buffer),
1252 "#!hihis",aop->aopu.aop_immd.aop_immd1);
1255 tsprintf(buffer, sizeof(buffer),
1256 "#!hihihis",aop->aopu.aop_immd.aop_immd1);
1258 default: /* should not need this (just in case) */
1259 SNPRINTF (buffer, sizeof(buffer),
1261 aop->aopu.aop_immd.aop_immd1,
1267 SNPRINTF (buffer, sizeof(buffer),
1268 "#%s", aop->aopu.aop_immd.aop_immd1);
1270 return Safe_strdup(buffer);
1275 SNPRINTF (buffer, sizeof(buffer),
1282 SNPRINTF(buffer, sizeof(buffer),
1283 "%s", aop->aopu.aop_dir);
1286 return Safe_strdup(buffer);
1290 return aop->aopu.aop_reg[offset]->dname;
1292 return aop->aopu.aop_reg[offset]->name;
1295 emitcode ("clr", "a");
1296 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1297 emitcode ("rlc", "a");
1298 return (dname ? "acc" : "a");
1301 if (!offset && dname)
1303 return aop->aopu.aop_str[offset];
1306 return aopLiteral (aop->aopu.aop_lit, offset);
1310 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1314 return aop->aopu.aop_str[offset];
1318 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1319 "aopget got unsupported aop->type");
1322 return NULL; // not reached, but makes compiler happy.
1324 /*-----------------------------------------------------------------*/
1325 /* aopPut - puts a string for a aop */
1326 /*-----------------------------------------------------------------*/
1328 aopPut (asmop * aop, char *s, int offset)
1330 if (aop->size && offset > (aop->size - 1))
1332 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1333 "aopPut got offset > aop->size");
1337 /* will assign value to value */
1338 /* depending on where it is ofcourse */
1344 SNPRINTF (buffer, sizeof(buffer),
1346 aop->aopu.aop_dir, offset);
1350 SNPRINTF (buffer, sizeof(buffer),
1351 "%s", aop->aopu.aop_dir);
1355 if (strcmp (buffer, s))
1357 emitcode ("mov", "%s,%s", buffer, s);
1362 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1363 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1366 strcmp (s, "r0") == 0 ||
1367 strcmp (s, "r1") == 0 ||
1368 strcmp (s, "r2") == 0 ||
1369 strcmp (s, "r3") == 0 ||
1370 strcmp (s, "r4") == 0 ||
1371 strcmp (s, "r5") == 0 ||
1372 strcmp (s, "r6") == 0 ||
1373 strcmp (s, "r7") == 0)
1375 emitcode ("mov", "%s,%s",
1376 aop->aopu.aop_reg[offset]->dname, s);
1380 emitcode ("mov", "%s,%s",
1381 aop->aopu.aop_reg[offset]->name, s);
1387 emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1393 if (aop->type == AOP_DPTR2)
1401 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1402 "aopPut writting to code space");
1406 while (offset > aop->coff)
1409 emitcode ("inc", "dptr");
1412 while (offset < aop->coff)
1415 emitcode ("lcall", "__decdptr");
1420 /* if not in accumulater */
1423 emitcode ("movx", "@dptr,a");
1425 if (aop->type == AOP_DPTR2)
1433 while (offset > aop->coff)
1436 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1438 while (offset < aop->coff)
1441 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1448 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1454 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1456 else if (strcmp (s, "r0") == 0 ||
1457 strcmp (s, "r1") == 0 ||
1458 strcmp (s, "r2") == 0 ||
1459 strcmp (s, "r3") == 0 ||
1460 strcmp (s, "r4") == 0 ||
1461 strcmp (s, "r5") == 0 ||
1462 strcmp (s, "r6") == 0 ||
1463 strcmp (s, "r7") == 0)
1466 SNPRINTF(buff, sizeof(buff),
1468 emitcode ("mov", "@%s,%s",
1469 aop->aopu.aop_ptr->name, buff);
1473 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1478 if (strcmp (s, "a") == 0)
1479 emitcode ("push", "acc");
1483 emitcode ("push", "acc");
1485 emitcode ("push", s);
1491 /* if bit variable */
1492 if (!aop->aopu.aop_dir)
1494 emitcode ("clr", "a");
1495 emitcode ("rlc", "a");
1500 emitcode ("clr", "%s", aop->aopu.aop_dir);
1502 emitcode ("setb", "%s", aop->aopu.aop_dir);
1503 else if (!strcmp (s, "c"))
1504 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1507 if (strcmp (s, "a"))
1512 /* set C, if a >= 1 */
1513 emitcode ("add", "a,#!constbyte",0xff);
1514 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1522 if (strcmp (aop->aopu.aop_str[offset], s))
1523 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1528 if (!offset && (strcmp (s, "acc") == 0))
1531 if (strcmp (aop->aopu.aop_str[offset], s))
1532 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1536 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1537 "aopPut got unsupported aop->type");
1544 /*--------------------------------------------------------------------*/
1545 /* reAdjustPreg - points a register back to where it should (coff==0) */
1546 /*--------------------------------------------------------------------*/
1548 reAdjustPreg (asmop * aop)
1550 if ((aop->coff==0) || (aop->size <= 1)) {
1559 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1563 if (aop->type == AOP_DPTR2)
1570 emitcode ("lcall", "__decdptr");
1573 if (aop->type == AOP_DPTR2)
1583 #define AOP(op) op->aop
1584 #define AOP_TYPE(op) AOP(op)->type
1585 #define AOP_SIZE(op) AOP(op)->size
1586 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1587 AOP_TYPE(x) == AOP_R0))
1589 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1590 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1593 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1594 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1595 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1596 #define AOP_INDPTRn(x) (AOP_TYPE(x) == AOP_DPTRn)
1597 #define AOP_USESDPTR(x) ((AOP_TYPE(x) == AOP_DPTR) || (AOP_TYPE(x) == AOP_STR))
1598 #define AOP_USESDPTR2(x) ((AOP_TYPE(x) == AOP_DPTR2) || (AOP_TYPE(x) == AOP_DPTRn))
1600 // The following two macros can be used even if the aop has not yet been aopOp'd.
1601 #define AOP_IS_STR(x) (IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
1602 #define AOP_IS_DPTRn(x) (IS_SYMOP(x) && OP_SYMBOL(x)->dptr)
1604 /* Workaround for DS80C390 bug: div ab may return bogus results
1605 * if A is accessed in instruction immediately before the div.
1607 * Will be fixed in B4 rev of processor, Dallas claims.
1610 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1611 if (!AOP_NEEDSACC(RIGHT)) \
1613 /* We can load A first, then B, since \
1614 * B (the RIGHT operand) won't clobber A, \
1615 * thus avoiding touching A right before the div. \
1617 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1618 L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL); \
1620 L = aopGet(AOP(RIGHT),0,FALSE,FALSE,"b"); \
1625 /* Just stuff in a nop after loading A. */ \
1626 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,NULL));\
1627 L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL); \
1629 emitcode("nop", "; workaround for DS80C390 div bug."); \
1633 /*-----------------------------------------------------------------*/
1634 /* opIsGptr: returns non-zero if the passed operand is */
1635 /* a generic pointer type. */
1636 /*-----------------------------------------------------------------*/
1638 opIsGptr (operand * op)
1640 sym_link *type = operandType (op);
1642 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1649 /*-----------------------------------------------------------------*/
1650 /* getDataSize - get the operand data size */
1651 /*-----------------------------------------------------------------*/
1653 getDataSize (operand * op)
1656 size = AOP_SIZE (op);
1657 if (size == GPTRSIZE)
1659 sym_link *type = operandType (op);
1660 if (IS_GENPTR (type))
1662 /* generic pointer; arithmetic operations
1663 * should ignore the high byte (pointer type).
1671 /*-----------------------------------------------------------------*/
1672 /* outAcc - output Acc */
1673 /*-----------------------------------------------------------------*/
1675 outAcc (operand * result)
1678 size = getDataSize (result);
1681 aopPut (AOP (result), "a", 0);
1684 /* unsigned or positive */
1687 aopPut (AOP (result), zero, offset++);
1692 /*-----------------------------------------------------------------*/
1693 /* outBitC - output a bit C */
1694 /*-----------------------------------------------------------------*/
1696 outBitC (operand * result)
1698 /* if the result is bit */
1699 if (AOP_TYPE (result) == AOP_CRY)
1701 aopPut (AOP (result), "c", 0);
1705 emitcode ("clr", "a");
1706 emitcode ("rlc", "a");
1711 /*-----------------------------------------------------------------*/
1712 /* toBoolean - emit code for orl a,operator(sizeop) */
1713 /*-----------------------------------------------------------------*/
1715 toBoolean (operand * oper)
1717 int size = AOP_SIZE (oper) - 1;
1721 /* The generic part of a generic pointer should
1722 * not participate in it's truth value.
1724 * i.e. 0x10000000 is zero.
1726 if (opIsGptr (oper))
1728 D (emitcode (";", "toBoolean: generic ptr special case."););
1732 _startLazyDPSEvaluation ();
1733 if (AOP_NEEDSACC (oper) && size)
1738 emitcode ("push", "b");
1740 MOVB (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1744 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1751 emitcode ("orl", "b,%s",
1752 aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1756 emitcode ("orl", "a,%s",
1757 aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1760 _endLazyDPSEvaluation ();
1764 emitcode ("mov", "a,b");
1767 emitcode ("pop", "b");
1774 /*-----------------------------------------------------------------*/
1775 /* genNot - generate code for ! operation */
1776 /*-----------------------------------------------------------------*/
1782 D (emitcode (";", "genNot "););
1784 /* assign asmOps to operand & result */
1785 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1786 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1788 /* if in bit space then a special case */
1789 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1791 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1792 emitcode ("cpl", "c");
1793 outBitC (IC_RESULT (ic));
1797 toBoolean (IC_LEFT (ic));
1799 tlbl = newiTempLabel (NULL);
1800 emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1801 emitcode ("", "!tlabeldef", tlbl->key + 100);
1802 outBitC (IC_RESULT (ic));
1805 /* release the aops */
1806 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1807 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1811 /*-----------------------------------------------------------------*/
1812 /* genCpl - generate code for complement */
1813 /*-----------------------------------------------------------------*/
1821 D (emitcode (";", "genCpl "););
1824 /* assign asmOps to operand & result */
1825 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1826 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1828 /* special case if in bit space */
1829 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1830 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1831 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1832 emitcode ("cpl", "c");
1833 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1836 tlbl=newiTempLabel(NULL);
1837 emitcode ("cjne", "%s,#0x01,%05d$",
1838 aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE,NULL), tlbl->key+100);
1839 emitcode ("", "%05d$:", tlbl->key+100);
1840 outBitC (IC_RESULT(ic));
1844 size = AOP_SIZE (IC_RESULT (ic));
1845 _startLazyDPSEvaluation ();
1848 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
1849 emitcode ("cpl", "a");
1850 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1852 _endLazyDPSEvaluation ();
1856 /* release the aops */
1857 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1858 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1861 /*-----------------------------------------------------------------*/
1862 /* genUminusFloat - unary minus for floating points */
1863 /*-----------------------------------------------------------------*/
1865 genUminusFloat (operand * op, operand * result)
1867 int size, offset = 0;
1869 D(emitcode (";", "genUminusFloat"););
1871 /* for this we just copy and then flip the bit */
1873 _startLazyDPSEvaluation ();
1874 size = AOP_SIZE (op) - 1;
1878 aopPut (AOP (result),
1879 aopGet (AOP (op), offset, FALSE, FALSE, NULL),
1884 MOVA(aopGet (AOP (op), offset, FALSE, FALSE, NULL));
1886 emitcode ("cpl", "acc.7");
1887 aopPut (AOP (result), "a", offset);
1888 _endLazyDPSEvaluation ();
1891 /*-----------------------------------------------------------------*/
1892 /* genUminus - unary minus code generation */
1893 /*-----------------------------------------------------------------*/
1895 genUminus (iCode * ic)
1900 D (emitcode (";", "genUminus "););
1903 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1904 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1906 /* if both in bit space then special
1908 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1909 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1912 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1913 emitcode ("cpl", "c");
1914 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1918 optype = operandType (IC_LEFT (ic));
1920 /* if float then do float stuff */
1921 if (IS_FLOAT (optype))
1923 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1927 /* otherwise subtract from zero */
1928 size = AOP_SIZE (IC_LEFT (ic));
1930 _startLazyDPSEvaluation ();
1933 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL);
1934 if (!strcmp (l, "a"))
1938 emitcode ("cpl", "a");
1939 emitcode ("addc", "a,#0");
1945 emitcode ("clr", "a");
1946 emitcode ("subb", "a,%s", l);
1948 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1950 _endLazyDPSEvaluation ();
1952 /* if any remaining bytes in the result */
1953 /* we just need to propagate the sign */
1954 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic)))) != 0)
1956 emitcode ("rlc", "a");
1957 emitcode ("subb", "a,acc");
1959 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1963 /* release the aops */
1964 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1965 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1968 /*-----------------------------------------------------------------*/
1969 /* savermask - saves registers in the mask */
1970 /*-----------------------------------------------------------------*/
1971 static void savermask(bitVect *rs_mask)
1974 if (options.useXstack) {
1975 if (bitVectBitValue (rs_mask, R0_IDX))
1976 emitcode ("mov", "b,r0");
1977 emitcode ("mov", "r0,%s", spname);
1978 for (i = 0; i < ds390_nRegs; i++) {
1979 if (bitVectBitValue (rs_mask, i)) {
1981 emitcode ("mov", "a,b");
1983 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1984 emitcode ("movx", "@r0,a");
1985 emitcode ("inc", "r0");
1988 emitcode ("mov", "%s,r0", spname);
1989 if (bitVectBitValue (rs_mask, R0_IDX))
1990 emitcode ("mov", "r0,b");
1992 for (i = 0; i < ds390_nRegs; i++) {
1993 if (bitVectBitValue (rs_mask, i))
1994 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
1999 /*-----------------------------------------------------------------*/
2000 /* saveRegisters - will look for a call and save the registers */
2001 /*-----------------------------------------------------------------*/
2003 saveRegisters (iCode * lic)
2009 for (ic = lic; ic; ic = ic->next)
2010 if (ic->op == CALL || ic->op == PCALL)
2015 fprintf (stderr, "found parameter push with no function call\n");
2019 /* if the registers have been saved already then
2022 || (IS_SYMOP(IC_LEFT(ic)) && IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))) && !TARGET_IS_DS400) )
2025 /* special case if DPTR alive across a function call then must save it
2026 even though callee saves */
2027 if (IS_SYMOP(IC_LEFT(ic)) &&
2028 IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2030 rsave = newBitVect(ic->rMask->size);
2031 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2032 if (bitVectBitValue(ic->rMask,i))
2033 rsave = bitVectSetBit(rsave,i);
2035 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2037 /* safe the registers in use at this time but skip the
2038 ones for the result */
2039 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2040 ds390_rUmaskForOp (IC_RESULT(ic)));
2046 /*-----------------------------------------------------------------*/
2047 /* usavermask - restore registers with mask */
2048 /*-----------------------------------------------------------------*/
2049 static void unsavermask(bitVect *rs_mask)
2052 if (options.useXstack) {
2053 emitcode ("mov", "r0,%s", spname);
2054 for (i = ds390_nRegs; i >= 0; i--) {
2055 if (bitVectBitValue (rs_mask, i)) {
2056 emitcode ("dec", "r0");
2057 emitcode ("movx", "a,@r0");
2059 emitcode ("mov", "b,a");
2061 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
2064 emitcode ("mov", "%s,r0", spname);
2065 if (bitVectBitValue (rs_mask, R0_IDX))
2066 emitcode ("mov", "r0,b");
2068 for (i = ds390_nRegs; i >= 0; i--) {
2069 if (bitVectBitValue (rs_mask, i))
2070 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2075 /*-----------------------------------------------------------------*/
2076 /* unsaveRegisters - pop the pushed registers */
2077 /*-----------------------------------------------------------------*/
2079 unsaveRegisters (iCode * ic)
2083 if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2085 rsave = newBitVect(ic->rMask->size);
2086 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2087 if (bitVectBitValue(ic->rMask,i))
2088 rsave = bitVectSetBit(rsave,i);
2090 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2092 /* restore the registers in use at this time but skip the
2093 ones for the result */
2094 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2095 ds390_rUmaskForOp (IC_RESULT(ic)));
2101 /*-----------------------------------------------------------------*/
2103 /*-----------------------------------------------------------------*/
2105 pushSide (operand * oper, int size)
2108 _startLazyDPSEvaluation ();
2111 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, NULL);
2112 if (AOP_TYPE (oper) != AOP_REG &&
2113 AOP_TYPE (oper) != AOP_DIR &&
2116 emitcode ("mov", "a,%s", l);
2117 emitcode ("push", "acc");
2120 emitcode ("push", "%s", l);
2122 _endLazyDPSEvaluation ();
2125 /*-----------------------------------------------------------------*/
2126 /* assignResultValue - */
2127 /*-----------------------------------------------------------------*/
2129 assignResultValue (operand * oper)
2132 int size = AOP_SIZE (oper);
2133 bool pushedAcc = FALSE;
2135 if (size == fReturnSizeDS390)
2137 /* I don't think this case can ever happen... */
2138 /* ACC is the last part of this. If writing the result
2139 * uses AC, we must preserve it.
2141 if (AOP_NEEDSACC(oper))
2143 emitcode(";", "assignResultValue special case for ACC.");
2144 emitcode("push", "acc");
2151 _startLazyDPSEvaluation ();
2154 aopPut (AOP (oper), fReturn[offset], offset);
2157 _endLazyDPSEvaluation ();
2161 emitcode("pop", "acc");
2162 aopPut(AOP(oper), "a", offset);
2167 /*-----------------------------------------------------------------*/
2168 /* genXpush - pushes onto the external stack */
2169 /*-----------------------------------------------------------------*/
2171 genXpush (iCode * ic)
2173 asmop *aop = newAsmop (0);
2175 int size, offset = 0;
2177 D (emitcode (";", "genXpush ");
2180 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2181 r = getFreePtr (ic, &aop, FALSE);
2184 emitcode ("mov", "%s,_spx", r->name);
2186 size = AOP_SIZE (IC_LEFT (ic));
2187 _startLazyDPSEvaluation ();
2191 MOVA (aopGet (AOP (IC_LEFT (ic)),
2192 offset++, FALSE, FALSE, NULL));
2193 emitcode ("movx", "@%s,a", r->name);
2194 emitcode ("inc", "%s", r->name);
2197 _endLazyDPSEvaluation ();
2200 emitcode ("mov", "_spx,%s", r->name);
2202 freeAsmop (NULL, aop, ic, TRUE);
2203 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2206 /*-----------------------------------------------------------------*/
2207 /* genIpush - generate code for pushing this gets a little complex */
2208 /*-----------------------------------------------------------------*/
2210 genIpush (iCode * ic)
2212 int size, offset = 0;
2215 D (emitcode (";", "genIpush ");
2218 /* if this is not a parm push : ie. it is spill push
2219 and spill push is always done on the local stack */
2223 /* and the item is spilt then do nothing */
2224 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2227 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2228 size = AOP_SIZE (IC_LEFT (ic));
2229 /* push it on the stack */
2230 _startLazyDPSEvaluation ();
2233 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2239 emitcode ("push", "%s", l);
2241 _endLazyDPSEvaluation ();
2245 /* this is a paramter push: in this case we call
2246 the routine to find the call and save those
2247 registers that need to be saved */
2250 /* if use external stack then call the external
2251 stack pushing routine */
2252 if (options.useXstack)
2258 /* then do the push */
2259 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2261 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2262 size = AOP_SIZE (IC_LEFT (ic));
2264 _startLazyDPSEvaluation ();
2267 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2268 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2269 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2272 emitcode ("mov", "a,%s", l);
2273 emitcode ("push", "acc");
2277 emitcode ("push", "%s", l);
2280 _endLazyDPSEvaluation ();
2282 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2285 /*-----------------------------------------------------------------*/
2286 /* genIpop - recover the registers: can happen only for spilling */
2287 /*-----------------------------------------------------------------*/
2289 genIpop (iCode * ic)
2293 D (emitcode (";", "genIpop ");
2297 /* if the temp was not pushed then */
2298 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2301 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2302 size = AOP_SIZE (IC_LEFT (ic));
2303 offset = (size - 1);
2304 _startLazyDPSEvaluation ();
2307 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2308 FALSE, TRUE, NULL));
2310 _endLazyDPSEvaluation ();
2312 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2315 /*-----------------------------------------------------------------*/
2316 /* unsaveRBank - restores the resgister bank from stack */
2317 /*-----------------------------------------------------------------*/
2319 unsaveRBank (int bank, iCode * ic, bool popPsw)
2325 if (options.useXstack)
2329 /* Assume r0 is available for use. */
2330 r = ds390_regWithIdx (R0_IDX);;
2335 r = getFreePtr (ic, &aop, FALSE);
2337 emitcode ("mov", "%s,_spx", r->name);
2342 if (options.useXstack)
2344 emitcode ("movx", "a,@%s", r->name);
2345 emitcode ("mov", "psw,a");
2346 emitcode ("dec", "%s", r->name);
2350 emitcode ("pop", "psw");
2354 for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2356 if (options.useXstack)
2358 emitcode ("movx", "a,@%s", r->name);
2359 emitcode ("mov", "(%s+%d),a",
2360 regs390[i].base, 8 * bank + regs390[i].offset);
2361 emitcode ("dec", "%s", r->name);
2365 emitcode ("pop", "(%s+%d)",
2366 regs390[i].base, 8 * bank + regs390[i].offset);
2369 if (options.useXstack)
2371 emitcode ("mov", "_spx,%s", r->name);
2376 freeAsmop (NULL, aop, ic, TRUE);
2380 /*-----------------------------------------------------------------*/
2381 /* saveRBank - saves an entire register bank on the stack */
2382 /*-----------------------------------------------------------------*/
2384 saveRBank (int bank, iCode * ic, bool pushPsw)
2390 if (options.useXstack)
2394 /* Assume r0 is available for use. */
2395 r = ds390_regWithIdx (R0_IDX);;
2400 r = getFreePtr (ic, &aop, FALSE);
2402 emitcode ("mov", "%s,_spx", r->name);
2405 for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2407 if (options.useXstack)
2409 emitcode ("inc", "%s", r->name);
2410 emitcode ("mov", "a,(%s+%d)",
2411 regs390[i].base, 8 * bank + regs390[i].offset);
2412 emitcode ("movx", "@%s,a", r->name);
2415 emitcode ("push", "(%s+%d)",
2416 regs390[i].base, 8 * bank + regs390[i].offset);
2421 if (options.useXstack)
2423 emitcode ("mov", "a,psw");
2424 emitcode ("movx", "@%s,a", r->name);
2425 emitcode ("inc", "%s", r->name);
2426 emitcode ("mov", "_spx,%s", r->name);
2430 emitcode ("push", "psw");
2433 emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2438 freeAsmop (NULL, aop, ic, TRUE);
2447 /*-----------------------------------------------------------------*/
2448 /* genSend - gen code for SEND */
2449 /*-----------------------------------------------------------------*/
2450 static void genSend(set *sendSet)
2454 static int rb1_count = 0;
2456 for (sic = setFirstItem (sendSet); sic;
2457 sic = setNextItem (sendSet)) {
2458 int size, offset = 0;
2460 size=getSize(operandType(IC_LEFT(sic)));
2461 D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2462 if (sendCount == 0) { /* first parameter */
2463 // we know that dpl(hxb) is the result, so
2465 _startLazyDPSEvaluation ();
2467 aopOp (IC_LEFT (sic), sic, FALSE,
2468 (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2470 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2473 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2474 FALSE, FALSE, NULL);
2475 if (strcmp (l, fReturn[offset])) {
2476 emitcode ("mov", "%s,%s",
2482 _endLazyDPSEvaluation ();
2483 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2485 } else { /* if more parameter in registers */
2486 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2488 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
2489 FALSE, FALSE, NULL));
2491 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2498 adjustEsp(const char *reg)
2500 emitcode ("anl","%s,#3", reg);
2501 if (TARGET_IS_DS400)
2503 emitcode ("orl","%s,#!constbyte",
2505 (options.stack_loc >> 8) & 0xff);
2509 /*-----------------------------------------------------------------*/
2510 /* genCall - generates a call statement */
2511 /*-----------------------------------------------------------------*/
2513 genCall (iCode * ic)
2516 bool restoreBank = FALSE;
2517 bool swapBanks = FALSE;
2519 D (emitcode (";", "genCall "););
2521 /* if we are calling a not _naked function that is not using
2522 the same register bank then we need to save the
2523 destination registers on the stack */
2524 dtype = operandType (IC_LEFT (ic));
2525 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2526 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2527 IFFUNC_ISISR (currFunc->type))
2531 /* This is unexpected; the bank should have been saved in
2534 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2540 /* if caller saves & we have not saved then */
2544 /* if send set is not empty the assign */
2545 /* We've saved all the registers we care about;
2546 * therefore, we may clobber any register not used
2547 * in the calling convention (i.e. anything not in
2552 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2553 genSend(reverseSet(_G.sendSet));
2555 genSend(_G.sendSet);
2562 emitcode ("mov", "psw,#!constbyte",
2563 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2567 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2568 OP_SYMBOL (IC_LEFT (ic))->rname :
2569 OP_SYMBOL (IC_LEFT (ic))->name));
2573 emitcode ("mov", "psw,#!constbyte",
2574 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2577 /* if we need assign a result value */
2578 if ((IS_ITEMP (IC_RESULT (ic)) &&
2579 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2580 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2581 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2582 IS_TRUE_SYMOP (IC_RESULT (ic)))
2584 if (isOperandInFarSpace (IC_RESULT (ic))
2585 && getSize (operandType (IC_RESULT (ic))) <= 2)
2587 int size = getSize (operandType (IC_RESULT (ic)));
2589 /* Special case for 1 or 2 byte return in far space. */
2593 emitcode ("mov", "b,%s", fReturn[1]);
2596 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2597 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2601 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2603 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2608 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2611 assignResultValue (IC_RESULT (ic));
2613 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2617 /* adjust the stack for parameters if
2619 if (ic->parmBytes) {
2621 if (options.stack10bit) {
2622 if (ic->parmBytes <= 10) {
2623 emitcode(";","stack adjustment for parms");
2624 for (i=0; i < ic->parmBytes ; i++) {
2625 emitcode("pop","acc");
2629 emitcode ("clr","c");
2630 emitcode ("mov","a,sp");
2631 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2632 emitcode ("mov","sp,a");
2633 emitcode ("mov","a,esp");
2635 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2636 emitcode ("mov","esp,a");
2640 if (ic->parmBytes > 3) {
2641 emitcode ("mov", "a,%s", spname);
2642 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2643 emitcode ("mov", "%s,a", spname);
2645 for (i = 0; i < ic->parmBytes; i++)
2646 emitcode ("dec", "%s", spname);
2650 /* if we hade saved some registers then unsave them */
2652 unsaveRegisters (ic);
2654 /* if register bank was saved then pop them */
2656 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2659 /*-----------------------------------------------------------------*/
2660 /* genPcall - generates a call by pointer statement */
2661 /*-----------------------------------------------------------------*/
2663 genPcall (iCode * ic)
2666 symbol *rlbl = newiTempLabel (NULL);
2667 bool restoreBank=FALSE;
2669 D (emitcode (";", "genPcall ");
2673 /* if caller saves & we have not saved then */
2677 /* if we are calling a function that is not using
2678 the same register bank then we need to save the
2679 destination registers on the stack */
2680 dtype = operandType (IC_LEFT (ic));
2681 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2682 IFFUNC_ISISR (currFunc->type) &&
2683 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2684 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2688 /* push the return address on to the stack */
2689 emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2690 emitcode ("push", "acc");
2691 emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2692 emitcode ("push", "acc");
2694 if (options.model == MODEL_FLAT24)
2696 emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2697 emitcode ("push", "acc");
2700 /* now push the calling address */
2701 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2703 pushSide (IC_LEFT (ic), FPTRSIZE);
2705 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2707 /* if send set is not empty the assign */
2710 genSend(reverseSet(_G.sendSet));
2714 emitcode ("ret", "");
2715 emitcode ("", "!tlabeldef", (rlbl->key + 100));
2718 /* if we need assign a result value */
2719 if ((IS_ITEMP (IC_RESULT (ic)) &&
2720 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2721 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2722 IS_TRUE_SYMOP (IC_RESULT (ic)))
2726 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2729 assignResultValue (IC_RESULT (ic));
2731 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2734 /* adjust the stack for parameters if
2739 if (options.stack10bit) {
2740 if (ic->parmBytes <= 10) {
2741 emitcode(";","stack adjustment for parms");
2742 for (i=0; i < ic->parmBytes ; i++) {
2743 emitcode("pop","acc");
2747 emitcode ("clr","c");
2748 emitcode ("mov","a,sp");
2749 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2750 emitcode ("mov","sp,a");
2751 emitcode ("mov","a,esp");
2753 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2754 emitcode ("mov","esp,a");
2758 if (ic->parmBytes > 3) {
2759 emitcode ("mov", "a,%s", spname);
2760 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2761 emitcode ("mov", "%s,a", spname);
2764 for (i = 0; i < ic->parmBytes; i++)
2765 emitcode ("dec", "%s", spname);
2769 /* if register bank was saved then unsave them */
2771 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2773 /* if we hade saved some registers then
2776 unsaveRegisters (ic);
2780 /*-----------------------------------------------------------------*/
2781 /* resultRemat - result is rematerializable */
2782 /*-----------------------------------------------------------------*/
2784 resultRemat (iCode * ic)
2786 if (SKIP_IC (ic) || ic->op == IFX)
2789 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2791 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2792 if (sym->remat && !POINTER_SET (ic))
2799 #if defined(__BORLANDC__) || defined(_MSC_VER)
2800 #define STRCASECMP stricmp
2802 #define STRCASECMP strcasecmp
2805 /*-----------------------------------------------------------------*/
2806 /* inExcludeList - return 1 if the string is in exclude Reg list */
2807 /*-----------------------------------------------------------------*/
2809 regsCmp(void *p1, void *p2)
2811 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2815 inExcludeList (char *s)
2817 const char *p = setFirstItem(options.excludeRegsSet);
2819 if (p == NULL || STRCASECMP(p, "none") == 0)
2823 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2826 /*-----------------------------------------------------------------*/
2827 /* genFunction - generated code for function entry */
2828 /*-----------------------------------------------------------------*/
2830 genFunction (iCode * ic)
2834 bool switchedPSW = FALSE;
2836 D (emitcode (";", "genFunction "););
2839 /* create the function header */
2840 emitcode (";", "-----------------------------------------");
2841 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2842 emitcode (";", "-----------------------------------------");
2844 emitcode ("", "%s:", sym->rname);
2845 ftype = operandType (IC_LEFT (ic));
2847 if (IFFUNC_ISNAKED(ftype))
2849 emitcode(";", "naked function: no prologue.");
2853 if (options.stack_probe)
2854 emitcode ("lcall","__stack_probe");
2855 /* if critical function then turn interrupts off */
2856 if (IFFUNC_ISCRITICAL (ftype))
2857 emitcode ("clr", "ea");
2859 /* here we need to generate the equates for the
2860 register bank if required */
2861 if (FUNC_REGBANK (ftype) != rbank)
2865 rbank = FUNC_REGBANK (ftype);
2866 for (i = 0; i < ds390_nRegs; i++)
2868 if (regs390[i].print) {
2869 if (strcmp (regs390[i].base, "0") == 0)
2870 emitcode ("", "%s !equ !constbyte",
2872 8 * rbank + regs390[i].offset);
2874 emitcode ("", "%s !equ %s + !constbyte",
2877 8 * rbank + regs390[i].offset);
2882 /* if this is an interrupt service routine then
2883 save acc, b, dpl, dph */
2884 if (IFFUNC_ISISR (sym->type))
2886 if (!inExcludeList ("acc"))
2887 emitcode ("push", "acc");
2888 if (!inExcludeList ("b"))
2889 emitcode ("push", "b");
2890 if (!inExcludeList ("dpl"))
2891 emitcode ("push", "dpl");
2892 if (!inExcludeList ("dph"))
2893 emitcode ("push", "dph");
2894 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2896 emitcode ("push", "dpx");
2897 /* Make sure we're using standard DPTR */
2898 emitcode ("push", "dps");
2899 emitcode ("mov", "dps,#0");
2900 if (options.stack10bit)
2902 /* This ISR could conceivably use DPTR2. Better save it. */
2903 emitcode ("push", "dpl1");
2904 emitcode ("push", "dph1");
2905 emitcode ("push", "dpx1");
2906 emitcode ("push", DP2_RESULT_REG);
2909 /* if this isr has no bank i.e. is going to
2910 run with bank 0 , then we need to save more
2912 if (!FUNC_REGBANK (sym->type))
2916 /* if this function does not call any other
2917 function then we can be economical and
2918 save only those registers that are used */
2919 if (!IFFUNC_HASFCALL(sym->type))
2922 /* if any registers used */
2925 /* save the registers used */
2926 for (i = 0; i < sym->regsUsed->size; i++)
2928 if (bitVectBitValue (sym->regsUsed, i) ||
2929 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2930 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2937 /* this function has a function call cannot
2938 determines register usage so we will have to push the
2940 saveRBank (0, ic, FALSE);
2941 if (options.parms_in_bank1) {
2942 for (i=0; i < 8 ; i++ ) {
2943 emitcode ("push","%s",rb1regs[i]);
2950 /* This ISR uses a non-zero bank.
2952 * We assume that the bank is available for our
2955 * However, if this ISR calls a function which uses some
2956 * other bank, we must save that bank entirely.
2958 unsigned long banksToSave = 0;
2960 if (IFFUNC_HASFCALL(sym->type))
2963 #define MAX_REGISTER_BANKS 4
2968 for (i = ic; i; i = i->next)
2970 if (i->op == ENDFUNCTION)
2972 /* we got to the end OK. */
2980 dtype = operandType (IC_LEFT(i));
2982 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2984 /* Mark this bank for saving. */
2985 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2987 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2991 banksToSave |= (1 << FUNC_REGBANK(dtype));
2994 /* And note that we don't need to do it in
3002 /* This is a mess; we have no idea what
3003 * register bank the called function might
3006 * The only thing I can think of to do is
3007 * throw a warning and hope.
3009 werror(W_FUNCPTR_IN_USING_ISR);
3013 if (banksToSave && options.useXstack)
3015 /* Since we aren't passing it an ic,
3016 * saveRBank will assume r0 is available to abuse.
3018 * So switch to our (trashable) bank now, so
3019 * the caller's R0 isn't trashed.
3021 emitcode ("push", "psw");
3022 emitcode ("mov", "psw,#!constbyte",
3023 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3027 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3029 if (banksToSave & (1 << ix))
3031 saveRBank(ix, NULL, FALSE);
3035 // TODO: this needs a closer look
3036 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3041 /* if callee-save to be used for this function
3042 then save the registers being used in this function */
3043 if (IFFUNC_CALLEESAVES(sym->type))
3047 /* if any registers used */
3050 /* save the registers used */
3051 for (i = 0; i < sym->regsUsed->size; i++)
3053 if (bitVectBitValue (sym->regsUsed, i) ||
3054 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3056 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3064 /* set the register bank to the desired value */
3065 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3068 emitcode ("push", "psw");
3069 emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3072 if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3073 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3074 if (options.stack10bit) {
3075 emitcode ("push","_bpx");
3076 emitcode ("push","_bpx+1");
3077 emitcode ("mov","_bpx,%s",spname);
3078 emitcode ("mov","_bpx+1,esp");
3079 adjustEsp("_bpx+1");
3081 if (options.useXstack) {
3082 emitcode ("mov", "r0,%s", spname);
3083 emitcode ("mov", "a,_bp");
3084 emitcode ("movx", "@r0,a");
3085 emitcode ("inc", "%s", spname);
3087 /* set up the stack */
3088 emitcode ("push", "_bp"); /* save the callers stack */
3090 emitcode ("mov", "_bp,%s", spname);
3094 /* adjust the stack for the function */
3097 if (options.stack10bit) {
3098 if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
3099 assert (sym->recvSize <= 4);
3100 if (sym->stack <= 8) {
3101 while (i--) emitcode ("push","acc");
3104 emitcode ("mov","a,sp");
3105 emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3106 emitcode ("mov","sp,a");
3107 emitcode ("mov","a,esp");
3109 emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3110 emitcode ("mov","esp,a");
3115 werror (W_STACK_OVERFLOW, sym->name);
3117 if (i > 3 && sym->recvSize < 4) {
3119 emitcode ("mov", "a,sp");
3120 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3121 emitcode ("mov", "sp,a");
3125 emitcode ("inc", "sp");
3132 emitcode ("mov", "a,_spx");
3133 emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3134 emitcode ("mov", "_spx,a");
3139 /*-----------------------------------------------------------------*/
3140 /* genEndFunction - generates epilogue for functions */
3141 /*-----------------------------------------------------------------*/
3143 genEndFunction (iCode * ic)
3145 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3147 D (emitcode (";", "genEndFunction "););
3149 if (IFFUNC_ISNAKED(sym->type))
3151 emitcode(";", "naked function: no epilogue.");
3155 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3156 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3158 if (options.stack10bit) {
3160 emitcode ("mov", "sp,_bpx", spname);
3161 emitcode ("mov", "esp,_bpx+1", spname);
3164 emitcode ("mov", "%s,_bp", spname);
3168 /* if use external stack but some variables were
3169 added to the local stack then decrement the
3171 if (options.useXstack && sym->stack) {
3172 emitcode ("mov", "a,sp");
3173 emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3174 emitcode ("mov", "sp,a");
3178 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3179 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3181 if (options.useXstack) {
3182 emitcode ("mov", "r0,%s", spname);
3183 emitcode ("movx", "a,@r0");
3184 emitcode ("mov", "_bp,a");
3185 emitcode ("dec", "%s", spname);
3187 if (options.stack10bit) {
3188 emitcode ("pop", "_bpx+1");
3189 emitcode ("pop", "_bpx");
3191 emitcode ("pop", "_bp");
3196 /* restore the register bank */
3197 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3199 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3200 || !options.useXstack)
3202 /* Special case of ISR using non-zero bank with useXstack
3205 emitcode ("pop", "psw");
3209 if (IFFUNC_ISISR (sym->type))
3212 /* now we need to restore the registers */
3213 /* if this isr has no bank i.e. is going to
3214 run with bank 0 , then we need to save more
3216 if (!FUNC_REGBANK (sym->type))
3219 /* if this function does not call any other
3220 function then we can be economical and
3221 save only those registers that are used */
3222 if (!IFFUNC_HASFCALL(sym->type))
3225 /* if any registers used */
3228 /* save the registers used */
3229 for (i = sym->regsUsed->size; i >= 0; i--)
3231 if (bitVectBitValue (sym->regsUsed, i) ||
3232 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3233 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3240 /* this function has a function call cannot
3241 determines register usage so we will have to pop the
3243 if (options.parms_in_bank1) {
3244 for (i = 7 ; i >= 0 ; i-- ) {
3245 emitcode ("pop","%s",rb1regs[i]);
3248 unsaveRBank (0, ic, FALSE);
3253 /* This ISR uses a non-zero bank.
3255 * Restore any register banks saved by genFunction
3258 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3261 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3263 if (savedBanks & (1 << ix))
3265 unsaveRBank(ix, NULL, FALSE);
3269 if (options.useXstack)
3271 /* Restore bank AFTER calling unsaveRBank,
3272 * since it can trash r0.
3274 emitcode ("pop", "psw");
3278 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3280 if (options.stack10bit)
3282 emitcode ("pop", DP2_RESULT_REG);
3283 emitcode ("pop", "dpx1");
3284 emitcode ("pop", "dph1");
3285 emitcode ("pop", "dpl1");
3287 emitcode ("pop", "dps");
3288 emitcode ("pop", "dpx");
3290 if (!inExcludeList ("dph"))
3291 emitcode ("pop", "dph");
3292 if (!inExcludeList ("dpl"))
3293 emitcode ("pop", "dpl");
3294 if (!inExcludeList ("b"))
3295 emitcode ("pop", "b");
3296 if (!inExcludeList ("acc"))
3297 emitcode ("pop", "acc");
3299 if (IFFUNC_ISCRITICAL (sym->type))
3300 emitcode ("setb", "ea");
3302 /* if debug then send end of function */
3303 if (options.debug && currFunc) {
3305 emitcode ("", "C$%s$%d$%d$%d ==.",
3306 FileBaseName (ic->filename), currFunc->lastLine,
3307 ic->level, ic->block);
3308 if (IS_STATIC (currFunc->etype))
3309 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3311 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3315 emitcode ("reti", "");
3319 if (IFFUNC_ISCRITICAL (sym->type))
3320 emitcode ("setb", "ea");
3322 if (IFFUNC_CALLEESAVES(sym->type))
3326 /* if any registers used */
3329 /* save the registers used */
3330 for (i = sym->regsUsed->size; i >= 0; i--)
3332 if (bitVectBitValue (sym->regsUsed, i) ||
3333 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3334 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3340 /* if debug then send end of function */
3341 if (options.debug && currFunc)
3344 emitcode ("", "C$%s$%d$%d$%d ==.",
3345 FileBaseName (ic->filename), currFunc->lastLine,
3346 ic->level, ic->block);
3347 if (IS_STATIC (currFunc->etype))
3348 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3350 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3354 emitcode ("ret", "");
3359 /*-----------------------------------------------------------------*/
3360 /* genJavaNativeRet - generate code for return JavaNative */
3361 /*-----------------------------------------------------------------*/
3362 static void genJavaNativeRet(iCode *ic)
3366 aopOp (IC_LEFT (ic), ic, FALSE,
3367 AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
3368 size = AOP_SIZE (IC_LEFT (ic));
3372 /* it is assigned to GPR0-R3 then push them */
3373 if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3374 aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3375 for (i = 0 ; i < size ; i++ ) {
3376 emitcode ("push","%s",
3377 aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3379 for (i = (size-1) ; i >= 0 ; i--) {
3380 emitcode ("pop","a%s",javaRet[i]);
3383 for (i = 0 ; i < size ; i++)
3384 emitcode ("mov","%s,%s",javaRet[i],
3385 aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3387 for (i = size ; i < 4 ; i++ )
3388 emitcode ("mov","%s,#0",javaRet[i]);
3392 /*-----------------------------------------------------------------*/
3393 /* genRet - generate code for return statement */
3394 /*-----------------------------------------------------------------*/
3398 int size, offset = 0, pushed = 0;
3400 D (emitcode (";", "genRet "););
3402 /* if we have no return value then
3403 just generate the "ret" */
3407 /* if this is a JavaNative function then return
3408 value in different register */
3409 if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3410 genJavaNativeRet(ic);
3413 /* we have something to return then
3414 move the return value into place */
3415 aopOp (IC_LEFT (ic), ic, FALSE,
3416 (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
3417 size = AOP_SIZE (IC_LEFT (ic));
3419 _startLazyDPSEvaluation ();
3423 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3425 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3427 emitcode ("push", "%s", l);
3432 /* Since A is the last element of fReturn,
3433 * is is OK to clobber it in the aopGet.
3435 l = aopGet (AOP (IC_LEFT (ic)), offset,
3436 FALSE, FALSE, NULL);
3437 if (strcmp (fReturn[offset], l))
3438 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3441 _endLazyDPSEvaluation ();
3448 if (strcmp (fReturn[pushed], "a"))
3449 emitcode ("pop", fReturn[pushed]);
3451 emitcode ("pop", "acc");
3454 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3457 /* generate a jump to the return label
3458 if the next is not the return statement */
3459 if (!(ic->next && ic->next->op == LABEL &&
3460 IC_LABEL (ic->next) == returnLabel))
3462 emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3466 /*-----------------------------------------------------------------*/
3467 /* genLabel - generates a label */
3468 /*-----------------------------------------------------------------*/
3470 genLabel (iCode * ic)
3472 /* special case never generate */
3473 if (IC_LABEL (ic) == entryLabel)
3476 D (emitcode (";", "genLabel ");
3479 emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3482 /*-----------------------------------------------------------------*/
3483 /* genGoto - generates a ljmp */
3484 /*-----------------------------------------------------------------*/
3486 genGoto (iCode * ic)
3488 D (emitcode (";", "genGoto ");
3490 emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3493 /*-----------------------------------------------------------------*/
3494 /* findLabelBackwards: walks back through the iCode chain looking */
3495 /* for the given label. Returns number of iCode instructions */
3496 /* between that label and given ic. */
3497 /* Returns zero if label not found. */
3498 /*-----------------------------------------------------------------*/
3500 findLabelBackwards (iCode * ic, int key)
3509 /* If we have any pushes or pops, we cannot predict the distance.
3510 I don't like this at all, this should be dealt with in the
3512 if (ic->op == IPUSH || ic->op == IPOP) {
3516 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3518 /* printf("findLabelBackwards = %d\n", count); */
3526 /*-----------------------------------------------------------------*/
3527 /* genPlusIncr :- does addition with increment if possible */
3528 /*-----------------------------------------------------------------*/
3530 genPlusIncr (iCode * ic)
3532 unsigned int icount;
3533 unsigned int size = getDataSize (IC_RESULT (ic));
3535 /* will try to generate an increment */
3536 /* if the right side is not a literal
3538 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3541 /* if the literal value of the right hand side
3542 is greater than 4 then it is not worth it */
3543 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3546 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3547 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3549 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
3553 /* if increment 16 bits in register */
3555 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3556 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3557 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3566 /* If the next instruction is a goto and the goto target
3567 * is <= 5 instructions previous to this, we can generate
3568 * jumps straight to that target.
3570 if (ic->next && ic->next->op == GOTO
3571 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3574 D(emitcode (";", "tail increment optimized (range %d)", labelRange););
3575 tlbl = IC_LABEL (ic->next);
3580 tlbl = newiTempLabel (NULL);
3584 l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
3585 emitcode ("inc", "%s", l);
3587 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3588 IS_AOP_PREG (IC_RESULT (ic)))
3590 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3594 emitcode ("clr", "a");
3595 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3598 l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
3599 emitcode ("inc", "%s", l);
3602 if (!strcmp(l, "acc"))
3604 emitcode("jnz", "!tlabel", tlbl->key + 100);
3606 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3607 IS_AOP_PREG (IC_RESULT (ic)))
3609 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3613 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3616 l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
3617 emitcode ("inc", "%s", l);
3621 if (!strcmp(l, "acc"))
3623 emitcode("jnz", "!tlabel", tlbl->key + 100);
3625 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3626 IS_AOP_PREG (IC_RESULT (ic)))
3628 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3632 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3635 l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
3636 emitcode ("inc", "%s", l); }
3640 emitcode ("", "!tlabeldef", tlbl->key + 100);
3645 if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3646 !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 &&
3647 options.model == MODEL_FLAT24 ) {
3651 emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, NULL));
3653 emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, NULL));
3655 emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3658 while (icount--) emitcode ("inc","dptr");
3662 if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3663 AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3665 emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3666 while (icount--) emitcode ("inc","dptr");
3667 emitcode ("mov","dps,#0");
3671 /* if the sizes are greater than 1 then we cannot */
3672 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3673 AOP_SIZE (IC_LEFT (ic)) > 1)
3676 /* we can if the aops of the left & result match or
3677 if they are in registers and the registers are the
3680 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3681 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3682 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3687 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3688 emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3689 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3694 _startLazyDPSEvaluation ();
3697 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3699 _endLazyDPSEvaluation ();
3708 /*-----------------------------------------------------------------*/
3709 /* outBitAcc - output a bit in acc */
3710 /*-----------------------------------------------------------------*/
3712 outBitAcc (operand * result)
3714 symbol *tlbl = newiTempLabel (NULL);
3715 /* if the result is a bit */
3716 if (AOP_TYPE (result) == AOP_CRY)
3718 aopPut (AOP (result), "a", 0);
3722 emitcode ("jz", "!tlabel", tlbl->key + 100);
3723 emitcode ("mov", "a,%s", one);
3724 emitcode ("", "!tlabeldef", tlbl->key + 100);
3729 /*-----------------------------------------------------------------*/
3730 /* genPlusBits - generates code for addition of two bits */
3731 /*-----------------------------------------------------------------*/
3733 genPlusBits (iCode * ic)
3735 D (emitcode (";", "genPlusBits "););
3737 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3739 symbol *lbl = newiTempLabel (NULL);
3740 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3741 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3742 emitcode ("cpl", "c");
3743 emitcode ("", "!tlabeldef", (lbl->key + 100));
3744 outBitC (IC_RESULT (ic));
3748 emitcode ("clr", "a");
3749 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3750 emitcode ("rlc", "a");
3751 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3752 emitcode ("addc", "a,#0");
3753 outAcc (IC_RESULT (ic));
3758 adjustArithmeticResult (iCode * ic)
3760 if (opIsGptr (IC_RESULT (ic)) &&
3761 opIsGptr (IC_LEFT (ic)) &&
3762 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3764 aopPut (AOP (IC_RESULT (ic)),
3765 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3769 if (opIsGptr (IC_RESULT (ic)) &&
3770 opIsGptr (IC_RIGHT (ic)) &&
3771 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3773 aopPut (AOP (IC_RESULT (ic)),
3774 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3778 if (opIsGptr (IC_RESULT (ic)) &&
3779 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3780 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3781 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3782 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3785 SNPRINTF (buff, sizeof(buff),
3786 "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3787 aopPut (AOP (IC_RESULT (ic)), buff, GPTRSIZE - 1);
3791 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
3792 // generates the result if possible. If result is generated, returns TRUE; otherwise
3793 // returns false and caller must deal with fact that result isn't aopOp'd.
3794 bool aopOp3(iCode * ic)
3796 bool dp1InUse, dp2InUse;
3799 // First, generate the right opcode. DPTR may be used if neither left nor result are
3802 // D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
3803 // AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
3804 // AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
3805 // AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
3807 // D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
3808 // AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
3809 // AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
3810 // AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
3813 // Right uses DPTR unless left or result is an AOP_STR; however,
3814 // if right is an AOP_STR, it must use DPTR regardless.
3815 if ((AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)))
3816 && !AOP_IS_STR(IC_RIGHT(ic)))
3825 aopOp (IC_RIGHT(ic),ic,FALSE, useDp2);
3827 // if the right used DPTR, left MUST use DPTR2.
3828 // if the right used DPTR2, left MUST use DPTR.
3829 // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
3830 // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
3831 // enabling us to assign DPTR to result.
3833 if (AOP_USESDPTR(IC_RIGHT(ic)))
3837 else if (AOP_USESDPTR2(IC_RIGHT(ic)))
3843 if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
3853 aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
3855 // We've op'd the left & right. So, if left or right are the same operand as result,
3856 // we know aopOp will succeed, and we can just do it & bail.
3857 if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)) ||
3858 isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
3860 // D(emitcode(";", "aopOp3: (left | right) & result equal"););
3861 aopOp(IC_RESULT(ic),ic,TRUE, FALSE);
3865 // Note which dptrs are currently in use.
3866 dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
3867 dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
3869 // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot
3871 if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
3876 // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
3877 if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
3882 // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck
3883 if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
3888 aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
3890 // Some sanity checking...
3891 if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
3894 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
3895 __FILE__, __LINE__, ic->filename, ic->lineno);
3896 emitcode(";", ">>> unexpected DPTR here.");
3899 if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
3902 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
3903 __FILE__, __LINE__, ic->filename, ic->lineno);
3904 emitcode(";", ">>> unexpected DPTR2 here.");
3910 // Macro to aopOp all three operands of an ic. If this cannot be done,
3911 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3912 // will be set TRUE. The caller must then handle the case specially, noting
3913 // that the IC_RESULT operand is not aopOp'd.
3915 #define AOP_OP_3_NOFATAL(ic, rc) \
3916 do { rc = !aopOp3(ic); } while (0)
3918 // aopOp the left & right operands of an ic.
3919 #define AOP_OP_2(ic) \
3920 aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
3921 aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
3923 // convienience macro.
3924 #define AOP_SET_LOCALS(ic) \
3925 left = IC_LEFT(ic); \
3926 right = IC_RIGHT(ic); \
3927 result = IC_RESULT(ic);
3930 // Given an integer value of pushedSize bytes on the stack,
3931 // adjust it to be resultSize bytes, either by discarding
3932 // the most significant bytes or by zero-padding.
3934 // On exit from this macro, pushedSize will have been adjusted to
3935 // equal resultSize, and ACC may be trashed.
3936 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3937 /* If the pushed data is bigger than the result, \
3938 * simply discard unused bytes. Icky, but works. \
3940 while (pushedSize > resultSize) \
3942 D (emitcode (";", "discarding unused result byte."););\
3943 emitcode ("pop", "acc"); \
3946 if (pushedSize < resultSize) \
3948 emitcode ("clr", "a"); \
3949 /* Conversly, we haven't pushed enough here. \
3950 * just zero-pad, and all is well. \
3952 while (pushedSize < resultSize) \
3954 emitcode("push", "acc"); \
3958 assert(pushedSize == resultSize);
3960 /*-----------------------------------------------------------------*/
3961 /* genPlus - generates code for addition */
3962 /*-----------------------------------------------------------------*/
3964 genPlus (iCode * ic)
3966 int size, offset = 0;
3970 D (emitcode (";", "genPlus "););
3972 /* special cases :- */
3973 if ( AOP_IS_STR(IC_LEFT(ic)) &&
3974 isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
3975 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
3976 size = (int)floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
3978 while (size--) emitcode ("inc","dptr");
3980 emitcode ("mov","a,dpl");
3981 emitcode ("add","a,#!constbyte",size & 0xff);
3982 emitcode ("mov","dpl,a");
3983 emitcode ("mov","a,dph");
3984 emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
3985 emitcode ("mov","dph,a");
3986 emitcode ("mov","a,dpx");
3987 emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
3988 emitcode ("mov","dpx,a");
3990 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
3993 if ( IS_SYMOP(IC_LEFT(ic)) &&
3994 OP_SYMBOL(IC_LEFT(ic))->remat &&
3995 isOperandInFarSpace(IC_RIGHT(ic))) {
3996 operand *op = IC_RIGHT(ic);
3997 IC_RIGHT(ic) = IC_LEFT(ic);
4001 AOP_OP_3_NOFATAL (ic, pushResult);
4005 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
4010 /* if literal, literal on the right or
4011 if left requires ACC or right is already
4013 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4014 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
4015 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4017 operand *t = IC_RIGHT (ic);
4018 IC_RIGHT (ic) = IC_LEFT (ic);
4020 emitcode (";", "Swapped plus args.");
4023 /* if both left & right are in bit
4025 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4026 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4032 /* if left in bit space & right literal */
4033 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4034 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4036 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4037 /* if result in bit space */
4038 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4040 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4041 emitcode ("cpl", "c");
4042 outBitC (IC_RESULT (ic));
4046 size = getDataSize (IC_RESULT (ic));
4047 _startLazyDPSEvaluation ();
4050 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4051 emitcode ("addc", "a,#0");
4052 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4054 _endLazyDPSEvaluation ();
4059 /* if I can do an increment instead
4060 of add then GOOD for ME */
4061 if (genPlusIncr (ic) == TRUE)
4063 emitcode (";", "did genPlusIncr");
4068 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4070 _startLazyDPSEvaluation ();
4073 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4075 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4077 emitcode ("add", "a,%s",
4078 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4080 emitcode ("addc", "a,%s",
4081 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4085 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4087 /* right is going to use ACC or we would have taken the
4090 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4092 D(emitcode(";", "+ AOP_ACC special case."););
4093 emitcode("xch", "a, %s", DP2_RESULT_REG);
4095 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4098 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4101 emitcode("add", "a, %s", DP2_RESULT_REG);
4105 emitcode ("add", "a,%s",
4106 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE,
4112 emitcode ("addc", "a,%s",
4113 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE,
4119 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4123 emitcode ("push", "acc");
4127 _endLazyDPSEvaluation ();
4131 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4133 size = getDataSize (IC_LEFT (ic));
4134 rSize = getDataSize (IC_RESULT (ic));
4136 ADJUST_PUSHED_RESULT(size, rSize);
4138 _startLazyDPSEvaluation ();
4141 emitcode ("pop", "acc");
4142 aopPut (AOP (IC_RESULT (ic)), "a", size);
4144 _endLazyDPSEvaluation ();
4147 adjustArithmeticResult (ic);
4150 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4151 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4152 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4155 /*-----------------------------------------------------------------*/
4156 /* genMinusDec :- does subtraction with deccrement if possible */
4157 /*-----------------------------------------------------------------*/
4159 genMinusDec (iCode * ic)
4161 unsigned int icount;
4162 unsigned int size = getDataSize (IC_RESULT (ic));
4164 /* will try to generate an increment */
4165 /* if the right side is not a literal
4167 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4170 /* if the literal value of the right hand side
4171 is greater than 4 then it is not worth it */
4172 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4175 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4176 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4178 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
4182 /* if decrement 16 bits in register */
4183 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4184 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4185 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4194 /* If the next instruction is a goto and the goto target
4195 * is <= 5 instructions previous to this, we can generate
4196 * jumps straight to that target.
4198 if (ic->next && ic->next->op == GOTO
4199 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4202 emitcode (";", "tail decrement optimized (range %d)", labelRange);
4203 tlbl = IC_LABEL (ic->next);
4208 tlbl = newiTempLabel (NULL);
4212 l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
4213 emitcode ("dec", "%s", l);
4215 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4216 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4217 IS_AOP_PREG (IC_RESULT (ic)))
4219 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4223 emitcode ("mov", "a,#!constbyte",0xff);
4224 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4226 l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
4227 emitcode ("dec", "%s", l);
4230 if (!strcmp(l, "acc"))
4232 emitcode("jnz", "!tlabel", tlbl->key + 100);
4234 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4235 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4236 IS_AOP_PREG (IC_RESULT (ic)))
4238 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4242 emitcode ("mov", "a,#!constbyte",0xff);
4243 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4245 l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
4246 emitcode ("dec", "%s", l);
4250 if (!strcmp(l, "acc"))
4252 emitcode("jnz", "!tlabel", tlbl->key + 100);
4254 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4255 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4256 IS_AOP_PREG (IC_RESULT (ic)))
4258 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4262 emitcode ("mov", "a,#!constbyte",0xff);
4263 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4265 l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
4266 emitcode ("dec", "%s", l);
4270 emitcode ("", "!tlabeldef", tlbl->key + 100);
4275 /* if the sizes are greater than 1 then we cannot */
4276 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4277 AOP_SIZE (IC_LEFT (ic)) > 1)
4280 /* we can if the aops of the left & result match or
4281 if they are in registers and the registers are the
4284 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4285 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4286 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4289 _startLazyDPSEvaluation ();
4292 emitcode ("dec", "%s",
4293 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
4295 _endLazyDPSEvaluation ();
4303 /*-----------------------------------------------------------------*/
4304 /* addSign - complete with sign */
4305 /*-----------------------------------------------------------------*/
4307 addSign (operand * result, int offset, int sign)
4309 int size = (getDataSize (result) - offset);
4312 _startLazyDPSEvaluation();
4315 emitcode ("rlc", "a");
4316 emitcode ("subb", "a,acc");
4319 aopPut (AOP (result), "a", offset++);
4326 aopPut (AOP (result), zero, offset++);
4329 _endLazyDPSEvaluation();
4333 /*-----------------------------------------------------------------*/
4334 /* genMinusBits - generates code for subtraction of two bits */
4335 /*-----------------------------------------------------------------*/
4337 genMinusBits (iCode * ic)
4339 symbol *lbl = newiTempLabel (NULL);
4341 D (emitcode (";", "genMinusBits "););
4343 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4345 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4346 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4347 emitcode ("cpl", "c");
4348 emitcode ("", "!tlabeldef", (lbl->key + 100));
4349 outBitC (IC_RESULT (ic));
4353 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4354 emitcode ("subb", "a,acc");
4355 emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4356 emitcode ("inc", "a");
4357 emitcode ("", "!tlabeldef", (lbl->key + 100));
4358 aopPut (AOP (IC_RESULT (ic)), "a", 0);
4359 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4363 /*-----------------------------------------------------------------*/
4364 /* genMinus - generates code for subtraction */
4365 /*-----------------------------------------------------------------*/
4367 genMinus (iCode * ic)
4369 int size, offset = 0;
4374 D (emitcode (";", "genMinus "););
4376 AOP_OP_3_NOFATAL(ic, pushResult);
4380 /* special cases :- */
4381 /* if both left & right are in bit space */
4382 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4383 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4389 /* if I can do an decrement instead
4390 of subtract then GOOD for ME */
4391 if (genMinusDec (ic) == TRUE)
4396 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4398 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4404 lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4409 /* if literal, add a,#-lit, else normal subb */
4410 _startLazyDPSEvaluation ();
4412 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4413 if (AOP_USESDPTR(IC_RIGHT(ic))) {
4414 emitcode ("mov","b,%s",
4415 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4416 MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4417 emitcode ("subb","a,b");
4419 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4420 emitcode ("subb", "a,%s",
4421 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE,
4425 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4426 /* first add without previous c */
4428 if (!size && lit==-1) {
4429 emitcode ("dec", "a");
4431 emitcode ("add", "a,#!constbyte",
4432 (unsigned int) (lit & 0x0FFL));
4435 emitcode ("addc", "a,#!constbyte",
4436 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4441 emitcode ("push", "acc");
4443 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4447 _endLazyDPSEvaluation ();
4451 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4453 size = getDataSize (IC_LEFT (ic));
4454 rSize = getDataSize (IC_RESULT (ic));
4456 ADJUST_PUSHED_RESULT(size, rSize);
4458 _startLazyDPSEvaluation ();
4461 emitcode ("pop", "acc");
4462 aopPut (AOP (IC_RESULT (ic)), "a", size);
4464 _endLazyDPSEvaluation ();
4467 adjustArithmeticResult (ic);
4470 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4471 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4472 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4476 /*-----------------------------------------------------------------*/
4477 /* genMultbits :- multiplication of bits */
4478 /*-----------------------------------------------------------------*/
4480 genMultbits (operand * left,
4485 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4486 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4487 aopOp(result, ic, TRUE, FALSE);
4492 /*-----------------------------------------------------------------*/
4493 /* genMultOneByte : 8*8=8/16 bit multiplication */
4494 /*-----------------------------------------------------------------*/
4496 genMultOneByte (operand * left,
4501 sym_link *opetype = operandType (result);
4505 /* (if two literals: the value is computed before) */
4506 /* if one literal, literal on the right */
4507 if (AOP_TYPE (left) == AOP_LIT)
4512 emitcode (";", "swapped left and right");
4515 if (SPEC_USIGN(opetype)
4516 // ignore the sign of left and right, what else can we do?
4517 || (SPEC_USIGN(operandType(left)) &&
4518 SPEC_USIGN(operandType(right)))) {
4519 // just an unsigned 8*8=8/16 multiply
4520 //emitcode (";","unsigned");
4521 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4522 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4523 emitcode ("mul", "ab");
4525 _G.accInUse++; _G.bInUse++;
4526 aopOp(result, ic, TRUE, FALSE);
4528 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4530 // this should never happen
4531 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4532 AOP_SIZE(result), __FILE__, lineno);
4536 aopPut (AOP (result), "a", 0);
4537 _G.accInUse--; _G.bInUse--;
4538 if (AOP_SIZE(result)==2)
4540 aopPut (AOP (result), "b", 1);
4545 // we have to do a signed multiply
4547 emitcode (";", "signed");
4548 emitcode ("clr", "F0"); // reset sign flag
4549 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4551 lbl=newiTempLabel(NULL);
4552 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4553 // left side is negative, 8-bit two's complement, this fails for -128
4554 emitcode ("setb", "F0"); // set sign flag
4555 emitcode ("cpl", "a");
4556 emitcode ("inc", "a");
4558 emitcode ("", "!tlabeldef", lbl->key+100);
4561 if (AOP_TYPE(right)==AOP_LIT) {
4562 signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
4563 /* AND literal negative */
4564 if ((int) val < 0) {
4565 emitcode ("cpl", "F0"); // complement sign flag
4566 emitcode ("mov", "b,#!constbyte", -val);
4568 emitcode ("mov", "b,#!constbyte", val);
4571 lbl=newiTempLabel(NULL);
4572 emitcode ("mov", "b,a");
4573 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4574 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4575 // right side is negative, 8-bit two's complement
4576 emitcode ("cpl", "F0"); // complement sign flag
4577 emitcode ("cpl", "a");
4578 emitcode ("inc", "a");
4579 emitcode ("", "!tlabeldef", lbl->key+100);
4581 emitcode ("mul", "ab");
4583 _G.accInUse++;_G.bInUse++;
4584 aopOp(result, ic, TRUE, FALSE);
4586 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4588 // this should never happen
4589 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4590 AOP_SIZE(result), __FILE__, lineno);
4594 lbl=newiTempLabel(NULL);
4595 emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4596 // only ONE op was negative, we have to do a 8/16-bit two's complement
4597 emitcode ("cpl", "a"); // lsb
4598 if (AOP_SIZE(result)==1) {
4599 emitcode ("inc", "a");
4601 emitcode ("add", "a,#1");
4602 emitcode ("xch", "a,b");
4603 emitcode ("cpl", "a"); // msb
4604 emitcode ("addc", "a,#0");
4605 emitcode ("xch", "a,b");
4608 emitcode ("", "!tlabeldef", lbl->key+100);
4609 aopPut (AOP (result), "a", 0);
4610 _G.accInUse--;_G.bInUse--;
4611 if (AOP_SIZE(result)==2) {
4612 aopPut (AOP (result), "b", 1);
4616 /*-----------------------------------------------------------------*/
4617 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
4618 /*-----------------------------------------------------------------*/
4619 static void genMultTwoByte (operand *left, operand *right,
4620 operand *result, iCode *ic)
4622 sym_link *retype = getSpec(operandType(right));
4623 sym_link *letype = getSpec(operandType(left));
4624 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4627 if (AOP_TYPE (left) == AOP_LIT) {
4632 /* save EA bit in F1 */
4633 lbl = newiTempLabel(NULL);
4634 emitcode ("setb","F1");
4635 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4636 emitcode ("clr","F1");
4637 emitcode("","!tlabeldef",lbl->key+100);
4639 /* load up MB with right */
4641 emitcode("clr","F0");
4642 if (AOP_TYPE(right) == AOP_LIT) {
4643 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
4645 emitcode("setb","F0");
4648 emitcode ("mov","mb,#!constbyte",val & 0xff);
4649 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4651 lbl = newiTempLabel(NULL);
4652 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4653 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4654 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4655 emitcode ("xch", "a,b");
4656 emitcode ("cpl","a");
4657 emitcode ("add", "a,#1");
4658 emitcode ("xch", "a,b");
4659 emitcode ("cpl", "a"); // msb
4660 emitcode ("addc", "a,#0");
4661 emitcode ("setb","F0");
4662 emitcode ("","!tlabeldef",lbl->key+100);
4663 emitcode ("mov","mb,b");
4664 emitcode ("mov","mb,a");
4667 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4668 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4670 /* load up MA with left */
4672 lbl = newiTempLabel(NULL);
4673 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4674 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4675 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4676 emitcode ("xch", "a,b");
4677 emitcode ("cpl","a");
4678 emitcode ("add", "a,#1");
4679 emitcode ("xch", "a,b");
4680 emitcode ("cpl", "a"); // msb
4681 emitcode ("addc","a,#0");
4682 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4683 emitcode ("setb","F0");
4684 emitcode ("","!tlabeldef",lbl->key+100);
4685 emitcode ("mov","ma,b");
4686 emitcode ("mov","ma,a");
4688 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4689 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4691 /* wait for multiplication to finish */
4692 lbl = newiTempLabel(NULL);
4693 emitcode("","!tlabeldef", lbl->key+100);
4694 emitcode("mov","a,mcnt1");
4695 emitcode("anl","a,#!constbyte",0x80);
4696 emitcode("jnz","!tlabel",lbl->key+100);
4698 freeAsmop (left, NULL, ic, TRUE);
4699 freeAsmop (right, NULL, ic,TRUE);
4700 aopOp(result, ic, TRUE, FALSE);
4702 /* if unsigned then simple */
4704 emitcode ("mov","a,ma");
4705 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4706 emitcode ("mov","a,ma");
4707 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4708 aopPut(AOP(result),"ma",1);
4709 aopPut(AOP(result),"ma",0);
4711 emitcode("push","ma");
4712 emitcode("push","ma");
4713 emitcode("push","ma");
4715 /* negate result if needed */
4716 lbl = newiTempLabel(NULL);
4717 emitcode("jnb","F0,!tlabel",lbl->key+100);
4718 emitcode("cpl","a");
4719 emitcode("add","a,#1");
4720 emitcode("","!tlabeldef", lbl->key+100);
4721 if (AOP_TYPE(result) == AOP_ACC)
4723 D(emitcode(";", "ACC special case."););
4724 /* We know result is the only live aop, and
4725 * it's obviously not a DPTR2, so AP is available.
4727 emitcode("mov", "%s,acc", DP2_RESULT_REG);
4731 aopPut(AOP(result),"a",0);
4734 emitcode("pop","acc");
4735 lbl = newiTempLabel(NULL);
4736 emitcode("jnb","F0,!tlabel",lbl->key+100);
4737 emitcode("cpl","a");
4738 emitcode("addc","a,#0");
4739 emitcode("","!tlabeldef", lbl->key+100);
4740 aopPut(AOP(result),"a",1);
4741 emitcode("pop","acc");
4742 if (AOP_SIZE(result) >= 3) {
4743 lbl = newiTempLabel(NULL);
4744 emitcode("jnb","F0,!tlabel",lbl->key+100);
4745 emitcode("cpl","a");
4746 emitcode("addc","a,#0");
4747 emitcode("","!tlabeldef", lbl->key+100);
4748 aopPut(AOP(result),"a",2);
4750 emitcode("pop","acc");
4751 if (AOP_SIZE(result) >= 4) {
4752 lbl = newiTempLabel(NULL);
4753 emitcode("jnb","F0,!tlabel",lbl->key+100);
4754 emitcode("cpl","a");
4755 emitcode("addc","a,#0");
4756 emitcode("","!tlabeldef", lbl->key+100);
4757 aopPut(AOP(result),"a",3);
4759 if (AOP_TYPE(result) == AOP_ACC)
4761 /* We stashed the result away above. */
4762 emitcode("mov", "acc,%s", DP2_RESULT_REG);
4766 freeAsmop (result, NULL, ic, TRUE);
4768 /* restore EA bit in F1 */
4769 lbl = newiTempLabel(NULL);
4770 emitcode ("jnb","F1,!tlabel",lbl->key+100);
4771 emitcode ("setb","EA");
4772 emitcode("","!tlabeldef",lbl->key+100);
4776 /*-----------------------------------------------------------------*/
4777 /* genMult - generates code for multiplication */
4778 /*-----------------------------------------------------------------*/
4780 genMult (iCode * ic)
4782 operand *left = IC_LEFT (ic);
4783 operand *right = IC_RIGHT (ic);
4784 operand *result = IC_RESULT (ic);
4786 D (emitcode (";", "genMult "););
4788 /* assign the amsops */
4791 /* special cases first */
4793 if (AOP_TYPE (left) == AOP_CRY &&
4794 AOP_TYPE (right) == AOP_CRY)
4796 genMultbits (left, right, result, ic);
4800 /* if both are of size == 1 */
4801 if (AOP_SIZE (left) == 1 &&
4802 AOP_SIZE (right) == 1)
4804 genMultOneByte (left, right, result, ic);
4808 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4809 /* use the ds390 ARITHMETIC accel UNIT */
4810 genMultTwoByte (left, right, result, ic);
4813 /* should have been converted to function call */
4817 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4818 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4819 freeAsmop (result, NULL, ic, TRUE);
4822 /*-----------------------------------------------------------------*/
4823 /* genDivbits :- division of bits */
4824 /*-----------------------------------------------------------------*/
4826 genDivbits (operand * left,
4834 /* the result must be bit */
4835 LOAD_AB_FOR_DIV (left, right, l);
4836 emitcode ("div", "ab");
4837 emitcode ("rrc", "a");
4838 aopOp(result, ic, TRUE, FALSE);
4840 aopPut (AOP (result), "c", 0);
4843 /*-----------------------------------------------------------------*/
4844 /* genDivOneByte : 8 bit division */
4845 /*-----------------------------------------------------------------*/
4847 genDivOneByte (operand * left,
4852 sym_link *opetype = operandType (result);
4858 /* signed or unsigned */
4859 if (SPEC_USIGN (opetype))
4861 /* unsigned is easy */
4862 LOAD_AB_FOR_DIV (left, right, l);
4863 emitcode ("div", "ab");
4866 aopOp(result, ic, TRUE, FALSE);
4867 aopPut (AOP (result), "a", 0);
4870 size = AOP_SIZE (result) - 1;
4874 aopPut (AOP (result), zero, offset++);
4879 /* signed is a little bit more difficult */
4881 /* save the signs of the operands */
4882 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4883 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4884 emitcode ("push", "acc"); /* save it on the stack */
4886 /* now sign adjust for both left & right */
4887 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4888 lbl = newiTempLabel (NULL);
4889 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4890 emitcode ("cpl", "a");
4891 emitcode ("inc", "a");
4892 emitcode ("", "!tlabeldef", (lbl->key + 100));
4893 emitcode ("mov", "b,a");
4895 /* sign adjust left side */
4896 MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4898 lbl = newiTempLabel (NULL);
4899 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4900 emitcode ("cpl", "a");
4901 emitcode ("inc", "a");
4902 emitcode ("", "!tlabeldef", (lbl->key + 100));
4904 /* now the division */
4905 emitcode ("nop", "; workaround for DS80C390 div bug.");
4906 emitcode ("div", "ab");
4907 /* we are interested in the lower order
4909 emitcode ("mov", "b,a");
4910 lbl = newiTempLabel (NULL);
4911 emitcode ("pop", "acc");
4912 /* if there was an over flow we don't
4913 adjust the sign of the result */
4914 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4915 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4917 emitcode ("clr", "a");
4918 emitcode ("subb", "a,b");
4919 emitcode ("mov", "b,a");
4920 emitcode ("", "!tlabeldef", (lbl->key + 100));
4922 /* now we are done */
4923 _G.accInUse++; _G.bInUse++;
4924 aopOp(result, ic, TRUE, FALSE);
4926 aopPut (AOP (result), "b", 0);
4928 size = AOP_SIZE (result) - 1;
4932 emitcode ("mov", "c,b.7");
4933 emitcode ("subb", "a,acc");
4937 aopPut (AOP (result), "a", offset++);
4939 _G.accInUse--; _G.bInUse--;
4943 /*-----------------------------------------------------------------*/
4944 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
4945 /*-----------------------------------------------------------------*/
4946 static void genDivTwoByte (operand *left, operand *right,
4947 operand *result, iCode *ic)
4949 sym_link *retype = getSpec(operandType(right));
4950 sym_link *letype = getSpec(operandType(left));
4951 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4954 /* save EA bit in F1 */
4955 lbl = newiTempLabel(NULL);
4956 emitcode ("setb","F1");
4957 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4958 emitcode ("clr","F1");
4959 emitcode("","!tlabeldef",lbl->key+100);
4961 /* load up MA with left */
4963 emitcode("clr","F0");
4964 lbl = newiTempLabel(NULL);
4965 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4966 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4967 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4968 emitcode ("xch", "a,b");
4969 emitcode ("cpl","a");
4970 emitcode ("add", "a,#1");
4971 emitcode ("xch", "a,b");
4972 emitcode ("cpl", "a"); // msb
4973 emitcode ("addc","a,#0");
4974 emitcode ("setb","F0");
4975 emitcode ("","!tlabeldef",lbl->key+100);
4976 emitcode ("mov","ma,b");
4977 emitcode ("mov","ma,a");
4979 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4980 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4983 /* load up MB with right */
4985 if (AOP_TYPE(right) == AOP_LIT) {
4986 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
4988 lbl = newiTempLabel(NULL);
4989 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4990 emitcode("setb","F0");
4991 emitcode ("","!tlabeldef",lbl->key+100);
4994 emitcode ("mov","mb,#!constbyte",val & 0xff);
4995 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4997 lbl = newiTempLabel(NULL);
4998 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4999 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5000 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5001 emitcode ("xch", "a,b");
5002 emitcode ("cpl","a");
5003 emitcode ("add", "a,#1");
5004 emitcode ("xch", "a,b");
5005 emitcode ("cpl", "a"); // msb
5006 emitcode ("addc", "a,#0");
5007 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5008 emitcode ("setb","F0");
5009 emitcode ("","!tlabeldef",lbl->key+100);
5010 emitcode ("mov","mb,b");
5011 emitcode ("mov","mb,a");
5014 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5015 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5018 /* wait for multiplication to finish */
5019 lbl = newiTempLabel(NULL);
5020 emitcode("","!tlabeldef", lbl->key+100);
5021 emitcode("mov","a,mcnt1");
5022 emitcode("anl","a,#!constbyte",0x80);
5023 emitcode("jnz","!tlabel",lbl->key+100);
5025 freeAsmop (left, NULL, ic, TRUE);
5026 freeAsmop (right, NULL, ic,TRUE);
5027 aopOp(result, ic, TRUE, FALSE);
5029 /* if unsigned then simple */
5031 aopPut(AOP(result),"ma",1);
5032 aopPut(AOP(result),"ma",0);
5034 emitcode("push","ma");
5036 /* negate result if needed */
5037 lbl = newiTempLabel(NULL);
5038 emitcode("jnb","F0,!tlabel",lbl->key+100);
5039 emitcode("cpl","a");
5040 emitcode("add","a,#1");
5041 emitcode("","!tlabeldef", lbl->key+100);
5042 aopPut(AOP(result),"a",0);
5043 emitcode("pop","acc");
5044 lbl = newiTempLabel(NULL);
5045 emitcode("jnb","F0,!tlabel",lbl->key+100);
5046 emitcode("cpl","a");
5047 emitcode("addc","a,#0");
5048 emitcode("","!tlabeldef", lbl->key+100);
5049 aopPut(AOP(result),"a",1);
5051 freeAsmop (result, NULL, ic, TRUE);
5052 /* restore EA bit in F1 */
5053 lbl = newiTempLabel(NULL);
5054 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5055 emitcode ("setb","EA");
5056 emitcode("","!tlabeldef",lbl->key+100);
5060 /*-----------------------------------------------------------------*/
5061 /* genDiv - generates code for division */
5062 /*-----------------------------------------------------------------*/
5066 operand *left = IC_LEFT (ic);
5067 operand *right = IC_RIGHT (ic);
5068 operand *result = IC_RESULT (ic);
5070 D (emitcode (";", "genDiv "););
5072 /* assign the amsops */
5075 /* special cases first */
5077 if (AOP_TYPE (left) == AOP_CRY &&
5078 AOP_TYPE (right) == AOP_CRY)
5080 genDivbits (left, right, result, ic);
5084 /* if both are of size == 1 */
5085 if (AOP_SIZE (left) == 1 &&
5086 AOP_SIZE (right) == 1)
5088 genDivOneByte (left, right, result, ic);
5092 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5093 /* use the ds390 ARITHMETIC accel UNIT */
5094 genDivTwoByte (left, right, result, ic);
5097 /* should have been converted to function call */
5100 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5101 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5102 freeAsmop (result, NULL, ic, TRUE);
5105 /*-----------------------------------------------------------------*/
5106 /* genModbits :- modulus of bits */
5107 /*-----------------------------------------------------------------*/
5109 genModbits (operand * left,
5117 /* the result must be bit */
5118 LOAD_AB_FOR_DIV (left, right, l);
5119 emitcode ("div", "ab");
5120 emitcode ("mov", "a,b");
5121 emitcode ("rrc", "a");
5122 aopOp(result, ic, TRUE, FALSE);
5123 aopPut (AOP (result), "c", 0);
5126 /*-----------------------------------------------------------------*/
5127 /* genModOneByte : 8 bit modulus */
5128 /*-----------------------------------------------------------------*/
5130 genModOneByte (operand * left,
5135 sym_link *opetype = operandType (result);
5139 /* signed or unsigned */
5140 if (SPEC_USIGN (opetype))
5142 /* unsigned is easy */
5143 LOAD_AB_FOR_DIV (left, right, l);
5144 emitcode ("div", "ab");
5145 aopOp(result, ic, TRUE, FALSE);
5146 aopPut (AOP (result), "b", 0);
5150 /* signed is a little bit more difficult */
5152 /* save the signs of the operands */
5153 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5155 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
5156 emitcode ("push", "acc"); /* save it on the stack */
5158 /* now sign adjust for both left & right */
5159 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5161 lbl = newiTempLabel (NULL);
5162 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5163 emitcode ("cpl", "a");
5164 emitcode ("inc", "a");
5165 emitcode ("", "!tlabeldef", (lbl->key + 100));
5166 emitcode ("mov", "b,a");
5168 /* sign adjust left side */
5169 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5171 lbl = newiTempLabel (NULL);
5172 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5173 emitcode ("cpl", "a");
5174 emitcode ("inc", "a");
5175 emitcode ("", "!tlabeldef", (lbl->key + 100));
5177 /* now the multiplication */
5178 emitcode ("nop", "; workaround for DS80C390 div bug.");
5179 emitcode ("div", "ab");
5180 /* we are interested in the lower order
5182 lbl = newiTempLabel (NULL);
5183 emitcode ("pop", "acc");
5184 /* if there was an over flow we don't
5185 adjust the sign of the result */
5186 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
5187 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5189 emitcode ("clr", "a");
5190 emitcode ("subb", "a,b");
5191 emitcode ("mov", "b,a");
5192 emitcode ("", "!tlabeldef", (lbl->key + 100));
5195 /* now we are done */
5196 aopOp(result, ic, TRUE, FALSE);
5197 aopPut (AOP (result), "b", 0);
5202 /*-----------------------------------------------------------------*/
5203 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
5204 /*-----------------------------------------------------------------*/
5205 static void genModTwoByte (operand *left, operand *right,
5206 operand *result, iCode *ic)
5208 sym_link *retype = getSpec(operandType(right));
5209 sym_link *letype = getSpec(operandType(left));
5210 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5213 /* load up MA with left */
5214 /* save EA bit in F1 */
5215 lbl = newiTempLabel(NULL);
5216 emitcode ("setb","F1");
5217 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5218 emitcode ("clr","F1");
5219 emitcode("","!tlabeldef",lbl->key+100);
5222 lbl = newiTempLabel(NULL);
5223 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5224 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5225 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5226 emitcode ("xch", "a,b");
5227 emitcode ("cpl","a");
5228 emitcode ("add", "a,#1");
5229 emitcode ("xch", "a,b");
5230 emitcode ("cpl", "a"); // msb
5231 emitcode ("addc","a,#0");
5232 emitcode ("","!tlabeldef",lbl->key+100);
5233 emitcode ("mov","ma,b");
5234 emitcode ("mov","ma,a");
5236 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5237 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5240 /* load up MB with right */
5242 if (AOP_TYPE(right) == AOP_LIT) {
5243 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5247 emitcode ("mov","mb,#!constbyte",val & 0xff);
5248 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5250 lbl = newiTempLabel(NULL);
5251 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5252 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5253 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5254 emitcode ("xch", "a,b");
5255 emitcode ("cpl","a");
5256 emitcode ("add", "a,#1");
5257 emitcode ("xch", "a,b");
5258 emitcode ("cpl", "a"); // msb
5259 emitcode ("addc", "a,#0");
5260 emitcode ("","!tlabeldef",lbl->key+100);
5261 emitcode ("mov","mb,b");
5262 emitcode ("mov","mb,a");
5265 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5266 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5269 /* wait for multiplication to finish */
5270 lbl = newiTempLabel(NULL);
5271 emitcode("","!tlabeldef", lbl->key+100);
5272 emitcode("mov","a,mcnt1");
5273 emitcode("anl","a,#!constbyte",0x80);
5274 emitcode("jnz","!tlabel",lbl->key+100);
5276 freeAsmop (left, NULL, ic, TRUE);
5277 freeAsmop (right, NULL, ic,TRUE);
5278 aopOp(result, ic, TRUE, FALSE);
5280 aopPut(AOP(result),"mb",1);
5281 aopPut(AOP(result),"mb",0);
5282 freeAsmop (result, NULL, ic, TRUE);
5284 /* restore EA bit in F1 */
5285 lbl = newiTempLabel(NULL);
5286 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5287 emitcode ("setb","EA");
5288 emitcode("","!tlabeldef",lbl->key+100);
5292 /*-----------------------------------------------------------------*/
5293 /* genMod - generates code for division */
5294 /*-----------------------------------------------------------------*/
5298 operand *left = IC_LEFT (ic);
5299 operand *right = IC_RIGHT (ic);
5300 operand *result = IC_RESULT (ic);
5302 D (emitcode (";", "genMod "); );
5304 /* assign the amsops */
5307 /* special cases first */
5309 if (AOP_TYPE (left) == AOP_CRY &&
5310 AOP_TYPE (right) == AOP_CRY)
5312 genModbits (left, right, result, ic);
5316 /* if both are of size == 1 */
5317 if (AOP_SIZE (left) == 1 &&
5318 AOP_SIZE (right) == 1)
5320 genModOneByte (left, right, result, ic);
5324 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5325 /* use the ds390 ARITHMETIC accel UNIT */
5326 genModTwoByte (left, right, result, ic);
5330 /* should have been converted to function call */
5334 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5335 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5336 freeAsmop (result, NULL, ic, TRUE);
5339 /*-----------------------------------------------------------------*/
5340 /* genIfxJump :- will create a jump depending on the ifx */
5341 /*-----------------------------------------------------------------*/
5343 genIfxJump (iCode * ic, char *jval)
5346 symbol *tlbl = newiTempLabel (NULL);
5349 D (emitcode (";", "genIfxJump"););
5351 /* if true label then we jump if condition
5355 jlbl = IC_TRUE (ic);
5356 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5357 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5361 /* false label is present */
5362 jlbl = IC_FALSE (ic);
5363 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5364 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5366 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5367 emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5369 emitcode (inst, "!tlabel", tlbl->key + 100);
5370 emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5371 emitcode ("", "!tlabeldef", tlbl->key + 100);
5373 /* mark the icode as generated */
5377 /*-----------------------------------------------------------------*/
5378 /* genCmp :- greater or less than comparison */
5379 /*-----------------------------------------------------------------*/
5381 genCmp (operand * left, operand * right,
5382 iCode * ic, iCode * ifx, int sign)
5384 int size, offset = 0;
5385 unsigned long lit = 0L;
5388 D (emitcode (";", "genCmp"););
5390 result = IC_RESULT (ic);
5392 /* if left & right are bit variables */
5393 if (AOP_TYPE (left) == AOP_CRY &&
5394 AOP_TYPE (right) == AOP_CRY)
5396 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5397 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5401 /* subtract right from left if at the
5402 end the carry flag is set then we know that
5403 left is greater than right */
5404 size = max (AOP_SIZE (left), AOP_SIZE (right));
5406 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5407 if ((size == 1) && !sign
5408 && (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5410 symbol *lbl = newiTempLabel (NULL);
5411 emitcode ("cjne", "%s,%s,!tlabel",
5412 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
5413 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5415 emitcode ("", "!tlabeldef", lbl->key + 100);
5419 if (AOP_TYPE (right) == AOP_LIT)
5421 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5422 /* optimize if(x < 0) or if(x >= 0) */
5431 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
5433 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5434 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5436 aopOp (result, ic, FALSE, FALSE);
5438 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5440 freeAsmop (result, NULL, ic, TRUE);
5441 genIfxJump (ifx, "acc.7");
5446 emitcode ("rlc", "a");
5448 goto release_freedLR;
5456 // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5457 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5458 // emitcode (";", "genCmp #2");
5459 if (sign && (size == 0))
5461 // emitcode (";", "genCmp #3");
5462 emitcode ("xrl", "a,#!constbyte",0x80);
5463 if (AOP_TYPE (right) == AOP_LIT)
5465 unsigned long lit = (unsigned long)
5466 floatFromVal (AOP (right)->aopu.aop_lit);
5467 // emitcode (";", "genCmp #3.1");
5468 emitcode ("subb", "a,#!constbyte",
5469 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5473 // emitcode (";", "genCmp #3.2");
5475 MOVB(aopGet (AOP (right), offset++, FALSE, FALSE, "b"));
5476 saveAccWarn = DEFAULT_ACC_WARNING;
5477 emitcode ("xrl", "b,#!constbyte",0x80);
5478 emitcode ("subb", "a,b");
5485 // emitcode (";", "genCmp #4");
5487 s = aopGet (AOP (right), offset++, FALSE, FALSE, "b");
5488 saveAccWarn = DEFAULT_ACC_WARNING;
5490 emitcode ("subb", "a,%s", s);
5497 /* Don't need the left & right operands any more; do need the result. */
5498 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5499 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5501 aopOp (result, ic, FALSE, FALSE);
5505 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5511 /* if the result is used in the next
5512 ifx conditional branch then generate
5513 code a little differently */
5516 genIfxJump (ifx, "c");
5522 /* leave the result in acc */
5524 freeAsmop (result, NULL, ic, TRUE);
5527 /*-----------------------------------------------------------------*/
5528 /* genCmpGt :- greater than comparison */
5529 /*-----------------------------------------------------------------*/
5531 genCmpGt (iCode * ic, iCode * ifx)
5533 operand *left, *right;
5534 sym_link *letype, *retype;
5537 D (emitcode (";", "genCmpGt ");
5540 left = IC_LEFT (ic);
5541 right = IC_RIGHT (ic);
5543 letype = getSpec (operandType (left));
5544 retype = getSpec (operandType (right));
5545 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5547 /* assign the left & right amsops */
5550 genCmp (right, left, ic, ifx, sign);
5553 /*-----------------------------------------------------------------*/
5554 /* genCmpLt - less than comparisons */
5555 /*-----------------------------------------------------------------*/
5557 genCmpLt (iCode * ic, iCode * ifx)
5559 operand *left, *right;
5560 sym_link *letype, *retype;
5563 D (emitcode (";", "genCmpLt "););
5565 left = IC_LEFT (ic);
5566 right = IC_RIGHT (ic);
5568 letype = getSpec (operandType (left));
5569 retype = getSpec (operandType (right));
5570 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5572 /* assign the left & right amsops */
5575 genCmp (left, right, ic, ifx, sign);
5578 /*-----------------------------------------------------------------*/
5579 /* gencjneshort - compare and jump if not equal */
5580 /*-----------------------------------------------------------------*/
5582 gencjneshort (operand * left, operand * right, symbol * lbl)
5584 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5586 unsigned long lit = 0L;
5588 D (emitcode (";", "gencjneshort");
5591 /* if the left side is a literal or
5592 if the right is in a pointer register and left
5594 if ((AOP_TYPE (left) == AOP_LIT) ||
5595 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5602 if (AOP_TYPE (right) == AOP_LIT)
5603 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5605 if (opIsGptr (left) || opIsGptr (right))
5607 /* We are comparing a generic pointer to something.
5608 * Exclude the generic type byte from the comparison.
5611 D (emitcode (";", "cjneshort: generic ptr special case."););
5615 /* if the right side is a literal then anything goes */
5616 if (AOP_TYPE (right) == AOP_LIT &&
5617 AOP_TYPE (left) != AOP_DIR)
5621 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5622 emitcode ("cjne", "a,%s,!tlabel",
5623 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5629 /* if the right side is in a register or in direct space or
5630 if the left is a pointer register & right is not */
5631 else if (AOP_TYPE (right) == AOP_REG ||
5632 AOP_TYPE (right) == AOP_DIR ||
5633 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5634 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5638 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5639 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5640 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5641 emitcode ("jnz", "!tlabel", lbl->key + 100);
5643 emitcode ("cjne", "a,%s,!tlabel",
5644 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
5651 /* right is a pointer reg need both a & b */
5654 MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5655 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
5656 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5662 /*-----------------------------------------------------------------*/
5663 /* gencjne - compare and jump if not equal */
5664 /*-----------------------------------------------------------------*/
5666 gencjne (operand * left, operand * right, symbol * lbl)
5668 symbol *tlbl = newiTempLabel (NULL);
5670 D (emitcode (";", "gencjne");
5673 gencjneshort (left, right, lbl);
5675 emitcode ("mov", "a,%s", one);
5676 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5677 emitcode ("", "!tlabeldef", lbl->key + 100);
5678 emitcode ("clr", "a");
5679 emitcode ("", "!tlabeldef", tlbl->key + 100);
5682 /*-----------------------------------------------------------------*/
5683 /* genCmpEq - generates code for equal to */
5684 /*-----------------------------------------------------------------*/
5686 genCmpEq (iCode * ic, iCode * ifx)
5688 operand *left, *right, *result;
5690 D (emitcode (";", "genCmpEq ");
5694 AOP_SET_LOCALS (ic);
5696 /* if literal, literal on the right or
5697 if the right is in a pointer register and left
5699 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5700 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5702 operand *t = IC_RIGHT (ic);
5703 IC_RIGHT (ic) = IC_LEFT (ic);
5707 if (ifx && /* !AOP_SIZE(result) */
5708 OP_SYMBOL (result) &&
5709 OP_SYMBOL (result)->regType == REG_CND)
5712 /* if they are both bit variables */
5713 if (AOP_TYPE (left) == AOP_CRY &&
5714 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5716 if (AOP_TYPE (right) == AOP_LIT)
5718 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5721 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5722 emitcode ("cpl", "c");
5726 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5730 emitcode ("clr", "c");
5732 /* AOP_TYPE(right) == AOP_CRY */
5736 symbol *lbl = newiTempLabel (NULL);
5737 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5738 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5739 emitcode ("cpl", "c");
5740 emitcode ("", "!tlabeldef", (lbl->key + 100));
5742 /* if true label then we jump if condition
5744 tlbl = newiTempLabel (NULL);
5747 emitcode ("jnc", "!tlabel", tlbl->key + 100);
5748 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5752 emitcode ("jc", "!tlabel", tlbl->key + 100);
5753 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5755 emitcode ("", "!tlabeldef", tlbl->key + 100);
5759 tlbl = newiTempLabel (NULL);
5760 gencjneshort (left, right, tlbl);
5763 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5764 emitcode ("", "!tlabeldef", tlbl->key + 100);
5768 symbol *lbl = newiTempLabel (NULL);
5769 emitcode ("sjmp", "!tlabel", lbl->key + 100);
5770 emitcode ("", "!tlabeldef", tlbl->key + 100);
5771 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5772 emitcode ("", "!tlabeldef", lbl->key + 100);
5775 /* mark the icode as generated */
5778 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5779 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5783 /* if they are both bit variables */
5784 if (AOP_TYPE (left) == AOP_CRY &&
5785 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5787 if (AOP_TYPE (right) == AOP_LIT)
5789 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5792 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5793 emitcode ("cpl", "c");
5797 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5801 emitcode ("clr", "c");
5803 /* AOP_TYPE(right) == AOP_CRY */
5807 symbol *lbl = newiTempLabel (NULL);
5808 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5809 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5810 emitcode ("cpl", "c");
5811 emitcode ("", "!tlabeldef", (lbl->key + 100));
5814 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5815 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5817 aopOp (result, ic, TRUE, FALSE);
5820 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5827 genIfxJump (ifx, "c");
5830 /* if the result is used in an arithmetic operation
5831 then put the result in place */
5836 gencjne (left, right, newiTempLabel (NULL));
5838 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5839 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5841 aopOp (result, ic, TRUE, FALSE);
5843 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5845 aopPut (AOP (result), "a", 0);
5850 genIfxJump (ifx, "a");
5853 /* if the result is used in an arithmetic operation
5854 then put the result in place */
5855 if (AOP_TYPE (result) != AOP_CRY)
5857 /* leave the result in acc */
5861 freeAsmop (result, NULL, ic, TRUE);
5864 /*-----------------------------------------------------------------*/
5865 /* ifxForOp - returns the icode containing the ifx for operand */
5866 /*-----------------------------------------------------------------*/
5868 ifxForOp (operand * op, iCode * ic)
5870 /* if true symbol then needs to be assigned */
5871 if (IS_TRUE_SYMOP (op))
5874 /* if this has register type condition and
5875 the next instruction is ifx with the same operand
5876 and live to of the operand is upto the ifx only then */
5878 ic->next->op == IFX &&
5879 IC_COND (ic->next)->key == op->key &&
5880 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5885 /*-----------------------------------------------------------------*/
5886 /* hasInc - operand is incremented before any other use */
5887 /*-----------------------------------------------------------------*/
5889 hasInc (operand *op, iCode *ic, int osize)
5891 sym_link *type = operandType(op);
5892 sym_link *retype = getSpec (type);
5893 iCode *lic = ic->next;
5896 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5897 if (!IS_SYMOP(op)) return NULL;
5899 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5900 if (IS_AGGREGATE(type->next)) return NULL;
5901 if (osize != (isize = getSize(type->next))) return NULL;
5904 /* if operand of the form op = op + <sizeof *op> */
5905 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5906 isOperandEqual(IC_RESULT(lic),op) &&
5907 isOperandLiteral(IC_RIGHT(lic)) &&
5908 operandLitValue(IC_RIGHT(lic)) == isize) {
5911 /* if the operand used or deffed */
5912 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5915 /* if GOTO or IFX */
5916 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5922 /*-----------------------------------------------------------------*/
5923 /* genAndOp - for && operation */
5924 /*-----------------------------------------------------------------*/
5926 genAndOp (iCode * ic)
5928 operand *left, *right, *result;
5931 D (emitcode (";", "genAndOp "););
5933 /* note here that && operations that are in an
5934 if statement are taken away by backPatchLabels
5935 only those used in arthmetic operations remain */
5937 AOP_SET_LOCALS (ic);
5939 /* if both are bit variables */
5940 if (AOP_TYPE (left) == AOP_CRY &&
5941 AOP_TYPE (right) == AOP_CRY)
5943 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5944 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5945 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5946 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5948 aopOp (result,ic,FALSE, FALSE);
5953 tlbl = newiTempLabel (NULL);
5955 emitcode ("jz", "!tlabel", tlbl->key + 100);
5957 emitcode ("", "!tlabeldef", tlbl->key + 100);
5958 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5959 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5961 aopOp (result,ic,FALSE, FALSE);
5964 freeAsmop (result, NULL, ic, TRUE);
5968 /*-----------------------------------------------------------------*/
5969 /* genOrOp - for || operation */
5970 /*-----------------------------------------------------------------*/
5972 genOrOp (iCode * ic)
5974 operand *left, *right, *result;
5977 D (emitcode (";", "genOrOp "););
5979 /* note here that || operations that are in an
5980 if statement are taken away by backPatchLabels
5981 only those used in arthmetic operations remain */
5983 AOP_SET_LOCALS (ic);
5985 /* if both are bit variables */
5986 if (AOP_TYPE (left) == AOP_CRY &&
5987 AOP_TYPE (right) == AOP_CRY)
5989 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5990 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5991 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5992 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5994 aopOp (result,ic,FALSE, FALSE);
6000 tlbl = newiTempLabel (NULL);
6002 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6004 emitcode ("", "!tlabeldef", tlbl->key + 100);
6005 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6006 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6008 aopOp (result,ic,FALSE, FALSE);
6013 freeAsmop (result, NULL, ic, TRUE);
6016 /*-----------------------------------------------------------------*/
6017 /* isLiteralBit - test if lit == 2^n */
6018 /*-----------------------------------------------------------------*/
6020 isLiteralBit (unsigned long lit)
6022 unsigned long pw[32] =
6023 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6024 0x100L, 0x200L, 0x400L, 0x800L,
6025 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6026 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6027 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6028 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6029 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6032 for (idx = 0; idx < 32; idx++)
6038 /*-----------------------------------------------------------------*/
6039 /* continueIfTrue - */
6040 /*-----------------------------------------------------------------*/
6042 continueIfTrue (iCode * ic)
6045 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6049 /*-----------------------------------------------------------------*/
6051 /*-----------------------------------------------------------------*/
6053 jumpIfTrue (iCode * ic)
6056 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6060 /*-----------------------------------------------------------------*/
6061 /* jmpTrueOrFalse - */
6062 /*-----------------------------------------------------------------*/
6064 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6066 // ugly but optimized by peephole
6069 symbol *nlbl = newiTempLabel (NULL);
6070 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6071 emitcode ("", "!tlabeldef", tlbl->key + 100);
6072 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6073 emitcode ("", "!tlabeldef", nlbl->key + 100);
6077 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6078 emitcode ("", "!tlabeldef", tlbl->key + 100);
6083 // Generate code to perform a bit-wise logic operation
6084 // on two operands in far space (assumed to already have been
6085 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6086 // in far space. This requires pushing the result on the stack
6087 // then popping it into the result.
6089 genFarFarLogicOp(iCode *ic, char *logicOp)
6091 int size, resultSize, compSize;
6095 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6096 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
6097 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6099 _startLazyDPSEvaluation();
6100 for (size = compSize; (size--); offset++)
6102 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6103 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6104 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6106 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6107 emitcode ("push", "acc");
6109 _endLazyDPSEvaluation();
6111 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6112 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6113 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6115 resultSize = AOP_SIZE(IC_RESULT(ic));
6117 ADJUST_PUSHED_RESULT(compSize, resultSize);
6119 _startLazyDPSEvaluation();
6122 emitcode ("pop", "acc");
6123 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6125 _endLazyDPSEvaluation();
6126 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6130 /*-----------------------------------------------------------------*/
6131 /* genAnd - code for and */
6132 /*-----------------------------------------------------------------*/
6134 genAnd (iCode * ic, iCode * ifx)
6136 operand *left, *right, *result;
6137 int size, offset = 0;
6138 unsigned long lit = 0L;
6143 D (emitcode (";", "genAnd "););
6145 AOP_OP_3_NOFATAL (ic, pushResult);
6146 AOP_SET_LOCALS (ic);
6150 genFarFarLogicOp(ic, "anl");
6155 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6157 AOP_TYPE (left), AOP_TYPE (right));
6158 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6160 AOP_SIZE (left), AOP_SIZE (right));
6163 /* if left is a literal & right is not then exchange them */
6164 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6165 #ifdef LOGIC_OPS_BROKEN
6166 || AOP_NEEDSACC (left)
6170 operand *tmp = right;
6175 /* if result = right then exchange them */
6176 if (sameRegs (AOP (result), AOP (right)))
6178 operand *tmp = right;
6183 /* if right is bit then exchange them */
6184 if (AOP_TYPE (right) == AOP_CRY &&
6185 AOP_TYPE (left) != AOP_CRY)
6187 operand *tmp = right;
6191 if (AOP_TYPE (right) == AOP_LIT)
6192 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6194 size = AOP_SIZE (result);
6197 // result = bit & yy;
6198 if (AOP_TYPE (left) == AOP_CRY)
6200 // c = bit & literal;
6201 if (AOP_TYPE (right) == AOP_LIT)
6205 if (size && sameRegs (AOP (result), AOP (left)))
6208 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6213 if (size && (AOP_TYPE (result) == AOP_CRY))
6215 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6218 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6223 emitcode ("clr", "c");
6228 if (AOP_TYPE (right) == AOP_CRY)
6231 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6232 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6237 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6239 emitcode ("rrc", "a");
6240 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6248 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6249 genIfxJump (ifx, "c");
6253 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6254 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6255 if ((AOP_TYPE (right) == AOP_LIT) &&
6256 (AOP_TYPE (result) == AOP_CRY) &&
6257 (AOP_TYPE (left) != AOP_CRY))
6259 int posbit = isLiteralBit (lit);
6264 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6267 emitcode ("mov", "c,acc.%d", posbit & 0x07);
6273 SNPRINTF (buff, sizeof(buff),
6274 "acc.%d", posbit & 0x07);
6275 genIfxJump (ifx, buff);
6279 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6286 symbol *tlbl = newiTempLabel (NULL);
6287 int sizel = AOP_SIZE (left);
6289 emitcode ("setb", "c");
6292 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6294 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6296 if ((posbit = isLiteralBit (bytelit)) != 0)
6297 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6300 if (bytelit != 0x0FFL)
6301 emitcode ("anl", "a,%s",
6302 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6303 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6308 // bit = left & literal
6311 emitcode ("clr", "c");
6312 emitcode ("", "!tlabeldef", tlbl->key + 100);
6314 // if(left & literal)
6318 jmpTrueOrFalse (ifx, tlbl);
6326 /* if left is same as result */
6327 if (sameRegs (AOP (result), AOP (left)))
6329 for (; size--; offset++)
6331 if (AOP_TYPE (right) == AOP_LIT)
6333 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6335 else if (bytelit == 0)
6336 aopPut (AOP (result), zero, offset);
6337 else if (IS_AOP_PREG (result))
6339 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6340 emitcode ("anl", "a,%s",
6341 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6342 aopPut (AOP (result), "a", offset);
6345 emitcode ("anl", "%s,%s",
6346 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6347 aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6351 if (AOP_TYPE (left) == AOP_ACC)
6352 emitcode ("anl", "a,%s",
6353 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6356 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6357 if (IS_AOP_PREG (result))
6359 emitcode ("anl", "a,%s",
6360 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6361 aopPut (AOP (result), "a", offset);
6364 emitcode ("anl", "%s,a",
6365 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6372 // left & result in different registers
6373 if (AOP_TYPE (result) == AOP_CRY)
6376 // if(size), result in bit
6377 // if(!size && ifx), conditional oper: if(left & right)
6378 symbol *tlbl = newiTempLabel (NULL);
6379 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6381 emitcode ("setb", "c");
6384 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6385 emitcode ("anl", "a,%s",
6386 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6388 if (AOP_TYPE(left)==AOP_ACC) {
6389 emitcode("mov", "b,a");
6390 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6391 emitcode("anl", "a,b");
6393 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6394 emitcode ("anl", "a,%s",
6395 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6398 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6404 emitcode ("", "!tlabeldef", tlbl->key + 100);
6408 jmpTrueOrFalse (ifx, tlbl);
6412 for (; (size--); offset++)
6415 // result = left & right
6416 if (AOP_TYPE (right) == AOP_LIT)
6418 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6420 aopPut (AOP (result),
6421 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6425 else if (bytelit == 0)
6427 aopPut (AOP (result), zero, offset);
6430 D (emitcode (";", "better literal AND."););
6431 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6432 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6433 FALSE, FALSE, DP2_RESULT_REG));
6438 // faster than result <- left, anl result,right
6439 // and better if result is SFR
6440 if (AOP_TYPE (left) == AOP_ACC)
6442 emitcode ("anl", "a,%s",
6443 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6447 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6448 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6450 emitcode("mov", "b,a");
6454 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6455 emitcode ("anl", "a,%s", rOp);
6458 aopPut (AOP (result), "a", offset);
6464 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6465 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6466 freeAsmop (result, NULL, ic, TRUE);
6470 /*-----------------------------------------------------------------*/
6471 /* genOr - code for or */
6472 /*-----------------------------------------------------------------*/
6474 genOr (iCode * ic, iCode * ifx)
6476 operand *left, *right, *result;
6477 int size, offset = 0;
6478 unsigned long lit = 0L;
6481 D (emitcode (";", "genOr "););
6483 AOP_OP_3_NOFATAL (ic, pushResult);
6484 AOP_SET_LOCALS (ic);
6488 genFarFarLogicOp(ic, "orl");
6494 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6496 AOP_TYPE (left), AOP_TYPE (right));
6497 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6499 AOP_SIZE (left), AOP_SIZE (right));
6502 /* if left is a literal & right is not then exchange them */
6503 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6504 #ifdef LOGIC_OPS_BROKEN
6505 || AOP_NEEDSACC (left) // I think this is a net loss now.
6509 operand *tmp = right;
6514 /* if result = right then exchange them */
6515 if (sameRegs (AOP (result), AOP (right)))
6517 operand *tmp = right;
6522 /* if right is bit then exchange them */
6523 if (AOP_TYPE (right) == AOP_CRY &&
6524 AOP_TYPE (left) != AOP_CRY)
6526 operand *tmp = right;
6530 if (AOP_TYPE (right) == AOP_LIT)
6531 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6533 size = AOP_SIZE (result);
6537 if (AOP_TYPE (left) == AOP_CRY)
6539 if (AOP_TYPE (right) == AOP_LIT)
6541 // c = bit & literal;
6544 // lit != 0 => result = 1
6545 if (AOP_TYPE (result) == AOP_CRY)
6548 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6550 continueIfTrue (ifx);
6553 emitcode ("setb", "c");
6557 // lit == 0 => result = left
6558 if (size && sameRegs (AOP (result), AOP (left)))
6560 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6565 if (AOP_TYPE (right) == AOP_CRY)
6568 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6569 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6574 symbol *tlbl = newiTempLabel (NULL);
6575 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6576 emitcode ("setb", "c");
6577 emitcode ("jb", "%s,!tlabel",
6578 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6580 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6581 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6583 jmpTrueOrFalse (ifx, tlbl);
6589 emitcode ("", "!tlabeldef", tlbl->key + 100);
6598 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6599 genIfxJump (ifx, "c");
6603 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6604 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6605 if ((AOP_TYPE (right) == AOP_LIT) &&
6606 (AOP_TYPE (result) == AOP_CRY) &&
6607 (AOP_TYPE (left) != AOP_CRY))
6613 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6615 continueIfTrue (ifx);
6620 // lit = 0, result = boolean(left)
6622 emitcode ("setb", "c");
6626 symbol *tlbl = newiTempLabel (NULL);
6627 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6629 emitcode ("", "!tlabeldef", tlbl->key + 100);
6633 genIfxJump (ifx, "a");
6641 /* if left is same as result */
6642 if (sameRegs (AOP (result), AOP (left)))
6644 for (; size--; offset++)
6646 if (AOP_TYPE (right) == AOP_LIT)
6648 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6654 if (IS_AOP_PREG (left))
6656 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6657 emitcode ("orl", "a,%s",
6658 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6659 aopPut (AOP (result), "a", offset);
6663 emitcode ("orl", "%s,%s",
6664 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6665 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6671 if (AOP_TYPE (left) == AOP_ACC)
6673 emitcode ("orl", "a,%s",
6674 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6678 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6679 if (IS_AOP_PREG (left))
6681 emitcode ("orl", "a,%s",
6682 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6683 aopPut (AOP (result), "a", offset);
6687 emitcode ("orl", "%s,a",
6688 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6696 // left & result in different registers
6697 if (AOP_TYPE (result) == AOP_CRY)
6700 // if(size), result in bit
6701 // if(!size && ifx), conditional oper: if(left | right)
6702 symbol *tlbl = newiTempLabel (NULL);
6703 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6705 emitcode ("setb", "c");
6708 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6709 emitcode ("orl", "a,%s",
6710 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6712 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6713 emitcode ("orl", "a,%s",
6714 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6716 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6722 emitcode ("", "!tlabeldef", tlbl->key + 100);
6726 jmpTrueOrFalse (ifx, tlbl);
6730 _startLazyDPSEvaluation();
6731 for (; (size--); offset++)
6734 // result = left & right
6735 if (AOP_TYPE (right) == AOP_LIT)
6737 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6739 aopPut (AOP (result),
6740 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6744 D (emitcode (";", "better literal OR."););
6745 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6746 emitcode ("orl", "a, %s",
6747 aopGet (AOP (right), offset,
6748 FALSE, FALSE, DP2_RESULT_REG));
6753 // faster than result <- left, anl result,right
6754 // and better if result is SFR
6755 if (AOP_TYPE (left) == AOP_ACC)
6757 emitcode ("orl", "a,%s",
6758 aopGet (AOP (right), offset,
6759 FALSE, FALSE, DP2_RESULT_REG));
6763 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6765 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6767 emitcode("mov", "b,a");
6771 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6772 emitcode ("orl", "a,%s", rOp);
6775 aopPut (AOP (result), "a", offset);
6777 _endLazyDPSEvaluation();
6782 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6783 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6784 freeAsmop (result, NULL, ic, TRUE);
6787 /*-----------------------------------------------------------------*/
6788 /* genXor - code for xclusive or */
6789 /*-----------------------------------------------------------------*/
6791 genXor (iCode * ic, iCode * ifx)
6793 operand *left, *right, *result;
6794 int size, offset = 0;
6795 unsigned long lit = 0L;
6798 D (emitcode (";", "genXor "););
6800 AOP_OP_3_NOFATAL (ic, pushResult);
6801 AOP_SET_LOCALS (ic);
6805 genFarFarLogicOp(ic, "xrl");
6810 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6812 AOP_TYPE (left), AOP_TYPE (right));
6813 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6815 AOP_SIZE (left), AOP_SIZE (right));
6818 /* if left is a literal & right is not ||
6819 if left needs acc & right does not */
6820 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6821 #ifdef LOGIC_OPS_BROKEN
6822 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6826 operand *tmp = right;
6831 /* if result = right then exchange them */
6832 if (sameRegs (AOP (result), AOP (right)))
6834 operand *tmp = right;
6839 /* if right is bit then exchange them */
6840 if (AOP_TYPE (right) == AOP_CRY &&
6841 AOP_TYPE (left) != AOP_CRY)
6843 operand *tmp = right;
6847 if (AOP_TYPE (right) == AOP_LIT)
6848 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6850 size = AOP_SIZE (result);
6854 if (AOP_TYPE (left) == AOP_CRY)
6856 if (AOP_TYPE (right) == AOP_LIT)
6858 // c = bit & literal;
6861 // lit>>1 != 0 => result = 1
6862 if (AOP_TYPE (result) == AOP_CRY)
6865 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6867 continueIfTrue (ifx);
6870 emitcode ("setb", "c");
6877 // lit == 0, result = left
6878 if (size && sameRegs (AOP (result), AOP (left)))
6880 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6884 // lit == 1, result = not(left)
6885 if (size && sameRegs (AOP (result), AOP (left)))
6887 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6892 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6893 emitcode ("cpl", "c");
6902 symbol *tlbl = newiTempLabel (NULL);
6903 if (AOP_TYPE (right) == AOP_CRY)
6906 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6910 int sizer = AOP_SIZE (right);
6912 // if val>>1 != 0, result = 1
6913 emitcode ("setb", "c");
6916 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
6918 // test the msb of the lsb
6919 emitcode ("anl", "a,#!constbyte",0xfe);
6920 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6924 emitcode ("rrc", "a");
6926 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6927 emitcode ("cpl", "c");
6928 emitcode ("", "!tlabeldef", (tlbl->key + 100));
6935 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6936 genIfxJump (ifx, "c");
6940 if (sameRegs (AOP (result), AOP (left)))
6942 /* if left is same as result */
6943 for (; size--; offset++)
6945 if (AOP_TYPE (right) == AOP_LIT)
6947 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6949 else if (IS_AOP_PREG (left))
6951 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6952 emitcode ("xrl", "a,%s",
6953 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6954 aopPut (AOP (result), "a", offset);
6957 emitcode ("xrl", "%s,%s",
6958 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6959 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6963 if (AOP_TYPE (left) == AOP_ACC)
6964 emitcode ("xrl", "a,%s",
6965 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6968 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6969 if (IS_AOP_PREG (left))
6971 emitcode ("xrl", "a,%s",
6972 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6973 aopPut (AOP (result), "a", offset);
6976 emitcode ("xrl", "%s,a",
6977 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6984 // left & result in different registers
6985 if (AOP_TYPE (result) == AOP_CRY)
6988 // if(size), result in bit
6989 // if(!size && ifx), conditional oper: if(left ^ right)
6990 symbol *tlbl = newiTempLabel (NULL);
6991 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6994 emitcode ("setb", "c");
6997 if ((AOP_TYPE (right) == AOP_LIT) &&
6998 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7000 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7004 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7005 emitcode ("xrl", "a,%s",
7006 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7008 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7009 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7011 emitcode("mov", "b,a");
7015 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7016 emitcode ("xrl", "a,%s", rOp);
7019 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7025 emitcode ("", "!tlabeldef", tlbl->key + 100);
7029 jmpTrueOrFalse (ifx, tlbl);
7033 for (; (size--); offset++)
7036 // result = left & right
7037 if (AOP_TYPE (right) == AOP_LIT)
7039 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7041 aopPut (AOP (result),
7042 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7046 D (emitcode (";", "better literal XOR."););
7047 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7048 emitcode ("xrl", "a, %s",
7049 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7053 // faster than result <- left, anl result,right
7054 // and better if result is SFR
7055 if (AOP_TYPE (left) == AOP_ACC)
7057 emitcode ("xrl", "a,%s",
7058 aopGet (AOP (right), offset,
7059 FALSE, FALSE, DP2_RESULT_REG));
7063 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7064 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7066 emitcode("mov", "b,a");
7070 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7071 emitcode ("xrl", "a,%s", rOp);
7074 aopPut (AOP (result), "a", offset);
7081 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7082 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7083 freeAsmop (result, NULL, ic, TRUE);
7086 /*-----------------------------------------------------------------*/
7087 /* genInline - write the inline code out */
7088 /*-----------------------------------------------------------------*/
7090 genInline (iCode * ic)
7092 char *buffer, *bp, *bp1;
7094 D (emitcode (";", "genInline "); );
7096 _G.inLine += (!options.asmpeep);
7098 buffer = Safe_strdup(IC_INLINE(ic));
7102 /* emit each line as a code */
7127 /* emitcode("",buffer); */
7128 _G.inLine -= (!options.asmpeep);
7131 /*-----------------------------------------------------------------*/
7132 /* genRRC - rotate right with carry */
7133 /*-----------------------------------------------------------------*/
7137 operand *left, *result;
7140 D (emitcode (";", "genRRC "););
7142 /* rotate right with carry */
7143 left = IC_LEFT (ic);
7144 result = IC_RESULT (ic);
7145 aopOp (left, ic, FALSE, FALSE);
7146 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7148 /* move it to the result */
7149 size = AOP_SIZE (result);
7153 _startLazyDPSEvaluation ();
7156 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7157 emitcode ("rrc", "a");
7158 if (AOP_SIZE (result) > 1)
7159 aopPut (AOP (result), "a", offset--);
7161 _endLazyDPSEvaluation ();
7163 /* now we need to put the carry into the
7164 highest order byte of the result */
7165 if (AOP_SIZE (result) > 1)
7167 MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7169 emitcode ("mov", "acc.7,c");
7170 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7171 freeAsmop (left, NULL, ic, TRUE);
7172 freeAsmop (result, NULL, ic, TRUE);
7175 /*-----------------------------------------------------------------*/
7176 /* genRLC - generate code for rotate left with carry */
7177 /*-----------------------------------------------------------------*/
7181 operand *left, *result;
7185 D (emitcode (";", "genRLC "););
7187 /* rotate right with carry */
7188 left = IC_LEFT (ic);
7189 result = IC_RESULT (ic);
7190 aopOp (left, ic, FALSE, FALSE);
7191 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7193 /* move it to the result */
7194 size = AOP_SIZE (result);
7198 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7200 emitcode ("add", "a,acc");
7201 if (AOP_SIZE (result) > 1)
7203 aopPut (AOP (result), "a", offset++);
7206 _startLazyDPSEvaluation ();
7209 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7211 emitcode ("rlc", "a");
7212 if (AOP_SIZE (result) > 1)
7213 aopPut (AOP (result), "a", offset++);
7215 _endLazyDPSEvaluation ();
7217 /* now we need to put the carry into the
7218 highest order byte of the result */
7219 if (AOP_SIZE (result) > 1)
7221 l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7224 emitcode ("mov", "acc.0,c");
7225 aopPut (AOP (result), "a", 0);
7226 freeAsmop (left, NULL, ic, TRUE);
7227 freeAsmop (result, NULL, ic, TRUE);
7230 /*-----------------------------------------------------------------*/
7231 /* genGetHbit - generates code get highest order bit */
7232 /*-----------------------------------------------------------------*/
7234 genGetHbit (iCode * ic)
7236 operand *left, *result;
7237 left = IC_LEFT (ic);
7238 result = IC_RESULT (ic);
7239 aopOp (left, ic, FALSE, FALSE);
7240 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7242 D (emitcode (";", "genGetHbit "););
7244 /* get the highest order byte into a */
7245 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7246 if (AOP_TYPE (result) == AOP_CRY)
7248 emitcode ("rlc", "a");
7253 emitcode ("rl", "a");
7254 emitcode ("anl", "a,#1");
7259 freeAsmop (left, NULL, ic, TRUE);
7260 freeAsmop (result, NULL, ic, TRUE);
7263 /*-----------------------------------------------------------------*/
7264 /* AccRol - rotate left accumulator by known count */
7265 /*-----------------------------------------------------------------*/
7267 AccRol (int shCount)
7269 shCount &= 0x0007; // shCount : 0..7
7276 emitcode ("rl", "a");
7279 emitcode ("rl", "a");
7280 emitcode ("rl", "a");
7283 emitcode ("swap", "a");
7284 emitcode ("rr", "a");
7287 emitcode ("swap", "a");
7290 emitcode ("swap", "a");
7291 emitcode ("rl", "a");
7294 emitcode ("rr", "a");
7295 emitcode ("rr", "a");
7298 emitcode ("rr", "a");
7303 /*-----------------------------------------------------------------*/
7304 /* AccLsh - left shift accumulator by known count */
7305 /*-----------------------------------------------------------------*/
7307 AccLsh (int shCount)
7312 emitcode ("add", "a,acc");
7313 else if (shCount == 2)
7315 emitcode ("add", "a,acc");
7316 emitcode ("add", "a,acc");
7320 /* rotate left accumulator */
7322 /* and kill the lower order bits */
7323 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7328 /*-----------------------------------------------------------------*/
7329 /* AccRsh - right shift accumulator by known count */
7330 /*-----------------------------------------------------------------*/
7332 AccRsh (int shCount)
7339 emitcode ("rrc", "a");
7343 /* rotate right accumulator */
7344 AccRol (8 - shCount);
7345 /* and kill the higher order bits */
7346 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7351 #ifdef BETTER_LITERAL_SHIFT
7352 /*-----------------------------------------------------------------*/
7353 /* AccSRsh - signed right shift accumulator by known count */
7354 /*-----------------------------------------------------------------*/
7356 AccSRsh (int shCount)
7363 emitcode ("mov", "c,acc.7");
7364 emitcode ("rrc", "a");
7366 else if (shCount == 2)
7368 emitcode ("mov", "c,acc.7");
7369 emitcode ("rrc", "a");
7370 emitcode ("mov", "c,acc.7");
7371 emitcode ("rrc", "a");
7375 tlbl = newiTempLabel (NULL);
7376 /* rotate right accumulator */
7377 AccRol (8 - shCount);
7378 /* and kill the higher order bits */
7379 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7380 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7381 emitcode ("orl", "a,#!constbyte",
7382 (unsigned char) ~SRMask[shCount]);
7383 emitcode ("", "!tlabeldef", tlbl->key + 100);
7389 #ifdef BETTER_LITERAL_SHIFT
7390 /*-----------------------------------------------------------------*/
7391 /* shiftR1Left2Result - shift right one byte from left to result */
7392 /*-----------------------------------------------------------------*/
7394 shiftR1Left2Result (operand * left, int offl,
7395 operand * result, int offr,
7396 int shCount, int sign)
7398 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7399 /* shift right accumulator */
7404 aopPut (AOP (result), "a", offr);
7408 #ifdef BETTER_LITERAL_SHIFT
7409 /*-----------------------------------------------------------------*/
7410 /* shiftL1Left2Result - shift left one byte from left to result */
7411 /*-----------------------------------------------------------------*/
7413 shiftL1Left2Result (operand * left, int offl,
7414 operand * result, int offr, int shCount)
7416 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7417 /* shift left accumulator */
7419 aopPut (AOP (result), "a", offr);
7423 #ifdef BETTER_LITERAL_SHIFT
7424 /*-----------------------------------------------------------------*/
7425 /* movLeft2Result - move byte from left to result */
7426 /*-----------------------------------------------------------------*/
7428 movLeft2Result (operand * left, int offl,
7429 operand * result, int offr, int sign)
7432 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7434 l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
7436 if (*l == '@' && (IS_AOP_PREG (result)))
7438 emitcode ("mov", "a,%s", l);
7439 aopPut (AOP (result), "a", offr);
7445 aopPut (AOP (result), l, offr);
7449 /* MSB sign in acc.7 ! */
7450 if (getDataSize (left) == offl + 1)
7452 emitcode ("mov", "a,%s", l);
7453 aopPut (AOP (result), "a", offr);
7461 #ifdef BETTER_LITERAL_SHIFT
7462 /*-----------------------------------------------------------------*/
7463 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7464 /*-----------------------------------------------------------------*/
7468 emitcode ("rrc", "a");
7469 emitcode ("xch", "a,%s", x);
7470 emitcode ("rrc", "a");
7471 emitcode ("xch", "a,%s", x);
7475 #ifdef BETTER_LITERAL_SHIFT
7477 /*-----------------------------------------------------------------*/
7478 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7479 /*-----------------------------------------------------------------*/
7483 emitcode ("xch", "a,%s", x);
7484 emitcode ("rlc", "a");
7485 emitcode ("xch", "a,%s", x);
7486 emitcode ("rlc", "a");
7490 #ifdef BETTER_LITERAL_SHIFT
7491 /*-----------------------------------------------------------------*/
7492 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7493 /*-----------------------------------------------------------------*/
7497 emitcode ("xch", "a,%s", x);
7498 emitcode ("add", "a,acc");
7499 emitcode ("xch", "a,%s", x);
7500 emitcode ("rlc", "a");
7504 #ifdef BETTER_LITERAL_SHIFT
7505 /*-----------------------------------------------------------------*/
7506 /* AccAXLsh - left shift a:x by known count (0..7) */
7507 /*-----------------------------------------------------------------*/
7509 AccAXLsh (char *x, int shCount)
7524 case 5: // AAAAABBB:CCCCCDDD
7526 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7528 emitcode ("anl", "a,#!constbyte",
7529 SLMask[shCount]); // BBB00000:CCCCCDDD
7531 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7533 AccRol (shCount); // DDDCCCCC:BBB00000
7535 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7537 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7539 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7541 emitcode ("anl", "a,#!constbyte",
7542 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7544 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7546 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7549 case 6: // AAAAAABB:CCCCCCDD
7550 emitcode ("anl", "a,#!constbyte",
7551 SRMask[shCount]); // 000000BB:CCCCCCDD
7552 emitcode ("mov", "c,acc.0"); // c = B
7553 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7555 AccAXRrl1 (x); // BCCCCCCD:D000000B
7556 AccAXRrl1 (x); // BBCCCCCC:DD000000
7558 emitcode("rrc","a");
7559 emitcode("xch","a,%s", x);
7560 emitcode("rrc","a");
7561 emitcode("mov","c,acc.0"); //<< get correct bit
7562 emitcode("xch","a,%s", x);
7564 emitcode("rrc","a");
7565 emitcode("xch","a,%s", x);
7566 emitcode("rrc","a");
7567 emitcode("xch","a,%s", x);
7570 case 7: // a:x <<= 7
7572 emitcode ("anl", "a,#!constbyte",
7573 SRMask[shCount]); // 0000000B:CCCCCCCD
7575 emitcode ("mov", "c,acc.0"); // c = B
7577 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7579 AccAXRrl1 (x); // BCCCCCCC:D0000000
7588 #ifdef BETTER_LITERAL_SHIFT
7590 /*-----------------------------------------------------------------*/
7591 /* AccAXRsh - right shift a:x known count (0..7) */
7592 /*-----------------------------------------------------------------*/
7594 AccAXRsh (char *x, int shCount)
7602 AccAXRrl1 (x); // 0->a:x
7607 AccAXRrl1 (x); // 0->a:x
7610 AccAXRrl1 (x); // 0->a:x
7615 case 5: // AAAAABBB:CCCCCDDD = a:x
7617 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7619 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7621 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7623 emitcode ("anl", "a,#!constbyte",
7624 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7626 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7628 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7630 emitcode ("anl", "a,#!constbyte",
7631 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7633 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7635 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7637 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7640 case 6: // AABBBBBB:CCDDDDDD
7642 emitcode ("mov", "c,acc.7");
7643 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7645 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7647 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7649 emitcode ("anl", "a,#!constbyte",
7650 SRMask[shCount]); // 000000AA:BBBBBBCC
7653 case 7: // ABBBBBBB:CDDDDDDD
7655 emitcode ("mov", "c,acc.7"); // c = A
7657 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7659 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7661 emitcode ("anl", "a,#!constbyte",
7662 SRMask[shCount]); // 0000000A:BBBBBBBC
7671 #ifdef BETTER_LITERAL_SHIFT
7672 /*-----------------------------------------------------------------*/
7673 /* AccAXRshS - right shift signed a:x known count (0..7) */
7674 /*-----------------------------------------------------------------*/
7676 AccAXRshS (char *x, int shCount)
7684 emitcode ("mov", "c,acc.7");
7685 AccAXRrl1 (x); // s->a:x
7689 emitcode ("mov", "c,acc.7");
7690 AccAXRrl1 (x); // s->a:x
7692 emitcode ("mov", "c,acc.7");
7693 AccAXRrl1 (x); // s->a:x
7698 case 5: // AAAAABBB:CCCCCDDD = a:x
7700 tlbl = newiTempLabel (NULL);
7701 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7703 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7705 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7707 emitcode ("anl", "a,#!constbyte",
7708 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7710 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7712 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7714 emitcode ("anl", "a,#!constbyte",
7715 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7717 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7719 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7721 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7723 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7724 emitcode ("orl", "a,#!constbyte",
7725 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7727 emitcode ("", "!tlabeldef", tlbl->key + 100);
7728 break; // SSSSAAAA:BBBCCCCC
7730 case 6: // AABBBBBB:CCDDDDDD
7732 tlbl = newiTempLabel (NULL);
7733 emitcode ("mov", "c,acc.7");
7734 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7736 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7738 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7740 emitcode ("anl", "a,#!constbyte",
7741 SRMask[shCount]); // 000000AA:BBBBBBCC
7743 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7744 emitcode ("orl", "a,#!constbyte",
7745 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7747 emitcode ("", "!tlabeldef", tlbl->key + 100);
7749 case 7: // ABBBBBBB:CDDDDDDD
7751 tlbl = newiTempLabel (NULL);
7752 emitcode ("mov", "c,acc.7"); // c = A
7754 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7756 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7758 emitcode ("anl", "a,#!constbyte",
7759 SRMask[shCount]); // 0000000A:BBBBBBBC
7761 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7762 emitcode ("orl", "a,#!constbyte",
7763 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7765 emitcode ("", "!tlabeldef", tlbl->key + 100);
7773 #ifdef BETTER_LITERAL_SHIFT
7775 _loadLeftIntoAx(char **lsb,
7781 // Get the initial value from left into a pair of registers.
7782 // MSB must be in A, LSB can be any register.
7784 // If the result is held in registers, it is an optimization
7785 // if the LSB can be held in the register which will hold the,
7786 // result LSB since this saves us from having to copy it into
7787 // the result following AccAXLsh.
7789 // If the result is addressed indirectly, this is not a gain.
7790 if (AOP_NEEDSACC(result))
7794 _startLazyDPSEvaluation();
7795 if (AOP_TYPE(left) == AOP_DPTR2)
7798 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
7799 // get LSB in DP2_RESULT_REG.
7800 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
7801 assert(!strcmp(leftByte, DP2_RESULT_REG));
7805 // get LSB into DP2_RESULT_REG
7806 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
7807 if (strcmp(leftByte, DP2_RESULT_REG))
7810 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7813 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
7814 assert(strcmp(leftByte, DP2_RESULT_REG));
7817 _endLazyDPSEvaluation();
7818 *lsb = DP2_RESULT_REG;
7822 if (sameRegs (AOP (result), AOP (left)) &&
7823 ((offl + MSB16) == offr))
7825 /* don't crash result[offr] */
7826 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
7827 emitcode ("xch", "a,%s",
7828 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
7832 movLeft2Result (left, offl, result, offr, 0);
7833 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
7835 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
7836 assert(strcmp(*lsb,"a"));
7841 _storeAxResults(char *lsb,
7845 _startLazyDPSEvaluation();
7846 if (AOP_NEEDSACC(result))
7848 /* We have to explicitly update the result LSB.
7850 emitcode("xch","a,%s", lsb);
7851 aopPut(AOP(result), "a", offr);
7852 emitcode("mov","a,%s", lsb);
7854 if (getDataSize (result) > 1)
7856 aopPut (AOP (result), "a", offr + MSB16);
7858 _endLazyDPSEvaluation();
7861 /*-----------------------------------------------------------------*/
7862 /* shiftL2Left2Result - shift left two bytes from left to result */
7863 /*-----------------------------------------------------------------*/
7865 shiftL2Left2Result (operand * left, int offl,
7866 operand * result, int offr, int shCount)
7870 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7872 AccAXLsh (lsb, shCount);
7874 _storeAxResults(lsb, result, offr);
7878 #ifdef BETTER_LITERAL_SHIFT
7879 /*-----------------------------------------------------------------*/
7880 /* shiftR2Left2Result - shift right two bytes from left to result */
7881 /*-----------------------------------------------------------------*/
7883 shiftR2Left2Result (operand * left, int offl,
7884 operand * result, int offr,
7885 int shCount, int sign)
7889 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7891 /* a:x >> shCount (x = lsb(result)) */
7894 AccAXRshS(lsb, shCount);
7898 AccAXRsh(lsb, shCount);
7901 _storeAxResults(lsb, result, offr);
7905 /*-----------------------------------------------------------------*/
7906 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7907 /*-----------------------------------------------------------------*/
7909 shiftLLeftOrResult (operand * left, int offl,
7910 operand * result, int offr, int shCount)
7912 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7913 /* shift left accumulator */
7915 /* or with result */
7916 emitcode ("orl", "a,%s",
7917 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7918 /* back to result */
7919 aopPut (AOP (result), "a", offr);
7924 /*-----------------------------------------------------------------*/
7925 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7926 /*-----------------------------------------------------------------*/
7928 shiftRLeftOrResult (operand * left, int offl,
7929 operand * result, int offr, int shCount)
7931 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7932 /* shift right accumulator */
7934 /* or with result */
7935 emitcode ("orl", "a,%s",
7936 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7937 /* back to result */
7938 aopPut (AOP (result), "a", offr);
7942 #ifdef BETTER_LITERAL_SHIFT
7943 /*-----------------------------------------------------------------*/
7944 /* genlshOne - left shift a one byte quantity by known count */
7945 /*-----------------------------------------------------------------*/
7947 genlshOne (operand * result, operand * left, int shCount)
7949 D (emitcode (";", "genlshOne "););
7950 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7954 #ifdef BETTER_LITERAL_SHIFT
7955 /*-----------------------------------------------------------------*/
7956 /* genlshTwo - left shift two bytes by known amount != 0 */
7957 /*-----------------------------------------------------------------*/
7959 genlshTwo (operand * result, operand * left, int shCount)
7963 D (emitcode (";", "genlshTwo "););
7965 size = getDataSize (result);
7967 /* if shCount >= 8 */
7972 _startLazyDPSEvaluation();
7978 _endLazyDPSEvaluation();
7979 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7980 aopPut (AOP (result), zero, LSB);
7984 movLeft2Result (left, LSB, result, MSB16, 0);
7985 aopPut (AOP (result), zero, LSB);
7986 _endLazyDPSEvaluation();
7991 aopPut (AOP (result), zero, LSB);
7992 _endLazyDPSEvaluation();
7996 /* 1 <= shCount <= 7 */
8001 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8005 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8013 /*-----------------------------------------------------------------*/
8014 /* shiftLLong - shift left one long from left to result */
8015 /* offl = LSB or MSB16 */
8016 /*-----------------------------------------------------------------*/
8018 shiftLLong (operand * left, operand * result, int offr)
8021 int size = AOP_SIZE (result);
8023 if (size >= LSB + offr)
8025 l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8027 emitcode ("add", "a,acc");
8028 if (sameRegs (AOP (left), AOP (result)) &&
8029 size >= MSB16 + offr && offr != LSB)
8030 emitcode ("xch", "a,%s",
8031 aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8033 aopPut (AOP (result), "a", LSB + offr);
8036 if (size >= MSB16 + offr)
8038 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8040 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8042 emitcode ("rlc", "a");
8043 if (sameRegs (AOP (left), AOP (result)) &&
8044 size >= MSB24 + offr && offr != LSB)
8045 emitcode ("xch", "a,%s",
8046 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8048 aopPut (AOP (result), "a", MSB16 + offr);
8051 if (size >= MSB24 + offr)
8053 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8055 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8057 emitcode ("rlc", "a");
8058 if (sameRegs (AOP (left), AOP (result)) &&
8059 size >= MSB32 + offr && offr != LSB)
8060 emitcode ("xch", "a,%s",
8061 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8063 aopPut (AOP (result), "a", MSB24 + offr);
8066 if (size > MSB32 + offr)
8068 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8070 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8072 emitcode ("rlc", "a");
8073 aopPut (AOP (result), "a", MSB32 + offr);
8076 aopPut (AOP (result), zero, LSB);
8082 /*-----------------------------------------------------------------*/
8083 /* genlshFour - shift four byte by a known amount != 0 */
8084 /*-----------------------------------------------------------------*/
8086 genlshFour (operand * result, operand * left, int shCount)
8090 D (emitcode (";", "genlshFour ");
8093 size = AOP_SIZE (result);
8095 /* if shifting more that 3 bytes */
8100 /* lowest order of left goes to the highest
8101 order of the destination */
8102 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8104 movLeft2Result (left, LSB, result, MSB32, 0);
8105 aopPut (AOP (result), zero, LSB);
8106 aopPut (AOP (result), zero, MSB16);
8107 aopPut (AOP (result), zero, MSB24);
8111 /* more than two bytes */
8112 else if (shCount >= 16)
8114 /* lower order two bytes goes to higher order two bytes */
8116 /* if some more remaining */
8118 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8121 movLeft2Result (left, MSB16, result, MSB32, 0);
8122 movLeft2Result (left, LSB, result, MSB24, 0);
8124 aopPut (AOP (result), zero, MSB16);
8125 aopPut (AOP (result), zero, LSB);
8129 /* if more than 1 byte */
8130 else if (shCount >= 8)
8132 /* lower order three bytes goes to higher order three bytes */
8137 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8139 movLeft2Result (left, LSB, result, MSB16, 0);
8145 movLeft2Result (left, MSB24, result, MSB32, 0);
8146 movLeft2Result (left, MSB16, result, MSB24, 0);
8147 movLeft2Result (left, LSB, result, MSB16, 0);
8148 aopPut (AOP (result), zero, LSB);
8150 else if (shCount == 1)
8151 shiftLLong (left, result, MSB16);
8154 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8155 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8156 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8157 aopPut (AOP (result), zero, LSB);
8162 /* 1 <= shCount <= 7 */
8163 else if (shCount <= 2)
8165 shiftLLong (left, result, LSB);
8167 shiftLLong (result, result, LSB);
8169 /* 3 <= shCount <= 7, optimize */
8172 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8173 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8174 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8179 #ifdef BETTER_LITERAL_SHIFT
8180 /*-----------------------------------------------------------------*/
8181 /* genLeftShiftLiteral - left shifting by known count */
8182 /*-----------------------------------------------------------------*/
8184 genLeftShiftLiteral (operand * left,
8189 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8192 size = getSize (operandType (result));
8194 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8196 /* We only handle certain easy cases so far. */
8198 && (shCount < (size * 8))
8202 D(emitcode (";", "genLeftShiftLiteral wimping out"););
8206 freeAsmop (right, NULL, ic, TRUE);
8208 aopOp(left, ic, FALSE, FALSE);
8209 aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8212 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8214 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8215 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8217 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8220 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8222 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8223 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8225 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8231 emitcode ("; shift left ", "result %d, left %d", size,
8235 /* I suppose that the left size >= result size */
8238 _startLazyDPSEvaluation();
8241 movLeft2Result (left, size, result, size, 0);
8243 _endLazyDPSEvaluation();
8245 else if (shCount >= (size * 8))
8247 _startLazyDPSEvaluation();
8250 aopPut (AOP (result), zero, size);
8252 _endLazyDPSEvaluation();
8259 genlshOne (result, left, shCount);
8263 genlshTwo (result, left, shCount);
8267 genlshFour (result, left, shCount);
8271 fprintf(stderr, "*** ack! mystery literal shift!\n");
8275 freeAsmop (left, NULL, ic, TRUE);
8276 freeAsmop (result, NULL, ic, TRUE);
8281 /*-----------------------------------------------------------------*/
8282 /* genLeftShift - generates code for left shifting */
8283 /*-----------------------------------------------------------------*/
8285 genLeftShift (iCode * ic)
8287 operand *left, *right, *result;
8290 symbol *tlbl, *tlbl1;
8292 D (emitcode (";", "genLeftShift "););
8294 right = IC_RIGHT (ic);
8295 left = IC_LEFT (ic);
8296 result = IC_RESULT (ic);
8298 aopOp (right, ic, FALSE, FALSE);
8301 #ifdef BETTER_LITERAL_SHIFT
8302 /* if the shift count is known then do it
8303 as efficiently as possible */
8304 if (AOP_TYPE (right) == AOP_LIT)
8306 if (genLeftShiftLiteral (left, right, result, ic))
8313 /* shift count is unknown then we have to form
8314 a loop get the loop count in B : Note: we take
8315 only the lower order byte since shifting
8316 more that 32 bits make no sense anyway, ( the
8317 largest size of an object can be only 32 bits ) */
8319 if (AOP_TYPE (right) == AOP_LIT)
8321 /* Really should be handled by genLeftShiftLiteral,
8322 * but since I'm too lazy to fix that today, at least we can make
8323 * some small improvement.
8325 emitcode("mov", "b,#!constbyte",
8326 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8330 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8331 emitcode ("inc", "b");
8333 freeAsmop (right, NULL, ic, TRUE);
8334 aopOp (left, ic, FALSE, FALSE);
8335 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8337 /* now move the left to the result if they are not the
8339 if (!sameRegs (AOP (left), AOP (result)) &&
8340 AOP_SIZE (result) > 1)
8343 size = AOP_SIZE (result);
8345 _startLazyDPSEvaluation ();
8348 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8349 if (*l == '@' && (IS_AOP_PREG (result)))
8352 emitcode ("mov", "a,%s", l);
8353 aopPut (AOP (result), "a", offset);
8356 aopPut (AOP (result), l, offset);
8359 _endLazyDPSEvaluation ();
8362 tlbl = newiTempLabel (NULL);
8363 size = AOP_SIZE (result);
8365 tlbl1 = newiTempLabel (NULL);
8367 /* if it is only one byte then */
8370 symbol *tlbl1 = newiTempLabel (NULL);
8372 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8373 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8374 emitcode ("", "!tlabeldef", tlbl->key + 100);
8375 emitcode ("add", "a,acc");
8376 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8377 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8378 aopPut (AOP (result), "a", 0);
8382 reAdjustPreg (AOP (result));
8384 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8385 emitcode ("", "!tlabeldef", tlbl->key + 100);
8386 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8387 emitcode ("add", "a,acc");
8388 aopPut (AOP (result), "a", offset++);
8389 _startLazyDPSEvaluation ();
8392 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8393 emitcode ("rlc", "a");
8394 aopPut (AOP (result), "a", offset++);
8396 _endLazyDPSEvaluation ();
8397 reAdjustPreg (AOP (result));
8399 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8400 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8402 freeAsmop (left, NULL, ic, TRUE);
8403 freeAsmop (result, NULL, ic, TRUE);
8406 #ifdef BETTER_LITERAL_SHIFT
8407 /*-----------------------------------------------------------------*/
8408 /* genrshOne - right shift a one byte quantity by known count */
8409 /*-----------------------------------------------------------------*/
8411 genrshOne (operand * result, operand * left,
8412 int shCount, int sign)
8414 D (emitcode (";", "genrshOne"););
8415 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8419 #ifdef BETTER_LITERAL_SHIFT
8420 /*-----------------------------------------------------------------*/
8421 /* genrshTwo - right shift two bytes by known amount != 0 */
8422 /*-----------------------------------------------------------------*/
8424 genrshTwo (operand * result, operand * left,
8425 int shCount, int sign)
8427 D (emitcode (";", "genrshTwo"););
8429 /* if shCount >= 8 */
8433 _startLazyDPSEvaluation();
8436 shiftR1Left2Result (left, MSB16, result, LSB,
8441 movLeft2Result (left, MSB16, result, LSB, sign);
8443 addSign (result, MSB16, sign);
8444 _endLazyDPSEvaluation();
8447 /* 1 <= shCount <= 7 */
8450 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8455 /*-----------------------------------------------------------------*/
8456 /* shiftRLong - shift right one long from left to result */
8457 /* offl = LSB or MSB16 */
8458 /*-----------------------------------------------------------------*/
8460 shiftRLong (operand * left, int offl,
8461 operand * result, int sign)
8463 int isSameRegs=sameRegs(AOP(left),AOP(result));
8465 if (isSameRegs && offl>1) {
8466 // we are in big trouble, but this shouldn't happen
8467 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8470 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8475 emitcode ("rlc", "a");
8476 emitcode ("subb", "a,acc");
8477 emitcode ("xch", "a,%s",
8478 aopGet(AOP(left), MSB32, FALSE, FALSE, DP2_RESULT_REG));
8480 aopPut (AOP(result), zero, MSB32);
8485 emitcode ("clr", "c");
8487 emitcode ("mov", "c,acc.7");
8490 emitcode ("rrc", "a");
8492 if (isSameRegs && offl==MSB16) {
8494 "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE, DP2_RESULT_REG));
8496 aopPut (AOP (result), "a", MSB32);
8497 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8500 emitcode ("rrc", "a");
8501 if (isSameRegs && offl==1) {
8502 emitcode ("xch", "a,%s",
8503 aopGet (AOP (left), MSB16, FALSE, FALSE, DP2_RESULT_REG));
8505 aopPut (AOP (result), "a", MSB24);
8506 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, NULL));
8508 emitcode ("rrc", "a");
8509 aopPut (AOP (result), "a", MSB16 - offl);
8513 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, NULL));
8514 emitcode ("rrc", "a");
8515 aopPut (AOP (result), "a", LSB);
8519 /*-----------------------------------------------------------------*/
8520 /* genrshFour - shift four byte by a known amount != 0 */
8521 /*-----------------------------------------------------------------*/
8523 genrshFour (operand * result, operand * left,
8524 int shCount, int sign)
8526 D (emitcode (";", "genrshFour"););
8528 /* if shifting more that 3 bytes */
8532 _startLazyDPSEvaluation();
8534 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8536 movLeft2Result (left, MSB32, result, LSB, sign);
8537 addSign (result, MSB16, sign);
8538 _endLazyDPSEvaluation();
8540 else if (shCount >= 16)
8543 _startLazyDPSEvaluation();
8545 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8548 movLeft2Result (left, MSB24, result, LSB, 0);
8549 movLeft2Result (left, MSB32, result, MSB16, sign);
8551 addSign (result, MSB24, sign);
8552 _endLazyDPSEvaluation();
8554 else if (shCount >= 8)
8557 _startLazyDPSEvaluation();
8560 shiftRLong (left, MSB16, result, sign);
8562 else if (shCount == 0)
8564 movLeft2Result (left, MSB16, result, LSB, 0);
8565 movLeft2Result (left, MSB24, result, MSB16, 0);
8566 movLeft2Result (left, MSB32, result, MSB24, sign);
8567 addSign (result, MSB32, sign);
8571 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8572 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8573 /* the last shift is signed */
8574 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8575 addSign (result, MSB32, sign);
8577 _endLazyDPSEvaluation();
8581 /* 1 <= shCount <= 7 */
8584 shiftRLong (left, LSB, result, sign);
8586 shiftRLong (result, LSB, result, sign);
8590 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8591 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8592 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8597 #ifdef BETTER_LITERAL_SHIFT
8598 /*-----------------------------------------------------------------*/
8599 /* genRightShiftLiteral - right shifting by known count */
8600 /*-----------------------------------------------------------------*/
8602 genRightShiftLiteral (operand * left,
8608 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8611 size = getSize (operandType (result));
8613 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8615 /* We only handle certain easy cases so far. */
8617 && (shCount < (size * 8))
8622 D(emitcode (";", "genRightShiftLiteral wimping out"););
8626 freeAsmop (right, NULL, ic, TRUE);
8628 aopOp (left, ic, FALSE, FALSE);
8629 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8632 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8636 /* test the LEFT size !!! */
8638 /* I suppose that the left size >= result size */
8641 size = getDataSize (result);
8642 _startLazyDPSEvaluation();
8645 movLeft2Result (left, size, result, size, 0);
8647 _endLazyDPSEvaluation();
8649 else if (shCount >= (size * 8))
8653 /* get sign in acc.7 */
8654 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
8656 addSign (result, LSB, sign);
8663 genrshOne (result, left, shCount, sign);
8667 genrshTwo (result, left, shCount, sign);
8671 genrshFour (result, left, shCount, sign);
8678 freeAsmop (left, NULL, ic, TRUE);
8679 freeAsmop (result, NULL, ic, TRUE);
8685 /*-----------------------------------------------------------------*/
8686 /* genSignedRightShift - right shift of signed number */
8687 /*-----------------------------------------------------------------*/
8689 genSignedRightShift (iCode * ic)
8691 operand *right, *left, *result;
8694 symbol *tlbl, *tlbl1;
8696 D (emitcode (";", "genSignedRightShift "););
8698 /* we do it the hard way put the shift count in b
8699 and loop thru preserving the sign */
8701 right = IC_RIGHT (ic);
8702 left = IC_LEFT (ic);
8703 result = IC_RESULT (ic);
8705 aopOp (right, ic, FALSE, FALSE);
8707 #ifdef BETTER_LITERAL_SHIFT
8708 if (AOP_TYPE (right) == AOP_LIT)
8710 if (genRightShiftLiteral (left, right, result, ic, 1))
8716 /* shift count is unknown then we have to form
8717 a loop get the loop count in B : Note: we take
8718 only the lower order byte since shifting
8719 more that 32 bits make no sense anyway, ( the
8720 largest size of an object can be only 32 bits ) */
8722 if (AOP_TYPE (right) == AOP_LIT)
8724 /* Really should be handled by genRightShiftLiteral,
8725 * but since I'm too lazy to fix that today, at least we can make
8726 * some small improvement.
8728 emitcode("mov", "b,#!constbyte",
8729 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8733 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8734 emitcode ("inc", "b");
8736 freeAsmop (right, NULL, ic, TRUE);
8737 aopOp (left, ic, FALSE, FALSE);
8738 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8740 /* now move the left to the result if they are not the
8742 if (!sameRegs (AOP (left), AOP (result)) &&
8743 AOP_SIZE (result) > 1)
8746 size = AOP_SIZE (result);
8748 _startLazyDPSEvaluation ();
8751 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8752 if (*l == '@' && IS_AOP_PREG (result))
8755 emitcode ("mov", "a,%s", l);
8756 aopPut (AOP (result), "a", offset);
8759 aopPut (AOP (result), l, offset);
8762 _endLazyDPSEvaluation ();
8765 /* mov the highest order bit to OVR */
8766 tlbl = newiTempLabel (NULL);
8767 tlbl1 = newiTempLabel (NULL);
8769 size = AOP_SIZE (result);
8771 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
8772 emitcode ("rlc", "a");
8773 emitcode ("mov", "ov,c");
8774 /* if it is only one byte then */
8777 MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8778 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8779 emitcode ("", "!tlabeldef", tlbl->key + 100);
8780 emitcode ("mov", "c,ov");
8781 emitcode ("rrc", "a");
8782 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8783 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8784 aopPut (AOP (result), "a", 0);
8788 reAdjustPreg (AOP (result));
8789 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8790 emitcode ("", "!tlabeldef", tlbl->key + 100);
8791 emitcode ("mov", "c,ov");
8792 _startLazyDPSEvaluation ();
8795 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8796 emitcode ("rrc", "a");
8797 aopPut (AOP (result), "a", offset--);
8799 _endLazyDPSEvaluation ();
8800 reAdjustPreg (AOP (result));
8801 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8802 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8805 freeAsmop (left, NULL, ic, TRUE);
8806 freeAsmop (result, NULL, ic, TRUE);
8809 /*-----------------------------------------------------------------*/
8810 /* genRightShift - generate code for right shifting */
8811 /*-----------------------------------------------------------------*/
8813 genRightShift (iCode * ic)
8815 operand *right, *left, *result;
8819 symbol *tlbl, *tlbl1;
8821 D (emitcode (";", "genRightShift "););
8823 /* if signed then we do it the hard way preserve the
8824 sign bit moving it inwards */
8825 retype = getSpec (operandType (IC_RESULT (ic)));
8827 if (!SPEC_USIGN (retype))
8829 genSignedRightShift (ic);
8833 /* signed & unsigned types are treated the same : i.e. the
8834 signed is NOT propagated inwards : quoting from the
8835 ANSI - standard : "for E1 >> E2, is equivalent to division
8836 by 2**E2 if unsigned or if it has a non-negative value,
8837 otherwise the result is implementation defined ", MY definition
8838 is that the sign does not get propagated */
8840 right = IC_RIGHT (ic);
8841 left = IC_LEFT (ic);
8842 result = IC_RESULT (ic);
8844 aopOp (right, ic, FALSE, FALSE);
8846 #ifdef BETTER_LITERAL_SHIFT
8847 /* if the shift count is known then do it
8848 as efficiently as possible */
8849 if (AOP_TYPE (right) == AOP_LIT)
8851 if (genRightShiftLiteral (left, right, result, ic, 0))
8858 /* shift count is unknown then we have to form
8859 a loop get the loop count in B : Note: we take
8860 only the lower order byte since shifting
8861 more that 32 bits make no sense anyway, ( the
8862 largest size of an object can be only 32 bits ) */
8864 if (AOP_TYPE (right) == AOP_LIT)
8866 /* Really should be handled by genRightShiftLiteral,
8867 * but since I'm too lazy to fix that today, at least we can make
8868 * some small improvement.
8870 emitcode("mov", "b,#!constbyte",
8871 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8875 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8876 emitcode ("inc", "b");
8878 freeAsmop (right, NULL, ic, TRUE);
8879 aopOp (left, ic, FALSE, FALSE);
8880 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8882 /* now move the left to the result if they are not the
8884 if (!sameRegs (AOP (left), AOP (result)) &&
8885 AOP_SIZE (result) > 1)
8888 size = AOP_SIZE (result);
8890 _startLazyDPSEvaluation ();
8893 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8894 if (*l == '@' && IS_AOP_PREG (result))
8897 emitcode ("mov", "a,%s", l);
8898 aopPut (AOP (result), "a", offset);
8901 aopPut (AOP (result), l, offset);
8904 _endLazyDPSEvaluation ();
8907 tlbl = newiTempLabel (NULL);
8908 tlbl1 = newiTempLabel (NULL);
8909 size = AOP_SIZE (result);
8912 /* if it is only one byte then */
8915 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8916 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8917 emitcode ("", "!tlabeldef", tlbl->key + 100);
8919 emitcode ("rrc", "a");
8920 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8921 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8922 aopPut (AOP (result), "a", 0);
8926 reAdjustPreg (AOP (result));
8927 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8928 emitcode ("", "!tlabeldef", tlbl->key + 100);
8930 _startLazyDPSEvaluation ();
8933 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8934 emitcode ("rrc", "a");
8935 aopPut (AOP (result), "a", offset--);
8937 _endLazyDPSEvaluation ();
8938 reAdjustPreg (AOP (result));
8940 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8941 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8944 freeAsmop (left, NULL, ic, TRUE);
8945 freeAsmop (result, NULL, ic, TRUE);
8949 /*-----------------------------------------------------------------*/
8950 /* emitPtrByteGet - emits code to get a byte into A through a */
8951 /* pointer register (R0, R1, or DPTR). The */
8952 /* original value of A can be preserved in B. */
8953 /*-----------------------------------------------------------------*/
8955 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
8962 emitcode ("mov", "b,a");
8963 emitcode ("mov", "a,@%s", rname);
8968 emitcode ("mov", "b,a");
8969 emitcode ("movx", "a,@%s", rname);
8974 emitcode ("mov", "b,a");
8975 emitcode ("movx", "a,@dptr");
8980 emitcode ("mov", "b,a");
8981 emitcode ("clr", "a");
8982 emitcode ("movc", "a,@a+dptr");
8988 emitcode ("push", "b");
8989 emitcode ("push", "acc");
8991 emitcode ("lcall", "__gptrget");
8993 emitcode ("pop", "b");
8998 /*-----------------------------------------------------------------*/
8999 /* emitPtrByteSet - emits code to set a byte from src through a */
9000 /* pointer register (R0, R1, or DPTR). */
9001 /*-----------------------------------------------------------------*/
9003 emitPtrByteSet (char *rname, int p_type, char *src)
9012 emitcode ("mov", "@%s,a", rname);
9015 emitcode ("mov", "@%s,%s", rname, src);
9020 emitcode ("movx", "@%s,a", rname);
9025 emitcode ("movx", "@dptr,a");
9030 emitcode ("lcall", "__gptrput");
9035 /*-----------------------------------------------------------------*/
9036 /* genUnpackBits - generates code for unpacking bits */
9037 /*-----------------------------------------------------------------*/
9039 genUnpackBits (operand * result, char *rname, int ptype)
9041 int offset = 0; /* result byte offset */
9042 int rsize; /* result size */
9043 int rlen = 0; /* remaining bitfield length */
9044 sym_link *etype; /* bitfield type information */
9045 int blen; /* bitfield length */
9046 int bstr; /* bitfield starting bit within byte */
9048 D(emitcode ("; genUnpackBits",""));
9050 etype = getSpec (operandType (result));
9051 rsize = getSize (operandType (result));
9052 blen = SPEC_BLEN (etype);
9053 bstr = SPEC_BSTR (etype);
9055 /* If the bitfield length is less than a byte */
9058 emitPtrByteGet (rname, ptype, FALSE);
9060 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
9061 aopPut (AOP (result), "a", offset++);
9065 /* Bit field did not fit in a byte. Copy all
9066 but the partial byte at the end. */
9067 for (rlen=blen;rlen>=8;rlen-=8)
9069 emitPtrByteGet (rname, ptype, FALSE);
9070 aopPut (AOP (result), "a", offset++);
9072 emitcode ("inc", "%s", rname);
9075 /* Handle the partial byte at the end */
9078 emitPtrByteGet (rname, ptype, FALSE);
9079 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
9080 aopPut (AOP (result), "a", offset++);
9088 aopPut (AOP (result), zero, offset++);
9093 /*-----------------------------------------------------------------*/
9094 /* genDataPointerGet - generates code when ptr offset is known */
9095 /*-----------------------------------------------------------------*/
9097 genDataPointerGet (operand * left,
9103 int size, offset = 0;
9104 aopOp (result, ic, TRUE, FALSE);
9106 /* get the string representation of the name */
9107 l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9108 size = AOP_SIZE (result);
9109 _startLazyDPSEvaluation ();
9114 SNPRINTF (buff, sizeof(buff),
9115 "(%s + %d)", l + 1, offset);
9119 SNPRINTF (buff, sizeof(buff),
9122 aopPut (AOP (result), buff, offset++);
9124 _endLazyDPSEvaluation ();
9126 freeAsmop (left, NULL, ic, TRUE);
9127 freeAsmop (result, NULL, ic, TRUE);
9130 /*-----------------------------------------------------------------*/
9131 /* genNearPointerGet - emitcode for near pointer fetch */
9132 /*-----------------------------------------------------------------*/
9134 genNearPointerGet (operand * left,
9142 sym_link *rtype, *retype, *letype;
9143 sym_link *ltype = operandType (left);
9146 rtype = operandType (result);
9147 retype = getSpec (rtype);
9148 letype = getSpec (ltype);
9150 aopOp (left, ic, FALSE, FALSE);
9152 /* if left is rematerialisable and
9153 result is not bit variable type and
9154 the left is pointer to data space i.e
9155 lower 128 bytes of space */
9156 if (AOP_TYPE (left) == AOP_IMMD &&
9157 !IS_BITVAR (retype) &&
9158 !IS_BITVAR (letype) &&
9159 DCL_TYPE (ltype) == POINTER)
9161 genDataPointerGet (left, result, ic);
9165 /* if the value is already in a pointer register
9166 then don't need anything more */
9167 if (!AOP_INPREG (AOP (left)))
9169 /* otherwise get a free pointer register */
9171 preg = getFreePtr (ic, &aop, FALSE);
9172 emitcode ("mov", "%s,%s",
9174 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9178 rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9180 freeAsmop (left, NULL, ic, TRUE);
9181 aopOp (result, ic, FALSE, FALSE);
9183 /* if bitfield then unpack the bits */
9184 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9185 genUnpackBits (result, rname, POINTER);
9188 /* we have can just get the values */
9189 int size = AOP_SIZE (result);
9194 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9197 emitcode ("mov", "a,@%s", rname);
9198 aopPut (AOP (result), "a", offset);
9202 SNPRINTF (buff, sizeof(buff), "@%s", rname);
9203 aopPut (AOP (result), buff, offset);
9208 emitcode ("inc", "%s", rname);
9213 /* now some housekeeping stuff */
9216 /* we had to allocate for this iCode */
9217 if (pi) { /* post increment present */
9218 aopPut(AOP ( left ),rname,0);
9220 freeAsmop (NULL, aop, ic, TRUE);
9224 /* we did not allocate which means left
9225 already in a pointer register, then
9226 if size > 0 && this could be used again
9227 we have to point it back to where it
9229 if (AOP_SIZE (result) > 1 &&
9230 !OP_SYMBOL (left)->remat &&
9231 (OP_SYMBOL (left)->liveTo > ic->seq ||
9235 int size = AOP_SIZE (result) - 1;
9237 emitcode ("dec", "%s", rname);
9242 freeAsmop (result, NULL, ic, TRUE);
9243 if (pi) pi->generated = 1;
9246 /*-----------------------------------------------------------------*/
9247 /* genPagedPointerGet - emitcode for paged pointer fetch */
9248 /*-----------------------------------------------------------------*/
9250 genPagedPointerGet (operand * left,
9258 sym_link *rtype, *retype, *letype;
9260 rtype = operandType (result);
9261 retype = getSpec (rtype);
9262 letype = getSpec (operandType (left));
9263 aopOp (left, ic, FALSE, FALSE);
9265 /* if the value is already in a pointer register
9266 then don't need anything more */
9267 if (!AOP_INPREG (AOP (left)))
9269 /* otherwise get a free pointer register */
9271 preg = getFreePtr (ic, &aop, FALSE);
9272 emitcode ("mov", "%s,%s",
9274 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9278 rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9280 freeAsmop (left, NULL, ic, TRUE);
9281 aopOp (result, ic, FALSE, FALSE);
9283 /* if bitfield then unpack the bits */
9284 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9285 genUnpackBits (result, rname, PPOINTER);
9288 /* we have can just get the values */
9289 int size = AOP_SIZE (result);
9295 emitcode ("movx", "a,@%s", rname);
9296 aopPut (AOP (result), "a", offset);
9301 emitcode ("inc", "%s", rname);
9305 /* now some housekeeping stuff */
9308 /* we had to allocate for this iCode */
9309 if (pi) aopPut ( AOP (left), rname, 0);
9310 freeAsmop (NULL, aop, ic, TRUE);
9314 /* we did not allocate which means left
9315 already in a pointer register, then
9316 if size > 0 && this could be used again
9317 we have to point it back to where it
9319 if (AOP_SIZE (result) > 1 &&
9320 !OP_SYMBOL (left)->remat &&
9321 (OP_SYMBOL (left)->liveTo > ic->seq ||
9325 int size = AOP_SIZE (result) - 1;
9327 emitcode ("dec", "%s", rname);
9332 freeAsmop (result, NULL, ic, TRUE);
9333 if (pi) pi->generated = 1;
9336 /*-----------------------------------------------------------------*/
9337 /* genFarPointerGet - gget value from far space */
9338 /*-----------------------------------------------------------------*/
9340 genFarPointerGet (operand * left,
9341 operand * result, iCode * ic, iCode *pi)
9343 int size, offset, dopi=1;
9344 sym_link *retype = getSpec (operandType (result));
9345 sym_link *letype = getSpec (operandType (left));
9346 D (emitcode (";", "genFarPointerGet"););
9348 aopOp (left, ic, FALSE, FALSE);
9350 /* if the operand is already in dptr
9351 then we do nothing else we move the value to dptr */
9352 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9354 /* if this is remateriazable */
9355 if (AOP_TYPE (left) == AOP_IMMD)
9357 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9361 /* we need to get it byte by byte */
9362 _startLazyDPSEvaluation ();
9363 if (AOP_TYPE (left) != AOP_DPTR)
9365 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9366 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9367 if (options.model == MODEL_FLAT24)
9368 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9372 /* We need to generate a load to DPTR indirect through DPTR. */
9373 D (emitcode (";", "genFarPointerGet -- indirection special case."););
9374 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9375 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9376 if (options.model == MODEL_FLAT24)
9377 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9378 emitcode ("pop", "dph");
9379 emitcode ("pop", "dpl");
9382 _endLazyDPSEvaluation ();
9385 /* so dptr know contains the address */
9386 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9388 /* if bit then unpack */
9389 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9390 if (AOP_INDPTRn(left)) {
9391 genSetDPTR(AOP(left)->aopu.dptr);
9393 genUnpackBits (result, "dptr", FPOINTER);
9394 if (AOP_INDPTRn(left)) {
9399 size = AOP_SIZE (result);
9402 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9404 genSetDPTR(AOP(left)->aopu.dptr);
9405 emitcode ("movx", "a,@dptr");
9406 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9407 emitcode ("inc", "dptr");
9409 aopPut (AOP (result), "a", offset++);
9412 _startLazyDPSEvaluation ();
9414 if (AOP_INDPTRn(left)) {
9415 genSetDPTR(AOP(left)->aopu.dptr);
9421 emitcode ("movx", "a,@dptr");
9422 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9423 emitcode ("inc", "dptr");
9425 aopPut (AOP (result), "a", offset++);
9427 _endLazyDPSEvaluation ();
9430 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9431 if (!AOP_INDPTRn(left)) {
9432 _startLazyDPSEvaluation ();
9433 aopPut ( AOP (left), "dpl", 0);
9434 aopPut ( AOP (left), "dph", 1);
9435 if (options.model == MODEL_FLAT24)
9436 aopPut ( AOP (left), "dpx", 2);
9437 _endLazyDPSEvaluation ();
9440 } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) &&
9441 AOP_SIZE(result) > 1 &&
9443 (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
9445 size = AOP_SIZE (result) - 1;
9446 if (AOP_INDPTRn(left)) {
9447 genSetDPTR(AOP(left)->aopu.dptr);
9449 while (size--) emitcode ("lcall","__decdptr");
9450 if (AOP_INDPTRn(left)) {
9455 freeAsmop (left, NULL, ic, TRUE);
9456 freeAsmop (result, NULL, ic, TRUE);
9459 /*-----------------------------------------------------------------*/
9460 /* genCodePointerGet - get value from code space */
9461 /*-----------------------------------------------------------------*/
9463 genCodePointerGet (operand * left,
9464 operand * result, iCode * ic, iCode *pi)
9466 int size, offset, dopi=1;
9467 sym_link *retype = getSpec (operandType (result));
9469 aopOp (left, ic, FALSE, FALSE);
9471 /* if the operand is already in dptr
9472 then we do nothing else we move the value to dptr */
9473 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
9475 /* if this is remateriazable */
9476 if (AOP_TYPE (left) == AOP_IMMD)
9478 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9481 { /* we need to get it byte by byte */
9482 _startLazyDPSEvaluation ();
9483 if (AOP_TYPE (left) != AOP_DPTR)
9485 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9486 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9487 if (options.model == MODEL_FLAT24)
9488 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9492 /* We need to generate a load to DPTR indirect through DPTR. */
9493 D (emitcode (";", "gencodePointerGet -- indirection special case."););
9494 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9495 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9496 if (options.model == MODEL_FLAT24)
9497 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9498 emitcode ("pop", "dph");
9499 emitcode ("pop", "dpl");
9502 _endLazyDPSEvaluation ();
9505 /* so dptr know contains the address */
9506 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9508 /* if bit then unpack */
9509 if (IS_BITVAR (retype)) {
9510 if (AOP_INDPTRn(left)) {
9511 genSetDPTR(AOP(left)->aopu.dptr);
9513 genUnpackBits (result, "dptr", CPOINTER);
9514 if (AOP_INDPTRn(left)) {
9519 size = AOP_SIZE (result);
9521 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9523 genSetDPTR(AOP(left)->aopu.dptr);
9524 emitcode ("clr", "a");
9525 emitcode ("movc", "a,@a+dptr");
9526 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9527 emitcode ("inc", "dptr");
9529 aopPut (AOP (result), "a", offset++);
9532 _startLazyDPSEvaluation ();
9535 if (AOP_INDPTRn(left)) {
9536 genSetDPTR(AOP(left)->aopu.dptr);
9542 emitcode ("clr", "a");
9543 emitcode ("movc", "a,@a+dptr");
9544 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9545 emitcode ("inc", "dptr");
9546 aopPut (AOP (result), "a", offset++);
9548 _endLazyDPSEvaluation ();
9551 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9552 if (!AOP_INDPTRn(left)) {
9553 _startLazyDPSEvaluation ();
9555 aopPut ( AOP (left), "dpl", 0);
9556 aopPut ( AOP (left), "dph", 1);
9557 if (options.model == MODEL_FLAT24)
9558 aopPut ( AOP (left), "dpx", 2);
9560 _endLazyDPSEvaluation ();
9563 } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
9564 AOP_SIZE(result) > 1 &&
9565 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9567 size = AOP_SIZE (result) - 1;
9568 if (AOP_INDPTRn(left)) {
9569 genSetDPTR(AOP(left)->aopu.dptr);
9571 while (size--) emitcode ("lcall","__decdptr");
9572 if (AOP_INDPTRn(left)) {
9577 freeAsmop (left, NULL, ic, TRUE);
9578 freeAsmop (result, NULL, ic, TRUE);
9581 /*-----------------------------------------------------------------*/
9582 /* genGenPointerGet - gget value from generic pointer space */
9583 /*-----------------------------------------------------------------*/
9585 genGenPointerGet (operand * left,
9586 operand * result, iCode * ic, iCode * pi)
9589 sym_link *retype = getSpec (operandType (result));
9590 sym_link *letype = getSpec (operandType (left));
9592 D (emitcode (";", "genGenPointerGet "); );
9594 aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
9596 /* if the operand is already in dptr
9597 then we do nothing else we move the value to dptr */
9598 if (AOP_TYPE (left) != AOP_STR)
9600 /* if this is remateriazable */
9601 if (AOP_TYPE (left) == AOP_IMMD)
9603 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9604 if (AOP(left)->aopu.aop_immd.from_cast_remat)
9606 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
9610 emitcode ("mov", "b,#%d", pointerCode (retype));
9614 { /* we need to get it byte by byte */
9615 _startLazyDPSEvaluation ();
9616 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
9617 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
9618 if (options.model == MODEL_FLAT24) {
9619 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9620 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
9622 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9624 _endLazyDPSEvaluation ();
9628 /* so dptr-b now contains the address */
9630 aopOp (result, ic, FALSE, TRUE);
9633 /* if bit then unpack */
9634 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9636 genUnpackBits (result, "dptr", GPOINTER);
9640 size = AOP_SIZE (result);
9647 // Get two bytes at a time, results in _AP & A.
9648 // dptr will be incremented ONCE by __gptrgetWord.
9650 // Note: any change here must be coordinated
9651 // with the implementation of __gptrgetWord
9652 // in device/lib/_gptrget.c
9653 emitcode ("lcall", "__gptrgetWord");
9654 aopPut (AOP (result), DP2_RESULT_REG, offset++);
9655 aopPut (AOP (result), "a", offset++);
9660 // Only one byte to get.
9661 emitcode ("lcall", "__gptrget");
9662 aopPut (AOP (result), "a", offset++);
9665 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9667 emitcode ("inc", "dptr");
9672 if (pi && AOP_TYPE (left) != AOP_IMMD) {
9673 _startLazyDPSEvaluation ();
9675 aopPut ( AOP (left), "dpl", 0);
9676 aopPut ( AOP (left), "dph", 1);
9677 if (options.model == MODEL_FLAT24) {
9678 aopPut ( AOP (left), "dpx", 2);
9679 aopPut ( AOP (left), "b", 3);
9680 } else aopPut ( AOP (left), "b", 2);
9682 _endLazyDPSEvaluation ();
9685 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9686 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9688 size = AOP_SIZE (result) - 1;
9689 while (size--) emitcode ("lcall","__decdptr");
9692 freeAsmop (left, NULL, ic, TRUE);
9693 freeAsmop (result, NULL, ic, TRUE);
9696 /*-----------------------------------------------------------------*/
9697 /* genPointerGet - generate code for pointer get */
9698 /*-----------------------------------------------------------------*/
9700 genPointerGet (iCode * ic, iCode *pi)
9702 operand *left, *result;
9703 sym_link *type, *etype;
9706 D (emitcode (";", "genPointerGet ");
9709 left = IC_LEFT (ic);
9710 result = IC_RESULT (ic);
9712 /* depending on the type of pointer we need to
9713 move it to the correct pointer register */
9714 type = operandType (left);
9715 etype = getSpec (type);
9716 /* if left is of type of pointer then it is simple */
9717 if (IS_PTR (type) && !IS_FUNC (type->next))
9718 p_type = DCL_TYPE (type);
9721 /* we have to go by the storage class */
9722 p_type = PTR_TYPE (SPEC_OCLS (etype));
9724 /* special case when cast remat */
9725 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9726 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9727 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9728 type = operandType (left);
9729 p_type = DCL_TYPE (type);
9731 /* now that we have the pointer type we assign
9732 the pointer values */
9738 genNearPointerGet (left, result, ic, pi);
9742 genPagedPointerGet (left, result, ic, pi);
9746 genFarPointerGet (left, result, ic, pi);
9750 genCodePointerGet (left, result, ic, pi);
9754 genGenPointerGet (left, result, ic, pi);
9760 /*-----------------------------------------------------------------*/
9761 /* genPackBits - generates code for packed bit storage */
9762 /*-----------------------------------------------------------------*/
9764 genPackBits (sym_link * etype,
9766 char *rname, int p_type)
9768 int offset = 0; /* source byte offset */
9769 int rlen = 0; /* remaining bitfield length */
9770 int blen; /* bitfield length */
9771 int bstr; /* bitfield starting bit within byte */
9772 int litval; /* source literal value (if AOP_LIT) */
9773 unsigned char mask; /* bitmask within current byte */
9775 D(emitcode ("; genPackBits",""));
9777 blen = SPEC_BLEN (etype);
9778 bstr = SPEC_BSTR (etype);
9780 /* If the bitfield length is less than a byte */
9783 mask = ((unsigned char) (0xFF << (blen + bstr)) |
9784 (unsigned char) (0xFF >> (8 - bstr)));
9786 if (AOP_TYPE (right) == AOP_LIT)
9788 /* Case with a bitfield length <8 and literal source
9790 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9792 litval &= (~mask) & 0xff;
9793 emitPtrByteGet (rname, p_type, FALSE);
9794 if ((mask|litval)!=0xff)
9795 emitcode ("anl","a,#!constbyte", mask);
9797 emitcode ("orl","a,#!constbyte", litval);
9801 if ((blen==1) && (p_type!=GPOINTER))
9803 /* Case with a bitfield length == 1 and no generic pointer
9805 if (AOP_TYPE (right) == AOP_CRY)
9806 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9809 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
9810 emitcode ("rrc","a");
9812 emitPtrByteGet (rname, p_type, FALSE);
9813 emitcode ("mov","acc.%d,c",bstr);
9817 /* Case with a bitfield length < 8 and arbitrary source
9819 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
9820 /* shift and mask source value */
9822 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
9824 /* transfer A to B and get next byte */
9825 emitPtrByteGet (rname, p_type, TRUE);
9827 emitcode ("anl", "a,#!constbyte", mask);
9828 emitcode ("orl", "a,b");
9829 if (p_type == GPOINTER)
9830 emitcode ("pop", "b");
9834 emitPtrByteSet (rname, p_type, "a");
9838 /* Bit length is greater than 7 bits. In this case, copy */
9839 /* all except the partial byte at the end */
9840 for (rlen=blen;rlen>=8;rlen-=8)
9842 emitPtrByteSet (rname, p_type,
9843 aopGet (AOP (right), offset++, FALSE, TRUE, NULL) );
9845 emitcode ("inc", "%s", rname);
9848 /* If there was a partial byte at the end */
9851 mask = (((unsigned char) -1 << rlen) & 0xff);
9853 if (AOP_TYPE (right) == AOP_LIT)
9855 /* Case with partial byte and literal source
9857 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9858 litval >>= (blen-rlen);
9859 litval &= (~mask) & 0xff;
9860 emitPtrByteGet (rname, p_type, FALSE);
9861 if ((mask|litval)!=0xff)
9862 emitcode ("anl","a,#!constbyte", mask);
9864 emitcode ("orl","a,#!constbyte", litval);
9868 /* Case with partial byte and arbitrary source
9870 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9871 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
9873 /* transfer A to B and get next byte */
9874 emitPtrByteGet (rname, p_type, TRUE);
9876 emitcode ("anl", "a,#!constbyte", mask);
9877 emitcode ("orl", "a,b");
9878 if (p_type == GPOINTER)
9879 emitcode ("pop", "b");
9881 emitPtrByteSet (rname, p_type, "a");
9887 /*-----------------------------------------------------------------*/
9888 /* genDataPointerSet - remat pointer to data space */
9889 /*-----------------------------------------------------------------*/
9891 genDataPointerSet (operand * right,
9895 int size, offset = 0;
9898 aopOp (right, ic, FALSE, FALSE);
9900 l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
9901 size = AOP_SIZE (right);
9906 SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
9910 SNPRINTF (buff, sizeof(buff), "%s", l + 1);
9913 emitcode ("mov", "%s,%s", buff,
9914 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9917 freeAsmop (right, NULL, ic, TRUE);
9918 freeAsmop (result, NULL, ic, TRUE);
9921 /*-----------------------------------------------------------------*/
9922 /* genNearPointerSet - emitcode for near pointer put */
9923 /*-----------------------------------------------------------------*/
9925 genNearPointerSet (operand * right,
9932 sym_link *retype, *letype;
9933 sym_link *ptype = operandType (result);
9935 retype = getSpec (operandType (right));
9936 letype = getSpec (ptype);
9938 aopOp (result, ic, FALSE, FALSE);
9940 /* if the result is rematerializable &
9941 in data space & not a bit variable */
9942 if (AOP_TYPE (result) == AOP_IMMD &&
9943 DCL_TYPE (ptype) == POINTER &&
9944 !IS_BITVAR (retype) &&
9945 !IS_BITVAR (letype))
9947 genDataPointerSet (right, result, ic);
9951 /* if the value is already in a pointer register
9952 then don't need anything more */
9953 if (!AOP_INPREG (AOP (result)))
9955 /* otherwise get a free pointer register */
9959 preg = getFreePtr (ic, &aop, FALSE);
9960 emitcode ("mov", "%s,%s",
9962 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
9966 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
9968 aopOp (right, ic, FALSE, FALSE);
9970 /* if bitfield then unpack the bits */
9971 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9972 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9975 /* we have can just get the values */
9976 int size = AOP_SIZE (right);
9981 l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
9985 emitcode ("mov", "@%s,a", rname);
9988 emitcode ("mov", "@%s,%s", rname, l);
9990 emitcode ("inc", "%s", rname);
9995 /* now some housekeeping stuff */
9998 /* we had to allocate for this iCode */
9999 if (pi) aopPut (AOP (result),rname,0);
10000 freeAsmop (NULL, aop, ic, TRUE);
10004 /* we did not allocate which means left
10005 already in a pointer register, then
10006 if size > 0 && this could be used again
10007 we have to point it back to where it
10009 if (AOP_SIZE (right) > 1 &&
10010 !OP_SYMBOL (result)->remat &&
10011 (OP_SYMBOL (result)->liveTo > ic->seq ||
10015 int size = AOP_SIZE (right) - 1;
10017 emitcode ("dec", "%s", rname);
10022 if (pi) pi->generated = 1;
10023 freeAsmop (result, NULL, ic, TRUE);
10024 freeAsmop (right, NULL, ic, TRUE);
10029 /*-----------------------------------------------------------------*/
10030 /* genPagedPointerSet - emitcode for Paged pointer put */
10031 /*-----------------------------------------------------------------*/
10033 genPagedPointerSet (operand * right,
10040 sym_link *retype, *letype;
10042 retype = getSpec (operandType (right));
10043 letype = getSpec (operandType (result));
10045 aopOp (result, ic, FALSE, FALSE);
10047 /* if the value is already in a pointer register
10048 then don't need anything more */
10049 if (!AOP_INPREG (AOP (result)))
10051 /* otherwise get a free pointer register */
10054 aop = newAsmop (0);
10055 preg = getFreePtr (ic, &aop, FALSE);
10056 emitcode ("mov", "%s,%s",
10058 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10059 rname = preg->name;
10062 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10064 aopOp (right, ic, FALSE, FALSE);
10066 /* if bitfield then unpack the bits */
10067 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10068 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
10071 /* we have can just get the values */
10072 int size = AOP_SIZE (right);
10077 MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10079 emitcode ("movx", "@%s,a", rname);
10082 emitcode ("inc", "%s", rname);
10088 /* now some housekeeping stuff */
10091 if (pi) aopPut (AOP (result),rname,0);
10092 /* we had to allocate for this iCode */
10093 freeAsmop (NULL, aop, ic, TRUE);
10097 /* we did not allocate which means left
10098 already in a pointer register, then
10099 if size > 0 && this could be used again
10100 we have to point it back to where it
10102 if (AOP_SIZE (right) > 1 &&
10103 !OP_SYMBOL (result)->remat &&
10104 (OP_SYMBOL (result)->liveTo > ic->seq ||
10108 int size = AOP_SIZE (right) - 1;
10110 emitcode ("dec", "%s", rname);
10115 if (pi) pi->generated = 1;
10116 freeAsmop (result, NULL, ic, TRUE);
10117 freeAsmop (right, NULL, ic, TRUE);
10122 /*-----------------------------------------------------------------*/
10123 /* genFarPointerSet - set value from far space */
10124 /*-----------------------------------------------------------------*/
10126 genFarPointerSet (operand * right,
10127 operand * result, iCode * ic, iCode *pi)
10129 int size, offset, dopi=1;
10130 sym_link *retype = getSpec (operandType (right));
10131 sym_link *letype = getSpec (operandType (result));
10133 aopOp (result, ic, FALSE, FALSE);
10135 /* if the operand is already in dptr
10136 then we do nothing else we move the value to dptr */
10137 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10139 /* if this is remateriazable */
10140 if (AOP_TYPE (result) == AOP_IMMD)
10141 emitcode ("mov", "dptr,%s",
10142 aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10145 /* we need to get it byte by byte */
10146 _startLazyDPSEvaluation ();
10147 if (AOP_TYPE (result) != AOP_DPTR)
10149 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10150 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10151 if (options.model == MODEL_FLAT24)
10152 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10156 /* We need to generate a load to DPTR indirect through DPTR. */
10157 D (emitcode (";", "genFarPointerSet -- indirection special case."););
10159 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10160 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10161 if (options.model == MODEL_FLAT24)
10162 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10163 emitcode ("pop", "dph");
10164 emitcode ("pop", "dpl");
10167 _endLazyDPSEvaluation ();
10170 /* so dptr know contains the address */
10171 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10173 /* if bit then unpack */
10174 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
10175 if (AOP_INDPTRn(result)) {
10176 genSetDPTR(AOP(result)->aopu.dptr);
10178 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
10179 if (AOP_INDPTRn(result)) {
10183 size = AOP_SIZE (right);
10185 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10187 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10189 genSetDPTR(AOP(result)->aopu.dptr);
10190 emitcode ("movx", "@dptr,a");
10191 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10192 emitcode ("inc", "dptr");
10196 _startLazyDPSEvaluation ();
10198 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10200 if (AOP_INDPTRn(result)) {
10201 genSetDPTR(AOP(result)->aopu.dptr);
10207 emitcode ("movx", "@dptr,a");
10208 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10209 emitcode ("inc", "dptr");
10211 _endLazyDPSEvaluation ();
10215 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10216 if (!AOP_INDPTRn(result)) {
10217 _startLazyDPSEvaluation ();
10219 aopPut (AOP(result),"dpl",0);
10220 aopPut (AOP(result),"dph",1);
10221 if (options.model == MODEL_FLAT24)
10222 aopPut (AOP(result),"dpx",2);
10224 _endLazyDPSEvaluation ();
10227 } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
10228 AOP_SIZE(right) > 1 &&
10229 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10231 size = AOP_SIZE (right) - 1;
10232 if (AOP_INDPTRn(result)) {
10233 genSetDPTR(AOP(result)->aopu.dptr);
10235 while (size--) emitcode ("lcall","__decdptr");
10236 if (AOP_INDPTRn(result)) {
10240 freeAsmop (result, NULL, ic, TRUE);
10241 freeAsmop (right, NULL, ic, TRUE);
10244 /*-----------------------------------------------------------------*/
10245 /* genGenPointerSet - set value from generic pointer space */
10246 /*-----------------------------------------------------------------*/
10248 genGenPointerSet (operand * right,
10249 operand * result, iCode * ic, iCode *pi)
10252 sym_link *retype = getSpec (operandType (right));
10253 sym_link *letype = getSpec (operandType (result));
10255 aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10257 /* if the operand is already in dptr
10258 then we do nothing else we move the value to dptr */
10259 if (AOP_TYPE (result) != AOP_STR)
10261 _startLazyDPSEvaluation ();
10262 /* if this is remateriazable */
10263 if (AOP_TYPE (result) == AOP_IMMD)
10265 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10266 if (AOP(result)->aopu.aop_immd.from_cast_remat)
10268 MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10273 "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10277 { /* we need to get it byte by byte */
10278 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10279 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10280 if (options.model == MODEL_FLAT24) {
10281 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10282 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10284 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10287 _endLazyDPSEvaluation ();
10289 /* so dptr + b now contains the address */
10291 aopOp (right, ic, FALSE, TRUE);
10295 /* if bit then unpack */
10296 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10298 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
10302 size = AOP_SIZE (right);
10305 _startLazyDPSEvaluation ();
10310 // Set two bytes at a time, passed in _AP & A.
10311 // dptr will be incremented ONCE by __gptrputWord.
10313 // Note: any change here must be coordinated
10314 // with the implementation of __gptrputWord
10315 // in device/lib/_gptrput.c
10316 emitcode("mov", "_ap, %s",
10317 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10318 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10322 emitcode ("lcall", "__gptrputWord");
10327 // Only one byte to put.
10328 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10332 emitcode ("lcall", "__gptrput");
10335 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10337 emitcode ("inc", "dptr");
10340 _endLazyDPSEvaluation ();
10343 if (pi && AOP_TYPE (result) != AOP_IMMD) {
10344 _startLazyDPSEvaluation ();
10346 aopPut (AOP(result),"dpl",0);
10347 aopPut (AOP(result),"dph",1);
10348 if (options.model == MODEL_FLAT24) {
10349 aopPut (AOP(result),"dpx",2);
10350 aopPut (AOP(result),"b",3);
10352 aopPut (AOP(result),"b",2);
10354 _endLazyDPSEvaluation ();
10357 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10358 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10360 size = AOP_SIZE (right) - 1;
10361 while (size--) emitcode ("lcall","__decdptr");
10363 freeAsmop (result, NULL, ic, TRUE);
10364 freeAsmop (right, NULL, ic, TRUE);
10367 /*-----------------------------------------------------------------*/
10368 /* genPointerSet - stores the value into a pointer location */
10369 /*-----------------------------------------------------------------*/
10371 genPointerSet (iCode * ic, iCode *pi)
10373 operand *right, *result;
10374 sym_link *type, *etype;
10377 D (emitcode (";", "genPointerSet "););
10379 right = IC_RIGHT (ic);
10380 result = IC_RESULT (ic);
10382 /* depending on the type of pointer we need to
10383 move it to the correct pointer register */
10384 type = operandType (result);
10385 etype = getSpec (type);
10386 /* if left is of type of pointer then it is simple */
10387 if (IS_PTR (type) && !IS_FUNC (type->next))
10389 p_type = DCL_TYPE (type);
10393 /* we have to go by the storage class */
10394 p_type = PTR_TYPE (SPEC_OCLS (etype));
10396 /* special case when cast remat */
10397 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10398 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10399 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10400 type = operandType (result);
10401 p_type = DCL_TYPE (type);
10404 /* now that we have the pointer type we assign
10405 the pointer values */
10411 genNearPointerSet (right, result, ic, pi);
10415 genPagedPointerSet (right, result, ic, pi);
10419 genFarPointerSet (right, result, ic, pi);
10423 genGenPointerSet (right, result, ic, pi);
10427 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10428 "genPointerSet: illegal pointer type");
10433 /*-----------------------------------------------------------------*/
10434 /* genIfx - generate code for Ifx statement */
10435 /*-----------------------------------------------------------------*/
10437 genIfx (iCode * ic, iCode * popIc)
10439 operand *cond = IC_COND (ic);
10442 D (emitcode (";", "genIfx "););
10444 aopOp (cond, ic, FALSE, FALSE);
10446 /* get the value into acc */
10447 if (AOP_TYPE (cond) != AOP_CRY)
10456 /* the result is now in the accumulator */
10457 freeAsmop (cond, NULL, ic, TRUE);
10459 /* if there was something to be popped then do it */
10463 /* if the condition is a bit variable */
10464 if (isbit && IS_ITEMP (cond) &&
10467 genIfxJump (ic, SPIL_LOC (cond)->rname);
10469 else if (isbit && !IS_ITEMP (cond))
10471 genIfxJump (ic, OP_SYMBOL (cond)->rname);
10475 genIfxJump (ic, "a");
10481 /*-----------------------------------------------------------------*/
10482 /* genAddrOf - generates code for address of */
10483 /*-----------------------------------------------------------------*/
10485 genAddrOf (iCode * ic)
10487 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10490 D (emitcode (";", "genAddrOf ");
10493 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10495 /* if the operand is on the stack then we
10496 need to get the stack offset of this
10498 if (sym->onStack) {
10500 /* if 10 bit stack */
10501 if (options.stack10bit) {
10505 tsprintf(buff, sizeof(buff),
10506 "#!constbyte",(options.stack_loc >> 16) & 0xff);
10507 /* if it has an offset then we need to compute it */
10508 /* emitcode ("subb", "a,#!constbyte", */
10509 /* -((sym->stack < 0) ? */
10510 /* ((short) (sym->stack - _G.nRegsSaved)) : */
10511 /* ((short) sym->stack)) & 0xff); */
10512 /* emitcode ("mov","b,a"); */
10513 /* emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
10514 /* ((short) (sym->stack - _G.nRegsSaved)) : */
10515 /* ((short) sym->stack)) >> 8) & 0xff); */
10517 emitcode ("mov", "a,_bpx");
10518 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
10519 ((char) (sym->stack - _G.nRegsSaved)) :
10520 ((char) sym->stack )) & 0xff);
10521 emitcode ("mov", "b,a");
10522 emitcode ("mov", "a,_bpx+1");
10524 offset = (((sym->stack < 0) ?
10525 ((short) (sym->stack - _G.nRegsSaved)) :
10526 ((short) sym->stack )) >> 8) & 0xff;
10528 emitcode ("addc","a,#!constbyte", offset);
10530 aopPut (AOP (IC_RESULT (ic)), "b", 0);
10531 aopPut (AOP (IC_RESULT (ic)), "a", 1);
10532 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10534 /* we can just move _bp */
10535 aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10536 aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10537 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10540 /* if it has an offset then we need to compute it */
10542 emitcode ("mov", "a,_bp");
10543 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10544 aopPut (AOP (IC_RESULT (ic)), "a", 0);
10546 /* we can just move _bp */
10547 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10549 /* fill the result with zero */
10550 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10553 if (options.stack10bit && size < (FPTRSIZE - 1)) {
10555 "*** warning: pointer to stack var truncated.\n");
10560 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10566 /* object not on stack then we need the name */
10567 size = AOP_SIZE (IC_RESULT (ic));
10572 char s[SDCC_NAME_MAX];
10576 tsprintf(s, sizeof(s), "#!his",sym->rname);
10579 tsprintf(s, sizeof(s), "#!hihis",sym->rname);
10582 tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
10584 default: /* should not need this (just in case) */
10585 SNPRINTF (s, sizeof(s), "#(%s >> %d)",
10592 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10595 aopPut (AOP (IC_RESULT (ic)), s, offset++);
10599 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10603 #if 0 // obsolete, and buggy for != xdata
10604 /*-----------------------------------------------------------------*/
10605 /* genArrayInit - generates code for address of */
10606 /*-----------------------------------------------------------------*/
10608 genArrayInit (iCode * ic)
10610 literalList *iLoop;
10612 int elementSize = 0, eIndex;
10613 unsigned val, lastVal;
10615 operand *left=IC_LEFT(ic);
10617 D (emitcode (";", "genArrayInit "););
10619 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10621 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10623 // Load immediate value into DPTR.
10624 emitcode("mov", "dptr, %s",
10625 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
10627 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10630 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10631 "Unexpected operand to genArrayInit.\n");
10634 // a regression because of SDCCcse.c:1.52
10635 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10636 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10637 if (options.model == MODEL_FLAT24)
10638 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10642 type = operandType(IC_LEFT(ic));
10644 if (type && type->next)
10646 elementSize = getSize(type->next);
10650 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10651 "can't determine element size in genArrayInit.\n");
10655 iLoop = IC_ARRAYILIST(ic);
10660 bool firstpass = TRUE;
10662 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
10663 iLoop->count, (int)iLoop->literalValue, elementSize);
10669 symbol *tlbl = NULL;
10671 count = ix > 256 ? 256 : ix;
10675 tlbl = newiTempLabel (NULL);
10676 if (firstpass || (count & 0xff))
10678 emitcode("mov", "b, #!constbyte", count & 0xff);
10681 emitcode ("", "!tlabeldef", tlbl->key + 100);
10686 for (eIndex = 0; eIndex < elementSize; eIndex++)
10688 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10689 if (val != lastVal)
10691 emitcode("mov", "a, #!constbyte", val);
10695 emitcode("movx", "@dptr, a");
10696 emitcode("inc", "dptr");
10701 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10707 iLoop = iLoop->next;
10710 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10714 /*-----------------------------------------------------------------*/
10715 /* genFarFarAssign - assignment when both are in far space */
10716 /*-----------------------------------------------------------------*/
10718 genFarFarAssign (operand * result, operand * right, iCode * ic)
10720 int size = AOP_SIZE (right);
10722 symbol *rSym = NULL;
10726 /* quick & easy case. */
10727 D(emitcode(";","genFarFarAssign (1 byte case)"););
10728 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
10729 freeAsmop (right, NULL, ic, FALSE);
10730 /* now assign DPTR to result */
10732 aopOp(result, ic, FALSE, FALSE);
10734 aopPut(AOP(result), "a", 0);
10735 freeAsmop(result, NULL, ic, FALSE);
10739 /* See if we've got an underlying symbol to abuse. */
10740 if (IS_SYMOP(result) && OP_SYMBOL(result))
10742 if (IS_TRUE_SYMOP(result))
10744 rSym = OP_SYMBOL(result);
10746 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10748 rSym = OP_SYMBOL(result)->usl.spillLoc;
10752 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10754 /* We can use the '390 auto-toggle feature to good effect here. */
10756 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10757 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
10758 emitcode ("mov", "dptr,#%s", rSym->rname);
10759 /* DP2 = result, DP1 = right, DP1 is current. */
10762 emitcode("movx", "a,@dptr");
10763 emitcode("movx", "@dptr,a");
10766 emitcode("inc", "dptr");
10767 emitcode("inc", "dptr");
10770 emitcode("mov", "dps,#0");
10771 freeAsmop (right, NULL, ic, FALSE);
10773 some alternative code for processors without auto-toggle
10774 no time to test now, so later well put in...kpb
10775 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10776 emitcode("mov", "dps,#1"); /* Select DPTR2. */
10777 emitcode ("mov", "dptr,#%s", rSym->rname);
10778 /* DP2 = result, DP1 = right, DP1 is current. */
10782 emitcode("movx", "a,@dptr");
10784 emitcode("inc", "dptr");
10785 emitcode("inc", "dps");
10786 emitcode("movx", "@dptr,a");
10788 emitcode("inc", "dptr");
10789 emitcode("inc", "dps");
10791 emitcode("mov", "dps,#0");
10792 freeAsmop (right, NULL, ic, FALSE);
10797 D (emitcode (";", "genFarFarAssign"););
10798 aopOp (result, ic, TRUE, TRUE);
10800 _startLazyDPSEvaluation ();
10804 aopPut (AOP (result),
10805 aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
10808 _endLazyDPSEvaluation ();
10809 freeAsmop (result, NULL, ic, FALSE);
10810 freeAsmop (right, NULL, ic, FALSE);
10814 /*-----------------------------------------------------------------*/
10815 /* genAssign - generate code for assignment */
10816 /*-----------------------------------------------------------------*/
10818 genAssign (iCode * ic)
10820 operand *result, *right;
10822 unsigned long lit = 0L;
10824 D (emitcode (";", "genAssign ");
10827 result = IC_RESULT (ic);
10828 right = IC_RIGHT (ic);
10830 /* if they are the same */
10831 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10834 aopOp (right, ic, FALSE, FALSE);
10836 emitcode (";", "genAssign: resultIsFar = %s",
10837 isOperandInFarSpace (result) ?
10840 /* special case both in far space */
10841 if ((AOP_TYPE (right) == AOP_DPTR ||
10842 AOP_TYPE (right) == AOP_DPTR2) &&
10843 /* IS_TRUE_SYMOP(result) && */
10844 isOperandInFarSpace (result))
10846 genFarFarAssign (result, right, ic);
10850 aopOp (result, ic, TRUE, FALSE);
10852 /* if they are the same registers */
10853 if (sameRegs (AOP (right), AOP (result)))
10856 /* if the result is a bit */
10857 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10859 /* if the right size is a literal then
10860 we know what the value is */
10861 if (AOP_TYPE (right) == AOP_LIT)
10863 if (((int) operandLitValue (right)))
10864 aopPut (AOP (result), one, 0);
10866 aopPut (AOP (result), zero, 0);
10870 /* the right is also a bit variable */
10871 if (AOP_TYPE (right) == AOP_CRY)
10873 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10874 aopPut (AOP (result), "c", 0);
10878 /* we need to or */
10880 aopPut (AOP (result), "a", 0);
10884 /* bit variables done */
10886 size = AOP_SIZE (result);
10888 if (AOP_TYPE (right) == AOP_LIT)
10889 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10892 (AOP_TYPE (result) != AOP_REG) &&
10893 (AOP_TYPE (right) == AOP_LIT) &&
10894 !IS_FLOAT (operandType (right)))
10896 _startLazyDPSEvaluation ();
10897 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10899 aopPut (AOP (result),
10900 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10905 /* And now fill the rest with zeros. */
10908 emitcode ("clr", "a");
10912 aopPut (AOP (result), "a", offset++);
10914 _endLazyDPSEvaluation ();
10918 _startLazyDPSEvaluation ();
10921 aopPut (AOP (result),
10922 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10926 _endLazyDPSEvaluation ();
10930 freeAsmop (right, NULL, ic, FALSE);
10931 freeAsmop (result, NULL, ic, TRUE);
10934 /*-----------------------------------------------------------------*/
10935 /* genJumpTab - generates code for jump table */
10936 /*-----------------------------------------------------------------*/
10938 genJumpTab (iCode * ic)
10943 D (emitcode (";", "genJumpTab ");
10946 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10947 /* get the condition into accumulator */
10948 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
10950 /* multiply by four! */
10951 emitcode ("add", "a,acc");
10952 emitcode ("add", "a,acc");
10953 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10955 jtab = newiTempLabel (NULL);
10956 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
10957 emitcode ("jmp", "@a+dptr");
10958 emitcode ("", "!tlabeldef", jtab->key + 100);
10959 /* now generate the jump labels */
10960 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10961 jtab = setNextItem (IC_JTLABELS (ic)))
10962 emitcode ("ljmp", "!tlabel", jtab->key + 100);
10966 /*-----------------------------------------------------------------*/
10967 /* genCast - gen code for casting */
10968 /*-----------------------------------------------------------------*/
10970 genCast (iCode * ic)
10972 operand *result = IC_RESULT (ic);
10973 sym_link *ctype = operandType (IC_LEFT (ic));
10974 sym_link *rtype = operandType (IC_RIGHT (ic));
10975 operand *right = IC_RIGHT (ic);
10978 D (emitcode (";", "genCast "););
10980 /* if they are equivalent then do nothing */
10981 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10984 aopOp (right, ic, FALSE, FALSE);
10985 aopOp (result, ic, FALSE, AOP_USESDPTR(right));
10987 /* if the result is a bit */
10988 if (IS_BITVAR (OP_SYMBOL (result)->type)
10989 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
10991 /* if the right size is a literal then
10992 we know what the value is */
10993 if (AOP_TYPE (right) == AOP_LIT)
10995 if (((int) operandLitValue (right)))
10996 aopPut (AOP (result), one, 0);
10998 aopPut (AOP (result), zero, 0);
11003 /* the right is also a bit variable */
11004 if (AOP_TYPE (right) == AOP_CRY)
11006 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11007 aopPut (AOP (result), "c", 0);
11011 /* we need to or */
11013 aopPut (AOP (result), "a", 0);
11017 /* if they are the same size : or less */
11018 if (AOP_SIZE (result) <= AOP_SIZE (right))
11021 /* if they are in the same place */
11022 if (sameRegs (AOP (right), AOP (result)))
11025 /* if they in different places then copy */
11026 size = AOP_SIZE (result);
11028 _startLazyDPSEvaluation ();
11031 aopPut (AOP (result),
11032 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11036 _endLazyDPSEvaluation ();
11041 /* if the result is of type pointer */
11042 if (IS_PTR (ctype))
11046 sym_link *type = operandType (right);
11048 /* pointer to generic pointer */
11049 if (IS_GENPTR (ctype))
11053 p_type = DCL_TYPE (type);
11057 #if OLD_CAST_BEHAVIOR
11058 /* KV: we are converting a non-pointer type to
11059 * a generic pointer. This (ifdef'd out) code
11060 * says that the resulting generic pointer
11061 * should have the same class as the storage
11062 * location of the non-pointer variable.
11064 * For example, converting an int (which happens
11065 * to be stored in DATA space) to a pointer results
11066 * in a DATA generic pointer; if the original int
11067 * in XDATA space, so will be the resulting pointer.
11069 * I don't like that behavior, and thus this change:
11070 * all such conversions will be forced to XDATA and
11071 * throw a warning. If you want some non-XDATA
11072 * type, or you want to suppress the warning, you
11073 * must go through an intermediate cast, like so:
11075 * char _generic *gp = (char _xdata *)(intVar);
11077 sym_link *etype = getSpec (type);
11079 /* we have to go by the storage class */
11080 if (SPEC_OCLS (etype) != generic)
11082 p_type = PTR_TYPE (SPEC_OCLS (etype));
11087 /* Converting unknown class (i.e. register variable)
11088 * to generic pointer. This is not good, but
11089 * we'll make a guess (and throw a warning).
11092 werror (W_INT_TO_GEN_PTR_CAST);
11096 /* the first two bytes are known */
11097 size = GPTRSIZE - 1;
11099 _startLazyDPSEvaluation ();
11102 aopPut (AOP (result),
11103 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11107 _endLazyDPSEvaluation ();
11109 /* the last byte depending on type */
11111 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11116 // pointerTypeToGPByte will have bitched.
11120 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11121 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11126 /* just copy the pointers */
11127 size = AOP_SIZE (result);
11129 _startLazyDPSEvaluation ();
11132 aopPut (AOP (result),
11133 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11137 _endLazyDPSEvaluation ();
11141 /* so we now know that the size of destination is greater
11142 than the size of the source */
11143 /* we move to result for the size of source */
11144 size = AOP_SIZE (right);
11146 _startLazyDPSEvaluation ();
11149 aopPut (AOP (result),
11150 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11154 _endLazyDPSEvaluation ();
11156 /* now depending on the sign of the source && destination */
11157 size = AOP_SIZE (result) - AOP_SIZE (right);
11158 /* if unsigned or not an integral type */
11159 /* also, if the source is a bit, we don't need to sign extend, because
11160 * it can't possibly have set the sign bit.
11162 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
11166 aopPut (AOP (result), zero, offset++);
11171 /* we need to extend the sign :{ */
11172 MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11173 FALSE, FALSE, NULL));
11174 emitcode ("rlc", "a");
11175 emitcode ("subb", "a,acc");
11177 aopPut (AOP (result), "a", offset++);
11180 /* we are done hurray !!!! */
11183 freeAsmop (right, NULL, ic, TRUE);
11184 freeAsmop (result, NULL, ic, TRUE);
11188 /*-----------------------------------------------------------------*/
11189 /* genDjnz - generate decrement & jump if not zero instrucion */
11190 /*-----------------------------------------------------------------*/
11192 genDjnz (iCode * ic, iCode * ifx)
11194 symbol *lbl, *lbl1;
11198 /* if the if condition has a false label
11199 then we cannot save */
11200 if (IC_FALSE (ifx))
11203 /* if the minus is not of the form
11205 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11206 !IS_OP_LITERAL (IC_RIGHT (ic)))
11209 if (operandLitValue (IC_RIGHT (ic)) != 1)
11212 /* if the size of this greater than one then no
11214 if (getSize (operandType (IC_RESULT (ic))) > 1)
11217 /* otherwise we can save BIG */
11218 D(emitcode(";", "genDjnz"););
11220 lbl = newiTempLabel (NULL);
11221 lbl1 = newiTempLabel (NULL);
11223 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11225 if (AOP_NEEDSACC(IC_RESULT(ic)))
11227 /* If the result is accessed indirectly via
11228 * the accumulator, we must explicitly write
11229 * it back after the decrement.
11231 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11233 if (strcmp(rByte, "a"))
11235 /* Something is hopelessly wrong */
11236 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11237 __FILE__, __LINE__);
11238 /* We can just give up; the generated code will be inefficient,
11239 * but what the hey.
11241 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11244 emitcode ("dec", "%s", rByte);
11245 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11246 emitcode ("jnz", "!tlabel", lbl->key + 100);
11248 else if (IS_AOP_PREG (IC_RESULT (ic)))
11250 emitcode ("dec", "%s",
11251 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11252 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11253 emitcode ("jnz", "!tlabel", lbl->key + 100);
11257 emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11260 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11261 emitcode ("", "!tlabeldef", lbl->key + 100);
11262 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11263 emitcode ("", "!tlabeldef", lbl1->key + 100);
11265 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11266 ifx->generated = 1;
11270 /*-----------------------------------------------------------------*/
11271 /* genReceive - generate code for a receive iCode */
11272 /*-----------------------------------------------------------------*/
11274 genReceive (iCode * ic)
11276 int size = getSize (operandType (IC_RESULT (ic)));
11280 D (emitcode (";", "genReceive "););
11282 if (ic->argreg == 1)
11284 /* first parameter */
11285 if (AOP_IS_STR(IC_RESULT(ic)))
11287 /* Nothing to do: it's already in the proper place. */
11294 useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11295 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11296 IS_TRUE_SYMOP (IC_RESULT (ic)));
11299 aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11302 /* Sanity checking... */
11303 if (AOP_USESDPTR(IC_RESULT(ic)))
11305 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11306 "genReceive got unexpected DPTR.");
11308 assignResultValue (IC_RESULT (ic));
11313 /* second receive onwards */
11314 /* this gets a little tricky since unused recevies will be
11315 eliminated, we have saved the reg in the type field . and
11316 we use that to figure out which register to use */
11317 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11318 rb1off = ic->argreg;
11321 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11324 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11327 /*-----------------------------------------------------------------*/
11328 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
11329 /*-----------------------------------------------------------------*/
11330 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11332 operand *from , *to , *count;
11337 /* we know it has to be 3 parameters */
11338 assert (nparms == 3);
11340 rsave = newBitVect(16);
11341 /* save DPTR if it needs to be saved */
11342 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11343 if (bitVectBitValue(ic->rMask,i))
11344 rsave = bitVectSetBit(rsave,i);
11346 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11347 ds390_rUmaskForOp (IC_RESULT(ic))));
11354 aopOp (from, ic->next, FALSE, FALSE);
11356 /* get from into DPTR1 */
11357 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11358 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11359 if (options.model == MODEL_FLAT24) {
11360 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11363 freeAsmop (from, NULL, ic, FALSE);
11364 aopOp (to, ic, FALSE, FALSE);
11365 /* get "to" into DPTR */
11366 /* if the operand is already in dptr
11367 then we do nothing else we move the value to dptr */
11368 if (AOP_TYPE (to) != AOP_STR) {
11369 /* if already in DPTR then we need to push */
11370 if (AOP_TYPE(to) == AOP_DPTR) {
11371 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11372 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11373 if (options.model == MODEL_FLAT24)
11374 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11375 emitcode ("pop", "dph");
11376 emitcode ("pop", "dpl");
11378 _startLazyDPSEvaluation ();
11379 /* if this is remateriazable */
11380 if (AOP_TYPE (to) == AOP_IMMD) {
11381 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11382 } else { /* we need to get it byte by byte */
11383 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11384 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11385 if (options.model == MODEL_FLAT24) {
11386 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11389 _endLazyDPSEvaluation ();
11392 freeAsmop (to, NULL, ic, FALSE);
11393 _G.dptrInUse = _G.dptr1InUse = 1;
11394 aopOp (count, ic->next->next, FALSE,FALSE);
11395 lbl =newiTempLabel(NULL);
11397 /* now for the actual copy */
11398 if (AOP_TYPE(count) == AOP_LIT &&
11399 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11400 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11402 emitcode ("lcall","__bi_memcpyc2x_s");
11404 emitcode ("lcall","__bi_memcpyx2x_s");
11406 freeAsmop (count, NULL, ic, FALSE);
11408 symbol *lbl1 = newiTempLabel(NULL);
11410 emitcode (";"," Auto increment but no djnz");
11411 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11412 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11413 freeAsmop (count, NULL, ic, FALSE);
11414 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11415 emitcode ("","!tlabeldef",lbl->key+100);
11417 emitcode ("clr","a");
11418 emitcode ("movc", "a,@a+dptr");
11420 emitcode ("movx", "a,@dptr");
11421 emitcode ("movx", "@dptr,a");
11422 emitcode ("inc", "dptr");
11423 emitcode ("inc", "dptr");
11424 emitcode ("mov","a,b");
11425 emitcode ("orl","a,_ap");
11426 emitcode ("jz","!tlabel",lbl1->key+100);
11427 emitcode ("mov","a,_ap");
11428 emitcode ("add","a,#!constbyte",0xFF);
11429 emitcode ("mov","_ap,a");
11430 emitcode ("mov","a,b");
11431 emitcode ("addc","a,#!constbyte",0xFF);
11432 emitcode ("mov","b,a");
11433 emitcode ("sjmp","!tlabel",lbl->key+100);
11434 emitcode ("","!tlabeldef",lbl1->key+100);
11436 emitcode ("mov", "dps,#0");
11437 _G.dptrInUse = _G.dptr1InUse = 0;
11438 unsavermask(rsave);
11442 /*-----------------------------------------------------------------*/
11443 /* genMemcmpX2X - gen code for memcmp xdata to xdata */
11444 /*-----------------------------------------------------------------*/
11445 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11447 operand *from , *to , *count;
11452 /* we know it has to be 3 parameters */
11453 assert (nparms == 3);
11455 rsave = newBitVect(16);
11456 /* save DPTR if it needs to be saved */
11457 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11458 if (bitVectBitValue(ic->rMask,i))
11459 rsave = bitVectSetBit(rsave,i);
11461 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11462 ds390_rUmaskForOp (IC_RESULT(ic))));
11469 aopOp (from, ic->next, FALSE, FALSE);
11471 /* get from into DPTR1 */
11472 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11473 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11474 if (options.model == MODEL_FLAT24) {
11475 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11478 freeAsmop (from, NULL, ic, FALSE);
11479 aopOp (to, ic, FALSE, FALSE);
11480 /* get "to" into DPTR */
11481 /* if the operand is already in dptr
11482 then we do nothing else we move the value to dptr */
11483 if (AOP_TYPE (to) != AOP_STR) {
11484 /* if already in DPTR then we need to push */
11485 if (AOP_TYPE(to) == AOP_DPTR) {
11486 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11487 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11488 if (options.model == MODEL_FLAT24)
11489 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11490 emitcode ("pop", "dph");
11491 emitcode ("pop", "dpl");
11493 _startLazyDPSEvaluation ();
11494 /* if this is remateriazable */
11495 if (AOP_TYPE (to) == AOP_IMMD) {
11496 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11497 } else { /* we need to get it byte by byte */
11498 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11499 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11500 if (options.model == MODEL_FLAT24) {
11501 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11504 _endLazyDPSEvaluation ();
11507 freeAsmop (to, NULL, ic, FALSE);
11508 _G.dptrInUse = _G.dptr1InUse = 1;
11509 aopOp (count, ic->next->next, FALSE,FALSE);
11510 lbl =newiTempLabel(NULL);
11511 lbl2 =newiTempLabel(NULL);
11513 /* now for the actual compare */
11514 if (AOP_TYPE(count) == AOP_LIT &&
11515 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11516 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11518 emitcode("lcall","__bi_memcmpc2x_s");
11520 emitcode("lcall","__bi_memcmpx2x_s");
11521 freeAsmop (count, NULL, ic, FALSE);
11522 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11523 aopPut(AOP(IC_RESULT(ic)),"a",0);
11524 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11526 symbol *lbl1 = newiTempLabel(NULL);
11528 emitcode("push","ar0");
11529 emitcode (";"," Auto increment but no djnz");
11530 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11531 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11532 freeAsmop (count, NULL, ic, FALSE);
11533 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11534 emitcode ("","!tlabeldef",lbl->key+100);
11536 emitcode ("clr","a");
11537 emitcode ("movc", "a,@a+dptr");
11539 emitcode ("movx", "a,@dptr");
11540 emitcode ("mov","r0,a");
11541 emitcode ("movx", "a,@dptr");
11542 emitcode ("clr","c");
11543 emitcode ("subb","a,r0");
11544 emitcode ("jnz","!tlabel",lbl2->key+100);
11545 emitcode ("inc", "dptr");
11546 emitcode ("inc", "dptr");
11547 emitcode ("mov","a,b");
11548 emitcode ("orl","a,_ap");
11549 emitcode ("jz","!tlabel",lbl1->key+100);
11550 emitcode ("mov","a,_ap");
11551 emitcode ("add","a,#!constbyte",0xFF);
11552 emitcode ("mov","_ap,a");
11553 emitcode ("mov","a,b");
11554 emitcode ("addc","a,#!constbyte",0xFF);
11555 emitcode ("mov","b,a");
11556 emitcode ("sjmp","!tlabel",lbl->key+100);
11557 emitcode ("","!tlabeldef",lbl1->key+100);
11558 emitcode ("clr","a");
11559 emitcode ("","!tlabeldef",lbl2->key+100);
11560 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11561 aopPut(AOP(IC_RESULT(ic)),"a",0);
11562 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11563 emitcode("pop","ar0");
11564 emitcode ("mov", "dps,#0");
11566 _G.dptrInUse = _G.dptr1InUse = 0;
11567 unsavermask(rsave);
11571 /*-----------------------------------------------------------------*/
11572 /* genInp - gen code for __builtin_inp read data from a mem mapped */
11573 /* port, first parameter output area second parameter pointer to */
11574 /* port third parameter count */
11575 /*-----------------------------------------------------------------*/
11576 static void genInp( iCode *ic, int nparms, operand **parms)
11578 operand *from , *to , *count;
11583 /* we know it has to be 3 parameters */
11584 assert (nparms == 3);
11586 rsave = newBitVect(16);
11587 /* save DPTR if it needs to be saved */
11588 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11589 if (bitVectBitValue(ic->rMask,i))
11590 rsave = bitVectSetBit(rsave,i);
11592 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11593 ds390_rUmaskForOp (IC_RESULT(ic))));
11600 aopOp (from, ic->next, FALSE, FALSE);
11602 /* get from into DPTR1 */
11603 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11604 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11605 if (options.model == MODEL_FLAT24) {
11606 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11609 freeAsmop (from, NULL, ic, FALSE);
11610 aopOp (to, ic, FALSE, FALSE);
11611 /* get "to" into DPTR */
11612 /* if the operand is already in dptr
11613 then we do nothing else we move the value to dptr */
11614 if (AOP_TYPE (to) != AOP_STR) {
11615 /* if already in DPTR then we need to push */
11616 if (AOP_TYPE(to) == AOP_DPTR) {
11617 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11618 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11619 if (options.model == MODEL_FLAT24)
11620 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11621 emitcode ("pop", "dph");
11622 emitcode ("pop", "dpl");
11624 _startLazyDPSEvaluation ();
11625 /* if this is remateriazable */
11626 if (AOP_TYPE (to) == AOP_IMMD) {
11627 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11628 } else { /* we need to get it byte by byte */
11629 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11630 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11631 if (options.model == MODEL_FLAT24) {
11632 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11635 _endLazyDPSEvaluation ();
11638 freeAsmop (to, NULL, ic, FALSE);
11640 _G.dptrInUse = _G.dptr1InUse = 1;
11641 aopOp (count, ic->next->next, FALSE,FALSE);
11642 lbl =newiTempLabel(NULL);
11644 /* now for the actual copy */
11645 if (AOP_TYPE(count) == AOP_LIT &&
11646 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11647 emitcode (";","OH JOY auto increment with djnz (very fast)");
11648 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11649 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11650 freeAsmop (count, NULL, ic, FALSE);
11651 emitcode ("","!tlabeldef",lbl->key+100);
11652 emitcode ("movx", "a,@dptr"); /* read data from port */
11653 emitcode ("dec","dps"); /* switch to DPTR */
11654 emitcode ("movx", "@dptr,a"); /* save into location */
11655 emitcode ("inc", "dptr"); /* point to next area */
11656 emitcode ("inc","dps"); /* switch to DPTR2 */
11657 emitcode ("djnz","b,!tlabel",lbl->key+100);
11659 symbol *lbl1 = newiTempLabel(NULL);
11661 emitcode (";"," Auto increment but no djnz");
11662 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11663 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11664 freeAsmop (count, NULL, ic, FALSE);
11665 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11666 emitcode ("","!tlabeldef",lbl->key+100);
11667 emitcode ("movx", "a,@dptr");
11668 emitcode ("dec","dps"); /* switch to DPTR */
11669 emitcode ("movx", "@dptr,a");
11670 emitcode ("inc", "dptr");
11671 emitcode ("inc","dps"); /* switch to DPTR2 */
11672 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
11673 /* emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
11674 emitcode ("mov","a,b");
11675 emitcode ("orl","a,_ap");
11676 emitcode ("jz","!tlabel",lbl1->key+100);
11677 emitcode ("mov","a,_ap");
11678 emitcode ("add","a,#!constbyte",0xFF);
11679 emitcode ("mov","_ap,a");
11680 emitcode ("mov","a,b");
11681 emitcode ("addc","a,#!constbyte",0xFF);
11682 emitcode ("mov","b,a");
11683 emitcode ("sjmp","!tlabel",lbl->key+100);
11684 emitcode ("","!tlabeldef",lbl1->key+100);
11686 emitcode ("mov", "dps,#0");
11687 _G.dptrInUse = _G.dptr1InUse = 0;
11688 unsavermask(rsave);
11692 /*-----------------------------------------------------------------*/
11693 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
11694 /* port, first parameter output area second parameter pointer to */
11695 /* port third parameter count */
11696 /*-----------------------------------------------------------------*/
11697 static void genOutp( iCode *ic, int nparms, operand **parms)
11699 operand *from , *to , *count;
11704 /* we know it has to be 3 parameters */
11705 assert (nparms == 3);
11707 rsave = newBitVect(16);
11708 /* save DPTR if it needs to be saved */
11709 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11710 if (bitVectBitValue(ic->rMask,i))
11711 rsave = bitVectSetBit(rsave,i);
11713 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11714 ds390_rUmaskForOp (IC_RESULT(ic))));
11721 aopOp (from, ic->next, FALSE, FALSE);
11723 /* get from into DPTR1 */
11724 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11725 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11726 if (options.model == MODEL_FLAT24) {
11727 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11730 freeAsmop (from, NULL, ic, FALSE);
11731 aopOp (to, ic, FALSE, FALSE);
11732 /* get "to" into DPTR */
11733 /* if the operand is already in dptr
11734 then we do nothing else we move the value to dptr */
11735 if (AOP_TYPE (to) != AOP_STR) {
11736 /* if already in DPTR then we need to push */
11737 if (AOP_TYPE(to) == AOP_DPTR) {
11738 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11739 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11740 if (options.model == MODEL_FLAT24)
11741 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11742 emitcode ("pop", "dph");
11743 emitcode ("pop", "dpl");
11745 _startLazyDPSEvaluation ();
11746 /* if this is remateriazable */
11747 if (AOP_TYPE (to) == AOP_IMMD) {
11748 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11749 } else { /* we need to get it byte by byte */
11750 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11751 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11752 if (options.model == MODEL_FLAT24) {
11753 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11756 _endLazyDPSEvaluation ();
11759 freeAsmop (to, NULL, ic, FALSE);
11761 _G.dptrInUse = _G.dptr1InUse = 1;
11762 aopOp (count, ic->next->next, FALSE,FALSE);
11763 lbl =newiTempLabel(NULL);
11765 /* now for the actual copy */
11766 if (AOP_TYPE(count) == AOP_LIT &&
11767 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11768 emitcode (";","OH JOY auto increment with djnz (very fast)");
11769 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
11770 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11771 emitcode ("","!tlabeldef",lbl->key+100);
11772 emitcode ("movx", "a,@dptr"); /* read data from port */
11773 emitcode ("inc","dps"); /* switch to DPTR2 */
11774 emitcode ("movx", "@dptr,a"); /* save into location */
11775 emitcode ("inc", "dptr"); /* point to next area */
11776 emitcode ("dec","dps"); /* switch to DPTR */
11777 emitcode ("djnz","b,!tlabel",lbl->key+100);
11778 freeAsmop (count, NULL, ic, FALSE);
11780 symbol *lbl1 = newiTempLabel(NULL);
11782 emitcode (";"," Auto increment but no djnz");
11783 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11784 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11785 freeAsmop (count, NULL, ic, FALSE);
11786 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
11787 emitcode ("","!tlabeldef",lbl->key+100);
11788 emitcode ("movx", "a,@dptr");
11789 emitcode ("inc", "dptr");
11790 emitcode ("inc","dps"); /* switch to DPTR2 */
11791 emitcode ("movx", "@dptr,a");
11792 emitcode ("dec","dps"); /* switch to DPTR */
11793 emitcode ("mov","a,b");
11794 emitcode ("orl","a,_ap");
11795 emitcode ("jz","!tlabel",lbl1->key+100);
11796 emitcode ("mov","a,_ap");
11797 emitcode ("add","a,#!constbyte",0xFF);
11798 emitcode ("mov","_ap,a");
11799 emitcode ("mov","a,b");
11800 emitcode ("addc","a,#!constbyte",0xFF);
11801 emitcode ("mov","b,a");
11802 emitcode ("sjmp","!tlabel",lbl->key+100);
11803 emitcode ("","!tlabeldef",lbl1->key+100);
11805 emitcode ("mov", "dps,#0");
11806 _G.dptrInUse = _G.dptr1InUse = 0;
11807 unsavermask(rsave);
11811 /*-----------------------------------------------------------------*/
11812 /* genSwapW - swap lower & high order bytes */
11813 /*-----------------------------------------------------------------*/
11814 static void genSwapW(iCode *ic, int nparms, operand **parms)
11818 assert (nparms==1);
11821 dest=IC_RESULT(ic);
11823 assert(getSize(operandType(src))==2);
11825 aopOp (src, ic, FALSE, FALSE);
11826 emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
11828 MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
11830 freeAsmop (src, NULL, ic, FALSE);
11832 aopOp (dest,ic, FALSE, FALSE);
11833 aopPut(AOP(dest),"b",0);
11834 aopPut(AOP(dest),"a",1);
11835 freeAsmop (dest, NULL, ic, FALSE);
11838 /*-----------------------------------------------------------------*/
11839 /* genMemsetX - gencode for memSetX data */
11840 /*-----------------------------------------------------------------*/
11841 static void genMemsetX(iCode *ic, int nparms, operand **parms)
11843 operand *to , *val , *count;
11849 /* we know it has to be 3 parameters */
11850 assert (nparms == 3);
11856 /* save DPTR if it needs to be saved */
11857 rsave = newBitVect(16);
11858 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11859 if (bitVectBitValue(ic->rMask,i))
11860 rsave = bitVectSetBit(rsave,i);
11862 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11863 ds390_rUmaskForOp (IC_RESULT(ic))));
11866 aopOp (to, ic, FALSE, FALSE);
11867 /* get "to" into DPTR */
11868 /* if the operand is already in dptr
11869 then we do nothing else we move the value to dptr */
11870 if (AOP_TYPE (to) != AOP_STR) {
11871 /* if already in DPTR then we need to push */
11872 if (AOP_TYPE(to) == AOP_DPTR) {
11873 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11874 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11875 if (options.model == MODEL_FLAT24)
11876 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11877 emitcode ("pop", "dph");
11878 emitcode ("pop", "dpl");
11880 _startLazyDPSEvaluation ();
11881 /* if this is remateriazable */
11882 if (AOP_TYPE (to) == AOP_IMMD) {
11883 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11884 } else { /* we need to get it byte by byte */
11885 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11886 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11887 if (options.model == MODEL_FLAT24) {
11888 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11891 _endLazyDPSEvaluation ();
11894 freeAsmop (to, NULL, ic, FALSE);
11896 aopOp (val, ic->next->next, FALSE,FALSE);
11897 aopOp (count, ic->next->next, FALSE,FALSE);
11898 lbl =newiTempLabel(NULL);
11899 /* now for the actual copy */
11900 if (AOP_TYPE(count) == AOP_LIT &&
11901 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11902 l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
11903 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11905 emitcode ("","!tlabeldef",lbl->key+100);
11906 emitcode ("movx", "@dptr,a");
11907 emitcode ("inc", "dptr");
11908 emitcode ("djnz","b,!tlabel",lbl->key+100);
11910 symbol *lbl1 = newiTempLabel(NULL);
11912 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11913 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11914 emitcode ("","!tlabeldef",lbl->key+100);
11915 MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
11916 emitcode ("movx", "@dptr,a");
11917 emitcode ("inc", "dptr");
11918 emitcode ("mov","a,b");
11919 emitcode ("orl","a,_ap");
11920 emitcode ("jz","!tlabel",lbl1->key+100);
11921 emitcode ("mov","a,_ap");
11922 emitcode ("add","a,#!constbyte",0xFF);
11923 emitcode ("mov","_ap,a");
11924 emitcode ("mov","a,b");
11925 emitcode ("addc","a,#!constbyte",0xFF);
11926 emitcode ("mov","b,a");
11927 emitcode ("sjmp","!tlabel",lbl->key+100);
11928 emitcode ("","!tlabeldef",lbl1->key+100);
11930 freeAsmop (count, NULL, ic, FALSE);
11931 unsavermask(rsave);
11934 /*-----------------------------------------------------------------*/
11935 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
11936 /*-----------------------------------------------------------------*/
11937 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
11940 operand *pnum, *result;
11943 assert (nparms==1);
11944 /* save registers that need to be saved */
11945 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11946 ds390_rUmaskForOp (IC_RESULT(ic))));
11949 aopOp (pnum, ic, FALSE, FALSE);
11950 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
11951 freeAsmop (pnum, NULL, ic, FALSE);
11952 emitcode ("lcall","NatLib_LoadPrimitive");
11953 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11954 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
11955 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
11956 for (i = (size-1) ; i >= 0 ; i-- ) {
11957 emitcode ("push","a%s",javaRet[i]);
11959 for (i=0; i < size ; i++ ) {
11960 emitcode ("pop","a%s",
11961 aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
11964 for (i = 0 ; i < size ; i++ ) {
11965 aopPut(AOP(result),javaRet[i],i);
11968 freeAsmop (result, NULL, ic, FALSE);
11969 unsavermask(rsave);
11972 /*-----------------------------------------------------------------*/
11973 /* genNatLibLoadPointer - calls TINI api function to load pointer */
11974 /*-----------------------------------------------------------------*/
11975 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
11978 operand *pnum, *result;
11982 assert (nparms==1);
11983 /* save registers that need to be saved */
11984 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11985 ds390_rUmaskForOp (IC_RESULT(ic))));
11988 aopOp (pnum, ic, FALSE, FALSE);
11989 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
11990 freeAsmop (pnum, NULL, ic, FALSE);
11991 emitcode ("lcall","NatLib_LoadPointer");
11992 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11993 if (AOP_TYPE(result)!=AOP_STR) {
11994 for (i = 0 ; i < size ; i++ ) {
11995 aopPut(AOP(result),fReturn[i],i);
11998 freeAsmop (result, NULL, ic, FALSE);
11999 unsavermask(rsave);
12002 /*-----------------------------------------------------------------*/
12003 /* genNatLibInstallStateBlock - */
12004 /*-----------------------------------------------------------------*/
12005 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
12006 operand **parms, const char *name)
12009 operand *psb, *handle;
12010 assert (nparms==2);
12012 /* save registers that need to be saved */
12013 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12014 ds390_rUmaskForOp (IC_RESULT(ic))));
12018 /* put pointer to state block into DPTR1 */
12019 aopOp (psb, ic, FALSE, FALSE);
12020 if (AOP_TYPE (psb) == AOP_IMMD) {
12021 emitcode ("mov","dps,#1");
12022 emitcode ("mov", "dptr,%s",
12023 aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12024 emitcode ("mov","dps,#0");
12026 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12027 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12028 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12030 freeAsmop (psb, NULL, ic, FALSE);
12032 /* put libraryID into DPTR */
12033 emitcode ("mov","dptr,#LibraryID");
12035 /* put handle into r3:r2 */
12036 aopOp (handle, ic, FALSE, FALSE);
12037 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12038 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12039 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12040 emitcode ("pop","ar3");
12041 emitcode ("pop","ar2");
12043 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12044 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12046 freeAsmop (psb, NULL, ic, FALSE);
12048 /* make the call */
12049 emitcode ("lcall","NatLib_Install%sStateBlock",name);
12051 /* put return value into place*/
12053 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12055 aopPut(AOP(IC_RESULT(ic)),"a",0);
12056 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12057 unsavermask(rsave);
12060 /*-----------------------------------------------------------------*/
12061 /* genNatLibRemoveStateBlock - */
12062 /*-----------------------------------------------------------------*/
12063 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12069 /* save registers that need to be saved */
12070 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12071 ds390_rUmaskForOp (IC_RESULT(ic))));
12073 /* put libraryID into DPTR */
12074 emitcode ("mov","dptr,#LibraryID");
12075 /* make the call */
12076 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12077 unsavermask(rsave);
12080 /*-----------------------------------------------------------------*/
12081 /* genNatLibGetStateBlock - */
12082 /*-----------------------------------------------------------------*/
12083 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12084 operand **parms,const char *name)
12087 symbol *lbl = newiTempLabel(NULL);
12090 /* save registers that need to be saved */
12091 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12092 ds390_rUmaskForOp (IC_RESULT(ic))));
12094 /* put libraryID into DPTR */
12095 emitcode ("mov","dptr,#LibraryID");
12096 /* make the call */
12097 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12098 emitcode ("jnz","!tlabel",lbl->key+100);
12100 /* put return value into place */
12101 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12102 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12103 emitcode ("push","ar3");
12104 emitcode ("push","ar2");
12105 emitcode ("pop","%s",
12106 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12107 emitcode ("pop","%s",
12108 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12110 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12111 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12113 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12114 emitcode ("","!tlabeldef",lbl->key+100);
12115 unsavermask(rsave);
12118 /*-----------------------------------------------------------------*/
12119 /* genMMMalloc - */
12120 /*-----------------------------------------------------------------*/
12121 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12122 int size, const char *name)
12127 symbol *lbl = newiTempLabel(NULL);
12129 assert (nparms == 1);
12130 /* save registers that need to be saved */
12131 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12132 ds390_rUmaskForOp (IC_RESULT(ic))));
12135 aopOp (bsize,ic,FALSE,FALSE);
12137 /* put the size in R4-R2 */
12138 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12139 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12140 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12142 emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12143 emitcode("pop","ar4");
12145 emitcode("pop","ar3");
12146 emitcode("pop","ar2");
12148 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12149 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12151 emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12154 freeAsmop (bsize, NULL, ic, FALSE);
12156 /* make the call */
12157 emitcode ("lcall","MM_%s",name);
12158 emitcode ("jz","!tlabel",lbl->key+100);
12159 emitcode ("mov","r2,#!constbyte",0xff);
12160 emitcode ("mov","r3,#!constbyte",0xff);
12161 emitcode ("","!tlabeldef",lbl->key+100);
12162 /* we don't care about the pointer : we just save the handle */
12163 rsym = OP_SYMBOL(IC_RESULT(ic));
12164 if (rsym->liveFrom != rsym->liveTo) {
12165 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12166 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12167 emitcode ("push","ar3");
12168 emitcode ("push","ar2");
12169 emitcode ("pop","%s",
12170 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12171 emitcode ("pop","%s",
12172 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12174 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12175 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12177 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12179 unsavermask(rsave);
12182 /*-----------------------------------------------------------------*/
12184 /*-----------------------------------------------------------------*/
12185 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12190 assert (nparms == 1);
12191 /* save registers that need to be saved */
12192 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12193 ds390_rUmaskForOp (IC_RESULT(ic))));
12196 aopOp (handle,ic,FALSE,FALSE);
12198 /* put the size in R4-R2 */
12199 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12200 emitcode("push","%s",
12201 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12202 emitcode("push","%s",
12203 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12204 emitcode("pop","ar3");
12205 emitcode("pop","ar2");
12207 emitcode ("mov","r2,%s",
12208 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12209 emitcode ("mov","r3,%s",
12210 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12212 freeAsmop (handle, NULL, ic, FALSE);
12214 /* make the call */
12215 emitcode ("lcall","MM_Deref");
12218 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12219 if (rsym->liveFrom != rsym->liveTo) {
12220 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12221 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12222 _startLazyDPSEvaluation ();
12224 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12225 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12226 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12228 _endLazyDPSEvaluation ();
12233 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12234 unsavermask(rsave);
12237 /*-----------------------------------------------------------------*/
12238 /* genMMUnrestrictedPersist - */
12239 /*-----------------------------------------------------------------*/
12240 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12245 assert (nparms == 1);
12246 /* save registers that need to be saved */
12247 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12248 ds390_rUmaskForOp (IC_RESULT(ic))));
12251 aopOp (handle,ic,FALSE,FALSE);
12253 /* put the size in R3-R2 */
12254 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12255 emitcode("push","%s",
12256 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12257 emitcode("push","%s",
12258 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12259 emitcode("pop","ar3");
12260 emitcode("pop","ar2");
12262 emitcode ("mov","r2,%s",
12263 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12264 emitcode ("mov","r3,%s",
12265 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12267 freeAsmop (handle, NULL, ic, FALSE);
12269 /* make the call */
12270 emitcode ("lcall","MM_UnrestrictedPersist");
12273 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12274 if (rsym->liveFrom != rsym->liveTo) {
12275 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12276 aopPut(AOP(IC_RESULT(ic)),"a",0);
12277 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12280 unsavermask(rsave);
12283 /*-----------------------------------------------------------------*/
12284 /* genSystemExecJavaProcess - */
12285 /*-----------------------------------------------------------------*/
12286 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12289 operand *handle, *pp;
12291 assert (nparms==2);
12292 /* save registers that need to be saved */
12293 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12294 ds390_rUmaskForOp (IC_RESULT(ic))));
12299 /* put the handle in R3-R2 */
12300 aopOp (handle,ic,FALSE,FALSE);
12301 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12302 emitcode("push","%s",
12303 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12304 emitcode("push","%s",
12305 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12306 emitcode("pop","ar3");
12307 emitcode("pop","ar2");
12309 emitcode ("mov","r2,%s",
12310 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12311 emitcode ("mov","r3,%s",
12312 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12314 freeAsmop (handle, NULL, ic, FALSE);
12316 /* put pointer in DPTR */
12317 aopOp (pp,ic,FALSE,FALSE);
12318 if (AOP_TYPE(pp) == AOP_IMMD) {
12319 emitcode ("mov", "dptr,%s",
12320 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12321 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12322 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12323 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12324 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12326 freeAsmop (handle, NULL, ic, FALSE);
12328 /* make the call */
12329 emitcode ("lcall","System_ExecJavaProcess");
12331 /* put result in place */
12333 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12334 if (rsym->liveFrom != rsym->liveTo) {
12335 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12336 aopPut(AOP(IC_RESULT(ic)),"a",0);
12337 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12341 unsavermask(rsave);
12344 /*-----------------------------------------------------------------*/
12345 /* genSystemRTCRegisters - */
12346 /*-----------------------------------------------------------------*/
12347 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12353 assert (nparms==1);
12354 /* save registers that need to be saved */
12355 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12356 ds390_rUmaskForOp (IC_RESULT(ic))));
12359 /* put pointer in DPTR */
12360 aopOp (pp,ic,FALSE,FALSE);
12361 if (AOP_TYPE (pp) == AOP_IMMD) {
12362 emitcode ("mov","dps,#1");
12363 emitcode ("mov", "dptr,%s",
12364 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12365 emitcode ("mov","dps,#0");
12367 emitcode ("mov","dpl1,%s",
12368 aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12369 emitcode ("mov","dph1,%s",
12370 aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12371 emitcode ("mov","dpx1,%s",
12372 aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12374 freeAsmop (pp, NULL, ic, FALSE);
12376 /* make the call */
12377 emitcode ("lcall","System_%sRTCRegisters",name);
12379 unsavermask(rsave);
12382 /*-----------------------------------------------------------------*/
12383 /* genSystemThreadSleep - */
12384 /*-----------------------------------------------------------------*/
12385 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12390 assert (nparms==1);
12391 /* save registers that need to be saved */
12392 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12393 ds390_rUmaskForOp (IC_RESULT(ic))));
12396 aopOp(to,ic,FALSE,FALSE);
12397 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12398 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12399 emitcode ("push","%s",
12400 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12401 emitcode ("push","%s",
12402 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12403 emitcode ("push","%s",
12404 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12405 emitcode ("push","%s",
12406 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12407 emitcode ("pop","ar3");
12408 emitcode ("pop","ar2");
12409 emitcode ("pop","ar1");
12410 emitcode ("pop","ar0");
12412 emitcode ("mov","r0,%s",
12413 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12414 emitcode ("mov","r1,%s",
12415 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12416 emitcode ("mov","r2,%s",
12417 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12418 emitcode ("mov","r3,%s",
12419 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12421 freeAsmop (to, NULL, ic, FALSE);
12423 /* suspend in acc */
12425 aopOp(s,ic,FALSE,FALSE);
12426 emitcode ("mov","a,%s",
12427 aopGet(AOP(s),0,FALSE,TRUE,NULL));
12428 freeAsmop (s, NULL, ic, FALSE);
12430 /* make the call */
12431 emitcode ("lcall","System_%s",name);
12433 unsavermask(rsave);
12436 /*-----------------------------------------------------------------*/
12437 /* genSystemThreadResume - */
12438 /*-----------------------------------------------------------------*/
12439 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12444 assert (nparms==2);
12445 /* save registers that need to be saved */
12446 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12447 ds390_rUmaskForOp (IC_RESULT(ic))));
12453 aopOp(pid,ic,FALSE,FALSE);
12454 emitcode ("mov","r0,%s",
12455 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12456 freeAsmop (pid, NULL, ic, FALSE);
12459 aopOp(tid,ic,FALSE,FALSE);
12460 emitcode ("mov","a,%s",
12461 aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
12462 freeAsmop (tid, NULL, ic, FALSE);
12464 emitcode ("lcall","System_ThreadResume");
12466 /* put result into place */
12468 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12469 if (rsym->liveFrom != rsym->liveTo) {
12470 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12471 aopPut(AOP(IC_RESULT(ic)),"a",0);
12472 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12475 unsavermask(rsave);
12478 /*-----------------------------------------------------------------*/
12479 /* genSystemProcessResume - */
12480 /*-----------------------------------------------------------------*/
12481 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
12486 assert (nparms==1);
12487 /* save registers that need to be saved */
12488 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12489 ds390_rUmaskForOp (IC_RESULT(ic))));
12494 aopOp(pid,ic,FALSE,FALSE);
12495 emitcode ("mov","a,%s",
12496 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12497 freeAsmop (pid, NULL, ic, FALSE);
12499 emitcode ("lcall","System_ProcessResume");
12501 unsavermask(rsave);
12504 /*-----------------------------------------------------------------*/
12506 /*-----------------------------------------------------------------*/
12507 static void genSystem (iCode *ic,int nparms,char *name)
12509 assert(nparms == 0);
12511 emitcode ("lcall","System_%s",name);
12514 /*-----------------------------------------------------------------*/
12515 /* genSystemPoll - */
12516 /*-----------------------------------------------------------------*/
12517 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
12522 assert (nparms==1);
12523 /* save registers that need to be saved */
12524 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12525 ds390_rUmaskForOp (IC_RESULT(ic))));
12528 aopOp (fp,ic,FALSE,FALSE);
12529 if (AOP_TYPE (fp) == AOP_IMMD) {
12530 emitcode ("mov", "dptr,%s",
12531 aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
12532 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
12533 emitcode ("mov","dpl,%s",
12534 aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
12535 emitcode ("mov","dph,%s",
12536 aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
12537 emitcode ("mov","dpx,%s",
12538 aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
12540 freeAsmop (fp, NULL, ic, FALSE);
12542 emitcode ("lcall","System_%sPoll",name);
12544 /* put result into place */
12546 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12547 if (rsym->liveFrom != rsym->liveTo) {
12548 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12549 aopPut(AOP(IC_RESULT(ic)),"a",0);
12550 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12553 unsavermask(rsave);
12556 /*-----------------------------------------------------------------*/
12557 /* genSystemGetCurrentID - */
12558 /*-----------------------------------------------------------------*/
12559 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
12561 assert (nparms==0);
12563 emitcode ("lcall","System_GetCurrent%sId",name);
12564 /* put result into place */
12566 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12567 if (rsym->liveFrom != rsym->liveTo) {
12568 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12569 aopPut(AOP(IC_RESULT(ic)),"a",0);
12570 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12575 /*-----------------------------------------------------------------*/
12576 /* genDummyRead - generate code for dummy read of volatiles */
12577 /*-----------------------------------------------------------------*/
12579 genDummyRead (iCode * ic)
12584 D(emitcode("; genDummyRead",""));
12586 right = IC_RIGHT (ic);
12588 aopOp (right, ic, FALSE, FALSE);
12590 /* if the result is a bit */
12591 if (AOP_TYPE (right) == AOP_CRY)
12593 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
12597 /* bit variables done */
12599 size = AOP_SIZE (right);
12603 emitcode ("mov", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
12608 freeAsmop (right, NULL, ic, TRUE);
12611 /*-----------------------------------------------------------------*/
12612 /* genBuiltIn - calls the appropriate function to generating code */
12613 /* for a built in function */
12614 /*-----------------------------------------------------------------*/
12615 static void genBuiltIn (iCode *ic)
12617 operand *bi_parms[MAX_BUILTIN_ARGS];
12622 /* get all the arguments for a built in function */
12623 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
12625 /* which function is it */
12626 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
12627 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
12628 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
12629 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
12630 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
12631 } else if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
12632 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
12633 } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
12634 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
12635 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
12636 genMemsetX(bi_iCode,nbi_parms,bi_parms);
12637 } else if (strcmp(bif->name,"__builtin_inp")==0) {
12638 genInp(bi_iCode,nbi_parms,bi_parms);
12639 } else if (strcmp(bif->name,"__builtin_outp")==0) {
12640 genOutp(bi_iCode,nbi_parms,bi_parms);
12641 } else if (strcmp(bif->name,"__builtin_swapw")==0) {
12642 genSwapW(bi_iCode,nbi_parms,bi_parms);
12643 /* JavaNative builtIns */
12644 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
12645 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
12646 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
12647 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
12648 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
12649 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
12650 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
12651 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
12652 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
12653 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12654 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
12655 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12656 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
12657 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
12658 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
12659 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
12660 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
12661 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12662 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
12663 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12664 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
12665 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
12666 } else if (strcmp(bif->name,"MM_Malloc")==0) {
12667 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
12668 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
12669 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
12670 } else if (strcmp(bif->name,"MM_Free")==0) {
12671 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
12672 } else if (strcmp(bif->name,"MM_Deref")==0) {
12673 genMMDeref(bi_iCode,nbi_parms,bi_parms);
12674 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
12675 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
12676 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
12677 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
12678 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
12679 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
12680 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
12681 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
12682 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
12683 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
12684 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
12685 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
12686 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
12687 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
12688 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
12689 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
12690 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12691 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12692 } else if (strcmp(bif->name,"System_SaveThread")==0) {
12693 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12694 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12695 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12696 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
12697 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
12698 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
12699 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
12700 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
12701 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
12702 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
12703 genSystem(bi_iCode,nbi_parms,"ProcessYield");
12704 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
12705 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
12706 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
12707 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
12708 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
12709 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
12710 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
12711 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
12712 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
12713 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
12715 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
12721 /*-----------------------------------------------------------------*/
12722 /* gen390Code - generate code for Dallas 390 based controllers */
12723 /*-----------------------------------------------------------------*/
12725 gen390Code (iCode * lic)
12730 lineHead = lineCurr = NULL;
12731 dptrn[1][0] = "dpl1";
12732 dptrn[1][1] = "dph1";
12733 dptrn[1][2] = "dpx1";
12735 if (options.model == MODEL_FLAT24) {
12736 fReturnSizeDS390 = 5;
12737 fReturn = fReturn24;
12739 fReturnSizeDS390 = 4;
12740 fReturn = fReturn16;
12741 options.stack10bit=0;
12744 /* print the allocation information */
12745 if (allocInfo && currFunc)
12746 printAllocInfo (currFunc, codeOutFile);
12748 /* if debug information required */
12749 if (options.debug && currFunc)
12751 debugFile->writeFunction(currFunc);
12753 if (IS_STATIC (currFunc->etype))
12754 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
12756 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
12759 /* stack pointer name */
12760 if (options.useXstack)
12766 for (ic = lic; ic; ic = ic->next)
12769 if (ic->lineno && cln != ic->lineno)
12774 emitcode ("", "C$%s$%d$%d$%d ==.",
12775 FileBaseName (ic->filename), ic->lineno,
12776 ic->level, ic->block);
12779 if (!options.noCcodeInAsm) {
12780 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
12781 printCLine(ic->filename, ic->lineno));
12785 if (options.iCodeInAsm) {
12786 emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
12788 /* if the result is marked as
12789 spilt and rematerializable or code for
12790 this has already been generated then
12792 if (resultRemat (ic) || ic->generated)
12795 /* depending on the operation */
12815 /* IPOP happens only when trying to restore a
12816 spilt live range, if there is an ifx statement
12817 following this pop then the if statement might
12818 be using some of the registers being popped which
12819 would destory the contents of the register so
12820 we need to check for this condition and handle it */
12822 ic->next->op == IFX &&
12823 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
12824 genIfx (ic->next, ic);
12842 genEndFunction (ic);
12862 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
12879 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
12883 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
12890 /* note these two are xlated by algebraic equivalence
12891 during parsing SDCC.y */
12892 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12893 "got '>=' or '<=' shouldn't have come here");
12897 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
12909 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
12913 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
12917 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
12941 genRightShift (ic);
12944 case GET_VALUE_AT_ADDRESS:
12945 genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
12949 if (POINTER_SET (ic))
12950 genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
12976 if (ic->builtinSEND) genBuiltIn(ic);
12977 else addSet (&_G.sendSet, ic);
12980 case DUMMY_READ_VOLATILE:
12984 #if 0 // obsolete, and buggy for != xdata
12996 /* now we are ready to call the
12997 peep hole optimizer */
12998 if (!options.nopeep)
12999 peepHole (&lineHead);
13001 /* now do the actual printing */
13002 printLine (lineHead, codeOutFile);