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)
454 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
455 "null iCode pointer");
462 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
465 size = getSize (OP_SYMBOL (op)->type);
470 else if (ic->op == JUMPTABLE)
473 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
476 size = getSize (OP_SYMBOL (op)->type);
484 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
487 size = getSize (OP_SYMBOL (op)->type);
492 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
495 size = getSize (OP_SYMBOL (op)->type);
507 /*-----------------------------------------------------------------*/
508 /* aopForSym - for a true symbol */
509 /*-----------------------------------------------------------------*/
511 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
514 memmap *space = SPEC_OCLS (sym->etype);
515 int accuse = leftRightUseAcc (ic);
517 /* if already has one */
521 /* assign depending on the storage class */
522 /* if it is on the stack or indirectly addressable */
523 /* space we need to assign either r0 or r1 to it */
524 if ((sym->onStack && !options.stack10bit) || sym->iaccess)
526 sym->aop = aop = newAsmop (0);
527 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
528 aop->size = getSize (sym->type);
530 /* now assign the address of the variable to
531 the pointer register */
532 if (aop->type != AOP_STK)
537 if (_G.accInUse || accuse)
538 emitcode ("push", "acc");
540 if (_G.bInUse || (accuse>1))
541 emitcode ("push", "b");
543 emitcode ("mov", "a,_bp");
544 emitcode ("add", "a,#!constbyte",
546 ((char) (sym->stack - _G.nRegsSaved)) :
547 ((char) sym->stack)) & 0xff);
548 emitcode ("mov", "%s,a",
549 aop->aopu.aop_ptr->name);
551 if (_G.bInUse || (accuse>1))
552 emitcode ("pop", "b");
554 if (_G.accInUse || accuse)
555 emitcode ("pop", "acc");
558 emitcode ("mov", "%s,#%s",
559 aop->aopu.aop_ptr->name,
561 aop->paged = space->paged;
564 aop->aopu.aop_stk = sym->stack;
568 if (sym->onStack && options.stack10bit)
570 short stack_val = -((sym->stack < 0) ?
571 ((short) (sym->stack - _G.nRegsSaved)) :
572 ((short) sym->stack)) ;
573 if (useDP2 && _G.dptr1InUse) {
574 emitcode ("push","dpl1");
575 emitcode ("push","dph1");
576 emitcode ("push","dpx1");
577 } else if (_G.dptrInUse ) {
578 emitcode ("push","dpl");
579 emitcode ("push","dph");
580 emitcode ("push","dpx");
582 /* It's on the 10 bit stack, which is located in
585 if (stack_val < 0 && stack_val > -5) { /* between -5 & -1 */
587 if (options.model == MODEL_FLAT24)
589 emitcode ("mov", "dpx1,#!constbyte",
590 (options.stack_loc >> 16) & 0xff);
592 emitcode ("mov", "dph1,_bpx+1");
594 emitcode ("mov", "dpl1,_bpx");
595 emitcode ("mov","dps,#1");
597 if (options.model == MODEL_FLAT24)
599 emitcode ("mov", "dpx,#!constbyte",
600 (options.stack_loc >> 16) & 0xff);
602 emitcode ("mov", "dph,_bpx+1");
603 emitcode ("mov", "dpl,_bpx");
605 stack_val = -stack_val;
606 while (stack_val--) {
607 emitcode ("inc","dptr");
610 emitcode("mov","dps,#0");
613 if (_G.accInUse || accuse)
614 emitcode ("push", "acc");
616 if (_G.bInUse || (accuse>1))
617 emitcode ("push", "b");
619 emitcode ("mov", "a,_bpx");
620 emitcode ("clr","c");
621 emitcode ("subb", "a,#!constbyte", stack_val & 0xff);
622 emitcode ("mov","b,a");
623 emitcode ("mov","a,_bpx+1");
624 emitcode ("subb","a,#!constbyte",(stack_val >> 8) & 0xff);
626 if (options.model == MODEL_FLAT24)
628 emitcode ("mov", "dpx1,#!constbyte",
629 (options.stack_loc >> 16) & 0xff);
631 emitcode ("mov", "dph1,a");
632 emitcode ("mov", "dpl1,b");
634 if (options.model == MODEL_FLAT24)
636 emitcode ("mov", "dpx,#!constbyte",
637 (options.stack_loc >> 16) & 0xff);
639 emitcode ("mov", "dph,a");
640 emitcode ("mov", "dpl,b");
643 if (_G.bInUse || (accuse>1))
644 emitcode ("pop", "b");
646 if (_G.accInUse || accuse)
647 emitcode ("pop", "acc");
649 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
650 aop->size = getSize (sym->type);
654 /* if in bit space */
655 if (IN_BITSPACE (space))
657 sym->aop = aop = newAsmop (AOP_CRY);
658 aop->aopu.aop_dir = sym->rname;
659 aop->size = getSize (sym->type);
662 /* if it is in direct space */
663 if (IN_DIRSPACE (space))
665 sym->aop = aop = newAsmop (AOP_DIR);
666 aop->aopu.aop_dir = sym->rname;
667 aop->size = getSize (sym->type);
671 /* special case for a function */
672 if (IS_FUNC (sym->type) && !(sym->isitmp))
674 sym->aop = aop = newAsmop (AOP_IMMD);
675 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
676 aop->size = FPTRSIZE;
680 /* only remaining is far space */
681 /* in which case DPTR gets the address */
682 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
687 emitcode ("mov", "dptr,#%s", sym->rname);
692 emitcode ("mov", "dptr,#%s", sym->rname);
694 aop->size = getSize (sym->type);
696 /* if it is in code space */
697 if (IN_CODESPACE (space))
703 /*-----------------------------------------------------------------*/
704 /* aopForRemat - rematerialzes an object */
705 /*-----------------------------------------------------------------*/
707 aopForRemat (symbol * sym)
709 iCode *ic = sym->rematiCode;
710 asmop *aop = newAsmop (AOP_IMMD);
717 val += (int) operandLitValue (IC_RIGHT (ic));
718 else if (ic->op == '-')
719 val -= (int) operandLitValue (IC_RIGHT (ic));
720 else if (IS_CAST_ICODE(ic)) {
721 sym_link *from_type = operandType(IC_RIGHT(ic));
722 aop->aopu.aop_immd.from_cast_remat = 1;
723 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
724 ptr_type = DCL_TYPE(from_type);
725 if (ptr_type == IPOINTER) {
732 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
737 SNPRINTF (buffer, sizeof(buffer),
739 OP_SYMBOL (IC_LEFT (ic))->rname,
740 val >= 0 ? '+' : '-',
741 abs (val) & 0xffffff);
745 if (IS_ASSIGN_ICODE(ic) && isOperandLiteral(IC_RIGHT(ic)))
747 SNPRINTF(buffer, sizeof(buffer),
748 "0x%x",(int) operandLitValue (IC_RIGHT (ic)));
752 strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
756 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);
757 /* set immd2 field if required */
758 if (aop->aopu.aop_immd.from_cast_remat)
760 tsprintf(buffer, sizeof(buffer), "#!constbyte",ptr_type);
761 aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
767 /*-----------------------------------------------------------------*/
768 /* aopHasRegs - returns true if aop has regs between from-to */
769 /*-----------------------------------------------------------------*/
770 static int aopHasRegs(asmop *aop, int from, int to)
774 if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
776 for (; size < aop->size ; size++) {
778 for (reg = from ; reg <= to ; reg++)
779 if (aop->aopu.aop_reg[size] == ds390_regWithIdx(reg)) return 1;
784 /*-----------------------------------------------------------------*/
785 /* regsInCommon - two operands have some registers in common */
786 /*-----------------------------------------------------------------*/
788 regsInCommon (operand * op1, operand * op2)
793 /* if they have registers in common */
794 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
797 sym1 = OP_SYMBOL (op1);
798 sym2 = OP_SYMBOL (op2);
800 if (sym1->nRegs == 0 || sym2->nRegs == 0)
803 for (i = 0; i < sym1->nRegs; i++)
809 for (j = 0; j < sym2->nRegs; j++)
814 if (sym2->regs[j] == sym1->regs[i])
822 /*-----------------------------------------------------------------*/
823 /* operandsEqu - equivalent */
824 /*-----------------------------------------------------------------*/
826 operandsEqu (operand * op1, operand * op2)
830 /* if they not symbols */
831 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
834 sym1 = OP_SYMBOL (op1);
835 sym2 = OP_SYMBOL (op2);
837 /* if both are itemps & one is spilt
838 and the other is not then false */
839 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
840 sym1->isspilt != sym2->isspilt)
843 /* if they are the same */
847 if (strcmp (sym1->rname, sym2->rname) == 0)
851 /* if left is a tmp & right is not */
852 if (IS_ITEMP (op1) &&
855 (sym1->usl.spillLoc == sym2))
858 if (IS_ITEMP (op2) &&
862 (sym2->usl.spillLoc == sym1))
868 /*-----------------------------------------------------------------*/
869 /* sameRegs - two asmops have the same registers */
870 /*-----------------------------------------------------------------*/
872 sameRegs (asmop * aop1, asmop * aop2)
878 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
885 if (aop1->type != AOP_REG ||
886 aop2->type != AOP_REG)
889 if (aop1->size != aop2->size)
892 for (i = 0; i < aop1->size; i++)
893 if (aop1->aopu.aop_reg[i] !=
894 aop2->aopu.aop_reg[i])
900 /*-----------------------------------------------------------------*/
901 /* aopOp - allocates an asmop for an operand : */
902 /*-----------------------------------------------------------------*/
904 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
913 /* if this a literal */
914 if (IS_OP_LITERAL (op))
916 op->aop = aop = newAsmop (AOP_LIT);
917 aop->aopu.aop_lit = op->operand.valOperand;
918 aop->size = getSize (operandType (op));
922 /* if already has a asmop then continue */
926 /* if the underlying symbol has a aop */
927 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
929 op->aop = OP_SYMBOL (op)->aop;
933 /* if this is a true symbol */
934 if (IS_TRUE_SYMOP (op))
936 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
940 /* this is a temporary : this has
946 e) can be a return use only */
948 sym = OP_SYMBOL (op);
951 /* if the type is a conditional */
952 if (sym->regType == REG_CND)
954 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
959 /* if it is spilt then two situations
961 b) has a spill location */
962 if (sym->isspilt || sym->nRegs == 0)
965 /* rematerialize it NOW */
968 sym->aop = op->aop = aop =
970 aop->size = getSize (sym->type);
977 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
978 aop->size = getSize (sym->type);
979 for (i = 0; i < 2; i++)
980 aop->aopu.aop_str[i] = accUse[i];
990 /* a AOP_STR uses DPTR, but DPTR is already in use;
993 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"AOP_STR with DPTR in use!");
996 aop = op->aop = sym->aop = newAsmop (AOP_STR);
997 aop->size = getSize (sym->type);
998 for (i = 0; i < (int) fReturnSizeDS390; i++)
999 aop->aopu.aop_str[i] = fReturn[i];
1003 if (sym->dptr) { /* has been allocated to a DPTRn */
1004 aop = op->aop = sym->aop = newAsmop (AOP_DPTRn);
1005 aop->size = getSize (sym->type);
1006 aop->aopu.dptr = sym->dptr;
1010 if (sym->usl.spillLoc)
1012 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1014 /* force a new aop if sizes differ */
1015 sym->usl.spillLoc->aop = NULL;
1017 sym->aop = op->aop = aop =
1018 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
1019 aop->size = getSize (sym->type);
1023 /* else must be a dummy iTemp */
1024 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1025 aop->size = getSize (sym->type);
1029 /* must be in a register */
1030 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1031 aop->size = sym->nRegs;
1032 for (i = 0; i < sym->nRegs; i++)
1033 aop->aopu.aop_reg[i] = sym->regs[i];
1036 /*-----------------------------------------------------------------*/
1037 /* freeAsmop - free up the asmop given to an operand */
1038 /*----------------------------------------------------------------*/
1040 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1057 /* depending on the asmop type only three cases need work AOP_RO
1058 , AOP_R1 && AOP_STK */
1066 emitcode ("pop", "ar0");
1070 bitVectUnSetBit (ic->rUsed, R0_IDX);
1078 emitcode ("pop", "ar1");
1082 bitVectUnSetBit (ic->rUsed, R1_IDX);
1088 int stk = aop->aopu.aop_stk + aop->size;
1089 bitVectUnSetBit (ic->rUsed, R0_IDX);
1090 bitVectUnSetBit (ic->rUsed, R1_IDX);
1092 getFreePtr (ic, &aop, FALSE);
1094 if (options.stack10bit)
1096 /* I'm not sure what to do here yet... */
1099 "*** Warning: probably generating bad code for "
1100 "10 bit stack mode.\n");
1105 emitcode ("mov", "a,_bp");
1106 emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
1107 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1111 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1116 emitcode ("pop", "acc");
1117 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1120 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1123 freeAsmop (op, NULL, ic, TRUE);
1126 emitcode ("pop", "ar0");
1132 emitcode ("pop", "ar1");
1137 if (_G.dptr1InUse) {
1138 emitcode ("pop","dpx1");
1139 emitcode ("pop","dph1");
1140 emitcode ("pop","dpl1");
1145 emitcode ("pop","dpx");
1146 emitcode ("pop","dph");
1147 emitcode ("pop","dpl");
1152 /* all other cases just dealloc */
1158 OP_SYMBOL (op)->aop = NULL;
1159 /* if the symbol has a spill */
1161 SPIL_LOC (op)->aop = NULL;
1166 #define DEFAULT_ACC_WARNING 0
1167 static int saveAccWarn = DEFAULT_ACC_WARNING;
1169 /*-------------------------------------------------------------------*/
1170 /* aopGet - for fetching value of the aop */
1172 /* Set saveAcc to NULL if you are sure it is OK to clobber the value */
1173 /* in the accumulator. Set it to the name of a free register */
1174 /* if acc must be preserved; the register will be used to preserve */
1175 /* acc temporarily and to return the result byte. */
1176 /*-------------------------------------------------------------------*/
1185 /* offset is greater than
1187 if (offset > (aop->size - 1) &&
1188 aop->type != AOP_LIT)
1191 /* depending on type */
1199 /* if we need to increment it */
1200 while (offset > aop->coff)
1202 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1206 while (offset < aop->coff)
1208 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1215 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1216 return (dname ? "acc" : "a");
1218 SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1219 return Safe_strdup(buffer);
1222 assert(offset <= 3);
1223 return dptrn[aop->aopu.dptr][offset];
1228 if (aop->type == AOP_DPTR2)
1236 // if (aop->type != AOP_DPTR2)
1238 // if (saveAccWarn) { fprintf(stderr, "saveAcc for DPTR...\n"); }
1239 // emitcode(";", "spanky: saveAcc for DPTR");
1242 emitcode ("xch", "a, %s", saveAcc);
1247 while (offset > aop->coff)
1249 emitcode ("inc", "dptr");
1253 while (offset < aop->coff)
1255 emitcode ("lcall", "__decdptr");
1262 emitcode ("clr", "a");
1263 emitcode ("movc", "a,@a+dptr");
1267 emitcode ("movx", "a,@dptr");
1270 if (aop->type == AOP_DPTR2)
1278 emitcode ("xch", "a, %s", saveAcc);
1279 // if (strcmp(saveAcc, "_ap"))
1281 // emitcode(";", "spiffy: non _ap return from aopGet.");
1286 return (dname ? "acc" : "a");
1289 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1291 SNPRINTF(buffer, sizeof(buffer),
1292 "%s",aop->aopu.aop_immd.aop_immd2);
1296 SNPRINTF(buffer, sizeof(buffer),
1297 "#%s", aop->aopu.aop_immd.aop_immd1);
1303 tsprintf(buffer, sizeof(buffer),
1304 "#!his",aop->aopu.aop_immd.aop_immd1);
1307 tsprintf(buffer, sizeof(buffer),
1308 "#!hihis",aop->aopu.aop_immd.aop_immd1);
1311 tsprintf(buffer, sizeof(buffer),
1312 "#!hihihis",aop->aopu.aop_immd.aop_immd1);
1314 default: /* should not need this (just in case) */
1315 SNPRINTF (buffer, sizeof(buffer),
1317 aop->aopu.aop_immd.aop_immd1,
1323 SNPRINTF (buffer, sizeof(buffer),
1324 "#%s", aop->aopu.aop_immd.aop_immd1);
1326 return Safe_strdup(buffer);
1331 SNPRINTF (buffer, sizeof(buffer),
1338 SNPRINTF(buffer, sizeof(buffer),
1339 "%s", aop->aopu.aop_dir);
1342 return Safe_strdup(buffer);
1346 return aop->aopu.aop_reg[offset]->dname;
1348 return aop->aopu.aop_reg[offset]->name;
1351 emitcode ("clr", "a");
1352 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1353 emitcode ("rlc", "a");
1354 return (dname ? "acc" : "a");
1357 if (!offset && dname)
1359 return aop->aopu.aop_str[offset];
1362 return aopLiteral (aop->aopu.aop_lit, offset);
1366 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1370 return aop->aopu.aop_str[offset];
1374 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1375 "aopget got unsupported aop->type");
1378 return NULL; // not reached, but makes compiler happy.
1380 /*-----------------------------------------------------------------*/
1381 /* aopPut - puts a string for a aop */
1382 /*-----------------------------------------------------------------*/
1384 aopPut (asmop * aop, char *s, int offset)
1386 if (aop->size && offset > (aop->size - 1))
1388 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1389 "aopPut got offset > aop->size");
1393 /* will assign value to value */
1394 /* depending on where it is ofcourse */
1398 MOVA (s); /* read s in case it was volatile */
1404 SNPRINTF (buffer, sizeof(buffer),
1406 aop->aopu.aop_dir, offset);
1410 SNPRINTF (buffer, sizeof(buffer),
1411 "%s", aop->aopu.aop_dir);
1415 if (strcmp (buffer, s))
1417 emitcode ("mov", "%s,%s", buffer, s);
1422 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1423 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1426 strcmp (s, "r0") == 0 ||
1427 strcmp (s, "r1") == 0 ||
1428 strcmp (s, "r2") == 0 ||
1429 strcmp (s, "r3") == 0 ||
1430 strcmp (s, "r4") == 0 ||
1431 strcmp (s, "r5") == 0 ||
1432 strcmp (s, "r6") == 0 ||
1433 strcmp (s, "r7") == 0)
1435 emitcode ("mov", "%s,%s",
1436 aop->aopu.aop_reg[offset]->dname, s);
1440 emitcode ("mov", "%s,%s",
1441 aop->aopu.aop_reg[offset]->name, s);
1447 emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1453 if (aop->type == AOP_DPTR2)
1461 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1462 "aopPut writting to code space");
1466 while (offset > aop->coff)
1469 emitcode ("inc", "dptr");
1472 while (offset < aop->coff)
1475 emitcode ("lcall", "__decdptr");
1480 /* if not in accumulater */
1483 emitcode ("movx", "@dptr,a");
1485 if (aop->type == AOP_DPTR2)
1493 while (offset > aop->coff)
1496 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1498 while (offset < aop->coff)
1501 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1508 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1514 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1516 else if (strcmp (s, "r0") == 0 ||
1517 strcmp (s, "r1") == 0 ||
1518 strcmp (s, "r2") == 0 ||
1519 strcmp (s, "r3") == 0 ||
1520 strcmp (s, "r4") == 0 ||
1521 strcmp (s, "r5") == 0 ||
1522 strcmp (s, "r6") == 0 ||
1523 strcmp (s, "r7") == 0)
1526 SNPRINTF(buff, sizeof(buff),
1528 emitcode ("mov", "@%s,%s",
1529 aop->aopu.aop_ptr->name, buff);
1533 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1538 if (strcmp (s, "a") == 0)
1539 emitcode ("push", "acc");
1543 emitcode ("push", "acc");
1545 emitcode ("push", s);
1551 /* if bit variable */
1552 if (!aop->aopu.aop_dir)
1554 emitcode ("clr", "a");
1555 emitcode ("rlc", "a");
1560 emitcode ("clr", "%s", aop->aopu.aop_dir);
1562 emitcode ("setb", "%s", aop->aopu.aop_dir);
1563 else if (!strcmp (s, "c"))
1564 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1567 if (strcmp (s, "a"))
1572 /* set C, if a >= 1 */
1573 emitcode ("add", "a,#!constbyte",0xff);
1574 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1582 if (strcmp (aop->aopu.aop_str[offset], s))
1583 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1588 if (!offset && (strcmp (s, "acc") == 0))
1591 if (strcmp (aop->aopu.aop_str[offset], s))
1592 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1596 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1597 "aopPut got unsupported aop->type");
1604 /*--------------------------------------------------------------------*/
1605 /* reAdjustPreg - points a register back to where it should (coff==0) */
1606 /*--------------------------------------------------------------------*/
1608 reAdjustPreg (asmop * aop)
1610 if ((aop->coff==0) || (aop->size <= 1)) {
1619 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1623 if (aop->type == AOP_DPTR2)
1630 emitcode ("lcall", "__decdptr");
1633 if (aop->type == AOP_DPTR2)
1643 #define AOP(op) op->aop
1644 #define AOP_TYPE(op) AOP(op)->type
1645 #define AOP_SIZE(op) AOP(op)->size
1646 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1647 AOP_TYPE(x) == AOP_R0))
1649 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1650 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1653 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1654 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1655 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1656 #define AOP_INDPTRn(x) (AOP_TYPE(x) == AOP_DPTRn)
1657 #define AOP_USESDPTR(x) ((AOP_TYPE(x) == AOP_DPTR) || (AOP_TYPE(x) == AOP_STR))
1658 #define AOP_USESDPTR2(x) ((AOP_TYPE(x) == AOP_DPTR2) || (AOP_TYPE(x) == AOP_DPTRn))
1660 // The following two macros can be used even if the aop has not yet been aopOp'd.
1661 #define AOP_IS_STR(x) (IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
1662 #define AOP_IS_DPTRn(x) (IS_SYMOP(x) && OP_SYMBOL(x)->dptr)
1664 /* Workaround for DS80C390 bug: div ab may return bogus results
1665 * if A is accessed in instruction immediately before the div.
1667 * Will be fixed in B4 rev of processor, Dallas claims.
1670 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1671 if (!AOP_NEEDSACC(RIGHT)) \
1673 /* We can load A first, then B, since \
1674 * B (the RIGHT operand) won't clobber A, \
1675 * thus avoiding touching A right before the div. \
1677 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1678 L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL); \
1680 L = aopGet(AOP(RIGHT),0,FALSE,FALSE,"b"); \
1685 /* Just stuff in a nop after loading A. */ \
1686 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,NULL));\
1687 L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL); \
1689 emitcode("nop", "; workaround for DS80C390 div bug."); \
1693 /*-----------------------------------------------------------------*/
1694 /* opIsGptr: returns non-zero if the passed operand is */
1695 /* a generic pointer type. */
1696 /*-----------------------------------------------------------------*/
1698 opIsGptr (operand * op)
1700 sym_link *type = operandType (op);
1702 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1709 /*-----------------------------------------------------------------*/
1710 /* getDataSize - get the operand data size */
1711 /*-----------------------------------------------------------------*/
1713 getDataSize (operand * op)
1716 size = AOP_SIZE (op);
1717 if (size == GPTRSIZE)
1719 sym_link *type = operandType (op);
1720 if (IS_GENPTR (type))
1722 /* generic pointer; arithmetic operations
1723 * should ignore the high byte (pointer type).
1731 /*-----------------------------------------------------------------*/
1732 /* outAcc - output Acc */
1733 /*-----------------------------------------------------------------*/
1735 outAcc (operand * result)
1738 size = getDataSize (result);
1741 aopPut (AOP (result), "a", 0);
1744 /* unsigned or positive */
1747 aopPut (AOP (result), zero, offset++);
1752 /*-----------------------------------------------------------------*/
1753 /* outBitC - output a bit C */
1754 /*-----------------------------------------------------------------*/
1756 outBitC (operand * result)
1758 /* if the result is bit */
1759 if (AOP_TYPE (result) == AOP_CRY)
1761 aopPut (AOP (result), "c", 0);
1765 emitcode ("clr", "a");
1766 emitcode ("rlc", "a");
1771 /*-----------------------------------------------------------------*/
1772 /* toBoolean - emit code for orl a,operator(sizeop) */
1773 /*-----------------------------------------------------------------*/
1775 toBoolean (operand * oper)
1777 int size = AOP_SIZE (oper) - 1;
1781 /* The generic part of a generic pointer should
1782 * not participate in it's truth value.
1784 * i.e. 0x10000000 is zero.
1786 if (opIsGptr (oper))
1788 D (emitcode (";", "toBoolean: generic ptr special case."););
1792 _startLazyDPSEvaluation ();
1793 if (AOP_NEEDSACC (oper) && size)
1798 emitcode ("push", "b");
1800 MOVB (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1804 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1811 emitcode ("orl", "b,%s",
1812 aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1816 emitcode ("orl", "a,%s",
1817 aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1820 _endLazyDPSEvaluation ();
1824 emitcode ("mov", "a,b");
1827 emitcode ("pop", "b");
1834 /*-----------------------------------------------------------------*/
1835 /* genNot - generate code for ! operation */
1836 /*-----------------------------------------------------------------*/
1842 D (emitcode (";", "genNot "););
1844 /* assign asmOps to operand & result */
1845 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1846 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1848 /* if in bit space then a special case */
1849 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1851 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1852 emitcode ("cpl", "c");
1853 outBitC (IC_RESULT (ic));
1857 toBoolean (IC_LEFT (ic));
1859 tlbl = newiTempLabel (NULL);
1860 emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1861 emitcode ("", "!tlabeldef", tlbl->key + 100);
1862 outBitC (IC_RESULT (ic));
1865 /* release the aops */
1866 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1867 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1871 /*-----------------------------------------------------------------*/
1872 /* genCpl - generate code for complement */
1873 /*-----------------------------------------------------------------*/
1881 D (emitcode (";", "genCpl "););
1884 /* assign asmOps to operand & result */
1885 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1886 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1888 /* special case if in bit space */
1889 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1890 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1891 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1892 emitcode ("cpl", "c");
1893 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1896 tlbl=newiTempLabel(NULL);
1897 emitcode ("cjne", "%s,#0x01,%05d$",
1898 aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE,NULL), tlbl->key+100);
1899 emitcode ("", "%05d$:", tlbl->key+100);
1900 outBitC (IC_RESULT(ic));
1904 size = AOP_SIZE (IC_RESULT (ic));
1905 _startLazyDPSEvaluation ();
1908 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
1909 emitcode ("cpl", "a");
1910 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1912 _endLazyDPSEvaluation ();
1916 /* release the aops */
1917 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1918 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1921 /*-----------------------------------------------------------------*/
1922 /* genUminusFloat - unary minus for floating points */
1923 /*-----------------------------------------------------------------*/
1925 genUminusFloat (operand * op, operand * result)
1927 int size, offset = 0;
1929 D(emitcode (";", "genUminusFloat"););
1931 /* for this we just copy and then flip the bit */
1933 _startLazyDPSEvaluation ();
1934 size = AOP_SIZE (op) - 1;
1938 aopPut (AOP (result),
1939 aopGet (AOP (op), offset, FALSE, FALSE, NULL),
1944 MOVA(aopGet (AOP (op), offset, FALSE, FALSE, NULL));
1946 emitcode ("cpl", "acc.7");
1947 aopPut (AOP (result), "a", offset);
1948 _endLazyDPSEvaluation ();
1951 /*-----------------------------------------------------------------*/
1952 /* genUminus - unary minus code generation */
1953 /*-----------------------------------------------------------------*/
1955 genUminus (iCode * ic)
1960 D (emitcode (";", "genUminus "););
1963 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1964 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1966 /* if both in bit space then special
1968 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1969 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1972 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1973 emitcode ("cpl", "c");
1974 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1978 optype = operandType (IC_LEFT (ic));
1980 /* if float then do float stuff */
1981 if (IS_FLOAT (optype))
1983 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1987 /* otherwise subtract from zero */
1988 size = AOP_SIZE (IC_LEFT (ic));
1990 _startLazyDPSEvaluation ();
1993 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL);
1994 if (!strcmp (l, "a"))
1998 emitcode ("cpl", "a");
1999 emitcode ("addc", "a,#0");
2005 emitcode ("clr", "a");
2006 emitcode ("subb", "a,%s", l);
2008 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2010 _endLazyDPSEvaluation ();
2012 /* if any remaining bytes in the result */
2013 /* we just need to propagate the sign */
2014 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic)))) != 0)
2016 emitcode ("rlc", "a");
2017 emitcode ("subb", "a,acc");
2019 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2023 /* release the aops */
2024 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2025 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2028 /*-----------------------------------------------------------------*/
2029 /* savermask - saves registers in the mask */
2030 /*-----------------------------------------------------------------*/
2031 static void savermask(bitVect *rs_mask)
2034 if (options.useXstack) {
2035 if (bitVectBitValue (rs_mask, R0_IDX))
2036 emitcode ("mov", "b,r0");
2037 emitcode ("mov", "r0,%s", spname);
2038 for (i = 0; i < ds390_nRegs; i++) {
2039 if (bitVectBitValue (rs_mask, i)) {
2041 emitcode ("mov", "a,b");
2043 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
2044 emitcode ("movx", "@r0,a");
2045 emitcode ("inc", "r0");
2048 emitcode ("mov", "%s,r0", spname);
2049 if (bitVectBitValue (rs_mask, R0_IDX))
2050 emitcode ("mov", "r0,b");
2052 for (i = 0; i < ds390_nRegs; i++) {
2053 if (bitVectBitValue (rs_mask, i))
2054 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2059 /*-----------------------------------------------------------------*/
2060 /* saveRegisters - will look for a call and save the registers */
2061 /*-----------------------------------------------------------------*/
2063 saveRegisters (iCode * lic)
2069 for (ic = lic; ic; ic = ic->next)
2070 if (ic->op == CALL || ic->op == PCALL)
2075 fprintf (stderr, "found parameter push with no function call\n");
2079 /* if the registers have been saved already then
2082 || (IS_SYMOP(IC_LEFT(ic)) && IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))) && !TARGET_IS_DS400) )
2085 /* special case if DPTR alive across a function call then must save it
2086 even though callee saves */
2087 if (IS_SYMOP(IC_LEFT(ic)) &&
2088 IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2090 rsave = newBitVect(ic->rMask->size);
2091 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2092 if (bitVectBitValue(ic->rMask,i))
2093 rsave = bitVectSetBit(rsave,i);
2095 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2097 /* safe the registers in use at this time but skip the
2098 ones for the result */
2099 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2100 ds390_rUmaskForOp (IC_RESULT(ic)));
2106 /*-----------------------------------------------------------------*/
2107 /* usavermask - restore registers with mask */
2108 /*-----------------------------------------------------------------*/
2109 static void unsavermask(bitVect *rs_mask)
2112 if (options.useXstack) {
2113 emitcode ("mov", "r0,%s", spname);
2114 for (i = ds390_nRegs; i >= 0; i--) {
2115 if (bitVectBitValue (rs_mask, i)) {
2116 emitcode ("dec", "r0");
2117 emitcode ("movx", "a,@r0");
2119 emitcode ("mov", "b,a");
2121 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
2124 emitcode ("mov", "%s,r0", spname);
2125 if (bitVectBitValue (rs_mask, R0_IDX))
2126 emitcode ("mov", "r0,b");
2128 for (i = ds390_nRegs; i >= 0; i--) {
2129 if (bitVectBitValue (rs_mask, i))
2130 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2135 /*-----------------------------------------------------------------*/
2136 /* unsaveRegisters - pop the pushed registers */
2137 /*-----------------------------------------------------------------*/
2139 unsaveRegisters (iCode * ic)
2143 if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2145 rsave = newBitVect(ic->rMask->size);
2146 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2147 if (bitVectBitValue(ic->rMask,i))
2148 rsave = bitVectSetBit(rsave,i);
2150 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2152 /* restore the registers in use at this time but skip the
2153 ones for the result */
2154 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2155 ds390_rUmaskForOp (IC_RESULT(ic)));
2161 /*-----------------------------------------------------------------*/
2163 /*-----------------------------------------------------------------*/
2165 pushSide (operand * oper, int size)
2168 _startLazyDPSEvaluation ();
2171 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, NULL);
2172 if (AOP_TYPE (oper) != AOP_REG &&
2173 AOP_TYPE (oper) != AOP_DIR &&
2176 emitcode ("mov", "a,%s", l);
2177 emitcode ("push", "acc");
2180 emitcode ("push", "%s", l);
2182 _endLazyDPSEvaluation ();
2185 /*-----------------------------------------------------------------*/
2186 /* assignResultValue - */
2187 /*-----------------------------------------------------------------*/
2189 assignResultValue (operand * oper)
2192 int size = AOP_SIZE (oper);
2193 bool pushedAcc = FALSE;
2195 if (size == fReturnSizeDS390)
2197 /* I don't think this case can ever happen... */
2198 /* ACC is the last part of this. If writing the result
2199 * uses AC, we must preserve it.
2201 if (AOP_NEEDSACC(oper))
2203 emitcode(";", "assignResultValue special case for ACC.");
2204 emitcode("push", "acc");
2211 _startLazyDPSEvaluation ();
2214 aopPut (AOP (oper), fReturn[offset], offset);
2217 _endLazyDPSEvaluation ();
2221 emitcode("pop", "acc");
2222 aopPut(AOP(oper), "a", offset);
2227 /*-----------------------------------------------------------------*/
2228 /* genXpush - pushes onto the external stack */
2229 /*-----------------------------------------------------------------*/
2231 genXpush (iCode * ic)
2233 asmop *aop = newAsmop (0);
2235 int size, offset = 0;
2237 D (emitcode (";", "genXpush ");
2240 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2241 r = getFreePtr (ic, &aop, FALSE);
2244 emitcode ("mov", "%s,_spx", r->name);
2246 size = AOP_SIZE (IC_LEFT (ic));
2247 _startLazyDPSEvaluation ();
2251 MOVA (aopGet (AOP (IC_LEFT (ic)),
2252 offset++, FALSE, FALSE, NULL));
2253 emitcode ("movx", "@%s,a", r->name);
2254 emitcode ("inc", "%s", r->name);
2257 _endLazyDPSEvaluation ();
2260 emitcode ("mov", "_spx,%s", r->name);
2262 freeAsmop (NULL, aop, ic, TRUE);
2263 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2266 /*-----------------------------------------------------------------*/
2267 /* genIpush - generate code for pushing this gets a little complex */
2268 /*-----------------------------------------------------------------*/
2270 genIpush (iCode * ic)
2272 int size, offset = 0;
2275 D (emitcode (";", "genIpush ");
2278 /* if this is not a parm push : ie. it is spill push
2279 and spill push is always done on the local stack */
2283 /* and the item is spilt then do nothing */
2284 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2287 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2288 size = AOP_SIZE (IC_LEFT (ic));
2289 /* push it on the stack */
2290 _startLazyDPSEvaluation ();
2293 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2299 emitcode ("push", "%s", l);
2301 _endLazyDPSEvaluation ();
2305 /* this is a paramter push: in this case we call
2306 the routine to find the call and save those
2307 registers that need to be saved */
2310 /* if use external stack then call the external
2311 stack pushing routine */
2312 if (options.useXstack)
2318 /* then do the push */
2319 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2321 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2322 size = AOP_SIZE (IC_LEFT (ic));
2324 _startLazyDPSEvaluation ();
2327 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2328 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2329 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2332 emitcode ("mov", "a,%s", l);
2333 emitcode ("push", "acc");
2337 emitcode ("push", "%s", l);
2340 _endLazyDPSEvaluation ();
2342 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2345 /*-----------------------------------------------------------------*/
2346 /* genIpop - recover the registers: can happen only for spilling */
2347 /*-----------------------------------------------------------------*/
2349 genIpop (iCode * ic)
2353 D (emitcode (";", "genIpop ");
2357 /* if the temp was not pushed then */
2358 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2361 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2362 size = AOP_SIZE (IC_LEFT (ic));
2363 offset = (size - 1);
2364 _startLazyDPSEvaluation ();
2367 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2368 FALSE, TRUE, NULL));
2370 _endLazyDPSEvaluation ();
2372 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2375 /*-----------------------------------------------------------------*/
2376 /* unsaveRBank - restores the resgister bank from stack */
2377 /*-----------------------------------------------------------------*/
2379 unsaveRBank (int bank, iCode * ic, bool popPsw)
2385 if (options.useXstack)
2389 /* Assume r0 is available for use. */
2390 r = ds390_regWithIdx (R0_IDX);;
2395 r = getFreePtr (ic, &aop, FALSE);
2397 emitcode ("mov", "%s,_spx", r->name);
2402 if (options.useXstack)
2404 emitcode ("movx", "a,@%s", r->name);
2405 emitcode ("mov", "psw,a");
2406 emitcode ("dec", "%s", r->name);
2410 emitcode ("pop", "psw");
2414 for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2416 if (options.useXstack)
2418 emitcode ("movx", "a,@%s", r->name);
2419 emitcode ("mov", "(%s+%d),a",
2420 regs390[i].base, 8 * bank + regs390[i].offset);
2421 emitcode ("dec", "%s", r->name);
2425 emitcode ("pop", "(%s+%d)",
2426 regs390[i].base, 8 * bank + regs390[i].offset);
2429 if (options.useXstack)
2431 emitcode ("mov", "_spx,%s", r->name);
2436 freeAsmop (NULL, aop, ic, TRUE);
2440 /*-----------------------------------------------------------------*/
2441 /* saveRBank - saves an entire register bank on the stack */
2442 /*-----------------------------------------------------------------*/
2444 saveRBank (int bank, iCode * ic, bool pushPsw)
2450 if (options.useXstack)
2454 /* Assume r0 is available for use. */
2455 r = ds390_regWithIdx (R0_IDX);;
2460 r = getFreePtr (ic, &aop, FALSE);
2462 emitcode ("mov", "%s,_spx", r->name);
2465 for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2467 if (options.useXstack)
2469 emitcode ("inc", "%s", r->name);
2470 emitcode ("mov", "a,(%s+%d)",
2471 regs390[i].base, 8 * bank + regs390[i].offset);
2472 emitcode ("movx", "@%s,a", r->name);
2475 emitcode ("push", "(%s+%d)",
2476 regs390[i].base, 8 * bank + regs390[i].offset);
2481 if (options.useXstack)
2483 emitcode ("mov", "a,psw");
2484 emitcode ("movx", "@%s,a", r->name);
2485 emitcode ("inc", "%s", r->name);
2486 emitcode ("mov", "_spx,%s", r->name);
2490 emitcode ("push", "psw");
2493 emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2498 freeAsmop (NULL, aop, ic, TRUE);
2507 /*-----------------------------------------------------------------*/
2508 /* genSend - gen code for SEND */
2509 /*-----------------------------------------------------------------*/
2510 static void genSend(set *sendSet)
2514 static int rb1_count = 0;
2516 for (sic = setFirstItem (sendSet); sic;
2517 sic = setNextItem (sendSet)) {
2518 int size, offset = 0;
2520 size=getSize(operandType(IC_LEFT(sic)));
2521 D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2522 if (sendCount == 0) { /* first parameter */
2523 // we know that dpl(hxb) is the result, so
2525 _startLazyDPSEvaluation ();
2527 aopOp (IC_LEFT (sic), sic, FALSE,
2528 (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2530 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2533 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2534 FALSE, FALSE, NULL);
2535 if (strcmp (l, fReturn[offset])) {
2536 emitcode ("mov", "%s,%s",
2542 _endLazyDPSEvaluation ();
2543 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2545 } else { /* if more parameter in registers */
2546 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2548 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
2549 FALSE, FALSE, NULL));
2551 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2558 adjustEsp(const char *reg)
2560 emitcode ("anl","%s,#3", reg);
2561 if (TARGET_IS_DS400)
2563 emitcode ("orl","%s,#!constbyte",
2565 (options.stack_loc >> 8) & 0xff);
2569 /*-----------------------------------------------------------------*/
2570 /* genCall - generates a call statement */
2571 /*-----------------------------------------------------------------*/
2573 genCall (iCode * ic)
2576 bool restoreBank = FALSE;
2577 bool swapBanks = FALSE;
2579 D (emitcode (";", "genCall "););
2581 /* if we are calling a not _naked function that is not using
2582 the same register bank then we need to save the
2583 destination registers on the stack */
2584 dtype = operandType (IC_LEFT (ic));
2585 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2586 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2587 IFFUNC_ISISR (currFunc->type))
2591 /* This is unexpected; the bank should have been saved in
2594 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2600 /* if caller saves & we have not saved then */
2604 /* if send set is not empty the assign */
2605 /* We've saved all the registers we care about;
2606 * therefore, we may clobber any register not used
2607 * in the calling convention (i.e. anything not in
2612 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2613 genSend(reverseSet(_G.sendSet));
2615 genSend(_G.sendSet);
2622 emitcode ("mov", "psw,#!constbyte",
2623 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2627 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2628 OP_SYMBOL (IC_LEFT (ic))->rname :
2629 OP_SYMBOL (IC_LEFT (ic))->name));
2633 emitcode ("mov", "psw,#!constbyte",
2634 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2637 /* if we need assign a result value */
2638 if ((IS_ITEMP (IC_RESULT (ic)) &&
2639 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2640 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2641 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2642 IS_TRUE_SYMOP (IC_RESULT (ic)))
2644 if (isOperandInFarSpace (IC_RESULT (ic))
2645 && getSize (operandType (IC_RESULT (ic))) <= 2)
2647 int size = getSize (operandType (IC_RESULT (ic)));
2649 /* Special case for 1 or 2 byte return in far space. */
2653 emitcode ("mov", "b,%s", fReturn[1]);
2656 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2657 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2661 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2663 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2668 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2671 assignResultValue (IC_RESULT (ic));
2673 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2677 /* adjust the stack for parameters if
2679 if (ic->parmBytes) {
2681 if (options.stack10bit) {
2682 if (ic->parmBytes <= 10) {
2683 emitcode(";","stack adjustment for parms");
2684 for (i=0; i < ic->parmBytes ; i++) {
2685 emitcode("pop","acc");
2689 emitcode ("clr","c");
2690 emitcode ("mov","a,sp");
2691 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2692 emitcode ("mov","sp,a");
2693 emitcode ("mov","a,esp");
2695 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2696 emitcode ("mov","esp,a");
2700 if (ic->parmBytes > 3) {
2701 emitcode ("mov", "a,%s", spname);
2702 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2703 emitcode ("mov", "%s,a", spname);
2705 for (i = 0; i < ic->parmBytes; i++)
2706 emitcode ("dec", "%s", spname);
2710 /* if we hade saved some registers then unsave them */
2712 unsaveRegisters (ic);
2714 /* if register bank was saved then pop them */
2716 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2719 /*-----------------------------------------------------------------*/
2720 /* genPcall - generates a call by pointer statement */
2721 /*-----------------------------------------------------------------*/
2723 genPcall (iCode * ic)
2726 symbol *rlbl = newiTempLabel (NULL);
2727 bool restoreBank=FALSE;
2729 D (emitcode (";", "genPcall ");
2733 /* if caller saves & we have not saved then */
2737 /* if we are calling a function that is not using
2738 the same register bank then we need to save the
2739 destination registers on the stack */
2740 dtype = operandType (IC_LEFT (ic));
2741 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2742 IFFUNC_ISISR (currFunc->type) &&
2743 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2744 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2748 /* push the return address on to the stack */
2749 emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2750 emitcode ("push", "acc");
2751 emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2752 emitcode ("push", "acc");
2754 if (options.model == MODEL_FLAT24)
2756 emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2757 emitcode ("push", "acc");
2760 /* now push the calling address */
2761 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2763 pushSide (IC_LEFT (ic), FPTRSIZE);
2765 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2767 /* if send set is not empty the assign */
2770 genSend(reverseSet(_G.sendSet));
2774 emitcode ("ret", "");
2775 emitcode ("", "!tlabeldef", (rlbl->key + 100));
2778 /* if we need assign a result value */
2779 if ((IS_ITEMP (IC_RESULT (ic)) &&
2780 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2781 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2782 IS_TRUE_SYMOP (IC_RESULT (ic)))
2786 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2789 assignResultValue (IC_RESULT (ic));
2791 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2794 /* adjust the stack for parameters if
2799 if (options.stack10bit) {
2800 if (ic->parmBytes <= 10) {
2801 emitcode(";","stack adjustment for parms");
2802 for (i=0; i < ic->parmBytes ; i++) {
2803 emitcode("pop","acc");
2807 emitcode ("clr","c");
2808 emitcode ("mov","a,sp");
2809 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2810 emitcode ("mov","sp,a");
2811 emitcode ("mov","a,esp");
2813 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2814 emitcode ("mov","esp,a");
2818 if (ic->parmBytes > 3) {
2819 emitcode ("mov", "a,%s", spname);
2820 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2821 emitcode ("mov", "%s,a", spname);
2824 for (i = 0; i < ic->parmBytes; i++)
2825 emitcode ("dec", "%s", spname);
2829 /* if register bank was saved then unsave them */
2831 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2833 /* if we hade saved some registers then
2836 unsaveRegisters (ic);
2840 /*-----------------------------------------------------------------*/
2841 /* resultRemat - result is rematerializable */
2842 /*-----------------------------------------------------------------*/
2844 resultRemat (iCode * ic)
2846 if (SKIP_IC (ic) || ic->op == IFX)
2849 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2851 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2852 if (sym->remat && !POINTER_SET (ic))
2859 #if defined(__BORLANDC__) || defined(_MSC_VER)
2860 #define STRCASECMP stricmp
2862 #define STRCASECMP strcasecmp
2865 /*-----------------------------------------------------------------*/
2866 /* inExcludeList - return 1 if the string is in exclude Reg list */
2867 /*-----------------------------------------------------------------*/
2869 regsCmp(void *p1, void *p2)
2871 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2875 inExcludeList (char *s)
2877 const char *p = setFirstItem(options.excludeRegsSet);
2879 if (p == NULL || STRCASECMP(p, "none") == 0)
2883 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2886 /*-----------------------------------------------------------------*/
2887 /* genFunction - generated code for function entry */
2888 /*-----------------------------------------------------------------*/
2890 genFunction (iCode * ic)
2894 bool switchedPSW = FALSE;
2896 D (emitcode (";", "genFunction "););
2899 /* create the function header */
2900 emitcode (";", "-----------------------------------------");
2901 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2902 emitcode (";", "-----------------------------------------");
2904 emitcode ("", "%s:", sym->rname);
2905 ftype = operandType (IC_LEFT (ic));
2907 if (IFFUNC_ISNAKED(ftype))
2909 emitcode(";", "naked function: no prologue.");
2913 if (options.stack_probe)
2914 emitcode ("lcall","__stack_probe");
2916 /* here we need to generate the equates for the
2917 register bank if required */
2918 if (FUNC_REGBANK (ftype) != rbank)
2922 rbank = FUNC_REGBANK (ftype);
2923 for (i = 0; i < ds390_nRegs; i++)
2925 if (regs390[i].print) {
2926 if (strcmp (regs390[i].base, "0") == 0)
2927 emitcode ("", "%s !equ !constbyte",
2929 8 * rbank + regs390[i].offset);
2931 emitcode ("", "%s !equ %s + !constbyte",
2934 8 * rbank + regs390[i].offset);
2939 /* if this is an interrupt service routine then
2940 save acc, b, dpl, dph */
2941 if (IFFUNC_ISISR (sym->type))
2943 if (!inExcludeList ("acc"))
2944 emitcode ("push", "acc");
2945 if (!inExcludeList ("b"))
2946 emitcode ("push", "b");
2947 if (!inExcludeList ("dpl"))
2948 emitcode ("push", "dpl");
2949 if (!inExcludeList ("dph"))
2950 emitcode ("push", "dph");
2951 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2953 emitcode ("push", "dpx");
2954 /* Make sure we're using standard DPTR */
2955 emitcode ("push", "dps");
2956 emitcode ("mov", "dps,#0");
2957 if (options.stack10bit)
2959 /* This ISR could conceivably use DPTR2. Better save it. */
2960 emitcode ("push", "dpl1");
2961 emitcode ("push", "dph1");
2962 emitcode ("push", "dpx1");
2963 emitcode ("push", DP2_RESULT_REG);
2966 /* if this isr has no bank i.e. is going to
2967 run with bank 0 , then we need to save more
2969 if (!FUNC_REGBANK (sym->type))
2973 /* if this function does not call any other
2974 function then we can be economical and
2975 save only those registers that are used */
2976 if (!IFFUNC_HASFCALL(sym->type))
2979 /* if any registers used */
2982 /* save the registers used */
2983 for (i = 0; i < sym->regsUsed->size; i++)
2985 if (bitVectBitValue (sym->regsUsed, i) ||
2986 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2987 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2994 /* this function has a function call cannot
2995 determines register usage so we will have to push the
2997 saveRBank (0, ic, FALSE);
2998 if (options.parms_in_bank1) {
2999 for (i=0; i < 8 ; i++ ) {
3000 emitcode ("push","%s",rb1regs[i]);
3007 /* This ISR uses a non-zero bank.
3009 * We assume that the bank is available for our
3012 * However, if this ISR calls a function which uses some
3013 * other bank, we must save that bank entirely.
3015 unsigned long banksToSave = 0;
3017 if (IFFUNC_HASFCALL(sym->type))
3020 #define MAX_REGISTER_BANKS 4
3025 for (i = ic; i; i = i->next)
3027 if (i->op == ENDFUNCTION)
3029 /* we got to the end OK. */
3037 dtype = operandType (IC_LEFT(i));
3039 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3041 /* Mark this bank for saving. */
3042 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3044 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3048 banksToSave |= (1 << FUNC_REGBANK(dtype));
3051 /* And note that we don't need to do it in
3059 /* This is a mess; we have no idea what
3060 * register bank the called function might
3063 * The only thing I can think of to do is
3064 * throw a warning and hope.
3066 werror(W_FUNCPTR_IN_USING_ISR);
3070 if (banksToSave && options.useXstack)
3072 /* Since we aren't passing it an ic,
3073 * saveRBank will assume r0 is available to abuse.
3075 * So switch to our (trashable) bank now, so
3076 * the caller's R0 isn't trashed.
3078 emitcode ("push", "psw");
3079 emitcode ("mov", "psw,#!constbyte",
3080 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3084 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3086 if (banksToSave & (1 << ix))
3088 saveRBank(ix, NULL, FALSE);
3092 // TODO: this needs a closer look
3093 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3098 /* if callee-save to be used for this function
3099 then save the registers being used in this function */
3100 if (IFFUNC_CALLEESAVES(sym->type))
3104 /* if any registers used */
3107 /* save the registers used */
3108 for (i = 0; i < sym->regsUsed->size; i++)
3110 if (bitVectBitValue (sym->regsUsed, i) ||
3111 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3113 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3121 /* set the register bank to the desired value */
3122 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3125 emitcode ("push", "psw");
3126 emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3129 if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3130 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3131 if (options.stack10bit) {
3132 emitcode ("push","_bpx");
3133 emitcode ("push","_bpx+1");
3134 emitcode ("mov","_bpx,%s",spname);
3135 emitcode ("mov","_bpx+1,esp");
3136 adjustEsp("_bpx+1");
3138 if (options.useXstack) {
3139 emitcode ("mov", "r0,%s", spname);
3140 emitcode ("mov", "a,_bp");
3141 emitcode ("movx", "@r0,a");
3142 emitcode ("inc", "%s", spname);
3144 /* set up the stack */
3145 emitcode ("push", "_bp"); /* save the callers stack */
3147 emitcode ("mov", "_bp,%s", spname);
3151 /* adjust the stack for the function */
3154 if (options.stack10bit) {
3155 if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
3156 assert (sym->recvSize <= 4);
3157 if (sym->stack <= 8) {
3158 while (i--) emitcode ("push","acc");
3161 emitcode ("mov","a,sp");
3162 emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3163 emitcode ("mov","sp,a");
3164 emitcode ("mov","a,esp");
3166 emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3167 emitcode ("mov","esp,a");
3172 werror (W_STACK_OVERFLOW, sym->name);
3174 if (i > 3 && sym->recvSize < 4) {
3176 emitcode ("mov", "a,sp");
3177 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3178 emitcode ("mov", "sp,a");
3182 emitcode ("inc", "sp");
3189 emitcode ("mov", "a,_spx");
3190 emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3191 emitcode ("mov", "_spx,a");
3194 /* if critical function then turn interrupts off */
3195 if (IFFUNC_ISCRITICAL (ftype))
3197 emitcode ("mov", "c,ea");
3198 emitcode ("push", "psw"); /* save old ea via c in psw */
3199 emitcode ("clr", "ea");
3204 /*-----------------------------------------------------------------*/
3205 /* genEndFunction - generates epilogue for functions */
3206 /*-----------------------------------------------------------------*/
3208 genEndFunction (iCode * ic)
3210 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3212 D (emitcode (";", "genEndFunction "););
3214 if (IFFUNC_ISNAKED(sym->type))
3216 emitcode(";", "naked function: no epilogue.");
3220 if (IFFUNC_ISCRITICAL (sym->type))
3222 emitcode ("pop", "psw"); /* restore ea via c in psw */
3223 emitcode ("mov", "ea,c");
3226 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3227 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3229 if (options.stack10bit) {
3231 emitcode ("mov", "sp,_bpx", spname);
3232 emitcode ("mov", "esp,_bpx+1", spname);
3235 emitcode ("mov", "%s,_bp", spname);
3239 /* if use external stack but some variables were
3240 added to the local stack then decrement the
3242 if (options.useXstack && sym->stack) {
3243 emitcode ("mov", "a,sp");
3244 emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3245 emitcode ("mov", "sp,a");
3249 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3250 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3252 if (options.useXstack) {
3253 emitcode ("mov", "r0,%s", spname);
3254 emitcode ("movx", "a,@r0");
3255 emitcode ("mov", "_bp,a");
3256 emitcode ("dec", "%s", spname);
3258 if (options.stack10bit) {
3259 emitcode ("pop", "_bpx+1");
3260 emitcode ("pop", "_bpx");
3262 emitcode ("pop", "_bp");
3267 /* restore the register bank */
3268 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3270 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3271 || !options.useXstack)
3273 /* Special case of ISR using non-zero bank with useXstack
3276 emitcode ("pop", "psw");
3280 if (IFFUNC_ISISR (sym->type))
3283 /* now we need to restore the registers */
3284 /* if this isr has no bank i.e. is going to
3285 run with bank 0 , then we need to save more
3287 if (!FUNC_REGBANK (sym->type))
3290 /* if this function does not call any other
3291 function then we can be economical and
3292 save only those registers that are used */
3293 if (!IFFUNC_HASFCALL(sym->type))
3296 /* if any registers used */
3299 /* save the registers used */
3300 for (i = sym->regsUsed->size; i >= 0; i--)
3302 if (bitVectBitValue (sym->regsUsed, i) ||
3303 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3304 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3311 /* this function has a function call cannot
3312 determines register usage so we will have to pop the
3314 if (options.parms_in_bank1) {
3315 for (i = 7 ; i >= 0 ; i-- ) {
3316 emitcode ("pop","%s",rb1regs[i]);
3319 unsaveRBank (0, ic, FALSE);
3324 /* This ISR uses a non-zero bank.
3326 * Restore any register banks saved by genFunction
3329 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3332 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3334 if (savedBanks & (1 << ix))
3336 unsaveRBank(ix, NULL, FALSE);
3340 if (options.useXstack)
3342 /* Restore bank AFTER calling unsaveRBank,
3343 * since it can trash r0.
3345 emitcode ("pop", "psw");
3349 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3351 if (options.stack10bit)
3353 emitcode ("pop", DP2_RESULT_REG);
3354 emitcode ("pop", "dpx1");
3355 emitcode ("pop", "dph1");
3356 emitcode ("pop", "dpl1");
3358 emitcode ("pop", "dps");
3359 emitcode ("pop", "dpx");
3361 if (!inExcludeList ("dph"))
3362 emitcode ("pop", "dph");
3363 if (!inExcludeList ("dpl"))
3364 emitcode ("pop", "dpl");
3365 if (!inExcludeList ("b"))
3366 emitcode ("pop", "b");
3367 if (!inExcludeList ("acc"))
3368 emitcode ("pop", "acc");
3370 /* if debug then send end of function */
3371 if (options.debug && currFunc) {
3373 emitcode ("", "C$%s$%d$%d$%d ==.",
3374 FileBaseName (ic->filename), currFunc->lastLine,
3375 ic->level, ic->block);
3376 if (IS_STATIC (currFunc->etype))
3377 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3379 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3383 emitcode ("reti", "");
3387 if (IFFUNC_CALLEESAVES(sym->type))
3391 /* if any registers used */
3394 /* save the registers used */
3395 for (i = sym->regsUsed->size; i >= 0; i--)
3397 if (bitVectBitValue (sym->regsUsed, i) ||
3398 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3399 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3405 /* if debug then send end of function */
3406 if (options.debug && currFunc)
3409 emitcode ("", "C$%s$%d$%d$%d ==.",
3410 FileBaseName (ic->filename), currFunc->lastLine,
3411 ic->level, ic->block);
3412 if (IS_STATIC (currFunc->etype))
3413 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3415 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3419 emitcode ("ret", "");
3424 /*-----------------------------------------------------------------*/
3425 /* genJavaNativeRet - generate code for return JavaNative */
3426 /*-----------------------------------------------------------------*/
3427 static void genJavaNativeRet(iCode *ic)
3431 aopOp (IC_LEFT (ic), ic, FALSE,
3432 AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
3433 size = AOP_SIZE (IC_LEFT (ic));
3437 /* it is assigned to GPR0-R3 then push them */
3438 if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3439 aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3440 for (i = 0 ; i < size ; i++ ) {
3441 emitcode ("push","%s",
3442 aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3444 for (i = (size-1) ; i >= 0 ; i--) {
3445 emitcode ("pop","a%s",javaRet[i]);
3448 for (i = 0 ; i < size ; i++)
3449 emitcode ("mov","%s,%s",javaRet[i],
3450 aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3452 for (i = size ; i < 4 ; i++ )
3453 emitcode ("mov","%s,#0",javaRet[i]);
3457 /*-----------------------------------------------------------------*/
3458 /* genRet - generate code for return statement */
3459 /*-----------------------------------------------------------------*/
3463 int size, offset = 0, pushed = 0;
3465 D (emitcode (";", "genRet "););
3467 /* if we have no return value then
3468 just generate the "ret" */
3472 /* if this is a JavaNative function then return
3473 value in different register */
3474 if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3475 genJavaNativeRet(ic);
3478 /* we have something to return then
3479 move the return value into place */
3480 aopOp (IC_LEFT (ic), ic, FALSE,
3481 (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
3482 size = AOP_SIZE (IC_LEFT (ic));
3484 _startLazyDPSEvaluation ();
3488 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3490 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3492 emitcode ("push", "%s", l);
3497 /* Since A is the last element of fReturn,
3498 * is is OK to clobber it in the aopGet.
3500 l = aopGet (AOP (IC_LEFT (ic)), offset,
3501 FALSE, FALSE, NULL);
3502 if (strcmp (fReturn[offset], l))
3503 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3506 _endLazyDPSEvaluation ();
3513 if (strcmp (fReturn[pushed], "a"))
3514 emitcode ("pop", fReturn[pushed]);
3516 emitcode ("pop", "acc");
3519 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3522 /* generate a jump to the return label
3523 if the next is not the return statement */
3524 if (!(ic->next && ic->next->op == LABEL &&
3525 IC_LABEL (ic->next) == returnLabel))
3527 emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3531 /*-----------------------------------------------------------------*/
3532 /* genLabel - generates a label */
3533 /*-----------------------------------------------------------------*/
3535 genLabel (iCode * ic)
3537 /* special case never generate */
3538 if (IC_LABEL (ic) == entryLabel)
3541 D (emitcode (";", "genLabel ");
3544 emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3547 /*-----------------------------------------------------------------*/
3548 /* genGoto - generates a ljmp */
3549 /*-----------------------------------------------------------------*/
3551 genGoto (iCode * ic)
3553 D (emitcode (";", "genGoto ");
3555 emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3558 /*-----------------------------------------------------------------*/
3559 /* findLabelBackwards: walks back through the iCode chain looking */
3560 /* for the given label. Returns number of iCode instructions */
3561 /* between that label and given ic. */
3562 /* Returns zero if label not found. */
3563 /*-----------------------------------------------------------------*/
3565 findLabelBackwards (iCode * ic, int key)
3574 /* If we have any pushes or pops, we cannot predict the distance.
3575 I don't like this at all, this should be dealt with in the
3577 if (ic->op == IPUSH || ic->op == IPOP) {
3581 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3583 /* printf("findLabelBackwards = %d\n", count); */
3591 /*-----------------------------------------------------------------*/
3592 /* genPlusIncr :- does addition with increment if possible */
3593 /*-----------------------------------------------------------------*/
3595 genPlusIncr (iCode * ic)
3597 unsigned int icount;
3598 unsigned int size = getDataSize (IC_RESULT (ic));
3600 /* will try to generate an increment */
3601 /* if the right side is not a literal
3603 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3606 /* if the literal value of the right hand side
3607 is greater than 4 then it is not worth it */
3608 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3611 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3612 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3614 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
3618 /* if increment 16 bits in register */
3620 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3621 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3622 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3631 /* If the next instruction is a goto and the goto target
3632 * is <= 5 instructions previous to this, we can generate
3633 * jumps straight to that target.
3635 if (ic->next && ic->next->op == GOTO
3636 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3639 D(emitcode (";", "tail increment optimized (range %d)", labelRange););
3640 tlbl = IC_LABEL (ic->next);
3645 tlbl = newiTempLabel (NULL);
3649 l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
3650 emitcode ("inc", "%s", l);
3652 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3653 IS_AOP_PREG (IC_RESULT (ic)))
3655 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3659 emitcode ("clr", "a");
3660 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3663 l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
3664 emitcode ("inc", "%s", l);
3667 if (!strcmp(l, "acc"))
3669 emitcode("jnz", "!tlabel", tlbl->key + 100);
3671 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3672 IS_AOP_PREG (IC_RESULT (ic)))
3674 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3678 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3681 l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
3682 emitcode ("inc", "%s", l);
3686 if (!strcmp(l, "acc"))
3688 emitcode("jnz", "!tlabel", tlbl->key + 100);
3690 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3691 IS_AOP_PREG (IC_RESULT (ic)))
3693 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3697 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3700 l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
3701 emitcode ("inc", "%s", l); }
3705 emitcode ("", "!tlabeldef", tlbl->key + 100);
3710 if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3711 !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 &&
3712 options.model == MODEL_FLAT24 ) {
3716 emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, NULL));
3718 emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, NULL));
3720 emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3723 while (icount--) emitcode ("inc","dptr");
3727 if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3728 AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3730 emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3731 while (icount--) emitcode ("inc","dptr");
3732 emitcode ("mov","dps,#0");
3736 /* if the sizes are greater than 1 then we cannot */
3737 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3738 AOP_SIZE (IC_LEFT (ic)) > 1)
3741 /* we can if the aops of the left & result match or
3742 if they are in registers and the registers are the
3745 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3746 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3747 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3752 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3753 emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3754 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3759 _startLazyDPSEvaluation ();
3762 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3764 _endLazyDPSEvaluation ();
3773 /*-----------------------------------------------------------------*/
3774 /* outBitAcc - output a bit in acc */
3775 /*-----------------------------------------------------------------*/
3777 outBitAcc (operand * result)
3779 symbol *tlbl = newiTempLabel (NULL);
3780 /* if the result is a bit */
3781 if (AOP_TYPE (result) == AOP_CRY)
3783 aopPut (AOP (result), "a", 0);
3787 emitcode ("jz", "!tlabel", tlbl->key + 100);
3788 emitcode ("mov", "a,%s", one);
3789 emitcode ("", "!tlabeldef", tlbl->key + 100);
3794 /*-----------------------------------------------------------------*/
3795 /* genPlusBits - generates code for addition of two bits */
3796 /*-----------------------------------------------------------------*/
3798 genPlusBits (iCode * ic)
3800 D (emitcode (";", "genPlusBits "););
3802 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3804 symbol *lbl = newiTempLabel (NULL);
3805 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3806 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3807 emitcode ("cpl", "c");
3808 emitcode ("", "!tlabeldef", (lbl->key + 100));
3809 outBitC (IC_RESULT (ic));
3813 emitcode ("clr", "a");
3814 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3815 emitcode ("rlc", "a");
3816 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3817 emitcode ("addc", "a,#0");
3818 outAcc (IC_RESULT (ic));
3823 adjustArithmeticResult (iCode * ic)
3825 if (opIsGptr (IC_RESULT (ic)) &&
3826 opIsGptr (IC_LEFT (ic)) &&
3827 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3829 aopPut (AOP (IC_RESULT (ic)),
3830 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3834 if (opIsGptr (IC_RESULT (ic)) &&
3835 opIsGptr (IC_RIGHT (ic)) &&
3836 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3838 aopPut (AOP (IC_RESULT (ic)),
3839 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3843 if (opIsGptr (IC_RESULT (ic)) &&
3844 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3845 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3846 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3847 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3850 SNPRINTF (buff, sizeof(buff),
3851 "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3852 aopPut (AOP (IC_RESULT (ic)), buff, GPTRSIZE - 1);
3856 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
3857 // generates the result if possible. If result is generated, returns TRUE; otherwise
3858 // returns false and caller must deal with fact that result isn't aopOp'd.
3859 bool aopOp3(iCode * ic)
3861 bool dp1InUse, dp2InUse;
3864 // First, generate the right opcode. DPTR may be used if neither left nor result are
3867 // D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
3868 // AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
3869 // AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
3870 // AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
3872 // D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
3873 // AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
3874 // AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
3875 // AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
3878 // Right uses DPTR unless left or result is an AOP_STR; however,
3879 // if right is an AOP_STR, it must use DPTR regardless.
3880 if ((AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)))
3881 && !AOP_IS_STR(IC_RIGHT(ic)))
3890 aopOp (IC_RIGHT(ic),ic,FALSE, useDp2);
3892 // if the right used DPTR, left MUST use DPTR2.
3893 // if the right used DPTR2, left MUST use DPTR.
3894 // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
3895 // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
3896 // enabling us to assign DPTR to result.
3898 if (AOP_USESDPTR(IC_RIGHT(ic)))
3902 else if (AOP_USESDPTR2(IC_RIGHT(ic)))
3908 if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
3918 aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
3920 // We've op'd the left & right. So, if left or right are the same operand as result,
3921 // we know aopOp will succeed, and we can just do it & bail.
3922 if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)) ||
3923 isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
3925 // D(emitcode(";", "aopOp3: (left | right) & result equal"););
3926 aopOp(IC_RESULT(ic),ic,TRUE, FALSE);
3930 // Note which dptrs are currently in use.
3931 dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
3932 dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
3934 // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot
3936 if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
3941 // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
3942 if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
3947 // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck
3948 if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
3953 aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
3955 // Some sanity checking...
3956 if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
3959 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
3960 __FILE__, __LINE__, ic->filename, ic->lineno);
3961 emitcode(";", ">>> unexpected DPTR here.");
3964 if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
3967 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
3968 __FILE__, __LINE__, ic->filename, ic->lineno);
3969 emitcode(";", ">>> unexpected DPTR2 here.");
3975 // Macro to aopOp all three operands of an ic. If this cannot be done,
3976 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3977 // will be set TRUE. The caller must then handle the case specially, noting
3978 // that the IC_RESULT operand is not aopOp'd.
3980 #define AOP_OP_3_NOFATAL(ic, rc) \
3981 do { rc = !aopOp3(ic); } while (0)
3983 // aopOp the left & right operands of an ic.
3984 #define AOP_OP_2(ic) \
3985 aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
3986 aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
3988 // convienience macro.
3989 #define AOP_SET_LOCALS(ic) \
3990 left = IC_LEFT(ic); \
3991 right = IC_RIGHT(ic); \
3992 result = IC_RESULT(ic);
3995 // Given an integer value of pushedSize bytes on the stack,
3996 // adjust it to be resultSize bytes, either by discarding
3997 // the most significant bytes or by zero-padding.
3999 // On exit from this macro, pushedSize will have been adjusted to
4000 // equal resultSize, and ACC may be trashed.
4001 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
4002 /* If the pushed data is bigger than the result, \
4003 * simply discard unused bytes. Icky, but works. \
4005 while (pushedSize > resultSize) \
4007 D (emitcode (";", "discarding unused result byte."););\
4008 emitcode ("pop", "acc"); \
4011 if (pushedSize < resultSize) \
4013 emitcode ("clr", "a"); \
4014 /* Conversly, we haven't pushed enough here. \
4015 * just zero-pad, and all is well. \
4017 while (pushedSize < resultSize) \
4019 emitcode("push", "acc"); \
4023 assert(pushedSize == resultSize);
4025 /*-----------------------------------------------------------------*/
4026 /* genPlus - generates code for addition */
4027 /*-----------------------------------------------------------------*/
4029 genPlus (iCode * ic)
4031 int size, offset = 0;
4035 D (emitcode (";", "genPlus "););
4037 /* special cases :- */
4038 if ( AOP_IS_STR(IC_LEFT(ic)) &&
4039 isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
4040 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
4041 size = (int)floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
4043 while (size--) emitcode ("inc","dptr");
4045 emitcode ("mov","a,dpl");
4046 emitcode ("add","a,#!constbyte",size & 0xff);
4047 emitcode ("mov","dpl,a");
4048 emitcode ("mov","a,dph");
4049 emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
4050 emitcode ("mov","dph,a");
4051 emitcode ("mov","a,dpx");
4052 emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
4053 emitcode ("mov","dpx,a");
4055 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
4058 if ( IS_SYMOP(IC_LEFT(ic)) &&
4059 OP_SYMBOL(IC_LEFT(ic))->remat &&
4060 isOperandInFarSpace(IC_RIGHT(ic))) {
4061 operand *op = IC_RIGHT(ic);
4062 IC_RIGHT(ic) = IC_LEFT(ic);
4066 AOP_OP_3_NOFATAL (ic, pushResult);
4070 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
4075 /* if literal, literal on the right or
4076 if left requires ACC or right is already
4078 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4079 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
4080 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4082 operand *t = IC_RIGHT (ic);
4083 IC_RIGHT (ic) = IC_LEFT (ic);
4085 emitcode (";", "Swapped plus args.");
4088 /* if both left & right are in bit
4090 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4091 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4097 /* if left in bit space & right literal */
4098 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4099 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4101 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4102 /* if result in bit space */
4103 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4105 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4106 emitcode ("cpl", "c");
4107 outBitC (IC_RESULT (ic));
4111 size = getDataSize (IC_RESULT (ic));
4112 _startLazyDPSEvaluation ();
4115 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4116 emitcode ("addc", "a,#0");
4117 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4119 _endLazyDPSEvaluation ();
4124 /* if I can do an increment instead
4125 of add then GOOD for ME */
4126 if (genPlusIncr (ic) == TRUE)
4128 emitcode (";", "did genPlusIncr");
4133 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4135 _startLazyDPSEvaluation ();
4138 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4140 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4142 emitcode ("add", "a,%s",
4143 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4145 emitcode ("addc", "a,%s",
4146 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4150 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4152 /* right is going to use ACC or we would have taken the
4155 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4157 D(emitcode(";", "+ AOP_ACC special case."););
4158 emitcode("xch", "a, %s", DP2_RESULT_REG);
4160 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4163 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4166 emitcode("add", "a, %s", DP2_RESULT_REG);
4170 emitcode ("add", "a,%s",
4171 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE,
4177 emitcode ("addc", "a,%s",
4178 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE,
4184 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4188 emitcode ("push", "acc");
4192 _endLazyDPSEvaluation ();
4196 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4198 size = getDataSize (IC_LEFT (ic));
4199 rSize = getDataSize (IC_RESULT (ic));
4201 ADJUST_PUSHED_RESULT(size, rSize);
4203 _startLazyDPSEvaluation ();
4206 emitcode ("pop", "acc");
4207 aopPut (AOP (IC_RESULT (ic)), "a", size);
4209 _endLazyDPSEvaluation ();
4212 adjustArithmeticResult (ic);
4215 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4216 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4217 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4220 /*-----------------------------------------------------------------*/
4221 /* genMinusDec :- does subtraction with deccrement if possible */
4222 /*-----------------------------------------------------------------*/
4224 genMinusDec (iCode * ic)
4226 unsigned int icount;
4227 unsigned int size = getDataSize (IC_RESULT (ic));
4229 /* will try to generate an increment */
4230 /* if the right side is not a literal
4232 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4235 /* if the literal value of the right hand side
4236 is greater than 4 then it is not worth it */
4237 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4240 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4241 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4243 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
4247 /* if decrement 16 bits in register */
4248 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4249 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4250 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4259 /* If the next instruction is a goto and the goto target
4260 * is <= 5 instructions previous to this, we can generate
4261 * jumps straight to that target.
4263 if (ic->next && ic->next->op == GOTO
4264 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4267 emitcode (";", "tail decrement optimized (range %d)", labelRange);
4268 tlbl = IC_LABEL (ic->next);
4273 tlbl = newiTempLabel (NULL);
4277 l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
4278 emitcode ("dec", "%s", l);
4280 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4281 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4282 IS_AOP_PREG (IC_RESULT (ic)))
4284 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4288 emitcode ("mov", "a,#!constbyte",0xff);
4289 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4291 l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
4292 emitcode ("dec", "%s", l);
4295 if (!strcmp(l, "acc"))
4297 emitcode("jnz", "!tlabel", tlbl->key + 100);
4299 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4300 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4301 IS_AOP_PREG (IC_RESULT (ic)))
4303 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4307 emitcode ("mov", "a,#!constbyte",0xff);
4308 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4310 l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
4311 emitcode ("dec", "%s", l);
4315 if (!strcmp(l, "acc"))
4317 emitcode("jnz", "!tlabel", tlbl->key + 100);
4319 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4320 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4321 IS_AOP_PREG (IC_RESULT (ic)))
4323 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4327 emitcode ("mov", "a,#!constbyte",0xff);
4328 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4330 l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
4331 emitcode ("dec", "%s", l);
4335 emitcode ("", "!tlabeldef", tlbl->key + 100);
4340 /* if the sizes are greater than 1 then we cannot */
4341 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4342 AOP_SIZE (IC_LEFT (ic)) > 1)
4345 /* we can if the aops of the left & result match or
4346 if they are in registers and the registers are the
4349 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4350 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4351 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4354 _startLazyDPSEvaluation ();
4357 emitcode ("dec", "%s",
4358 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
4360 _endLazyDPSEvaluation ();
4368 /*-----------------------------------------------------------------*/
4369 /* addSign - complete with sign */
4370 /*-----------------------------------------------------------------*/
4372 addSign (operand * result, int offset, int sign)
4374 int size = (getDataSize (result) - offset);
4377 _startLazyDPSEvaluation();
4380 emitcode ("rlc", "a");
4381 emitcode ("subb", "a,acc");
4384 aopPut (AOP (result), "a", offset++);
4391 aopPut (AOP (result), zero, offset++);
4394 _endLazyDPSEvaluation();
4398 /*-----------------------------------------------------------------*/
4399 /* genMinusBits - generates code for subtraction of two bits */
4400 /*-----------------------------------------------------------------*/
4402 genMinusBits (iCode * ic)
4404 symbol *lbl = newiTempLabel (NULL);
4406 D (emitcode (";", "genMinusBits "););
4408 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4410 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4411 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4412 emitcode ("cpl", "c");
4413 emitcode ("", "!tlabeldef", (lbl->key + 100));
4414 outBitC (IC_RESULT (ic));
4418 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4419 emitcode ("subb", "a,acc");
4420 emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4421 emitcode ("inc", "a");
4422 emitcode ("", "!tlabeldef", (lbl->key + 100));
4423 aopPut (AOP (IC_RESULT (ic)), "a", 0);
4424 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4428 /*-----------------------------------------------------------------*/
4429 /* genMinus - generates code for subtraction */
4430 /*-----------------------------------------------------------------*/
4432 genMinus (iCode * ic)
4434 int size, offset = 0;
4439 D (emitcode (";", "genMinus "););
4441 AOP_OP_3_NOFATAL(ic, pushResult);
4445 /* special cases :- */
4446 /* if both left & right are in bit space */
4447 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4448 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4454 /* if I can do an decrement instead
4455 of subtract then GOOD for ME */
4456 if (genMinusDec (ic) == TRUE)
4461 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4463 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4469 lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4474 /* if literal, add a,#-lit, else normal subb */
4475 _startLazyDPSEvaluation ();
4477 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4478 if (AOP_USESDPTR(IC_RIGHT(ic))) {
4479 emitcode ("mov","b,%s",
4480 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4481 MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4482 emitcode ("subb","a,b");
4484 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4485 emitcode ("subb", "a,%s",
4486 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE,
4490 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4491 /* first add without previous c */
4493 if (!size && lit==-1) {
4494 emitcode ("dec", "a");
4496 emitcode ("add", "a,#!constbyte",
4497 (unsigned int) (lit & 0x0FFL));
4500 emitcode ("addc", "a,#!constbyte",
4501 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4506 emitcode ("push", "acc");
4508 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4512 _endLazyDPSEvaluation ();
4516 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4518 size = getDataSize (IC_LEFT (ic));
4519 rSize = getDataSize (IC_RESULT (ic));
4521 ADJUST_PUSHED_RESULT(size, rSize);
4523 _startLazyDPSEvaluation ();
4526 emitcode ("pop", "acc");
4527 aopPut (AOP (IC_RESULT (ic)), "a", size);
4529 _endLazyDPSEvaluation ();
4532 adjustArithmeticResult (ic);
4535 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4536 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4537 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4541 /*-----------------------------------------------------------------*/
4542 /* genMultbits :- multiplication of bits */
4543 /*-----------------------------------------------------------------*/
4545 genMultbits (operand * left,
4550 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4551 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4552 aopOp(result, ic, TRUE, FALSE);
4557 /*-----------------------------------------------------------------*/
4558 /* genMultOneByte : 8*8=8/16 bit multiplication */
4559 /*-----------------------------------------------------------------*/
4561 genMultOneByte (operand * left,
4566 sym_link *opetype = operandType (result);
4570 /* (if two literals: the value is computed before) */
4571 /* if one literal, literal on the right */
4572 if (AOP_TYPE (left) == AOP_LIT)
4577 emitcode (";", "swapped left and right");
4580 if (SPEC_USIGN(opetype)
4581 // ignore the sign of left and right, what else can we do?
4582 || (SPEC_USIGN(operandType(left)) &&
4583 SPEC_USIGN(operandType(right)))) {
4584 // just an unsigned 8*8=8/16 multiply
4585 //emitcode (";","unsigned");
4586 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4587 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4588 emitcode ("mul", "ab");
4590 _G.accInUse++; _G.bInUse++;
4591 aopOp(result, ic, TRUE, FALSE);
4593 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4595 // this should never happen
4596 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4597 AOP_SIZE(result), __FILE__, lineno);
4601 aopPut (AOP (result), "a", 0);
4602 _G.accInUse--; _G.bInUse--;
4603 if (AOP_SIZE(result)==2)
4605 aopPut (AOP (result), "b", 1);
4610 // we have to do a signed multiply
4612 emitcode (";", "signed");
4613 emitcode ("clr", "F0"); // reset sign flag
4614 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4616 lbl=newiTempLabel(NULL);
4617 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4618 // left side is negative, 8-bit two's complement, this fails for -128
4619 emitcode ("setb", "F0"); // set sign flag
4620 emitcode ("cpl", "a");
4621 emitcode ("inc", "a");
4623 emitcode ("", "!tlabeldef", lbl->key+100);
4626 if (AOP_TYPE(right)==AOP_LIT) {
4627 signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
4628 /* AND literal negative */
4629 if ((int) val < 0) {
4630 emitcode ("cpl", "F0"); // complement sign flag
4631 emitcode ("mov", "b,#!constbyte", -val);
4633 emitcode ("mov", "b,#!constbyte", val);
4636 lbl=newiTempLabel(NULL);
4637 emitcode ("mov", "b,a");
4638 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4639 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4640 // right side is negative, 8-bit two's complement
4641 emitcode ("cpl", "F0"); // complement sign flag
4642 emitcode ("cpl", "a");
4643 emitcode ("inc", "a");
4644 emitcode ("", "!tlabeldef", lbl->key+100);
4646 emitcode ("mul", "ab");
4648 _G.accInUse++;_G.bInUse++;
4649 aopOp(result, ic, TRUE, FALSE);
4651 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4653 // this should never happen
4654 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4655 AOP_SIZE(result), __FILE__, lineno);
4659 lbl=newiTempLabel(NULL);
4660 emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4661 // only ONE op was negative, we have to do a 8/16-bit two's complement
4662 emitcode ("cpl", "a"); // lsb
4663 if (AOP_SIZE(result)==1) {
4664 emitcode ("inc", "a");
4666 emitcode ("add", "a,#1");
4667 emitcode ("xch", "a,b");
4668 emitcode ("cpl", "a"); // msb
4669 emitcode ("addc", "a,#0");
4670 emitcode ("xch", "a,b");
4673 emitcode ("", "!tlabeldef", lbl->key+100);
4674 aopPut (AOP (result), "a", 0);
4675 _G.accInUse--;_G.bInUse--;
4676 if (AOP_SIZE(result)==2) {
4677 aopPut (AOP (result), "b", 1);
4681 /*-----------------------------------------------------------------*/
4682 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
4683 /*-----------------------------------------------------------------*/
4684 static void genMultTwoByte (operand *left, operand *right,
4685 operand *result, iCode *ic)
4687 sym_link *retype = getSpec(operandType(right));
4688 sym_link *letype = getSpec(operandType(left));
4689 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4692 if (AOP_TYPE (left) == AOP_LIT) {
4697 /* save EA bit in F1 */
4698 lbl = newiTempLabel(NULL);
4699 emitcode ("setb","F1");
4700 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4701 emitcode ("clr","F1");
4702 emitcode("","!tlabeldef",lbl->key+100);
4704 /* load up MB with right */
4706 emitcode("clr","F0");
4707 if (AOP_TYPE(right) == AOP_LIT) {
4708 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
4710 emitcode("setb","F0");
4713 emitcode ("mov","mb,#!constbyte",val & 0xff);
4714 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4716 lbl = newiTempLabel(NULL);
4717 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4718 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4719 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4720 emitcode ("xch", "a,b");
4721 emitcode ("cpl","a");
4722 emitcode ("add", "a,#1");
4723 emitcode ("xch", "a,b");
4724 emitcode ("cpl", "a"); // msb
4725 emitcode ("addc", "a,#0");
4726 emitcode ("setb","F0");
4727 emitcode ("","!tlabeldef",lbl->key+100);
4728 emitcode ("mov","mb,b");
4729 emitcode ("mov","mb,a");
4732 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4733 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4735 /* load up MA with left */
4737 lbl = newiTempLabel(NULL);
4738 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4739 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4740 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4741 emitcode ("xch", "a,b");
4742 emitcode ("cpl","a");
4743 emitcode ("add", "a,#1");
4744 emitcode ("xch", "a,b");
4745 emitcode ("cpl", "a"); // msb
4746 emitcode ("addc","a,#0");
4747 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4748 emitcode ("setb","F0");
4749 emitcode ("","!tlabeldef",lbl->key+100);
4750 emitcode ("mov","ma,b");
4751 emitcode ("mov","ma,a");
4753 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4754 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4756 /* wait for multiplication to finish */
4757 lbl = newiTempLabel(NULL);
4758 emitcode("","!tlabeldef", lbl->key+100);
4759 emitcode("mov","a,mcnt1");
4760 emitcode("anl","a,#!constbyte",0x80);
4761 emitcode("jnz","!tlabel",lbl->key+100);
4763 freeAsmop (left, NULL, ic, TRUE);
4764 freeAsmop (right, NULL, ic,TRUE);
4765 aopOp(result, ic, TRUE, FALSE);
4767 /* if unsigned then simple */
4769 emitcode ("mov","a,ma");
4770 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4771 emitcode ("mov","a,ma");
4772 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4773 aopPut(AOP(result),"ma",1);
4774 aopPut(AOP(result),"ma",0);
4776 emitcode("push","ma");
4777 emitcode("push","ma");
4778 emitcode("push","ma");
4780 /* negate result if needed */
4781 lbl = newiTempLabel(NULL);
4782 emitcode("jnb","F0,!tlabel",lbl->key+100);
4783 emitcode("cpl","a");
4784 emitcode("add","a,#1");
4785 emitcode("","!tlabeldef", lbl->key+100);
4786 if (AOP_TYPE(result) == AOP_ACC)
4788 D(emitcode(";", "ACC special case."););
4789 /* We know result is the only live aop, and
4790 * it's obviously not a DPTR2, so AP is available.
4792 emitcode("mov", "%s,acc", DP2_RESULT_REG);
4796 aopPut(AOP(result),"a",0);
4799 emitcode("pop","acc");
4800 lbl = newiTempLabel(NULL);
4801 emitcode("jnb","F0,!tlabel",lbl->key+100);
4802 emitcode("cpl","a");
4803 emitcode("addc","a,#0");
4804 emitcode("","!tlabeldef", lbl->key+100);
4805 aopPut(AOP(result),"a",1);
4806 emitcode("pop","acc");
4807 if (AOP_SIZE(result) >= 3) {
4808 lbl = newiTempLabel(NULL);
4809 emitcode("jnb","F0,!tlabel",lbl->key+100);
4810 emitcode("cpl","a");
4811 emitcode("addc","a,#0");
4812 emitcode("","!tlabeldef", lbl->key+100);
4813 aopPut(AOP(result),"a",2);
4815 emitcode("pop","acc");
4816 if (AOP_SIZE(result) >= 4) {
4817 lbl = newiTempLabel(NULL);
4818 emitcode("jnb","F0,!tlabel",lbl->key+100);
4819 emitcode("cpl","a");
4820 emitcode("addc","a,#0");
4821 emitcode("","!tlabeldef", lbl->key+100);
4822 aopPut(AOP(result),"a",3);
4824 if (AOP_TYPE(result) == AOP_ACC)
4826 /* We stashed the result away above. */
4827 emitcode("mov", "acc,%s", DP2_RESULT_REG);
4831 freeAsmop (result, NULL, ic, TRUE);
4833 /* restore EA bit in F1 */
4834 lbl = newiTempLabel(NULL);
4835 emitcode ("jnb","F1,!tlabel",lbl->key+100);
4836 emitcode ("setb","EA");
4837 emitcode("","!tlabeldef",lbl->key+100);
4841 /*-----------------------------------------------------------------*/
4842 /* genMult - generates code for multiplication */
4843 /*-----------------------------------------------------------------*/
4845 genMult (iCode * ic)
4847 operand *left = IC_LEFT (ic);
4848 operand *right = IC_RIGHT (ic);
4849 operand *result = IC_RESULT (ic);
4851 D (emitcode (";", "genMult "););
4853 /* assign the amsops */
4856 /* special cases first */
4858 if (AOP_TYPE (left) == AOP_CRY &&
4859 AOP_TYPE (right) == AOP_CRY)
4861 genMultbits (left, right, result, ic);
4865 /* if both are of size == 1 */
4866 if (AOP_SIZE (left) == 1 &&
4867 AOP_SIZE (right) == 1)
4869 genMultOneByte (left, right, result, ic);
4873 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4874 /* use the ds390 ARITHMETIC accel UNIT */
4875 genMultTwoByte (left, right, result, ic);
4878 /* should have been converted to function call */
4882 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4883 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4884 freeAsmop (result, NULL, ic, TRUE);
4887 /*-----------------------------------------------------------------*/
4888 /* genDivbits :- division of bits */
4889 /*-----------------------------------------------------------------*/
4891 genDivbits (operand * left,
4899 /* the result must be bit */
4900 LOAD_AB_FOR_DIV (left, right, l);
4901 emitcode ("div", "ab");
4902 emitcode ("rrc", "a");
4903 aopOp(result, ic, TRUE, FALSE);
4905 aopPut (AOP (result), "c", 0);
4908 /*-----------------------------------------------------------------*/
4909 /* genDivOneByte : 8 bit division */
4910 /*-----------------------------------------------------------------*/
4912 genDivOneByte (operand * left,
4917 sym_link *opetype = operandType (result);
4923 /* signed or unsigned */
4924 if (SPEC_USIGN (opetype))
4926 /* unsigned is easy */
4927 LOAD_AB_FOR_DIV (left, right, l);
4928 emitcode ("div", "ab");
4931 aopOp(result, ic, TRUE, FALSE);
4932 aopPut (AOP (result), "a", 0);
4935 size = AOP_SIZE (result) - 1;
4939 aopPut (AOP (result), zero, offset++);
4944 /* signed is a little bit more difficult */
4946 /* save the signs of the operands */
4947 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4948 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4949 emitcode ("push", "acc"); /* save it on the stack */
4951 /* now sign adjust for both left & right */
4952 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4953 lbl = newiTempLabel (NULL);
4954 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4955 emitcode ("cpl", "a");
4956 emitcode ("inc", "a");
4957 emitcode ("", "!tlabeldef", (lbl->key + 100));
4958 emitcode ("mov", "b,a");
4960 /* sign adjust left side */
4961 MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4963 lbl = newiTempLabel (NULL);
4964 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4965 emitcode ("cpl", "a");
4966 emitcode ("inc", "a");
4967 emitcode ("", "!tlabeldef", (lbl->key + 100));
4969 /* now the division */
4970 emitcode ("nop", "; workaround for DS80C390 div bug.");
4971 emitcode ("div", "ab");
4972 /* we are interested in the lower order
4974 emitcode ("mov", "b,a");
4975 lbl = newiTempLabel (NULL);
4976 emitcode ("pop", "acc");
4977 /* if there was an over flow we don't
4978 adjust the sign of the result */
4979 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4980 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4982 emitcode ("clr", "a");
4983 emitcode ("subb", "a,b");
4984 emitcode ("mov", "b,a");
4985 emitcode ("", "!tlabeldef", (lbl->key + 100));
4987 /* now we are done */
4988 _G.accInUse++; _G.bInUse++;
4989 aopOp(result, ic, TRUE, FALSE);
4991 aopPut (AOP (result), "b", 0);
4993 size = AOP_SIZE (result) - 1;
4997 emitcode ("mov", "c,b.7");
4998 emitcode ("subb", "a,acc");
5002 aopPut (AOP (result), "a", offset++);
5004 _G.accInUse--; _G.bInUse--;
5008 /*-----------------------------------------------------------------*/
5009 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
5010 /*-----------------------------------------------------------------*/
5011 static void genDivTwoByte (operand *left, operand *right,
5012 operand *result, iCode *ic)
5014 sym_link *retype = getSpec(operandType(right));
5015 sym_link *letype = getSpec(operandType(left));
5016 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5019 /* save EA bit in F1 */
5020 lbl = newiTempLabel(NULL);
5021 emitcode ("setb","F1");
5022 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5023 emitcode ("clr","F1");
5024 emitcode("","!tlabeldef",lbl->key+100);
5026 /* load up MA with left */
5028 emitcode("clr","F0");
5029 lbl = newiTempLabel(NULL);
5030 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5031 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5032 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5033 emitcode ("xch", "a,b");
5034 emitcode ("cpl","a");
5035 emitcode ("add", "a,#1");
5036 emitcode ("xch", "a,b");
5037 emitcode ("cpl", "a"); // msb
5038 emitcode ("addc","a,#0");
5039 emitcode ("setb","F0");
5040 emitcode ("","!tlabeldef",lbl->key+100);
5041 emitcode ("mov","ma,b");
5042 emitcode ("mov","ma,a");
5044 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5045 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5048 /* load up MB with right */
5050 if (AOP_TYPE(right) == AOP_LIT) {
5051 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5053 lbl = newiTempLabel(NULL);
5054 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5055 emitcode("setb","F0");
5056 emitcode ("","!tlabeldef",lbl->key+100);
5059 emitcode ("mov","mb,#!constbyte",val & 0xff);
5060 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5062 lbl = newiTempLabel(NULL);
5063 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5064 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5065 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5066 emitcode ("xch", "a,b");
5067 emitcode ("cpl","a");
5068 emitcode ("add", "a,#1");
5069 emitcode ("xch", "a,b");
5070 emitcode ("cpl", "a"); // msb
5071 emitcode ("addc", "a,#0");
5072 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5073 emitcode ("setb","F0");
5074 emitcode ("","!tlabeldef",lbl->key+100);
5075 emitcode ("mov","mb,b");
5076 emitcode ("mov","mb,a");
5079 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5080 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5083 /* wait for multiplication to finish */
5084 lbl = newiTempLabel(NULL);
5085 emitcode("","!tlabeldef", lbl->key+100);
5086 emitcode("mov","a,mcnt1");
5087 emitcode("anl","a,#!constbyte",0x80);
5088 emitcode("jnz","!tlabel",lbl->key+100);
5090 freeAsmop (left, NULL, ic, TRUE);
5091 freeAsmop (right, NULL, ic,TRUE);
5092 aopOp(result, ic, TRUE, FALSE);
5094 /* if unsigned then simple */
5096 aopPut(AOP(result),"ma",1);
5097 aopPut(AOP(result),"ma",0);
5099 emitcode("push","ma");
5101 /* negate result if needed */
5102 lbl = newiTempLabel(NULL);
5103 emitcode("jnb","F0,!tlabel",lbl->key+100);
5104 emitcode("cpl","a");
5105 emitcode("add","a,#1");
5106 emitcode("","!tlabeldef", lbl->key+100);
5107 aopPut(AOP(result),"a",0);
5108 emitcode("pop","acc");
5109 lbl = newiTempLabel(NULL);
5110 emitcode("jnb","F0,!tlabel",lbl->key+100);
5111 emitcode("cpl","a");
5112 emitcode("addc","a,#0");
5113 emitcode("","!tlabeldef", lbl->key+100);
5114 aopPut(AOP(result),"a",1);
5116 freeAsmop (result, NULL, ic, TRUE);
5117 /* restore EA bit in F1 */
5118 lbl = newiTempLabel(NULL);
5119 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5120 emitcode ("setb","EA");
5121 emitcode("","!tlabeldef",lbl->key+100);
5125 /*-----------------------------------------------------------------*/
5126 /* genDiv - generates code for division */
5127 /*-----------------------------------------------------------------*/
5131 operand *left = IC_LEFT (ic);
5132 operand *right = IC_RIGHT (ic);
5133 operand *result = IC_RESULT (ic);
5135 D (emitcode (";", "genDiv "););
5137 /* assign the amsops */
5140 /* special cases first */
5142 if (AOP_TYPE (left) == AOP_CRY &&
5143 AOP_TYPE (right) == AOP_CRY)
5145 genDivbits (left, right, result, ic);
5149 /* if both are of size == 1 */
5150 if (AOP_SIZE (left) == 1 &&
5151 AOP_SIZE (right) == 1)
5153 genDivOneByte (left, right, result, ic);
5157 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5158 /* use the ds390 ARITHMETIC accel UNIT */
5159 genDivTwoByte (left, right, result, ic);
5162 /* should have been converted to function call */
5165 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5166 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5167 freeAsmop (result, NULL, ic, TRUE);
5170 /*-----------------------------------------------------------------*/
5171 /* genModbits :- modulus of bits */
5172 /*-----------------------------------------------------------------*/
5174 genModbits (operand * left,
5182 /* the result must be bit */
5183 LOAD_AB_FOR_DIV (left, right, l);
5184 emitcode ("div", "ab");
5185 emitcode ("mov", "a,b");
5186 emitcode ("rrc", "a");
5187 aopOp(result, ic, TRUE, FALSE);
5188 aopPut (AOP (result), "c", 0);
5191 /*-----------------------------------------------------------------*/
5192 /* genModOneByte : 8 bit modulus */
5193 /*-----------------------------------------------------------------*/
5195 genModOneByte (operand * left,
5200 sym_link *opetype = operandType (result);
5204 /* signed or unsigned */
5205 if (SPEC_USIGN (opetype))
5207 /* unsigned is easy */
5208 LOAD_AB_FOR_DIV (left, right, l);
5209 emitcode ("div", "ab");
5210 aopOp(result, ic, TRUE, FALSE);
5211 aopPut (AOP (result), "b", 0);
5215 /* signed is a little bit more difficult */
5217 /* save the signs of the operands */
5218 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5220 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
5221 emitcode ("push", "acc"); /* save it on the stack */
5223 /* now sign adjust for both left & right */
5224 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5226 lbl = newiTempLabel (NULL);
5227 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5228 emitcode ("cpl", "a");
5229 emitcode ("inc", "a");
5230 emitcode ("", "!tlabeldef", (lbl->key + 100));
5231 emitcode ("mov", "b,a");
5233 /* sign adjust left side */
5234 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5236 lbl = newiTempLabel (NULL);
5237 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5238 emitcode ("cpl", "a");
5239 emitcode ("inc", "a");
5240 emitcode ("", "!tlabeldef", (lbl->key + 100));
5242 /* now the multiplication */
5243 emitcode ("nop", "; workaround for DS80C390 div bug.");
5244 emitcode ("div", "ab");
5245 /* we are interested in the lower order
5247 lbl = newiTempLabel (NULL);
5248 emitcode ("pop", "acc");
5249 /* if there was an over flow we don't
5250 adjust the sign of the result */
5251 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
5252 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5254 emitcode ("clr", "a");
5255 emitcode ("subb", "a,b");
5256 emitcode ("mov", "b,a");
5257 emitcode ("", "!tlabeldef", (lbl->key + 100));
5260 /* now we are done */
5261 aopOp(result, ic, TRUE, FALSE);
5262 aopPut (AOP (result), "b", 0);
5267 /*-----------------------------------------------------------------*/
5268 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
5269 /*-----------------------------------------------------------------*/
5270 static void genModTwoByte (operand *left, operand *right,
5271 operand *result, iCode *ic)
5273 sym_link *retype = getSpec(operandType(right));
5274 sym_link *letype = getSpec(operandType(left));
5275 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5278 /* load up MA with left */
5279 /* save EA bit in F1 */
5280 lbl = newiTempLabel(NULL);
5281 emitcode ("setb","F1");
5282 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5283 emitcode ("clr","F1");
5284 emitcode("","!tlabeldef",lbl->key+100);
5287 lbl = newiTempLabel(NULL);
5288 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5289 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5290 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5291 emitcode ("xch", "a,b");
5292 emitcode ("cpl","a");
5293 emitcode ("add", "a,#1");
5294 emitcode ("xch", "a,b");
5295 emitcode ("cpl", "a"); // msb
5296 emitcode ("addc","a,#0");
5297 emitcode ("","!tlabeldef",lbl->key+100);
5298 emitcode ("mov","ma,b");
5299 emitcode ("mov","ma,a");
5301 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5302 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5305 /* load up MB with right */
5307 if (AOP_TYPE(right) == AOP_LIT) {
5308 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5312 emitcode ("mov","mb,#!constbyte",val & 0xff);
5313 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5315 lbl = newiTempLabel(NULL);
5316 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5317 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5318 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5319 emitcode ("xch", "a,b");
5320 emitcode ("cpl","a");
5321 emitcode ("add", "a,#1");
5322 emitcode ("xch", "a,b");
5323 emitcode ("cpl", "a"); // msb
5324 emitcode ("addc", "a,#0");
5325 emitcode ("","!tlabeldef",lbl->key+100);
5326 emitcode ("mov","mb,b");
5327 emitcode ("mov","mb,a");
5330 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5331 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5334 /* wait for multiplication to finish */
5335 lbl = newiTempLabel(NULL);
5336 emitcode("","!tlabeldef", lbl->key+100);
5337 emitcode("mov","a,mcnt1");
5338 emitcode("anl","a,#!constbyte",0x80);
5339 emitcode("jnz","!tlabel",lbl->key+100);
5341 freeAsmop (left, NULL, ic, TRUE);
5342 freeAsmop (right, NULL, ic,TRUE);
5343 aopOp(result, ic, TRUE, FALSE);
5345 aopPut(AOP(result),"mb",1);
5346 aopPut(AOP(result),"mb",0);
5347 freeAsmop (result, NULL, ic, TRUE);
5349 /* restore EA bit in F1 */
5350 lbl = newiTempLabel(NULL);
5351 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5352 emitcode ("setb","EA");
5353 emitcode("","!tlabeldef",lbl->key+100);
5357 /*-----------------------------------------------------------------*/
5358 /* genMod - generates code for division */
5359 /*-----------------------------------------------------------------*/
5363 operand *left = IC_LEFT (ic);
5364 operand *right = IC_RIGHT (ic);
5365 operand *result = IC_RESULT (ic);
5367 D (emitcode (";", "genMod "); );
5369 /* assign the amsops */
5372 /* special cases first */
5374 if (AOP_TYPE (left) == AOP_CRY &&
5375 AOP_TYPE (right) == AOP_CRY)
5377 genModbits (left, right, result, ic);
5381 /* if both are of size == 1 */
5382 if (AOP_SIZE (left) == 1 &&
5383 AOP_SIZE (right) == 1)
5385 genModOneByte (left, right, result, ic);
5389 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5390 /* use the ds390 ARITHMETIC accel UNIT */
5391 genModTwoByte (left, right, result, ic);
5395 /* should have been converted to function call */
5399 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5400 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5401 freeAsmop (result, NULL, ic, TRUE);
5404 /*-----------------------------------------------------------------*/
5405 /* genIfxJump :- will create a jump depending on the ifx */
5406 /*-----------------------------------------------------------------*/
5408 genIfxJump (iCode * ic, char *jval)
5411 symbol *tlbl = newiTempLabel (NULL);
5414 D (emitcode (";", "genIfxJump"););
5416 /* if true label then we jump if condition
5420 jlbl = IC_TRUE (ic);
5421 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5422 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5426 /* false label is present */
5427 jlbl = IC_FALSE (ic);
5428 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5429 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5431 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5432 emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5434 emitcode (inst, "!tlabel", tlbl->key + 100);
5435 emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5436 emitcode ("", "!tlabeldef", tlbl->key + 100);
5438 /* mark the icode as generated */
5442 /*-----------------------------------------------------------------*/
5443 /* genCmp :- greater or less than comparison */
5444 /*-----------------------------------------------------------------*/
5446 genCmp (operand * left, operand * right,
5447 iCode * ic, iCode * ifx, int sign)
5449 int size, offset = 0;
5450 unsigned long lit = 0L;
5453 D (emitcode (";", "genCmp"););
5455 result = IC_RESULT (ic);
5457 /* if left & right are bit variables */
5458 if (AOP_TYPE (left) == AOP_CRY &&
5459 AOP_TYPE (right) == AOP_CRY)
5461 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5462 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5466 /* subtract right from left if at the
5467 end the carry flag is set then we know that
5468 left is greater than right */
5469 size = max (AOP_SIZE (left), AOP_SIZE (right));
5471 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5472 if ((size == 1) && !sign
5473 && (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5475 symbol *lbl = newiTempLabel (NULL);
5476 emitcode ("cjne", "%s,%s,!tlabel",
5477 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
5478 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5480 emitcode ("", "!tlabeldef", lbl->key + 100);
5484 if (AOP_TYPE (right) == AOP_LIT)
5486 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5487 /* optimize if(x < 0) or if(x >= 0) */
5496 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
5498 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5499 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5501 aopOp (result, ic, FALSE, FALSE);
5503 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5505 freeAsmop (result, NULL, ic, TRUE);
5506 genIfxJump (ifx, "acc.7");
5511 emitcode ("rlc", "a");
5513 goto release_freedLR;
5521 // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5522 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5523 // emitcode (";", "genCmp #2");
5524 if (sign && (size == 0))
5526 // emitcode (";", "genCmp #3");
5527 emitcode ("xrl", "a,#!constbyte",0x80);
5528 if (AOP_TYPE (right) == AOP_LIT)
5530 unsigned long lit = (unsigned long)
5531 floatFromVal (AOP (right)->aopu.aop_lit);
5532 // emitcode (";", "genCmp #3.1");
5533 emitcode ("subb", "a,#!constbyte",
5534 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5538 // emitcode (";", "genCmp #3.2");
5540 MOVB(aopGet (AOP (right), offset++, FALSE, FALSE, "b"));
5541 saveAccWarn = DEFAULT_ACC_WARNING;
5542 emitcode ("xrl", "b,#!constbyte",0x80);
5543 emitcode ("subb", "a,b");
5550 // emitcode (";", "genCmp #4");
5552 s = aopGet (AOP (right), offset++, FALSE, FALSE, "b");
5553 saveAccWarn = DEFAULT_ACC_WARNING;
5555 emitcode ("subb", "a,%s", s);
5562 /* Don't need the left & right operands any more; do need the result. */
5563 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5564 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5566 aopOp (result, ic, FALSE, FALSE);
5570 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5576 /* if the result is used in the next
5577 ifx conditional branch then generate
5578 code a little differently */
5581 genIfxJump (ifx, "c");
5587 /* leave the result in acc */
5589 freeAsmop (result, NULL, ic, TRUE);
5592 /*-----------------------------------------------------------------*/
5593 /* genCmpGt :- greater than comparison */
5594 /*-----------------------------------------------------------------*/
5596 genCmpGt (iCode * ic, iCode * ifx)
5598 operand *left, *right;
5599 sym_link *letype, *retype;
5602 D (emitcode (";", "genCmpGt ");
5605 left = IC_LEFT (ic);
5606 right = IC_RIGHT (ic);
5608 letype = getSpec (operandType (left));
5609 retype = getSpec (operandType (right));
5610 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5612 /* assign the left & right amsops */
5615 genCmp (right, left, ic, ifx, sign);
5618 /*-----------------------------------------------------------------*/
5619 /* genCmpLt - less than comparisons */
5620 /*-----------------------------------------------------------------*/
5622 genCmpLt (iCode * ic, iCode * ifx)
5624 operand *left, *right;
5625 sym_link *letype, *retype;
5628 D (emitcode (";", "genCmpLt "););
5630 left = IC_LEFT (ic);
5631 right = IC_RIGHT (ic);
5633 letype = getSpec (operandType (left));
5634 retype = getSpec (operandType (right));
5635 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5637 /* assign the left & right amsops */
5640 genCmp (left, right, ic, ifx, sign);
5643 /*-----------------------------------------------------------------*/
5644 /* gencjneshort - compare and jump if not equal */
5645 /*-----------------------------------------------------------------*/
5647 gencjneshort (operand * left, operand * right, symbol * lbl)
5649 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5651 unsigned long lit = 0L;
5653 D (emitcode (";", "gencjneshort");
5656 /* if the left side is a literal or
5657 if the right is in a pointer register and left
5659 if ((AOP_TYPE (left) == AOP_LIT) ||
5660 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5667 if (AOP_TYPE (right) == AOP_LIT)
5668 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5670 if (opIsGptr (left) || opIsGptr (right))
5672 /* We are comparing a generic pointer to something.
5673 * Exclude the generic type byte from the comparison.
5676 D (emitcode (";", "cjneshort: generic ptr special case."););
5680 /* if the right side is a literal then anything goes */
5681 if (AOP_TYPE (right) == AOP_LIT &&
5682 AOP_TYPE (left) != AOP_DIR)
5686 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5687 emitcode ("cjne", "a,%s,!tlabel",
5688 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5694 /* if the right side is in a register or in direct space or
5695 if the left is a pointer register & right is not */
5696 else if (AOP_TYPE (right) == AOP_REG ||
5697 AOP_TYPE (right) == AOP_DIR ||
5698 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5699 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5703 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5704 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5705 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5706 emitcode ("jnz", "!tlabel", lbl->key + 100);
5708 emitcode ("cjne", "a,%s,!tlabel",
5709 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
5716 /* right is a pointer reg need both a & b */
5719 MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5720 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
5721 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5727 /*-----------------------------------------------------------------*/
5728 /* gencjne - compare and jump if not equal */
5729 /*-----------------------------------------------------------------*/
5731 gencjne (operand * left, operand * right, symbol * lbl)
5733 symbol *tlbl = newiTempLabel (NULL);
5735 D (emitcode (";", "gencjne");
5738 gencjneshort (left, right, lbl);
5740 emitcode ("mov", "a,%s", one);
5741 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5742 emitcode ("", "!tlabeldef", lbl->key + 100);
5743 emitcode ("clr", "a");
5744 emitcode ("", "!tlabeldef", tlbl->key + 100);
5747 /*-----------------------------------------------------------------*/
5748 /* genCmpEq - generates code for equal to */
5749 /*-----------------------------------------------------------------*/
5751 genCmpEq (iCode * ic, iCode * ifx)
5753 operand *left, *right, *result;
5755 D (emitcode (";", "genCmpEq ");
5759 AOP_SET_LOCALS (ic);
5761 /* if literal, literal on the right or
5762 if the right is in a pointer register and left
5764 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5765 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5767 operand *t = IC_RIGHT (ic);
5768 IC_RIGHT (ic) = IC_LEFT (ic);
5772 if (ifx && /* !AOP_SIZE(result) */
5773 OP_SYMBOL (result) &&
5774 OP_SYMBOL (result)->regType == REG_CND)
5777 /* if they are both bit variables */
5778 if (AOP_TYPE (left) == AOP_CRY &&
5779 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5781 if (AOP_TYPE (right) == AOP_LIT)
5783 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5786 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5787 emitcode ("cpl", "c");
5791 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5795 emitcode ("clr", "c");
5797 /* AOP_TYPE(right) == AOP_CRY */
5801 symbol *lbl = newiTempLabel (NULL);
5802 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5803 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5804 emitcode ("cpl", "c");
5805 emitcode ("", "!tlabeldef", (lbl->key + 100));
5807 /* if true label then we jump if condition
5809 tlbl = newiTempLabel (NULL);
5812 emitcode ("jnc", "!tlabel", tlbl->key + 100);
5813 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5817 emitcode ("jc", "!tlabel", tlbl->key + 100);
5818 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5820 emitcode ("", "!tlabeldef", tlbl->key + 100);
5824 tlbl = newiTempLabel (NULL);
5825 gencjneshort (left, right, tlbl);
5828 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5829 emitcode ("", "!tlabeldef", tlbl->key + 100);
5833 symbol *lbl = newiTempLabel (NULL);
5834 emitcode ("sjmp", "!tlabel", lbl->key + 100);
5835 emitcode ("", "!tlabeldef", tlbl->key + 100);
5836 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5837 emitcode ("", "!tlabeldef", lbl->key + 100);
5840 /* mark the icode as generated */
5843 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5844 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5848 /* if they are both bit variables */
5849 if (AOP_TYPE (left) == AOP_CRY &&
5850 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5852 if (AOP_TYPE (right) == AOP_LIT)
5854 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5857 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5858 emitcode ("cpl", "c");
5862 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5866 emitcode ("clr", "c");
5868 /* AOP_TYPE(right) == AOP_CRY */
5872 symbol *lbl = newiTempLabel (NULL);
5873 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5874 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5875 emitcode ("cpl", "c");
5876 emitcode ("", "!tlabeldef", (lbl->key + 100));
5879 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5880 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5882 aopOp (result, ic, TRUE, FALSE);
5885 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5892 genIfxJump (ifx, "c");
5895 /* if the result is used in an arithmetic operation
5896 then put the result in place */
5901 gencjne (left, right, newiTempLabel (NULL));
5903 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5904 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5906 aopOp (result, ic, TRUE, FALSE);
5908 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5910 aopPut (AOP (result), "a", 0);
5915 genIfxJump (ifx, "a");
5918 /* if the result is used in an arithmetic operation
5919 then put the result in place */
5920 if (AOP_TYPE (result) != AOP_CRY)
5922 /* leave the result in acc */
5926 freeAsmop (result, NULL, ic, TRUE);
5929 /*-----------------------------------------------------------------*/
5930 /* ifxForOp - returns the icode containing the ifx for operand */
5931 /*-----------------------------------------------------------------*/
5933 ifxForOp (operand * op, iCode * ic)
5935 /* if true symbol then needs to be assigned */
5936 if (IS_TRUE_SYMOP (op))
5939 /* if this has register type condition and
5940 the next instruction is ifx with the same operand
5941 and live to of the operand is upto the ifx only then */
5943 ic->next->op == IFX &&
5944 IC_COND (ic->next)->key == op->key &&
5945 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5950 /*-----------------------------------------------------------------*/
5951 /* hasInc - operand is incremented before any other use */
5952 /*-----------------------------------------------------------------*/
5954 hasInc (operand *op, iCode *ic, int osize)
5956 sym_link *type = operandType(op);
5957 sym_link *retype = getSpec (type);
5958 iCode *lic = ic->next;
5961 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5962 if (!IS_SYMOP(op)) return NULL;
5964 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5965 if (IS_AGGREGATE(type->next)) return NULL;
5966 if (osize != (isize = getSize(type->next))) return NULL;
5969 /* if operand of the form op = op + <sizeof *op> */
5970 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5971 isOperandEqual(IC_RESULT(lic),op) &&
5972 isOperandLiteral(IC_RIGHT(lic)) &&
5973 operandLitValue(IC_RIGHT(lic)) == isize) {
5976 /* if the operand used or deffed */
5977 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5980 /* if GOTO or IFX */
5981 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5987 /*-----------------------------------------------------------------*/
5988 /* genAndOp - for && operation */
5989 /*-----------------------------------------------------------------*/
5991 genAndOp (iCode * ic)
5993 operand *left, *right, *result;
5996 D (emitcode (";", "genAndOp "););
5998 /* note here that && operations that are in an
5999 if statement are taken away by backPatchLabels
6000 only those used in arthmetic operations remain */
6002 AOP_SET_LOCALS (ic);
6004 /* if both are bit variables */
6005 if (AOP_TYPE (left) == AOP_CRY &&
6006 AOP_TYPE (right) == AOP_CRY)
6008 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6009 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6010 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6011 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6013 aopOp (result,ic,FALSE, FALSE);
6018 tlbl = newiTempLabel (NULL);
6020 emitcode ("jz", "!tlabel", tlbl->key + 100);
6022 emitcode ("", "!tlabeldef", tlbl->key + 100);
6023 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6024 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6026 aopOp (result,ic,FALSE, FALSE);
6029 freeAsmop (result, NULL, ic, TRUE);
6033 /*-----------------------------------------------------------------*/
6034 /* genOrOp - for || operation */
6035 /*-----------------------------------------------------------------*/
6037 genOrOp (iCode * ic)
6039 operand *left, *right, *result;
6042 D (emitcode (";", "genOrOp "););
6044 /* note here that || operations that are in an
6045 if statement are taken away by backPatchLabels
6046 only those used in arthmetic operations remain */
6048 AOP_SET_LOCALS (ic);
6050 /* if both are bit variables */
6051 if (AOP_TYPE (left) == AOP_CRY &&
6052 AOP_TYPE (right) == AOP_CRY)
6054 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6055 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6056 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6057 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6059 aopOp (result,ic,FALSE, FALSE);
6065 tlbl = newiTempLabel (NULL);
6067 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6069 emitcode ("", "!tlabeldef", tlbl->key + 100);
6070 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6071 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6073 aopOp (result,ic,FALSE, FALSE);
6078 freeAsmop (result, NULL, ic, TRUE);
6081 /*-----------------------------------------------------------------*/
6082 /* isLiteralBit - test if lit == 2^n */
6083 /*-----------------------------------------------------------------*/
6085 isLiteralBit (unsigned long lit)
6087 unsigned long pw[32] =
6088 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6089 0x100L, 0x200L, 0x400L, 0x800L,
6090 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6091 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6092 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6093 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6094 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6097 for (idx = 0; idx < 32; idx++)
6103 /*-----------------------------------------------------------------*/
6104 /* continueIfTrue - */
6105 /*-----------------------------------------------------------------*/
6107 continueIfTrue (iCode * ic)
6110 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6114 /*-----------------------------------------------------------------*/
6116 /*-----------------------------------------------------------------*/
6118 jumpIfTrue (iCode * ic)
6121 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6125 /*-----------------------------------------------------------------*/
6126 /* jmpTrueOrFalse - */
6127 /*-----------------------------------------------------------------*/
6129 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6131 // ugly but optimized by peephole
6134 symbol *nlbl = newiTempLabel (NULL);
6135 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6136 emitcode ("", "!tlabeldef", tlbl->key + 100);
6137 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6138 emitcode ("", "!tlabeldef", nlbl->key + 100);
6142 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6143 emitcode ("", "!tlabeldef", tlbl->key + 100);
6148 // Generate code to perform a bit-wise logic operation
6149 // on two operands in far space (assumed to already have been
6150 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6151 // in far space. This requires pushing the result on the stack
6152 // then popping it into the result.
6154 genFarFarLogicOp(iCode *ic, char *logicOp)
6156 int size, resultSize, compSize;
6160 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6161 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
6162 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6164 _startLazyDPSEvaluation();
6165 for (size = compSize; (size--); offset++)
6167 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6168 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6169 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6171 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6172 emitcode ("push", "acc");
6174 _endLazyDPSEvaluation();
6176 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6177 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6178 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6180 resultSize = AOP_SIZE(IC_RESULT(ic));
6182 ADJUST_PUSHED_RESULT(compSize, resultSize);
6184 _startLazyDPSEvaluation();
6187 emitcode ("pop", "acc");
6188 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6190 _endLazyDPSEvaluation();
6191 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6195 /*-----------------------------------------------------------------*/
6196 /* genAnd - code for and */
6197 /*-----------------------------------------------------------------*/
6199 genAnd (iCode * ic, iCode * ifx)
6201 operand *left, *right, *result;
6202 int size, offset = 0;
6203 unsigned long lit = 0L;
6208 D (emitcode (";", "genAnd "););
6210 AOP_OP_3_NOFATAL (ic, pushResult);
6211 AOP_SET_LOCALS (ic);
6215 genFarFarLogicOp(ic, "anl");
6220 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6222 AOP_TYPE (left), AOP_TYPE (right));
6223 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6225 AOP_SIZE (left), AOP_SIZE (right));
6228 /* if left is a literal & right is not then exchange them */
6229 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6230 #ifdef LOGIC_OPS_BROKEN
6231 || AOP_NEEDSACC (left)
6235 operand *tmp = right;
6240 /* if result = right then exchange them */
6241 if (sameRegs (AOP (result), AOP (right)))
6243 operand *tmp = right;
6248 /* if right is bit then exchange them */
6249 if (AOP_TYPE (right) == AOP_CRY &&
6250 AOP_TYPE (left) != AOP_CRY)
6252 operand *tmp = right;
6256 if (AOP_TYPE (right) == AOP_LIT)
6257 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6259 size = AOP_SIZE (result);
6262 // result = bit & yy;
6263 if (AOP_TYPE (left) == AOP_CRY)
6265 // c = bit & literal;
6266 if (AOP_TYPE (right) == AOP_LIT)
6270 if (size && sameRegs (AOP (result), AOP (left)))
6273 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6278 if (size && (AOP_TYPE (result) == AOP_CRY))
6280 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6283 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6288 emitcode ("clr", "c");
6293 if (AOP_TYPE (right) == AOP_CRY)
6296 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6297 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6302 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6304 emitcode ("rrc", "a");
6305 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6313 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6314 genIfxJump (ifx, "c");
6318 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6319 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6320 if ((AOP_TYPE (right) == AOP_LIT) &&
6321 (AOP_TYPE (result) == AOP_CRY) &&
6322 (AOP_TYPE (left) != AOP_CRY))
6324 int posbit = isLiteralBit (lit);
6329 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6332 emitcode ("mov", "c,acc.%d", posbit & 0x07);
6338 SNPRINTF (buff, sizeof(buff),
6339 "acc.%d", posbit & 0x07);
6340 genIfxJump (ifx, buff);
6344 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6351 symbol *tlbl = newiTempLabel (NULL);
6352 int sizel = AOP_SIZE (left);
6354 emitcode ("setb", "c");
6357 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6359 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6361 if ((posbit = isLiteralBit (bytelit)) != 0)
6362 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6365 if (bytelit != 0x0FFL)
6366 emitcode ("anl", "a,%s",
6367 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6368 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6373 // bit = left & literal
6376 emitcode ("clr", "c");
6377 emitcode ("", "!tlabeldef", tlbl->key + 100);
6379 // if(left & literal)
6383 jmpTrueOrFalse (ifx, tlbl);
6391 /* if left is same as result */
6392 if (sameRegs (AOP (result), AOP (left)))
6394 for (; size--; offset++)
6396 if (AOP_TYPE (right) == AOP_LIT)
6398 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6400 else if (bytelit == 0)
6401 aopPut (AOP (result), zero, offset);
6402 else if (IS_AOP_PREG (result))
6404 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6405 emitcode ("anl", "a,%s",
6406 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6407 aopPut (AOP (result), "a", offset);
6410 emitcode ("anl", "%s,%s",
6411 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6412 aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6416 if (AOP_TYPE (left) == AOP_ACC)
6417 emitcode ("anl", "a,%s",
6418 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6421 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6422 if (IS_AOP_PREG (result))
6424 emitcode ("anl", "a,%s",
6425 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6426 aopPut (AOP (result), "a", offset);
6429 emitcode ("anl", "%s,a",
6430 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6437 // left & result in different registers
6438 if (AOP_TYPE (result) == AOP_CRY)
6441 // if(size), result in bit
6442 // if(!size && ifx), conditional oper: if(left & right)
6443 symbol *tlbl = newiTempLabel (NULL);
6444 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6446 emitcode ("setb", "c");
6449 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6450 emitcode ("anl", "a,%s",
6451 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6453 if (AOP_TYPE(left)==AOP_ACC) {
6454 emitcode("mov", "b,a");
6455 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6456 emitcode("anl", "a,b");
6458 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6459 emitcode ("anl", "a,%s",
6460 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6463 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6469 emitcode ("", "!tlabeldef", tlbl->key + 100);
6473 jmpTrueOrFalse (ifx, tlbl);
6477 for (; (size--); offset++)
6480 // result = left & right
6481 if (AOP_TYPE (right) == AOP_LIT)
6483 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6485 aopPut (AOP (result),
6486 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6490 else if (bytelit == 0)
6492 aopPut (AOP (result), zero, offset);
6495 D (emitcode (";", "better literal AND."););
6496 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6497 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6498 FALSE, FALSE, DP2_RESULT_REG));
6503 // faster than result <- left, anl result,right
6504 // and better if result is SFR
6505 if (AOP_TYPE (left) == AOP_ACC)
6507 emitcode ("anl", "a,%s",
6508 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6512 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6513 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6515 emitcode("mov", "b,a");
6519 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6520 emitcode ("anl", "a,%s", rOp);
6523 aopPut (AOP (result), "a", offset);
6529 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6530 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6531 freeAsmop (result, NULL, ic, TRUE);
6535 /*-----------------------------------------------------------------*/
6536 /* genOr - code for or */
6537 /*-----------------------------------------------------------------*/
6539 genOr (iCode * ic, iCode * ifx)
6541 operand *left, *right, *result;
6542 int size, offset = 0;
6543 unsigned long lit = 0L;
6546 D (emitcode (";", "genOr "););
6548 AOP_OP_3_NOFATAL (ic, pushResult);
6549 AOP_SET_LOCALS (ic);
6553 genFarFarLogicOp(ic, "orl");
6559 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6561 AOP_TYPE (left), AOP_TYPE (right));
6562 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6564 AOP_SIZE (left), AOP_SIZE (right));
6567 /* if left is a literal & right is not then exchange them */
6568 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6569 #ifdef LOGIC_OPS_BROKEN
6570 || AOP_NEEDSACC (left) // I think this is a net loss now.
6574 operand *tmp = right;
6579 /* if result = right then exchange them */
6580 if (sameRegs (AOP (result), AOP (right)))
6582 operand *tmp = right;
6587 /* if right is bit then exchange them */
6588 if (AOP_TYPE (right) == AOP_CRY &&
6589 AOP_TYPE (left) != AOP_CRY)
6591 operand *tmp = right;
6595 if (AOP_TYPE (right) == AOP_LIT)
6596 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6598 size = AOP_SIZE (result);
6602 if (AOP_TYPE (left) == AOP_CRY)
6604 if (AOP_TYPE (right) == AOP_LIT)
6606 // c = bit & literal;
6609 // lit != 0 => result = 1
6610 if (AOP_TYPE (result) == AOP_CRY)
6613 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6615 continueIfTrue (ifx);
6618 emitcode ("setb", "c");
6622 // lit == 0 => result = left
6623 if (size && sameRegs (AOP (result), AOP (left)))
6625 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6630 if (AOP_TYPE (right) == AOP_CRY)
6633 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6634 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6639 symbol *tlbl = newiTempLabel (NULL);
6640 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6641 emitcode ("setb", "c");
6642 emitcode ("jb", "%s,!tlabel",
6643 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6645 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6646 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6648 jmpTrueOrFalse (ifx, tlbl);
6654 emitcode ("", "!tlabeldef", tlbl->key + 100);
6663 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6664 genIfxJump (ifx, "c");
6668 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6669 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6670 if ((AOP_TYPE (right) == AOP_LIT) &&
6671 (AOP_TYPE (result) == AOP_CRY) &&
6672 (AOP_TYPE (left) != AOP_CRY))
6678 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6680 continueIfTrue (ifx);
6685 // lit = 0, result = boolean(left)
6687 emitcode ("setb", "c");
6691 symbol *tlbl = newiTempLabel (NULL);
6692 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6694 emitcode ("", "!tlabeldef", tlbl->key + 100);
6698 genIfxJump (ifx, "a");
6706 /* if left is same as result */
6707 if (sameRegs (AOP (result), AOP (left)))
6709 for (; size--; offset++)
6711 if (AOP_TYPE (right) == AOP_LIT)
6713 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6719 if (IS_AOP_PREG (left))
6721 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6722 emitcode ("orl", "a,%s",
6723 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6724 aopPut (AOP (result), "a", offset);
6728 emitcode ("orl", "%s,%s",
6729 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6730 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6736 if (AOP_TYPE (left) == AOP_ACC)
6738 emitcode ("orl", "a,%s",
6739 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6743 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6744 if (IS_AOP_PREG (left))
6746 emitcode ("orl", "a,%s",
6747 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6748 aopPut (AOP (result), "a", offset);
6752 emitcode ("orl", "%s,a",
6753 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6761 // left & result in different registers
6762 if (AOP_TYPE (result) == AOP_CRY)
6765 // if(size), result in bit
6766 // if(!size && ifx), conditional oper: if(left | right)
6767 symbol *tlbl = newiTempLabel (NULL);
6768 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6770 emitcode ("setb", "c");
6773 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6774 emitcode ("orl", "a,%s",
6775 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6777 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6778 emitcode ("orl", "a,%s",
6779 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6781 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6787 emitcode ("", "!tlabeldef", tlbl->key + 100);
6791 jmpTrueOrFalse (ifx, tlbl);
6795 _startLazyDPSEvaluation();
6796 for (; (size--); offset++)
6799 // result = left & right
6800 if (AOP_TYPE (right) == AOP_LIT)
6802 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6804 aopPut (AOP (result),
6805 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6809 D (emitcode (";", "better literal OR."););
6810 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6811 emitcode ("orl", "a, %s",
6812 aopGet (AOP (right), offset,
6813 FALSE, FALSE, DP2_RESULT_REG));
6818 // faster than result <- left, anl result,right
6819 // and better if result is SFR
6820 if (AOP_TYPE (left) == AOP_ACC)
6822 emitcode ("orl", "a,%s",
6823 aopGet (AOP (right), offset,
6824 FALSE, FALSE, DP2_RESULT_REG));
6828 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6830 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6832 emitcode("mov", "b,a");
6836 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6837 emitcode ("orl", "a,%s", rOp);
6840 aopPut (AOP (result), "a", offset);
6842 _endLazyDPSEvaluation();
6847 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6848 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6849 freeAsmop (result, NULL, ic, TRUE);
6852 /*-----------------------------------------------------------------*/
6853 /* genXor - code for xclusive or */
6854 /*-----------------------------------------------------------------*/
6856 genXor (iCode * ic, iCode * ifx)
6858 operand *left, *right, *result;
6859 int size, offset = 0;
6860 unsigned long lit = 0L;
6863 D (emitcode (";", "genXor "););
6865 AOP_OP_3_NOFATAL (ic, pushResult);
6866 AOP_SET_LOCALS (ic);
6870 genFarFarLogicOp(ic, "xrl");
6875 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6877 AOP_TYPE (left), AOP_TYPE (right));
6878 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6880 AOP_SIZE (left), AOP_SIZE (right));
6883 /* if left is a literal & right is not ||
6884 if left needs acc & right does not */
6885 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6886 #ifdef LOGIC_OPS_BROKEN
6887 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6891 operand *tmp = right;
6896 /* if result = right then exchange them */
6897 if (sameRegs (AOP (result), AOP (right)))
6899 operand *tmp = right;
6904 /* if right is bit then exchange them */
6905 if (AOP_TYPE (right) == AOP_CRY &&
6906 AOP_TYPE (left) != AOP_CRY)
6908 operand *tmp = right;
6912 if (AOP_TYPE (right) == AOP_LIT)
6913 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6915 size = AOP_SIZE (result);
6919 if (AOP_TYPE (left) == AOP_CRY)
6921 if (AOP_TYPE (right) == AOP_LIT)
6923 // c = bit & literal;
6926 // lit>>1 != 0 => result = 1
6927 if (AOP_TYPE (result) == AOP_CRY)
6930 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6932 continueIfTrue (ifx);
6935 emitcode ("setb", "c");
6942 // lit == 0, result = left
6943 if (size && sameRegs (AOP (result), AOP (left)))
6945 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6949 // lit == 1, result = not(left)
6950 if (size && sameRegs (AOP (result), AOP (left)))
6952 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6957 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6958 emitcode ("cpl", "c");
6967 symbol *tlbl = newiTempLabel (NULL);
6968 if (AOP_TYPE (right) == AOP_CRY)
6971 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6975 int sizer = AOP_SIZE (right);
6977 // if val>>1 != 0, result = 1
6978 emitcode ("setb", "c");
6981 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
6983 // test the msb of the lsb
6984 emitcode ("anl", "a,#!constbyte",0xfe);
6985 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6989 emitcode ("rrc", "a");
6991 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6992 emitcode ("cpl", "c");
6993 emitcode ("", "!tlabeldef", (tlbl->key + 100));
7000 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7001 genIfxJump (ifx, "c");
7005 if (sameRegs (AOP (result), AOP (left)))
7007 /* if left is same as result */
7008 for (; size--; offset++)
7010 if (AOP_TYPE (right) == AOP_LIT)
7012 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7014 else if (IS_AOP_PREG (left))
7016 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7017 emitcode ("xrl", "a,%s",
7018 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7019 aopPut (AOP (result), "a", offset);
7022 emitcode ("xrl", "%s,%s",
7023 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
7024 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7028 if (AOP_TYPE (left) == AOP_ACC)
7029 emitcode ("xrl", "a,%s",
7030 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7033 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7034 if (IS_AOP_PREG (left))
7036 emitcode ("xrl", "a,%s",
7037 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7038 aopPut (AOP (result), "a", offset);
7041 emitcode ("xrl", "%s,a",
7042 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7049 // left & result in different registers
7050 if (AOP_TYPE (result) == AOP_CRY)
7053 // if(size), result in bit
7054 // if(!size && ifx), conditional oper: if(left ^ right)
7055 symbol *tlbl = newiTempLabel (NULL);
7056 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7059 emitcode ("setb", "c");
7062 if ((AOP_TYPE (right) == AOP_LIT) &&
7063 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7065 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7069 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7070 emitcode ("xrl", "a,%s",
7071 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7073 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7074 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7076 emitcode("mov", "b,a");
7080 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7081 emitcode ("xrl", "a,%s", rOp);
7084 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7090 emitcode ("", "!tlabeldef", tlbl->key + 100);
7094 jmpTrueOrFalse (ifx, tlbl);
7098 for (; (size--); offset++)
7101 // result = left & right
7102 if (AOP_TYPE (right) == AOP_LIT)
7104 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7106 aopPut (AOP (result),
7107 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7111 D (emitcode (";", "better literal XOR."););
7112 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7113 emitcode ("xrl", "a, %s",
7114 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7118 // faster than result <- left, anl result,right
7119 // and better if result is SFR
7120 if (AOP_TYPE (left) == AOP_ACC)
7122 emitcode ("xrl", "a,%s",
7123 aopGet (AOP (right), offset,
7124 FALSE, FALSE, DP2_RESULT_REG));
7128 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7129 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7131 emitcode("mov", "b,a");
7135 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7136 emitcode ("xrl", "a,%s", rOp);
7139 aopPut (AOP (result), "a", offset);
7146 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7147 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7148 freeAsmop (result, NULL, ic, TRUE);
7151 /*-----------------------------------------------------------------*/
7152 /* genInline - write the inline code out */
7153 /*-----------------------------------------------------------------*/
7155 genInline (iCode * ic)
7157 char *buffer, *bp, *bp1;
7159 D (emitcode (";", "genInline "); );
7161 _G.inLine += (!options.asmpeep);
7163 buffer = Safe_strdup(IC_INLINE(ic));
7167 /* emit each line as a code */
7192 /* emitcode("",buffer); */
7193 _G.inLine -= (!options.asmpeep);
7196 /*-----------------------------------------------------------------*/
7197 /* genRRC - rotate right with carry */
7198 /*-----------------------------------------------------------------*/
7202 operand *left, *result;
7205 D (emitcode (";", "genRRC "););
7207 /* rotate right with carry */
7208 left = IC_LEFT (ic);
7209 result = IC_RESULT (ic);
7210 aopOp (left, ic, FALSE, FALSE);
7211 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7213 /* move it to the result */
7214 size = AOP_SIZE (result);
7218 _startLazyDPSEvaluation ();
7221 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7222 emitcode ("rrc", "a");
7223 if (AOP_SIZE (result) > 1)
7224 aopPut (AOP (result), "a", offset--);
7226 _endLazyDPSEvaluation ();
7228 /* now we need to put the carry into the
7229 highest order byte of the result */
7230 if (AOP_SIZE (result) > 1)
7232 MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7234 emitcode ("mov", "acc.7,c");
7235 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7236 freeAsmop (left, NULL, ic, TRUE);
7237 freeAsmop (result, NULL, ic, TRUE);
7240 /*-----------------------------------------------------------------*/
7241 /* genRLC - generate code for rotate left with carry */
7242 /*-----------------------------------------------------------------*/
7246 operand *left, *result;
7250 D (emitcode (";", "genRLC "););
7252 /* rotate right with carry */
7253 left = IC_LEFT (ic);
7254 result = IC_RESULT (ic);
7255 aopOp (left, ic, FALSE, FALSE);
7256 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7258 /* move it to the result */
7259 size = AOP_SIZE (result);
7263 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7265 emitcode ("add", "a,acc");
7266 if (AOP_SIZE (result) > 1)
7268 aopPut (AOP (result), "a", offset++);
7271 _startLazyDPSEvaluation ();
7274 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7276 emitcode ("rlc", "a");
7277 if (AOP_SIZE (result) > 1)
7278 aopPut (AOP (result), "a", offset++);
7280 _endLazyDPSEvaluation ();
7282 /* now we need to put the carry into the
7283 highest order byte of the result */
7284 if (AOP_SIZE (result) > 1)
7286 l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7289 emitcode ("mov", "acc.0,c");
7290 aopPut (AOP (result), "a", 0);
7291 freeAsmop (left, NULL, ic, TRUE);
7292 freeAsmop (result, NULL, ic, TRUE);
7295 /*-----------------------------------------------------------------*/
7296 /* genGetHbit - generates code get highest order bit */
7297 /*-----------------------------------------------------------------*/
7299 genGetHbit (iCode * ic)
7301 operand *left, *result;
7302 left = IC_LEFT (ic);
7303 result = IC_RESULT (ic);
7304 aopOp (left, ic, FALSE, FALSE);
7305 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7307 D (emitcode (";", "genGetHbit "););
7309 /* get the highest order byte into a */
7310 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7311 if (AOP_TYPE (result) == AOP_CRY)
7313 emitcode ("rlc", "a");
7318 emitcode ("rl", "a");
7319 emitcode ("anl", "a,#1");
7324 freeAsmop (left, NULL, ic, TRUE);
7325 freeAsmop (result, NULL, ic, TRUE);
7328 /*-----------------------------------------------------------------*/
7329 /* AccRol - rotate left accumulator by known count */
7330 /*-----------------------------------------------------------------*/
7332 AccRol (int shCount)
7334 shCount &= 0x0007; // shCount : 0..7
7341 emitcode ("rl", "a");
7344 emitcode ("rl", "a");
7345 emitcode ("rl", "a");
7348 emitcode ("swap", "a");
7349 emitcode ("rr", "a");
7352 emitcode ("swap", "a");
7355 emitcode ("swap", "a");
7356 emitcode ("rl", "a");
7359 emitcode ("rr", "a");
7360 emitcode ("rr", "a");
7363 emitcode ("rr", "a");
7368 /*-----------------------------------------------------------------*/
7369 /* AccLsh - left shift accumulator by known count */
7370 /*-----------------------------------------------------------------*/
7372 AccLsh (int shCount)
7377 emitcode ("add", "a,acc");
7378 else if (shCount == 2)
7380 emitcode ("add", "a,acc");
7381 emitcode ("add", "a,acc");
7385 /* rotate left accumulator */
7387 /* and kill the lower order bits */
7388 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7393 /*-----------------------------------------------------------------*/
7394 /* AccRsh - right shift accumulator by known count */
7395 /*-----------------------------------------------------------------*/
7397 AccRsh (int shCount)
7404 emitcode ("rrc", "a");
7408 /* rotate right accumulator */
7409 AccRol (8 - shCount);
7410 /* and kill the higher order bits */
7411 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7416 #ifdef BETTER_LITERAL_SHIFT
7417 /*-----------------------------------------------------------------*/
7418 /* AccSRsh - signed right shift accumulator by known count */
7419 /*-----------------------------------------------------------------*/
7421 AccSRsh (int shCount)
7428 emitcode ("mov", "c,acc.7");
7429 emitcode ("rrc", "a");
7431 else if (shCount == 2)
7433 emitcode ("mov", "c,acc.7");
7434 emitcode ("rrc", "a");
7435 emitcode ("mov", "c,acc.7");
7436 emitcode ("rrc", "a");
7440 tlbl = newiTempLabel (NULL);
7441 /* rotate right accumulator */
7442 AccRol (8 - shCount);
7443 /* and kill the higher order bits */
7444 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7445 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7446 emitcode ("orl", "a,#!constbyte",
7447 (unsigned char) ~SRMask[shCount]);
7448 emitcode ("", "!tlabeldef", tlbl->key + 100);
7454 #ifdef BETTER_LITERAL_SHIFT
7455 /*-----------------------------------------------------------------*/
7456 /* shiftR1Left2Result - shift right one byte from left to result */
7457 /*-----------------------------------------------------------------*/
7459 shiftR1Left2Result (operand * left, int offl,
7460 operand * result, int offr,
7461 int shCount, int sign)
7463 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7464 /* shift right accumulator */
7469 aopPut (AOP (result), "a", offr);
7473 #ifdef BETTER_LITERAL_SHIFT
7474 /*-----------------------------------------------------------------*/
7475 /* shiftL1Left2Result - shift left one byte from left to result */
7476 /*-----------------------------------------------------------------*/
7478 shiftL1Left2Result (operand * left, int offl,
7479 operand * result, int offr, int shCount)
7481 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7482 /* shift left accumulator */
7484 aopPut (AOP (result), "a", offr);
7488 #ifdef BETTER_LITERAL_SHIFT
7489 /*-----------------------------------------------------------------*/
7490 /* movLeft2Result - move byte from left to result */
7491 /*-----------------------------------------------------------------*/
7493 movLeft2Result (operand * left, int offl,
7494 operand * result, int offr, int sign)
7497 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7499 l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
7501 if (*l == '@' && (IS_AOP_PREG (result)))
7503 emitcode ("mov", "a,%s", l);
7504 aopPut (AOP (result), "a", offr);
7510 aopPut (AOP (result), l, offr);
7514 /* MSB sign in acc.7 ! */
7515 if (getDataSize (left) == offl + 1)
7517 emitcode ("mov", "a,%s", l);
7518 aopPut (AOP (result), "a", offr);
7526 #ifdef BETTER_LITERAL_SHIFT
7527 /*-----------------------------------------------------------------*/
7528 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7529 /*-----------------------------------------------------------------*/
7533 emitcode ("rrc", "a");
7534 emitcode ("xch", "a,%s", x);
7535 emitcode ("rrc", "a");
7536 emitcode ("xch", "a,%s", x);
7540 #ifdef BETTER_LITERAL_SHIFT
7542 /*-----------------------------------------------------------------*/
7543 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7544 /*-----------------------------------------------------------------*/
7548 emitcode ("xch", "a,%s", x);
7549 emitcode ("rlc", "a");
7550 emitcode ("xch", "a,%s", x);
7551 emitcode ("rlc", "a");
7555 #ifdef BETTER_LITERAL_SHIFT
7556 /*-----------------------------------------------------------------*/
7557 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7558 /*-----------------------------------------------------------------*/
7562 emitcode ("xch", "a,%s", x);
7563 emitcode ("add", "a,acc");
7564 emitcode ("xch", "a,%s", x);
7565 emitcode ("rlc", "a");
7569 #ifdef BETTER_LITERAL_SHIFT
7570 /*-----------------------------------------------------------------*/
7571 /* AccAXLsh - left shift a:x by known count (0..7) */
7572 /*-----------------------------------------------------------------*/
7574 AccAXLsh (char *x, int shCount)
7589 case 5: // AAAAABBB:CCCCCDDD
7591 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7593 emitcode ("anl", "a,#!constbyte",
7594 SLMask[shCount]); // BBB00000:CCCCCDDD
7596 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7598 AccRol (shCount); // DDDCCCCC:BBB00000
7600 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7602 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7604 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7606 emitcode ("anl", "a,#!constbyte",
7607 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7609 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7611 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7614 case 6: // AAAAAABB:CCCCCCDD
7615 emitcode ("anl", "a,#!constbyte",
7616 SRMask[shCount]); // 000000BB:CCCCCCDD
7617 emitcode ("mov", "c,acc.0"); // c = B
7618 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7620 AccAXRrl1 (x); // BCCCCCCD:D000000B
7621 AccAXRrl1 (x); // BBCCCCCC:DD000000
7623 emitcode("rrc","a");
7624 emitcode("xch","a,%s", x);
7625 emitcode("rrc","a");
7626 emitcode("mov","c,acc.0"); //<< get correct bit
7627 emitcode("xch","a,%s", x);
7629 emitcode("rrc","a");
7630 emitcode("xch","a,%s", x);
7631 emitcode("rrc","a");
7632 emitcode("xch","a,%s", x);
7635 case 7: // a:x <<= 7
7637 emitcode ("anl", "a,#!constbyte",
7638 SRMask[shCount]); // 0000000B:CCCCCCCD
7640 emitcode ("mov", "c,acc.0"); // c = B
7642 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7644 AccAXRrl1 (x); // BCCCCCCC:D0000000
7653 #ifdef BETTER_LITERAL_SHIFT
7655 /*-----------------------------------------------------------------*/
7656 /* AccAXRsh - right shift a:x known count (0..7) */
7657 /*-----------------------------------------------------------------*/
7659 AccAXRsh (char *x, int shCount)
7667 AccAXRrl1 (x); // 0->a:x
7672 AccAXRrl1 (x); // 0->a:x
7675 AccAXRrl1 (x); // 0->a:x
7680 case 5: // AAAAABBB:CCCCCDDD = a:x
7682 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7684 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7686 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7688 emitcode ("anl", "a,#!constbyte",
7689 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7691 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7693 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7695 emitcode ("anl", "a,#!constbyte",
7696 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7698 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7700 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7702 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7705 case 6: // AABBBBBB:CCDDDDDD
7707 emitcode ("mov", "c,acc.7");
7708 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7710 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7712 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7714 emitcode ("anl", "a,#!constbyte",
7715 SRMask[shCount]); // 000000AA:BBBBBBCC
7718 case 7: // ABBBBBBB:CDDDDDDD
7720 emitcode ("mov", "c,acc.7"); // c = A
7722 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7724 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7726 emitcode ("anl", "a,#!constbyte",
7727 SRMask[shCount]); // 0000000A:BBBBBBBC
7736 #ifdef BETTER_LITERAL_SHIFT
7737 /*-----------------------------------------------------------------*/
7738 /* AccAXRshS - right shift signed a:x known count (0..7) */
7739 /*-----------------------------------------------------------------*/
7741 AccAXRshS (char *x, int shCount)
7749 emitcode ("mov", "c,acc.7");
7750 AccAXRrl1 (x); // s->a:x
7754 emitcode ("mov", "c,acc.7");
7755 AccAXRrl1 (x); // s->a:x
7757 emitcode ("mov", "c,acc.7");
7758 AccAXRrl1 (x); // s->a:x
7763 case 5: // AAAAABBB:CCCCCDDD = a:x
7765 tlbl = newiTempLabel (NULL);
7766 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7768 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7770 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7772 emitcode ("anl", "a,#!constbyte",
7773 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7775 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7777 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7779 emitcode ("anl", "a,#!constbyte",
7780 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7782 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7784 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7786 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7788 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7789 emitcode ("orl", "a,#!constbyte",
7790 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7792 emitcode ("", "!tlabeldef", tlbl->key + 100);
7793 break; // SSSSAAAA:BBBCCCCC
7795 case 6: // AABBBBBB:CCDDDDDD
7797 tlbl = newiTempLabel (NULL);
7798 emitcode ("mov", "c,acc.7");
7799 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7801 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7803 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7805 emitcode ("anl", "a,#!constbyte",
7806 SRMask[shCount]); // 000000AA:BBBBBBCC
7808 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7809 emitcode ("orl", "a,#!constbyte",
7810 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7812 emitcode ("", "!tlabeldef", tlbl->key + 100);
7814 case 7: // ABBBBBBB:CDDDDDDD
7816 tlbl = newiTempLabel (NULL);
7817 emitcode ("mov", "c,acc.7"); // c = A
7819 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7821 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7823 emitcode ("anl", "a,#!constbyte",
7824 SRMask[shCount]); // 0000000A:BBBBBBBC
7826 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7827 emitcode ("orl", "a,#!constbyte",
7828 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7830 emitcode ("", "!tlabeldef", tlbl->key + 100);
7838 #ifdef BETTER_LITERAL_SHIFT
7840 _loadLeftIntoAx(char **lsb,
7846 // Get the initial value from left into a pair of registers.
7847 // MSB must be in A, LSB can be any register.
7849 // If the result is held in registers, it is an optimization
7850 // if the LSB can be held in the register which will hold the,
7851 // result LSB since this saves us from having to copy it into
7852 // the result following AccAXLsh.
7854 // If the result is addressed indirectly, this is not a gain.
7855 if (AOP_NEEDSACC(result))
7859 _startLazyDPSEvaluation();
7860 if (AOP_TYPE(left) == AOP_DPTR2)
7863 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
7864 // get LSB in DP2_RESULT_REG.
7865 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
7866 assert(!strcmp(leftByte, DP2_RESULT_REG));
7870 // get LSB into DP2_RESULT_REG
7871 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
7872 if (strcmp(leftByte, DP2_RESULT_REG))
7875 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7878 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
7879 assert(strcmp(leftByte, DP2_RESULT_REG));
7882 _endLazyDPSEvaluation();
7883 *lsb = DP2_RESULT_REG;
7887 if (sameRegs (AOP (result), AOP (left)) &&
7888 ((offl + MSB16) == offr))
7890 /* don't crash result[offr] */
7891 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
7892 emitcode ("xch", "a,%s",
7893 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
7897 movLeft2Result (left, offl, result, offr, 0);
7898 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
7900 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
7901 assert(strcmp(*lsb,"a"));
7906 _storeAxResults(char *lsb,
7910 _startLazyDPSEvaluation();
7911 if (AOP_NEEDSACC(result))
7913 /* We have to explicitly update the result LSB.
7915 emitcode("xch","a,%s", lsb);
7916 aopPut(AOP(result), "a", offr);
7917 emitcode("mov","a,%s", lsb);
7919 if (getDataSize (result) > 1)
7921 aopPut (AOP (result), "a", offr + MSB16);
7923 _endLazyDPSEvaluation();
7926 /*-----------------------------------------------------------------*/
7927 /* shiftL2Left2Result - shift left two bytes from left to result */
7928 /*-----------------------------------------------------------------*/
7930 shiftL2Left2Result (operand * left, int offl,
7931 operand * result, int offr, int shCount)
7935 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7937 AccAXLsh (lsb, shCount);
7939 _storeAxResults(lsb, result, offr);
7943 #ifdef BETTER_LITERAL_SHIFT
7944 /*-----------------------------------------------------------------*/
7945 /* shiftR2Left2Result - shift right two bytes from left to result */
7946 /*-----------------------------------------------------------------*/
7948 shiftR2Left2Result (operand * left, int offl,
7949 operand * result, int offr,
7950 int shCount, int sign)
7954 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7956 /* a:x >> shCount (x = lsb(result)) */
7959 AccAXRshS(lsb, shCount);
7963 AccAXRsh(lsb, shCount);
7966 _storeAxResults(lsb, result, offr);
7970 /*-----------------------------------------------------------------*/
7971 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7972 /*-----------------------------------------------------------------*/
7974 shiftLLeftOrResult (operand * left, int offl,
7975 operand * result, int offr, int shCount)
7977 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7978 /* shift left accumulator */
7980 /* or with result */
7981 emitcode ("orl", "a,%s",
7982 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7983 /* back to result */
7984 aopPut (AOP (result), "a", offr);
7989 /*-----------------------------------------------------------------*/
7990 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7991 /*-----------------------------------------------------------------*/
7993 shiftRLeftOrResult (operand * left, int offl,
7994 operand * result, int offr, int shCount)
7996 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7997 /* shift right accumulator */
7999 /* or with result */
8000 emitcode ("orl", "a,%s",
8001 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8002 /* back to result */
8003 aopPut (AOP (result), "a", offr);
8007 #ifdef BETTER_LITERAL_SHIFT
8008 /*-----------------------------------------------------------------*/
8009 /* genlshOne - left shift a one byte quantity by known count */
8010 /*-----------------------------------------------------------------*/
8012 genlshOne (operand * result, operand * left, int shCount)
8014 D (emitcode (";", "genlshOne "););
8015 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8019 #ifdef BETTER_LITERAL_SHIFT
8020 /*-----------------------------------------------------------------*/
8021 /* genlshTwo - left shift two bytes by known amount != 0 */
8022 /*-----------------------------------------------------------------*/
8024 genlshTwo (operand * result, operand * left, int shCount)
8028 D (emitcode (";", "genlshTwo "););
8030 size = getDataSize (result);
8032 /* if shCount >= 8 */
8037 _startLazyDPSEvaluation();
8043 _endLazyDPSEvaluation();
8044 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8045 aopPut (AOP (result), zero, LSB);
8049 movLeft2Result (left, LSB, result, MSB16, 0);
8050 aopPut (AOP (result), zero, LSB);
8051 _endLazyDPSEvaluation();
8056 aopPut (AOP (result), zero, LSB);
8057 _endLazyDPSEvaluation();
8061 /* 1 <= shCount <= 7 */
8066 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8070 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8078 /*-----------------------------------------------------------------*/
8079 /* shiftLLong - shift left one long from left to result */
8080 /* offl = LSB or MSB16 */
8081 /*-----------------------------------------------------------------*/
8083 shiftLLong (operand * left, operand * result, int offr)
8086 int size = AOP_SIZE (result);
8088 if (size >= LSB + offr)
8090 l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8092 emitcode ("add", "a,acc");
8093 if (sameRegs (AOP (left), AOP (result)) &&
8094 size >= MSB16 + offr && offr != LSB)
8095 emitcode ("xch", "a,%s",
8096 aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8098 aopPut (AOP (result), "a", LSB + offr);
8101 if (size >= MSB16 + offr)
8103 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8105 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8107 emitcode ("rlc", "a");
8108 if (sameRegs (AOP (left), AOP (result)) &&
8109 size >= MSB24 + offr && offr != LSB)
8110 emitcode ("xch", "a,%s",
8111 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8113 aopPut (AOP (result), "a", MSB16 + offr);
8116 if (size >= MSB24 + offr)
8118 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8120 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8122 emitcode ("rlc", "a");
8123 if (sameRegs (AOP (left), AOP (result)) &&
8124 size >= MSB32 + offr && offr != LSB)
8125 emitcode ("xch", "a,%s",
8126 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8128 aopPut (AOP (result), "a", MSB24 + offr);
8131 if (size > MSB32 + offr)
8133 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8135 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8137 emitcode ("rlc", "a");
8138 aopPut (AOP (result), "a", MSB32 + offr);
8141 aopPut (AOP (result), zero, LSB);
8147 /*-----------------------------------------------------------------*/
8148 /* genlshFour - shift four byte by a known amount != 0 */
8149 /*-----------------------------------------------------------------*/
8151 genlshFour (operand * result, operand * left, int shCount)
8155 D (emitcode (";", "genlshFour ");
8158 size = AOP_SIZE (result);
8160 /* if shifting more that 3 bytes */
8165 /* lowest order of left goes to the highest
8166 order of the destination */
8167 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8169 movLeft2Result (left, LSB, result, MSB32, 0);
8170 aopPut (AOP (result), zero, LSB);
8171 aopPut (AOP (result), zero, MSB16);
8172 aopPut (AOP (result), zero, MSB24);
8176 /* more than two bytes */
8177 else if (shCount >= 16)
8179 /* lower order two bytes goes to higher order two bytes */
8181 /* if some more remaining */
8183 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8186 movLeft2Result (left, MSB16, result, MSB32, 0);
8187 movLeft2Result (left, LSB, result, MSB24, 0);
8189 aopPut (AOP (result), zero, MSB16);
8190 aopPut (AOP (result), zero, LSB);
8194 /* if more than 1 byte */
8195 else if (shCount >= 8)
8197 /* lower order three bytes goes to higher order three bytes */
8202 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8204 movLeft2Result (left, LSB, result, MSB16, 0);
8210 movLeft2Result (left, MSB24, result, MSB32, 0);
8211 movLeft2Result (left, MSB16, result, MSB24, 0);
8212 movLeft2Result (left, LSB, result, MSB16, 0);
8213 aopPut (AOP (result), zero, LSB);
8215 else if (shCount == 1)
8216 shiftLLong (left, result, MSB16);
8219 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8220 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8221 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8222 aopPut (AOP (result), zero, LSB);
8227 /* 1 <= shCount <= 7 */
8228 else if (shCount <= 2)
8230 shiftLLong (left, result, LSB);
8232 shiftLLong (result, result, LSB);
8234 /* 3 <= shCount <= 7, optimize */
8237 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8238 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8239 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8244 #ifdef BETTER_LITERAL_SHIFT
8245 /*-----------------------------------------------------------------*/
8246 /* genLeftShiftLiteral - left shifting by known count */
8247 /*-----------------------------------------------------------------*/
8249 genLeftShiftLiteral (operand * left,
8254 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8257 size = getSize (operandType (result));
8259 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8261 /* We only handle certain easy cases so far. */
8263 && (shCount < (size * 8))
8267 D(emitcode (";", "genLeftShiftLiteral wimping out"););
8271 freeAsmop (right, NULL, ic, TRUE);
8273 aopOp(left, ic, FALSE, FALSE);
8274 aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8277 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8279 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8280 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8282 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8285 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8287 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8288 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8290 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8296 emitcode ("; shift left ", "result %d, left %d", size,
8300 /* I suppose that the left size >= result size */
8303 _startLazyDPSEvaluation();
8306 movLeft2Result (left, size, result, size, 0);
8308 _endLazyDPSEvaluation();
8310 else if (shCount >= (size * 8))
8312 _startLazyDPSEvaluation();
8315 aopPut (AOP (result), zero, size);
8317 _endLazyDPSEvaluation();
8324 genlshOne (result, left, shCount);
8328 genlshTwo (result, left, shCount);
8332 genlshFour (result, left, shCount);
8336 fprintf(stderr, "*** ack! mystery literal shift!\n");
8340 freeAsmop (left, NULL, ic, TRUE);
8341 freeAsmop (result, NULL, ic, TRUE);
8346 /*-----------------------------------------------------------------*/
8347 /* genLeftShift - generates code for left shifting */
8348 /*-----------------------------------------------------------------*/
8350 genLeftShift (iCode * ic)
8352 operand *left, *right, *result;
8355 symbol *tlbl, *tlbl1;
8357 D (emitcode (";", "genLeftShift "););
8359 right = IC_RIGHT (ic);
8360 left = IC_LEFT (ic);
8361 result = IC_RESULT (ic);
8363 aopOp (right, ic, FALSE, FALSE);
8366 #ifdef BETTER_LITERAL_SHIFT
8367 /* if the shift count is known then do it
8368 as efficiently as possible */
8369 if (AOP_TYPE (right) == AOP_LIT)
8371 if (genLeftShiftLiteral (left, right, result, ic))
8378 /* shift count is unknown then we have to form
8379 a loop get the loop count in B : Note: we take
8380 only the lower order byte since shifting
8381 more that 32 bits make no sense anyway, ( the
8382 largest size of an object can be only 32 bits ) */
8384 if (AOP_TYPE (right) == AOP_LIT)
8386 /* Really should be handled by genLeftShiftLiteral,
8387 * but since I'm too lazy to fix that today, at least we can make
8388 * some small improvement.
8390 emitcode("mov", "b,#!constbyte",
8391 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8395 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8396 emitcode ("inc", "b");
8398 freeAsmop (right, NULL, ic, TRUE);
8399 aopOp (left, ic, FALSE, FALSE);
8400 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8402 /* now move the left to the result if they are not the
8404 if (!sameRegs (AOP (left), AOP (result)) &&
8405 AOP_SIZE (result) > 1)
8408 size = AOP_SIZE (result);
8410 _startLazyDPSEvaluation ();
8413 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8414 if (*l == '@' && (IS_AOP_PREG (result)))
8417 emitcode ("mov", "a,%s", l);
8418 aopPut (AOP (result), "a", offset);
8421 aopPut (AOP (result), l, offset);
8424 _endLazyDPSEvaluation ();
8427 tlbl = newiTempLabel (NULL);
8428 size = AOP_SIZE (result);
8430 tlbl1 = newiTempLabel (NULL);
8432 /* if it is only one byte then */
8435 symbol *tlbl1 = newiTempLabel (NULL);
8437 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8438 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8439 emitcode ("", "!tlabeldef", tlbl->key + 100);
8440 emitcode ("add", "a,acc");
8441 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8442 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8443 aopPut (AOP (result), "a", 0);
8447 reAdjustPreg (AOP (result));
8449 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8450 emitcode ("", "!tlabeldef", tlbl->key + 100);
8451 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8452 emitcode ("add", "a,acc");
8453 aopPut (AOP (result), "a", offset++);
8454 _startLazyDPSEvaluation ();
8457 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8458 emitcode ("rlc", "a");
8459 aopPut (AOP (result), "a", offset++);
8461 _endLazyDPSEvaluation ();
8462 reAdjustPreg (AOP (result));
8464 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8465 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8467 freeAsmop (left, NULL, ic, TRUE);
8468 freeAsmop (result, NULL, ic, TRUE);
8471 #ifdef BETTER_LITERAL_SHIFT
8472 /*-----------------------------------------------------------------*/
8473 /* genrshOne - right shift a one byte quantity by known count */
8474 /*-----------------------------------------------------------------*/
8476 genrshOne (operand * result, operand * left,
8477 int shCount, int sign)
8479 D (emitcode (";", "genrshOne"););
8480 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8484 #ifdef BETTER_LITERAL_SHIFT
8485 /*-----------------------------------------------------------------*/
8486 /* genrshTwo - right shift two bytes by known amount != 0 */
8487 /*-----------------------------------------------------------------*/
8489 genrshTwo (operand * result, operand * left,
8490 int shCount, int sign)
8492 D (emitcode (";", "genrshTwo"););
8494 /* if shCount >= 8 */
8498 _startLazyDPSEvaluation();
8501 shiftR1Left2Result (left, MSB16, result, LSB,
8506 movLeft2Result (left, MSB16, result, LSB, sign);
8508 addSign (result, MSB16, sign);
8509 _endLazyDPSEvaluation();
8512 /* 1 <= shCount <= 7 */
8515 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8520 /*-----------------------------------------------------------------*/
8521 /* shiftRLong - shift right one long from left to result */
8522 /* offl = LSB or MSB16 */
8523 /*-----------------------------------------------------------------*/
8525 shiftRLong (operand * left, int offl,
8526 operand * result, int sign)
8528 int isSameRegs=sameRegs(AOP(left),AOP(result));
8530 if (isSameRegs && offl>1) {
8531 // we are in big trouble, but this shouldn't happen
8532 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8535 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8540 emitcode ("rlc", "a");
8541 emitcode ("subb", "a,acc");
8542 emitcode ("xch", "a,%s",
8543 aopGet(AOP(left), MSB32, FALSE, FALSE, DP2_RESULT_REG));
8545 aopPut (AOP(result), zero, MSB32);
8550 emitcode ("clr", "c");
8552 emitcode ("mov", "c,acc.7");
8555 emitcode ("rrc", "a");
8557 if (isSameRegs && offl==MSB16) {
8559 "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE, DP2_RESULT_REG));
8561 aopPut (AOP (result), "a", MSB32);
8562 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8565 emitcode ("rrc", "a");
8566 if (isSameRegs && offl==1) {
8567 emitcode ("xch", "a,%s",
8568 aopGet (AOP (left), MSB16, FALSE, FALSE, DP2_RESULT_REG));
8570 aopPut (AOP (result), "a", MSB24);
8571 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, NULL));
8573 emitcode ("rrc", "a");
8574 aopPut (AOP (result), "a", MSB16 - offl);
8578 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, NULL));
8579 emitcode ("rrc", "a");
8580 aopPut (AOP (result), "a", LSB);
8584 /*-----------------------------------------------------------------*/
8585 /* genrshFour - shift four byte by a known amount != 0 */
8586 /*-----------------------------------------------------------------*/
8588 genrshFour (operand * result, operand * left,
8589 int shCount, int sign)
8591 D (emitcode (";", "genrshFour"););
8593 /* if shifting more that 3 bytes */
8597 _startLazyDPSEvaluation();
8599 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8601 movLeft2Result (left, MSB32, result, LSB, sign);
8602 addSign (result, MSB16, sign);
8603 _endLazyDPSEvaluation();
8605 else if (shCount >= 16)
8608 _startLazyDPSEvaluation();
8610 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8613 movLeft2Result (left, MSB24, result, LSB, 0);
8614 movLeft2Result (left, MSB32, result, MSB16, sign);
8616 addSign (result, MSB24, sign);
8617 _endLazyDPSEvaluation();
8619 else if (shCount >= 8)
8622 _startLazyDPSEvaluation();
8625 shiftRLong (left, MSB16, result, sign);
8627 else if (shCount == 0)
8629 movLeft2Result (left, MSB16, result, LSB, 0);
8630 movLeft2Result (left, MSB24, result, MSB16, 0);
8631 movLeft2Result (left, MSB32, result, MSB24, sign);
8632 addSign (result, MSB32, sign);
8636 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8637 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8638 /* the last shift is signed */
8639 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8640 addSign (result, MSB32, sign);
8642 _endLazyDPSEvaluation();
8646 /* 1 <= shCount <= 7 */
8649 shiftRLong (left, LSB, result, sign);
8651 shiftRLong (result, LSB, result, sign);
8655 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8656 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8657 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8662 #ifdef BETTER_LITERAL_SHIFT
8663 /*-----------------------------------------------------------------*/
8664 /* genRightShiftLiteral - right shifting by known count */
8665 /*-----------------------------------------------------------------*/
8667 genRightShiftLiteral (operand * left,
8673 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8676 size = getSize (operandType (result));
8678 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8680 /* We only handle certain easy cases so far. */
8682 && (shCount < (size * 8))
8687 D(emitcode (";", "genRightShiftLiteral wimping out"););
8691 freeAsmop (right, NULL, ic, TRUE);
8693 aopOp (left, ic, FALSE, FALSE);
8694 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8697 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8701 /* test the LEFT size !!! */
8703 /* I suppose that the left size >= result size */
8706 size = getDataSize (result);
8707 _startLazyDPSEvaluation();
8710 movLeft2Result (left, size, result, size, 0);
8712 _endLazyDPSEvaluation();
8714 else if (shCount >= (size * 8))
8718 /* get sign in acc.7 */
8719 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
8721 addSign (result, LSB, sign);
8728 genrshOne (result, left, shCount, sign);
8732 genrshTwo (result, left, shCount, sign);
8736 genrshFour (result, left, shCount, sign);
8743 freeAsmop (left, NULL, ic, TRUE);
8744 freeAsmop (result, NULL, ic, TRUE);
8750 /*-----------------------------------------------------------------*/
8751 /* genSignedRightShift - right shift of signed number */
8752 /*-----------------------------------------------------------------*/
8754 genSignedRightShift (iCode * ic)
8756 operand *right, *left, *result;
8759 symbol *tlbl, *tlbl1;
8761 D (emitcode (";", "genSignedRightShift "););
8763 /* we do it the hard way put the shift count in b
8764 and loop thru preserving the sign */
8766 right = IC_RIGHT (ic);
8767 left = IC_LEFT (ic);
8768 result = IC_RESULT (ic);
8770 aopOp (right, ic, FALSE, FALSE);
8772 #ifdef BETTER_LITERAL_SHIFT
8773 if (AOP_TYPE (right) == AOP_LIT)
8775 if (genRightShiftLiteral (left, right, result, ic, 1))
8781 /* shift count is unknown then we have to form
8782 a loop get the loop count in B : Note: we take
8783 only the lower order byte since shifting
8784 more that 32 bits make no sense anyway, ( the
8785 largest size of an object can be only 32 bits ) */
8787 if (AOP_TYPE (right) == AOP_LIT)
8789 /* Really should be handled by genRightShiftLiteral,
8790 * but since I'm too lazy to fix that today, at least we can make
8791 * some small improvement.
8793 emitcode("mov", "b,#!constbyte",
8794 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8798 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8799 emitcode ("inc", "b");
8801 freeAsmop (right, NULL, ic, TRUE);
8802 aopOp (left, ic, FALSE, FALSE);
8803 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8805 /* now move the left to the result if they are not the
8807 if (!sameRegs (AOP (left), AOP (result)) &&
8808 AOP_SIZE (result) > 1)
8811 size = AOP_SIZE (result);
8813 _startLazyDPSEvaluation ();
8816 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8817 if (*l == '@' && IS_AOP_PREG (result))
8820 emitcode ("mov", "a,%s", l);
8821 aopPut (AOP (result), "a", offset);
8824 aopPut (AOP (result), l, offset);
8827 _endLazyDPSEvaluation ();
8830 /* mov the highest order bit to OVR */
8831 tlbl = newiTempLabel (NULL);
8832 tlbl1 = newiTempLabel (NULL);
8834 size = AOP_SIZE (result);
8836 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
8837 emitcode ("rlc", "a");
8838 emitcode ("mov", "ov,c");
8839 /* if it is only one byte then */
8842 MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8843 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8844 emitcode ("", "!tlabeldef", tlbl->key + 100);
8845 emitcode ("mov", "c,ov");
8846 emitcode ("rrc", "a");
8847 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8848 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8849 aopPut (AOP (result), "a", 0);
8853 reAdjustPreg (AOP (result));
8854 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8855 emitcode ("", "!tlabeldef", tlbl->key + 100);
8856 emitcode ("mov", "c,ov");
8857 _startLazyDPSEvaluation ();
8860 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8861 emitcode ("rrc", "a");
8862 aopPut (AOP (result), "a", offset--);
8864 _endLazyDPSEvaluation ();
8865 reAdjustPreg (AOP (result));
8866 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8867 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8870 freeAsmop (left, NULL, ic, TRUE);
8871 freeAsmop (result, NULL, ic, TRUE);
8874 /*-----------------------------------------------------------------*/
8875 /* genRightShift - generate code for right shifting */
8876 /*-----------------------------------------------------------------*/
8878 genRightShift (iCode * ic)
8880 operand *right, *left, *result;
8884 symbol *tlbl, *tlbl1;
8886 D (emitcode (";", "genRightShift "););
8888 /* if signed then we do it the hard way preserve the
8889 sign bit moving it inwards */
8890 retype = getSpec (operandType (IC_RESULT (ic)));
8892 if (!SPEC_USIGN (retype))
8894 genSignedRightShift (ic);
8898 /* signed & unsigned types are treated the same : i.e. the
8899 signed is NOT propagated inwards : quoting from the
8900 ANSI - standard : "for E1 >> E2, is equivalent to division
8901 by 2**E2 if unsigned or if it has a non-negative value,
8902 otherwise the result is implementation defined ", MY definition
8903 is that the sign does not get propagated */
8905 right = IC_RIGHT (ic);
8906 left = IC_LEFT (ic);
8907 result = IC_RESULT (ic);
8909 aopOp (right, ic, FALSE, FALSE);
8911 #ifdef BETTER_LITERAL_SHIFT
8912 /* if the shift count is known then do it
8913 as efficiently as possible */
8914 if (AOP_TYPE (right) == AOP_LIT)
8916 if (genRightShiftLiteral (left, right, result, ic, 0))
8923 /* shift count is unknown then we have to form
8924 a loop get the loop count in B : Note: we take
8925 only the lower order byte since shifting
8926 more that 32 bits make no sense anyway, ( the
8927 largest size of an object can be only 32 bits ) */
8929 if (AOP_TYPE (right) == AOP_LIT)
8931 /* Really should be handled by genRightShiftLiteral,
8932 * but since I'm too lazy to fix that today, at least we can make
8933 * some small improvement.
8935 emitcode("mov", "b,#!constbyte",
8936 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8940 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8941 emitcode ("inc", "b");
8943 freeAsmop (right, NULL, ic, TRUE);
8944 aopOp (left, ic, FALSE, FALSE);
8945 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8947 /* now move the left to the result if they are not the
8949 if (!sameRegs (AOP (left), AOP (result)) &&
8950 AOP_SIZE (result) > 1)
8953 size = AOP_SIZE (result);
8955 _startLazyDPSEvaluation ();
8958 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8959 if (*l == '@' && IS_AOP_PREG (result))
8962 emitcode ("mov", "a,%s", l);
8963 aopPut (AOP (result), "a", offset);
8966 aopPut (AOP (result), l, offset);
8969 _endLazyDPSEvaluation ();
8972 tlbl = newiTempLabel (NULL);
8973 tlbl1 = newiTempLabel (NULL);
8974 size = AOP_SIZE (result);
8977 /* if it is only one byte then */
8980 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8981 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8982 emitcode ("", "!tlabeldef", tlbl->key + 100);
8984 emitcode ("rrc", "a");
8985 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8986 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8987 aopPut (AOP (result), "a", 0);
8991 reAdjustPreg (AOP (result));
8992 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8993 emitcode ("", "!tlabeldef", tlbl->key + 100);
8995 _startLazyDPSEvaluation ();
8998 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8999 emitcode ("rrc", "a");
9000 aopPut (AOP (result), "a", offset--);
9002 _endLazyDPSEvaluation ();
9003 reAdjustPreg (AOP (result));
9005 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9006 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9009 freeAsmop (left, NULL, ic, TRUE);
9010 freeAsmop (result, NULL, ic, TRUE);
9014 /*-----------------------------------------------------------------*/
9015 /* emitPtrByteGet - emits code to get a byte into A through a */
9016 /* pointer register (R0, R1, or DPTR). The */
9017 /* original value of A can be preserved in B. */
9018 /*-----------------------------------------------------------------*/
9020 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9027 emitcode ("mov", "b,a");
9028 emitcode ("mov", "a,@%s", rname);
9033 emitcode ("mov", "b,a");
9034 emitcode ("movx", "a,@%s", rname);
9039 emitcode ("mov", "b,a");
9040 emitcode ("movx", "a,@dptr");
9045 emitcode ("mov", "b,a");
9046 emitcode ("clr", "a");
9047 emitcode ("movc", "a,@a+dptr");
9053 emitcode ("push", "b");
9054 emitcode ("push", "acc");
9056 emitcode ("lcall", "__gptrget");
9058 emitcode ("pop", "b");
9063 /*-----------------------------------------------------------------*/
9064 /* emitPtrByteSet - emits code to set a byte from src through a */
9065 /* pointer register (R0, R1, or DPTR). */
9066 /*-----------------------------------------------------------------*/
9068 emitPtrByteSet (char *rname, int p_type, char *src)
9077 emitcode ("mov", "@%s,a", rname);
9080 emitcode ("mov", "@%s,%s", rname, src);
9085 emitcode ("movx", "@%s,a", rname);
9090 emitcode ("movx", "@dptr,a");
9095 emitcode ("lcall", "__gptrput");
9100 /*-----------------------------------------------------------------*/
9101 /* genUnpackBits - generates code for unpacking bits */
9102 /*-----------------------------------------------------------------*/
9104 genUnpackBits (operand * result, char *rname, int ptype)
9106 int offset = 0; /* result byte offset */
9107 int rsize; /* result size */
9108 int rlen = 0; /* remaining bitfield length */
9109 sym_link *etype; /* bitfield type information */
9110 int blen; /* bitfield length */
9111 int bstr; /* bitfield starting bit within byte */
9113 D(emitcode ("; genUnpackBits",""));
9115 etype = getSpec (operandType (result));
9116 rsize = getSize (operandType (result));
9117 blen = SPEC_BLEN (etype);
9118 bstr = SPEC_BSTR (etype);
9120 /* If the bitfield length is less than a byte */
9123 emitPtrByteGet (rname, ptype, FALSE);
9125 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
9126 aopPut (AOP (result), "a", offset++);
9130 /* Bit field did not fit in a byte. Copy all
9131 but the partial byte at the end. */
9132 for (rlen=blen;rlen>=8;rlen-=8)
9134 emitPtrByteGet (rname, ptype, FALSE);
9135 aopPut (AOP (result), "a", offset++);
9137 emitcode ("inc", "%s", rname);
9140 /* Handle the partial byte at the end */
9143 emitPtrByteGet (rname, ptype, FALSE);
9144 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
9145 aopPut (AOP (result), "a", offset++);
9153 aopPut (AOP (result), zero, offset++);
9158 /*-----------------------------------------------------------------*/
9159 /* genDataPointerGet - generates code when ptr offset is known */
9160 /*-----------------------------------------------------------------*/
9162 genDataPointerGet (operand * left,
9168 int size, offset = 0;
9169 aopOp (result, ic, TRUE, FALSE);
9171 /* get the string representation of the name */
9172 l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9173 size = AOP_SIZE (result);
9174 _startLazyDPSEvaluation ();
9179 SNPRINTF (buff, sizeof(buff),
9180 "(%s + %d)", l + 1, offset);
9184 SNPRINTF (buff, sizeof(buff),
9187 aopPut (AOP (result), buff, offset++);
9189 _endLazyDPSEvaluation ();
9191 freeAsmop (left, NULL, ic, TRUE);
9192 freeAsmop (result, NULL, ic, TRUE);
9195 /*-----------------------------------------------------------------*/
9196 /* genNearPointerGet - emitcode for near pointer fetch */
9197 /*-----------------------------------------------------------------*/
9199 genNearPointerGet (operand * left,
9207 sym_link *rtype, *retype, *letype;
9208 sym_link *ltype = operandType (left);
9211 rtype = operandType (result);
9212 retype = getSpec (rtype);
9213 letype = getSpec (ltype);
9215 aopOp (left, ic, FALSE, FALSE);
9217 /* if left is rematerialisable and
9218 result is not bit variable type and
9219 the left is pointer to data space i.e
9220 lower 128 bytes of space */
9221 if (AOP_TYPE (left) == AOP_IMMD &&
9222 !IS_BITVAR (retype) &&
9223 !IS_BITVAR (letype) &&
9224 DCL_TYPE (ltype) == POINTER)
9226 genDataPointerGet (left, result, ic);
9230 /* if the value is already in a pointer register
9231 then don't need anything more */
9232 if (!AOP_INPREG (AOP (left)))
9234 /* otherwise get a free pointer register */
9236 preg = getFreePtr (ic, &aop, FALSE);
9237 emitcode ("mov", "%s,%s",
9239 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9243 rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9245 freeAsmop (left, NULL, ic, TRUE);
9246 aopOp (result, ic, FALSE, FALSE);
9248 /* if bitfield then unpack the bits */
9249 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9250 genUnpackBits (result, rname, POINTER);
9253 /* we have can just get the values */
9254 int size = AOP_SIZE (result);
9259 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9262 emitcode ("mov", "a,@%s", rname);
9263 aopPut (AOP (result), "a", offset);
9267 SNPRINTF (buff, sizeof(buff), "@%s", rname);
9268 aopPut (AOP (result), buff, offset);
9273 emitcode ("inc", "%s", rname);
9278 /* now some housekeeping stuff */
9281 /* we had to allocate for this iCode */
9282 if (pi) { /* post increment present */
9283 aopPut(AOP ( left ),rname,0);
9285 freeAsmop (NULL, aop, ic, TRUE);
9289 /* we did not allocate which means left
9290 already in a pointer register, then
9291 if size > 0 && this could be used again
9292 we have to point it back to where it
9294 if (AOP_SIZE (result) > 1 &&
9295 !OP_SYMBOL (left)->remat &&
9296 (OP_SYMBOL (left)->liveTo > ic->seq ||
9300 int size = AOP_SIZE (result) - 1;
9302 emitcode ("dec", "%s", rname);
9307 freeAsmop (result, NULL, ic, TRUE);
9308 if (pi) pi->generated = 1;
9311 /*-----------------------------------------------------------------*/
9312 /* genPagedPointerGet - emitcode for paged pointer fetch */
9313 /*-----------------------------------------------------------------*/
9315 genPagedPointerGet (operand * left,
9323 sym_link *rtype, *retype, *letype;
9325 rtype = operandType (result);
9326 retype = getSpec (rtype);
9327 letype = getSpec (operandType (left));
9328 aopOp (left, ic, FALSE, FALSE);
9330 /* if the value is already in a pointer register
9331 then don't need anything more */
9332 if (!AOP_INPREG (AOP (left)))
9334 /* otherwise get a free pointer register */
9336 preg = getFreePtr (ic, &aop, FALSE);
9337 emitcode ("mov", "%s,%s",
9339 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9343 rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9345 freeAsmop (left, NULL, ic, TRUE);
9346 aopOp (result, ic, FALSE, FALSE);
9348 /* if bitfield then unpack the bits */
9349 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9350 genUnpackBits (result, rname, PPOINTER);
9353 /* we have can just get the values */
9354 int size = AOP_SIZE (result);
9360 emitcode ("movx", "a,@%s", rname);
9361 aopPut (AOP (result), "a", offset);
9366 emitcode ("inc", "%s", rname);
9370 /* now some housekeeping stuff */
9373 /* we had to allocate for this iCode */
9374 if (pi) aopPut ( AOP (left), rname, 0);
9375 freeAsmop (NULL, aop, ic, TRUE);
9379 /* we did not allocate which means left
9380 already in a pointer register, then
9381 if size > 0 && this could be used again
9382 we have to point it back to where it
9384 if (AOP_SIZE (result) > 1 &&
9385 !OP_SYMBOL (left)->remat &&
9386 (OP_SYMBOL (left)->liveTo > ic->seq ||
9390 int size = AOP_SIZE (result) - 1;
9392 emitcode ("dec", "%s", rname);
9397 freeAsmop (result, NULL, ic, TRUE);
9398 if (pi) pi->generated = 1;
9401 /*-----------------------------------------------------------------*/
9402 /* genFarPointerGet - gget value from far space */
9403 /*-----------------------------------------------------------------*/
9405 genFarPointerGet (operand * left,
9406 operand * result, iCode * ic, iCode *pi)
9408 int size, offset, dopi=1;
9409 sym_link *retype = getSpec (operandType (result));
9410 sym_link *letype = getSpec (operandType (left));
9411 D (emitcode (";", "genFarPointerGet"););
9413 aopOp (left, ic, FALSE, FALSE);
9415 /* if the operand is already in dptr
9416 then we do nothing else we move the value to dptr */
9417 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9419 /* if this is remateriazable */
9420 if (AOP_TYPE (left) == AOP_IMMD)
9422 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9426 /* we need to get it byte by byte */
9427 _startLazyDPSEvaluation ();
9428 if (AOP_TYPE (left) != AOP_DPTR)
9430 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9431 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9432 if (options.model == MODEL_FLAT24)
9433 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9437 /* We need to generate a load to DPTR indirect through DPTR. */
9438 D (emitcode (";", "genFarPointerGet -- indirection special case."););
9439 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9440 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9441 if (options.model == MODEL_FLAT24)
9442 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9443 emitcode ("pop", "dph");
9444 emitcode ("pop", "dpl");
9447 _endLazyDPSEvaluation ();
9450 /* so dptr know contains the address */
9451 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9453 /* if bit then unpack */
9454 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9455 if (AOP_INDPTRn(left)) {
9456 genSetDPTR(AOP(left)->aopu.dptr);
9458 genUnpackBits (result, "dptr", FPOINTER);
9459 if (AOP_INDPTRn(left)) {
9464 size = AOP_SIZE (result);
9467 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9469 genSetDPTR(AOP(left)->aopu.dptr);
9470 emitcode ("movx", "a,@dptr");
9471 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9472 emitcode ("inc", "dptr");
9474 aopPut (AOP (result), "a", offset++);
9477 _startLazyDPSEvaluation ();
9479 if (AOP_INDPTRn(left)) {
9480 genSetDPTR(AOP(left)->aopu.dptr);
9486 emitcode ("movx", "a,@dptr");
9487 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9488 emitcode ("inc", "dptr");
9490 aopPut (AOP (result), "a", offset++);
9492 _endLazyDPSEvaluation ();
9495 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9496 if (!AOP_INDPTRn(left)) {
9497 _startLazyDPSEvaluation ();
9498 aopPut ( AOP (left), "dpl", 0);
9499 aopPut ( AOP (left), "dph", 1);
9500 if (options.model == MODEL_FLAT24)
9501 aopPut ( AOP (left), "dpx", 2);
9502 _endLazyDPSEvaluation ();
9505 } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) &&
9506 AOP_SIZE(result) > 1 &&
9508 (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
9510 size = AOP_SIZE (result) - 1;
9511 if (AOP_INDPTRn(left)) {
9512 genSetDPTR(AOP(left)->aopu.dptr);
9514 while (size--) emitcode ("lcall","__decdptr");
9515 if (AOP_INDPTRn(left)) {
9520 freeAsmop (left, NULL, ic, TRUE);
9521 freeAsmop (result, NULL, ic, TRUE);
9524 /*-----------------------------------------------------------------*/
9525 /* genCodePointerGet - get value from code space */
9526 /*-----------------------------------------------------------------*/
9528 genCodePointerGet (operand * left,
9529 operand * result, iCode * ic, iCode *pi)
9531 int size, offset, dopi=1;
9532 sym_link *retype = getSpec (operandType (result));
9534 aopOp (left, ic, FALSE, FALSE);
9536 /* if the operand is already in dptr
9537 then we do nothing else we move the value to dptr */
9538 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
9540 /* if this is remateriazable */
9541 if (AOP_TYPE (left) == AOP_IMMD)
9543 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9546 { /* we need to get it byte by byte */
9547 _startLazyDPSEvaluation ();
9548 if (AOP_TYPE (left) != AOP_DPTR)
9550 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9551 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9552 if (options.model == MODEL_FLAT24)
9553 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9557 /* We need to generate a load to DPTR indirect through DPTR. */
9558 D (emitcode (";", "gencodePointerGet -- indirection special case."););
9559 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9560 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9561 if (options.model == MODEL_FLAT24)
9562 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9563 emitcode ("pop", "dph");
9564 emitcode ("pop", "dpl");
9567 _endLazyDPSEvaluation ();
9570 /* so dptr know contains the address */
9571 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9573 /* if bit then unpack */
9574 if (IS_BITVAR (retype)) {
9575 if (AOP_INDPTRn(left)) {
9576 genSetDPTR(AOP(left)->aopu.dptr);
9578 genUnpackBits (result, "dptr", CPOINTER);
9579 if (AOP_INDPTRn(left)) {
9584 size = AOP_SIZE (result);
9586 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9588 genSetDPTR(AOP(left)->aopu.dptr);
9589 emitcode ("clr", "a");
9590 emitcode ("movc", "a,@a+dptr");
9591 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9592 emitcode ("inc", "dptr");
9594 aopPut (AOP (result), "a", offset++);
9597 _startLazyDPSEvaluation ();
9600 if (AOP_INDPTRn(left)) {
9601 genSetDPTR(AOP(left)->aopu.dptr);
9607 emitcode ("clr", "a");
9608 emitcode ("movc", "a,@a+dptr");
9609 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9610 emitcode ("inc", "dptr");
9611 aopPut (AOP (result), "a", offset++);
9613 _endLazyDPSEvaluation ();
9616 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9617 if (!AOP_INDPTRn(left)) {
9618 _startLazyDPSEvaluation ();
9620 aopPut ( AOP (left), "dpl", 0);
9621 aopPut ( AOP (left), "dph", 1);
9622 if (options.model == MODEL_FLAT24)
9623 aopPut ( AOP (left), "dpx", 2);
9625 _endLazyDPSEvaluation ();
9628 } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
9629 AOP_SIZE(result) > 1 &&
9630 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9632 size = AOP_SIZE (result) - 1;
9633 if (AOP_INDPTRn(left)) {
9634 genSetDPTR(AOP(left)->aopu.dptr);
9636 while (size--) emitcode ("lcall","__decdptr");
9637 if (AOP_INDPTRn(left)) {
9642 freeAsmop (left, NULL, ic, TRUE);
9643 freeAsmop (result, NULL, ic, TRUE);
9646 /*-----------------------------------------------------------------*/
9647 /* genGenPointerGet - gget value from generic pointer space */
9648 /*-----------------------------------------------------------------*/
9650 genGenPointerGet (operand * left,
9651 operand * result, iCode * ic, iCode * pi)
9654 sym_link *retype = getSpec (operandType (result));
9655 sym_link *letype = getSpec (operandType (left));
9657 D (emitcode (";", "genGenPointerGet "); );
9659 aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
9661 /* if the operand is already in dptr
9662 then we do nothing else we move the value to dptr */
9663 if (AOP_TYPE (left) != AOP_STR)
9665 /* if this is remateriazable */
9666 if (AOP_TYPE (left) == AOP_IMMD)
9668 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9669 if (AOP(left)->aopu.aop_immd.from_cast_remat)
9671 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
9675 emitcode ("mov", "b,#%d", pointerCode (retype));
9679 { /* we need to get it byte by byte */
9680 _startLazyDPSEvaluation ();
9681 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
9682 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
9683 if (options.model == MODEL_FLAT24) {
9684 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9685 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
9687 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9689 _endLazyDPSEvaluation ();
9693 /* so dptr-b now contains the address */
9695 aopOp (result, ic, FALSE, TRUE);
9698 /* if bit then unpack */
9699 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9701 genUnpackBits (result, "dptr", GPOINTER);
9705 size = AOP_SIZE (result);
9712 // Get two bytes at a time, results in _AP & A.
9713 // dptr will be incremented ONCE by __gptrgetWord.
9715 // Note: any change here must be coordinated
9716 // with the implementation of __gptrgetWord
9717 // in device/lib/_gptrget.c
9718 emitcode ("lcall", "__gptrgetWord");
9719 aopPut (AOP (result), DP2_RESULT_REG, offset++);
9720 aopPut (AOP (result), "a", offset++);
9725 // Only one byte to get.
9726 emitcode ("lcall", "__gptrget");
9727 aopPut (AOP (result), "a", offset++);
9730 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9732 emitcode ("inc", "dptr");
9737 if (pi && AOP_TYPE (left) != AOP_IMMD) {
9738 _startLazyDPSEvaluation ();
9740 aopPut ( AOP (left), "dpl", 0);
9741 aopPut ( AOP (left), "dph", 1);
9742 if (options.model == MODEL_FLAT24) {
9743 aopPut ( AOP (left), "dpx", 2);
9744 aopPut ( AOP (left), "b", 3);
9745 } else aopPut ( AOP (left), "b", 2);
9747 _endLazyDPSEvaluation ();
9750 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9751 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9753 size = AOP_SIZE (result) - 1;
9754 while (size--) emitcode ("lcall","__decdptr");
9757 freeAsmop (left, NULL, ic, TRUE);
9758 freeAsmop (result, NULL, ic, TRUE);
9761 /*-----------------------------------------------------------------*/
9762 /* genPointerGet - generate code for pointer get */
9763 /*-----------------------------------------------------------------*/
9765 genPointerGet (iCode * ic, iCode *pi)
9767 operand *left, *result;
9768 sym_link *type, *etype;
9771 D (emitcode (";", "genPointerGet ");
9774 left = IC_LEFT (ic);
9775 result = IC_RESULT (ic);
9777 /* depending on the type of pointer we need to
9778 move it to the correct pointer register */
9779 type = operandType (left);
9780 etype = getSpec (type);
9781 /* if left is of type of pointer then it is simple */
9782 if (IS_PTR (type) && !IS_FUNC (type->next))
9783 p_type = DCL_TYPE (type);
9786 /* we have to go by the storage class */
9787 p_type = PTR_TYPE (SPEC_OCLS (etype));
9789 /* special case when cast remat */
9790 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9791 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9792 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9793 type = operandType (left);
9794 p_type = DCL_TYPE (type);
9796 /* now that we have the pointer type we assign
9797 the pointer values */
9803 genNearPointerGet (left, result, ic, pi);
9807 genPagedPointerGet (left, result, ic, pi);
9811 genFarPointerGet (left, result, ic, pi);
9815 genCodePointerGet (left, result, ic, pi);
9819 genGenPointerGet (left, result, ic, pi);
9825 /*-----------------------------------------------------------------*/
9826 /* genPackBits - generates code for packed bit storage */
9827 /*-----------------------------------------------------------------*/
9829 genPackBits (sym_link * etype,
9831 char *rname, int p_type)
9833 int offset = 0; /* source byte offset */
9834 int rlen = 0; /* remaining bitfield length */
9835 int blen; /* bitfield length */
9836 int bstr; /* bitfield starting bit within byte */
9837 int litval; /* source literal value (if AOP_LIT) */
9838 unsigned char mask; /* bitmask within current byte */
9840 D(emitcode ("; genPackBits",""));
9842 blen = SPEC_BLEN (etype);
9843 bstr = SPEC_BSTR (etype);
9845 /* If the bitfield length is less than a byte */
9848 mask = ((unsigned char) (0xFF << (blen + bstr)) |
9849 (unsigned char) (0xFF >> (8 - bstr)));
9851 if (AOP_TYPE (right) == AOP_LIT)
9853 /* Case with a bitfield length <8 and literal source
9855 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9857 litval &= (~mask) & 0xff;
9858 emitPtrByteGet (rname, p_type, FALSE);
9859 if ((mask|litval)!=0xff)
9860 emitcode ("anl","a,#!constbyte", mask);
9862 emitcode ("orl","a,#!constbyte", litval);
9866 if ((blen==1) && (p_type!=GPOINTER))
9868 /* Case with a bitfield length == 1 and no generic pointer
9870 if (AOP_TYPE (right) == AOP_CRY)
9871 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9874 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
9875 emitcode ("rrc","a");
9877 emitPtrByteGet (rname, p_type, FALSE);
9878 emitcode ("mov","acc.%d,c",bstr);
9882 /* Case with a bitfield length < 8 and arbitrary source
9884 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
9885 /* shift and mask source value */
9887 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
9889 /* transfer A to B and get next byte */
9890 emitPtrByteGet (rname, p_type, TRUE);
9892 emitcode ("anl", "a,#!constbyte", mask);
9893 emitcode ("orl", "a,b");
9894 if (p_type == GPOINTER)
9895 emitcode ("pop", "b");
9899 emitPtrByteSet (rname, p_type, "a");
9903 /* Bit length is greater than 7 bits. In this case, copy */
9904 /* all except the partial byte at the end */
9905 for (rlen=blen;rlen>=8;rlen-=8)
9907 emitPtrByteSet (rname, p_type,
9908 aopGet (AOP (right), offset++, FALSE, TRUE, NULL) );
9910 emitcode ("inc", "%s", rname);
9913 /* If there was a partial byte at the end */
9916 mask = (((unsigned char) -1 << rlen) & 0xff);
9918 if (AOP_TYPE (right) == AOP_LIT)
9920 /* Case with partial byte and literal source
9922 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9923 litval >>= (blen-rlen);
9924 litval &= (~mask) & 0xff;
9925 emitPtrByteGet (rname, p_type, FALSE);
9926 if ((mask|litval)!=0xff)
9927 emitcode ("anl","a,#!constbyte", mask);
9929 emitcode ("orl","a,#!constbyte", litval);
9933 /* Case with partial byte and arbitrary source
9935 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9936 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
9938 /* transfer A to B and get next byte */
9939 emitPtrByteGet (rname, p_type, TRUE);
9941 emitcode ("anl", "a,#!constbyte", mask);
9942 emitcode ("orl", "a,b");
9943 if (p_type == GPOINTER)
9944 emitcode ("pop", "b");
9946 emitPtrByteSet (rname, p_type, "a");
9952 /*-----------------------------------------------------------------*/
9953 /* genDataPointerSet - remat pointer to data space */
9954 /*-----------------------------------------------------------------*/
9956 genDataPointerSet (operand * right,
9960 int size, offset = 0;
9963 aopOp (right, ic, FALSE, FALSE);
9965 l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
9966 size = AOP_SIZE (right);
9971 SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
9975 SNPRINTF (buff, sizeof(buff), "%s", l + 1);
9978 emitcode ("mov", "%s,%s", buff,
9979 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9982 freeAsmop (right, NULL, ic, TRUE);
9983 freeAsmop (result, NULL, ic, TRUE);
9986 /*-----------------------------------------------------------------*/
9987 /* genNearPointerSet - emitcode for near pointer put */
9988 /*-----------------------------------------------------------------*/
9990 genNearPointerSet (operand * right,
9997 sym_link *retype, *letype;
9998 sym_link *ptype = operandType (result);
10000 retype = getSpec (operandType (right));
10001 letype = getSpec (ptype);
10003 aopOp (result, ic, FALSE, FALSE);
10005 /* if the result is rematerializable &
10006 in data space & not a bit variable */
10007 if (AOP_TYPE (result) == AOP_IMMD &&
10008 DCL_TYPE (ptype) == POINTER &&
10009 !IS_BITVAR (retype) &&
10010 !IS_BITVAR (letype))
10012 genDataPointerSet (right, result, ic);
10016 /* if the value is already in a pointer register
10017 then don't need anything more */
10018 if (!AOP_INPREG (AOP (result)))
10020 /* otherwise get a free pointer register */
10023 aop = newAsmop (0);
10024 preg = getFreePtr (ic, &aop, FALSE);
10025 emitcode ("mov", "%s,%s",
10027 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10028 rname = preg->name;
10031 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10033 aopOp (right, ic, FALSE, FALSE);
10035 /* if bitfield then unpack the bits */
10036 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10037 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
10040 /* we have can just get the values */
10041 int size = AOP_SIZE (right);
10046 l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
10050 emitcode ("mov", "@%s,a", rname);
10053 emitcode ("mov", "@%s,%s", rname, l);
10055 emitcode ("inc", "%s", rname);
10060 /* now some housekeeping stuff */
10063 /* we had to allocate for this iCode */
10064 if (pi) aopPut (AOP (result),rname,0);
10065 freeAsmop (NULL, aop, ic, TRUE);
10069 /* we did not allocate which means left
10070 already in a pointer register, then
10071 if size > 0 && this could be used again
10072 we have to point it back to where it
10074 if (AOP_SIZE (right) > 1 &&
10075 !OP_SYMBOL (result)->remat &&
10076 (OP_SYMBOL (result)->liveTo > ic->seq ||
10080 int size = AOP_SIZE (right) - 1;
10082 emitcode ("dec", "%s", rname);
10087 if (pi) pi->generated = 1;
10088 freeAsmop (result, NULL, ic, TRUE);
10089 freeAsmop (right, NULL, ic, TRUE);
10094 /*-----------------------------------------------------------------*/
10095 /* genPagedPointerSet - emitcode for Paged pointer put */
10096 /*-----------------------------------------------------------------*/
10098 genPagedPointerSet (operand * right,
10105 sym_link *retype, *letype;
10107 retype = getSpec (operandType (right));
10108 letype = getSpec (operandType (result));
10110 aopOp (result, ic, FALSE, FALSE);
10112 /* if the value is already in a pointer register
10113 then don't need anything more */
10114 if (!AOP_INPREG (AOP (result)))
10116 /* otherwise get a free pointer register */
10119 aop = newAsmop (0);
10120 preg = getFreePtr (ic, &aop, FALSE);
10121 emitcode ("mov", "%s,%s",
10123 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10124 rname = preg->name;
10127 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10129 aopOp (right, ic, FALSE, FALSE);
10131 /* if bitfield then unpack the bits */
10132 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10133 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
10136 /* we have can just get the values */
10137 int size = AOP_SIZE (right);
10142 MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10144 emitcode ("movx", "@%s,a", rname);
10147 emitcode ("inc", "%s", rname);
10153 /* now some housekeeping stuff */
10156 if (pi) aopPut (AOP (result),rname,0);
10157 /* we had to allocate for this iCode */
10158 freeAsmop (NULL, aop, ic, TRUE);
10162 /* we did not allocate which means left
10163 already in a pointer register, then
10164 if size > 0 && this could be used again
10165 we have to point it back to where it
10167 if (AOP_SIZE (right) > 1 &&
10168 !OP_SYMBOL (result)->remat &&
10169 (OP_SYMBOL (result)->liveTo > ic->seq ||
10173 int size = AOP_SIZE (right) - 1;
10175 emitcode ("dec", "%s", rname);
10180 if (pi) pi->generated = 1;
10181 freeAsmop (result, NULL, ic, TRUE);
10182 freeAsmop (right, NULL, ic, TRUE);
10187 /*-----------------------------------------------------------------*/
10188 /* genFarPointerSet - set value from far space */
10189 /*-----------------------------------------------------------------*/
10191 genFarPointerSet (operand * right,
10192 operand * result, iCode * ic, iCode *pi)
10194 int size, offset, dopi=1;
10195 sym_link *retype = getSpec (operandType (right));
10196 sym_link *letype = getSpec (operandType (result));
10198 aopOp (result, ic, FALSE, FALSE);
10200 /* if the operand is already in dptr
10201 then we do nothing else we move the value to dptr */
10202 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10204 /* if this is remateriazable */
10205 if (AOP_TYPE (result) == AOP_IMMD)
10206 emitcode ("mov", "dptr,%s",
10207 aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10210 /* we need to get it byte by byte */
10211 _startLazyDPSEvaluation ();
10212 if (AOP_TYPE (result) != AOP_DPTR)
10214 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10215 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10216 if (options.model == MODEL_FLAT24)
10217 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10221 /* We need to generate a load to DPTR indirect through DPTR. */
10222 D (emitcode (";", "genFarPointerSet -- indirection special case."););
10224 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10225 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10226 if (options.model == MODEL_FLAT24)
10227 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10228 emitcode ("pop", "dph");
10229 emitcode ("pop", "dpl");
10232 _endLazyDPSEvaluation ();
10235 /* so dptr know contains the address */
10236 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10238 /* if bit then unpack */
10239 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
10240 if (AOP_INDPTRn(result)) {
10241 genSetDPTR(AOP(result)->aopu.dptr);
10243 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
10244 if (AOP_INDPTRn(result)) {
10248 size = AOP_SIZE (right);
10250 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10252 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10254 genSetDPTR(AOP(result)->aopu.dptr);
10255 emitcode ("movx", "@dptr,a");
10256 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10257 emitcode ("inc", "dptr");
10261 _startLazyDPSEvaluation ();
10263 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10265 if (AOP_INDPTRn(result)) {
10266 genSetDPTR(AOP(result)->aopu.dptr);
10272 emitcode ("movx", "@dptr,a");
10273 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10274 emitcode ("inc", "dptr");
10276 _endLazyDPSEvaluation ();
10280 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10281 if (!AOP_INDPTRn(result)) {
10282 _startLazyDPSEvaluation ();
10284 aopPut (AOP(result),"dpl",0);
10285 aopPut (AOP(result),"dph",1);
10286 if (options.model == MODEL_FLAT24)
10287 aopPut (AOP(result),"dpx",2);
10289 _endLazyDPSEvaluation ();
10292 } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
10293 AOP_SIZE(right) > 1 &&
10294 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10296 size = AOP_SIZE (right) - 1;
10297 if (AOP_INDPTRn(result)) {
10298 genSetDPTR(AOP(result)->aopu.dptr);
10300 while (size--) emitcode ("lcall","__decdptr");
10301 if (AOP_INDPTRn(result)) {
10305 freeAsmop (result, NULL, ic, TRUE);
10306 freeAsmop (right, NULL, ic, TRUE);
10309 /*-----------------------------------------------------------------*/
10310 /* genGenPointerSet - set value from generic pointer space */
10311 /*-----------------------------------------------------------------*/
10313 genGenPointerSet (operand * right,
10314 operand * result, iCode * ic, iCode *pi)
10317 sym_link *retype = getSpec (operandType (right));
10318 sym_link *letype = getSpec (operandType (result));
10320 aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10322 /* if the operand is already in dptr
10323 then we do nothing else we move the value to dptr */
10324 if (AOP_TYPE (result) != AOP_STR)
10326 _startLazyDPSEvaluation ();
10327 /* if this is remateriazable */
10328 if (AOP_TYPE (result) == AOP_IMMD)
10330 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10331 if (AOP(result)->aopu.aop_immd.from_cast_remat)
10333 MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10338 "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10342 { /* we need to get it byte by byte */
10343 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10344 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10345 if (options.model == MODEL_FLAT24) {
10346 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10347 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10349 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10352 _endLazyDPSEvaluation ();
10354 /* so dptr + b now contains the address */
10356 aopOp (right, ic, FALSE, TRUE);
10360 /* if bit then unpack */
10361 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10363 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
10367 size = AOP_SIZE (right);
10370 _startLazyDPSEvaluation ();
10375 // Set two bytes at a time, passed in _AP & A.
10376 // dptr will be incremented ONCE by __gptrputWord.
10378 // Note: any change here must be coordinated
10379 // with the implementation of __gptrputWord
10380 // in device/lib/_gptrput.c
10381 emitcode("mov", "_ap, %s",
10382 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10383 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10387 emitcode ("lcall", "__gptrputWord");
10392 // Only one byte to put.
10393 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10397 emitcode ("lcall", "__gptrput");
10400 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10402 emitcode ("inc", "dptr");
10405 _endLazyDPSEvaluation ();
10408 if (pi && AOP_TYPE (result) != AOP_IMMD) {
10409 _startLazyDPSEvaluation ();
10411 aopPut (AOP(result),"dpl",0);
10412 aopPut (AOP(result),"dph",1);
10413 if (options.model == MODEL_FLAT24) {
10414 aopPut (AOP(result),"dpx",2);
10415 aopPut (AOP(result),"b",3);
10417 aopPut (AOP(result),"b",2);
10419 _endLazyDPSEvaluation ();
10422 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10423 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10425 size = AOP_SIZE (right) - 1;
10426 while (size--) emitcode ("lcall","__decdptr");
10428 freeAsmop (result, NULL, ic, TRUE);
10429 freeAsmop (right, NULL, ic, TRUE);
10432 /*-----------------------------------------------------------------*/
10433 /* genPointerSet - stores the value into a pointer location */
10434 /*-----------------------------------------------------------------*/
10436 genPointerSet (iCode * ic, iCode *pi)
10438 operand *right, *result;
10439 sym_link *type, *etype;
10442 D (emitcode (";", "genPointerSet "););
10444 right = IC_RIGHT (ic);
10445 result = IC_RESULT (ic);
10447 /* depending on the type of pointer we need to
10448 move it to the correct pointer register */
10449 type = operandType (result);
10450 etype = getSpec (type);
10451 /* if left is of type of pointer then it is simple */
10452 if (IS_PTR (type) && !IS_FUNC (type->next))
10454 p_type = DCL_TYPE (type);
10458 /* we have to go by the storage class */
10459 p_type = PTR_TYPE (SPEC_OCLS (etype));
10461 /* special case when cast remat */
10462 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10463 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10464 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10465 type = operandType (result);
10466 p_type = DCL_TYPE (type);
10469 /* now that we have the pointer type we assign
10470 the pointer values */
10476 genNearPointerSet (right, result, ic, pi);
10480 genPagedPointerSet (right, result, ic, pi);
10484 genFarPointerSet (right, result, ic, pi);
10488 genGenPointerSet (right, result, ic, pi);
10492 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10493 "genPointerSet: illegal pointer type");
10498 /*-----------------------------------------------------------------*/
10499 /* genIfx - generate code for Ifx statement */
10500 /*-----------------------------------------------------------------*/
10502 genIfx (iCode * ic, iCode * popIc)
10504 operand *cond = IC_COND (ic);
10507 D (emitcode (";", "genIfx "););
10509 aopOp (cond, ic, FALSE, FALSE);
10511 /* get the value into acc */
10512 if (AOP_TYPE (cond) != AOP_CRY)
10521 /* the result is now in the accumulator */
10522 freeAsmop (cond, NULL, ic, TRUE);
10524 /* if there was something to be popped then do it */
10528 /* if the condition is a bit variable */
10529 if (isbit && IS_ITEMP (cond) &&
10532 genIfxJump (ic, SPIL_LOC (cond)->rname);
10534 else if (isbit && !IS_ITEMP (cond))
10536 genIfxJump (ic, OP_SYMBOL (cond)->rname);
10540 genIfxJump (ic, "a");
10546 /*-----------------------------------------------------------------*/
10547 /* genAddrOf - generates code for address of */
10548 /*-----------------------------------------------------------------*/
10550 genAddrOf (iCode * ic)
10552 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10555 D (emitcode (";", "genAddrOf ");
10558 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10560 /* if the operand is on the stack then we
10561 need to get the stack offset of this
10563 if (sym->onStack) {
10565 /* if 10 bit stack */
10566 if (options.stack10bit) {
10570 tsprintf(buff, sizeof(buff),
10571 "#!constbyte",(options.stack_loc >> 16) & 0xff);
10572 /* if it has an offset then we need to compute it */
10573 /* emitcode ("subb", "a,#!constbyte", */
10574 /* -((sym->stack < 0) ? */
10575 /* ((short) (sym->stack - _G.nRegsSaved)) : */
10576 /* ((short) sym->stack)) & 0xff); */
10577 /* emitcode ("mov","b,a"); */
10578 /* emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
10579 /* ((short) (sym->stack - _G.nRegsSaved)) : */
10580 /* ((short) sym->stack)) >> 8) & 0xff); */
10582 emitcode ("mov", "a,_bpx");
10583 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
10584 ((char) (sym->stack - _G.nRegsSaved)) :
10585 ((char) sym->stack )) & 0xff);
10586 emitcode ("mov", "b,a");
10587 emitcode ("mov", "a,_bpx+1");
10589 offset = (((sym->stack < 0) ?
10590 ((short) (sym->stack - _G.nRegsSaved)) :
10591 ((short) sym->stack )) >> 8) & 0xff;
10593 emitcode ("addc","a,#!constbyte", offset);
10595 aopPut (AOP (IC_RESULT (ic)), "b", 0);
10596 aopPut (AOP (IC_RESULT (ic)), "a", 1);
10597 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10599 /* we can just move _bp */
10600 aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10601 aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10602 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10605 /* if it has an offset then we need to compute it */
10607 emitcode ("mov", "a,_bp");
10608 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10609 aopPut (AOP (IC_RESULT (ic)), "a", 0);
10611 /* we can just move _bp */
10612 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10614 /* fill the result with zero */
10615 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10618 if (options.stack10bit && size < (FPTRSIZE - 1)) {
10620 "*** warning: pointer to stack var truncated.\n");
10625 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10631 /* object not on stack then we need the name */
10632 size = AOP_SIZE (IC_RESULT (ic));
10637 char s[SDCC_NAME_MAX];
10641 tsprintf(s, sizeof(s), "#!his",sym->rname);
10644 tsprintf(s, sizeof(s), "#!hihis",sym->rname);
10647 tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
10649 default: /* should not need this (just in case) */
10650 SNPRINTF (s, sizeof(s), "#(%s >> %d)",
10657 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10660 aopPut (AOP (IC_RESULT (ic)), s, offset++);
10664 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10668 #if 0 // obsolete, and buggy for != xdata
10669 /*-----------------------------------------------------------------*/
10670 /* genArrayInit - generates code for address of */
10671 /*-----------------------------------------------------------------*/
10673 genArrayInit (iCode * ic)
10675 literalList *iLoop;
10677 int elementSize = 0, eIndex;
10678 unsigned val, lastVal;
10680 operand *left=IC_LEFT(ic);
10682 D (emitcode (";", "genArrayInit "););
10684 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10686 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10688 // Load immediate value into DPTR.
10689 emitcode("mov", "dptr, %s",
10690 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
10692 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10695 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10696 "Unexpected operand to genArrayInit.\n");
10699 // a regression because of SDCCcse.c:1.52
10700 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10701 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10702 if (options.model == MODEL_FLAT24)
10703 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10707 type = operandType(IC_LEFT(ic));
10709 if (type && type->next)
10711 elementSize = getSize(type->next);
10715 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10716 "can't determine element size in genArrayInit.\n");
10720 iLoop = IC_ARRAYILIST(ic);
10725 bool firstpass = TRUE;
10727 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
10728 iLoop->count, (int)iLoop->literalValue, elementSize);
10734 symbol *tlbl = NULL;
10736 count = ix > 256 ? 256 : ix;
10740 tlbl = newiTempLabel (NULL);
10741 if (firstpass || (count & 0xff))
10743 emitcode("mov", "b, #!constbyte", count & 0xff);
10746 emitcode ("", "!tlabeldef", tlbl->key + 100);
10751 for (eIndex = 0; eIndex < elementSize; eIndex++)
10753 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10754 if (val != lastVal)
10756 emitcode("mov", "a, #!constbyte", val);
10760 emitcode("movx", "@dptr, a");
10761 emitcode("inc", "dptr");
10766 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10772 iLoop = iLoop->next;
10775 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10779 /*-----------------------------------------------------------------*/
10780 /* genFarFarAssign - assignment when both are in far space */
10781 /*-----------------------------------------------------------------*/
10783 genFarFarAssign (operand * result, operand * right, iCode * ic)
10785 int size = AOP_SIZE (right);
10787 symbol *rSym = NULL;
10791 /* quick & easy case. */
10792 D(emitcode(";","genFarFarAssign (1 byte case)"););
10793 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
10794 freeAsmop (right, NULL, ic, FALSE);
10795 /* now assign DPTR to result */
10797 aopOp(result, ic, FALSE, FALSE);
10799 aopPut(AOP(result), "a", 0);
10800 freeAsmop(result, NULL, ic, FALSE);
10804 /* See if we've got an underlying symbol to abuse. */
10805 if (IS_SYMOP(result) && OP_SYMBOL(result))
10807 if (IS_TRUE_SYMOP(result))
10809 rSym = OP_SYMBOL(result);
10811 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10813 rSym = OP_SYMBOL(result)->usl.spillLoc;
10817 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10819 /* We can use the '390 auto-toggle feature to good effect here. */
10821 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10822 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
10823 emitcode ("mov", "dptr,#%s", rSym->rname);
10824 /* DP2 = result, DP1 = right, DP1 is current. */
10827 emitcode("movx", "a,@dptr");
10828 emitcode("movx", "@dptr,a");
10831 emitcode("inc", "dptr");
10832 emitcode("inc", "dptr");
10835 emitcode("mov", "dps,#0");
10836 freeAsmop (right, NULL, ic, FALSE);
10838 some alternative code for processors without auto-toggle
10839 no time to test now, so later well put in...kpb
10840 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10841 emitcode("mov", "dps,#1"); /* Select DPTR2. */
10842 emitcode ("mov", "dptr,#%s", rSym->rname);
10843 /* DP2 = result, DP1 = right, DP1 is current. */
10847 emitcode("movx", "a,@dptr");
10849 emitcode("inc", "dptr");
10850 emitcode("inc", "dps");
10851 emitcode("movx", "@dptr,a");
10853 emitcode("inc", "dptr");
10854 emitcode("inc", "dps");
10856 emitcode("mov", "dps,#0");
10857 freeAsmop (right, NULL, ic, FALSE);
10862 D (emitcode (";", "genFarFarAssign"););
10863 aopOp (result, ic, TRUE, TRUE);
10865 _startLazyDPSEvaluation ();
10869 aopPut (AOP (result),
10870 aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
10873 _endLazyDPSEvaluation ();
10874 freeAsmop (result, NULL, ic, FALSE);
10875 freeAsmop (right, NULL, ic, FALSE);
10879 /*-----------------------------------------------------------------*/
10880 /* genAssign - generate code for assignment */
10881 /*-----------------------------------------------------------------*/
10883 genAssign (iCode * ic)
10885 operand *result, *right;
10887 unsigned long lit = 0L;
10889 D (emitcode (";", "genAssign ");
10892 result = IC_RESULT (ic);
10893 right = IC_RIGHT (ic);
10895 /* if they are the same */
10896 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10899 aopOp (right, ic, FALSE, FALSE);
10901 emitcode (";", "genAssign: resultIsFar = %s",
10902 isOperandInFarSpace (result) ?
10905 /* special case both in far space */
10906 if ((AOP_TYPE (right) == AOP_DPTR ||
10907 AOP_TYPE (right) == AOP_DPTR2) &&
10908 /* IS_TRUE_SYMOP(result) && */
10909 isOperandInFarSpace (result))
10911 genFarFarAssign (result, right, ic);
10915 aopOp (result, ic, TRUE, FALSE);
10917 /* if they are the same registers */
10918 if (sameRegs (AOP (right), AOP (result)))
10921 /* if the result is a bit */
10922 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10924 /* if the right size is a literal then
10925 we know what the value is */
10926 if (AOP_TYPE (right) == AOP_LIT)
10928 if (((int) operandLitValue (right)))
10929 aopPut (AOP (result), one, 0);
10931 aopPut (AOP (result), zero, 0);
10935 /* the right is also a bit variable */
10936 if (AOP_TYPE (right) == AOP_CRY)
10938 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10939 aopPut (AOP (result), "c", 0);
10943 /* we need to or */
10945 aopPut (AOP (result), "a", 0);
10949 /* bit variables done */
10951 size = AOP_SIZE (result);
10953 if (AOP_TYPE (right) == AOP_LIT)
10954 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10957 (AOP_TYPE (result) != AOP_REG) &&
10958 (AOP_TYPE (right) == AOP_LIT) &&
10959 !IS_FLOAT (operandType (right)))
10961 _startLazyDPSEvaluation ();
10962 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10964 aopPut (AOP (result),
10965 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10970 /* And now fill the rest with zeros. */
10973 emitcode ("clr", "a");
10977 aopPut (AOP (result), "a", offset++);
10979 _endLazyDPSEvaluation ();
10983 _startLazyDPSEvaluation ();
10986 aopPut (AOP (result),
10987 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10991 _endLazyDPSEvaluation ();
10995 freeAsmop (right, NULL, ic, FALSE);
10996 freeAsmop (result, NULL, ic, TRUE);
10999 /*-----------------------------------------------------------------*/
11000 /* genJumpTab - generates code for jump table */
11001 /*-----------------------------------------------------------------*/
11003 genJumpTab (iCode * ic)
11008 D (emitcode (";", "genJumpTab ");
11011 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
11012 /* get the condition into accumulator */
11013 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
11015 /* multiply by four! */
11016 emitcode ("add", "a,acc");
11017 emitcode ("add", "a,acc");
11018 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11020 jtab = newiTempLabel (NULL);
11021 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
11022 emitcode ("jmp", "@a+dptr");
11023 emitcode ("", "!tlabeldef", jtab->key + 100);
11024 /* now generate the jump labels */
11025 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11026 jtab = setNextItem (IC_JTLABELS (ic)))
11027 emitcode ("ljmp", "!tlabel", jtab->key + 100);
11031 /*-----------------------------------------------------------------*/
11032 /* genCast - gen code for casting */
11033 /*-----------------------------------------------------------------*/
11035 genCast (iCode * ic)
11037 operand *result = IC_RESULT (ic);
11038 sym_link *ctype = operandType (IC_LEFT (ic));
11039 sym_link *rtype = operandType (IC_RIGHT (ic));
11040 operand *right = IC_RIGHT (ic);
11043 D (emitcode (";", "genCast "););
11045 /* if they are equivalent then do nothing */
11046 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11049 aopOp (right, ic, FALSE, FALSE);
11050 aopOp (result, ic, FALSE, (AOP_TYPE(right) == AOP_DPTR));
11052 /* if the result is a bit */
11053 if (IS_BITVAR (OP_SYMBOL (result)->type)
11054 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
11056 /* if the right size is a literal then
11057 we know what the value is */
11058 if (AOP_TYPE (right) == AOP_LIT)
11060 if (((int) operandLitValue (right)))
11061 aopPut (AOP (result), one, 0);
11063 aopPut (AOP (result), zero, 0);
11068 /* the right is also a bit variable */
11069 if (AOP_TYPE (right) == AOP_CRY)
11071 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11072 aopPut (AOP (result), "c", 0);
11076 /* we need to or */
11078 aopPut (AOP (result), "a", 0);
11082 /* if they are the same size : or less */
11083 if (AOP_SIZE (result) <= AOP_SIZE (right))
11086 /* if they are in the same place */
11087 if (sameRegs (AOP (right), AOP (result)))
11090 /* if they in different places then copy */
11091 size = AOP_SIZE (result);
11093 _startLazyDPSEvaluation ();
11096 aopPut (AOP (result),
11097 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11101 _endLazyDPSEvaluation ();
11106 /* if the result is of type pointer */
11107 if (IS_PTR (ctype))
11111 sym_link *type = operandType (right);
11113 /* pointer to generic pointer */
11114 if (IS_GENPTR (ctype))
11118 p_type = DCL_TYPE (type);
11122 #if OLD_CAST_BEHAVIOR
11123 /* KV: we are converting a non-pointer type to
11124 * a generic pointer. This (ifdef'd out) code
11125 * says that the resulting generic pointer
11126 * should have the same class as the storage
11127 * location of the non-pointer variable.
11129 * For example, converting an int (which happens
11130 * to be stored in DATA space) to a pointer results
11131 * in a DATA generic pointer; if the original int
11132 * in XDATA space, so will be the resulting pointer.
11134 * I don't like that behavior, and thus this change:
11135 * all such conversions will be forced to XDATA and
11136 * throw a warning. If you want some non-XDATA
11137 * type, or you want to suppress the warning, you
11138 * must go through an intermediate cast, like so:
11140 * char _generic *gp = (char _xdata *)(intVar);
11142 sym_link *etype = getSpec (type);
11144 /* we have to go by the storage class */
11145 if (SPEC_OCLS (etype) != generic)
11147 p_type = PTR_TYPE (SPEC_OCLS (etype));
11152 /* Converting unknown class (i.e. register variable)
11153 * to generic pointer. This is not good, but
11154 * we'll make a guess (and throw a warning).
11157 werror (W_INT_TO_GEN_PTR_CAST);
11161 /* the first two bytes are known */
11162 size = GPTRSIZE - 1;
11164 _startLazyDPSEvaluation ();
11167 aopPut (AOP (result),
11168 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11172 _endLazyDPSEvaluation ();
11174 /* the last byte depending on type */
11176 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11181 // pointerTypeToGPByte will have bitched.
11185 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11186 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11191 /* just copy the pointers */
11192 size = AOP_SIZE (result);
11194 _startLazyDPSEvaluation ();
11197 aopPut (AOP (result),
11198 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11202 _endLazyDPSEvaluation ();
11206 /* so we now know that the size of destination is greater
11207 than the size of the source */
11208 /* we move to result for the size of source */
11209 size = AOP_SIZE (right);
11211 _startLazyDPSEvaluation ();
11214 aopPut (AOP (result),
11215 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11219 _endLazyDPSEvaluation ();
11221 /* now depending on the sign of the source && destination */
11222 size = AOP_SIZE (result) - AOP_SIZE (right);
11223 /* if unsigned or not an integral type */
11224 /* also, if the source is a bit, we don't need to sign extend, because
11225 * it can't possibly have set the sign bit.
11227 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
11231 aopPut (AOP (result), zero, offset++);
11236 /* we need to extend the sign :{ */
11237 MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11238 FALSE, FALSE, NULL));
11239 emitcode ("rlc", "a");
11240 emitcode ("subb", "a,acc");
11242 aopPut (AOP (result), "a", offset++);
11245 /* we are done hurray !!!! */
11248 freeAsmop (right, NULL, ic, TRUE);
11249 freeAsmop (result, NULL, ic, TRUE);
11253 /*-----------------------------------------------------------------*/
11254 /* genDjnz - generate decrement & jump if not zero instrucion */
11255 /*-----------------------------------------------------------------*/
11257 genDjnz (iCode * ic, iCode * ifx)
11259 symbol *lbl, *lbl1;
11263 /* if the if condition has a false label
11264 then we cannot save */
11265 if (IC_FALSE (ifx))
11268 /* if the minus is not of the form
11270 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11271 !IS_OP_LITERAL (IC_RIGHT (ic)))
11274 if (operandLitValue (IC_RIGHT (ic)) != 1)
11277 /* if the size of this greater than one then no
11279 if (getSize (operandType (IC_RESULT (ic))) > 1)
11282 /* otherwise we can save BIG */
11283 D(emitcode(";", "genDjnz"););
11285 lbl = newiTempLabel (NULL);
11286 lbl1 = newiTempLabel (NULL);
11288 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11290 if (AOP_NEEDSACC(IC_RESULT(ic)))
11292 /* If the result is accessed indirectly via
11293 * the accumulator, we must explicitly write
11294 * it back after the decrement.
11296 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11298 if (strcmp(rByte, "a"))
11300 /* Something is hopelessly wrong */
11301 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11302 __FILE__, __LINE__);
11303 /* We can just give up; the generated code will be inefficient,
11304 * but what the hey.
11306 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11309 emitcode ("dec", "%s", rByte);
11310 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11311 emitcode ("jnz", "!tlabel", lbl->key + 100);
11313 else if (IS_AOP_PREG (IC_RESULT (ic)))
11315 emitcode ("dec", "%s",
11316 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11317 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11318 emitcode ("jnz", "!tlabel", lbl->key + 100);
11322 emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11325 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11326 emitcode ("", "!tlabeldef", lbl->key + 100);
11327 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11328 emitcode ("", "!tlabeldef", lbl1->key + 100);
11330 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11331 ifx->generated = 1;
11335 /*-----------------------------------------------------------------*/
11336 /* genReceive - generate code for a receive iCode */
11337 /*-----------------------------------------------------------------*/
11339 genReceive (iCode * ic)
11341 int size = getSize (operandType (IC_RESULT (ic)));
11345 D (emitcode (";", "genReceive "););
11347 if (ic->argreg == 1)
11349 /* first parameter */
11350 if (AOP_IS_STR(IC_RESULT(ic)))
11352 /* Nothing to do: it's already in the proper place. */
11359 useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11360 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11361 IS_TRUE_SYMOP (IC_RESULT (ic)));
11364 aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11367 /* Sanity checking... */
11368 if (AOP_USESDPTR(IC_RESULT(ic)))
11370 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11371 "genReceive got unexpected DPTR.");
11373 assignResultValue (IC_RESULT (ic));
11378 /* second receive onwards */
11379 /* this gets a little tricky since unused recevies will be
11380 eliminated, we have saved the reg in the type field . and
11381 we use that to figure out which register to use */
11382 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11383 rb1off = ic->argreg;
11386 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11389 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11392 /*-----------------------------------------------------------------*/
11393 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
11394 /*-----------------------------------------------------------------*/
11395 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11397 operand *from , *to , *count;
11402 /* we know it has to be 3 parameters */
11403 assert (nparms == 3);
11405 rsave = newBitVect(16);
11406 /* save DPTR if it needs to be saved */
11407 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11408 if (bitVectBitValue(ic->rMask,i))
11409 rsave = bitVectSetBit(rsave,i);
11411 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11412 ds390_rUmaskForOp (IC_RESULT(ic))));
11419 aopOp (from, ic->next, FALSE, FALSE);
11421 /* get from into DPTR1 */
11422 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11423 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11424 if (options.model == MODEL_FLAT24) {
11425 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11428 freeAsmop (from, NULL, ic, FALSE);
11429 aopOp (to, ic, FALSE, FALSE);
11430 /* get "to" into DPTR */
11431 /* if the operand is already in dptr
11432 then we do nothing else we move the value to dptr */
11433 if (AOP_TYPE (to) != AOP_STR) {
11434 /* if already in DPTR then we need to push */
11435 if (AOP_TYPE(to) == AOP_DPTR) {
11436 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11437 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11438 if (options.model == MODEL_FLAT24)
11439 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11440 emitcode ("pop", "dph");
11441 emitcode ("pop", "dpl");
11443 _startLazyDPSEvaluation ();
11444 /* if this is remateriazable */
11445 if (AOP_TYPE (to) == AOP_IMMD) {
11446 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11447 } else { /* we need to get it byte by byte */
11448 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11449 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11450 if (options.model == MODEL_FLAT24) {
11451 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11454 _endLazyDPSEvaluation ();
11457 freeAsmop (to, NULL, ic, FALSE);
11458 _G.dptrInUse = _G.dptr1InUse = 1;
11459 aopOp (count, ic->next->next, FALSE,FALSE);
11460 lbl =newiTempLabel(NULL);
11462 /* now for the actual copy */
11463 if (AOP_TYPE(count) == AOP_LIT &&
11464 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11465 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11467 emitcode ("lcall","__bi_memcpyc2x_s");
11469 emitcode ("lcall","__bi_memcpyx2x_s");
11471 freeAsmop (count, NULL, ic, FALSE);
11473 symbol *lbl1 = newiTempLabel(NULL);
11475 emitcode (";"," Auto increment but no djnz");
11476 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11477 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11478 freeAsmop (count, NULL, ic, FALSE);
11479 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11480 emitcode ("","!tlabeldef",lbl->key+100);
11482 emitcode ("clr","a");
11483 emitcode ("movc", "a,@a+dptr");
11485 emitcode ("movx", "a,@dptr");
11486 emitcode ("movx", "@dptr,a");
11487 emitcode ("inc", "dptr");
11488 emitcode ("inc", "dptr");
11489 emitcode ("mov","a,b");
11490 emitcode ("orl","a,_ap");
11491 emitcode ("jz","!tlabel",lbl1->key+100);
11492 emitcode ("mov","a,_ap");
11493 emitcode ("add","a,#!constbyte",0xFF);
11494 emitcode ("mov","_ap,a");
11495 emitcode ("mov","a,b");
11496 emitcode ("addc","a,#!constbyte",0xFF);
11497 emitcode ("mov","b,a");
11498 emitcode ("sjmp","!tlabel",lbl->key+100);
11499 emitcode ("","!tlabeldef",lbl1->key+100);
11501 emitcode ("mov", "dps,#0");
11502 _G.dptrInUse = _G.dptr1InUse = 0;
11503 unsavermask(rsave);
11507 /*-----------------------------------------------------------------*/
11508 /* genMemcmpX2X - gen code for memcmp xdata to xdata */
11509 /*-----------------------------------------------------------------*/
11510 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11512 operand *from , *to , *count;
11517 /* we know it has to be 3 parameters */
11518 assert (nparms == 3);
11520 rsave = newBitVect(16);
11521 /* save DPTR if it needs to be saved */
11522 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11523 if (bitVectBitValue(ic->rMask,i))
11524 rsave = bitVectSetBit(rsave,i);
11526 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11527 ds390_rUmaskForOp (IC_RESULT(ic))));
11534 aopOp (from, ic->next, FALSE, FALSE);
11536 /* get from into DPTR1 */
11537 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11538 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11539 if (options.model == MODEL_FLAT24) {
11540 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11543 freeAsmop (from, NULL, ic, FALSE);
11544 aopOp (to, ic, FALSE, FALSE);
11545 /* get "to" into DPTR */
11546 /* if the operand is already in dptr
11547 then we do nothing else we move the value to dptr */
11548 if (AOP_TYPE (to) != AOP_STR) {
11549 /* if already in DPTR then we need to push */
11550 if (AOP_TYPE(to) == AOP_DPTR) {
11551 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11552 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11553 if (options.model == MODEL_FLAT24)
11554 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11555 emitcode ("pop", "dph");
11556 emitcode ("pop", "dpl");
11558 _startLazyDPSEvaluation ();
11559 /* if this is remateriazable */
11560 if (AOP_TYPE (to) == AOP_IMMD) {
11561 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11562 } else { /* we need to get it byte by byte */
11563 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11564 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11565 if (options.model == MODEL_FLAT24) {
11566 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11569 _endLazyDPSEvaluation ();
11572 freeAsmop (to, NULL, ic, FALSE);
11573 _G.dptrInUse = _G.dptr1InUse = 1;
11574 aopOp (count, ic->next->next, FALSE,FALSE);
11575 lbl =newiTempLabel(NULL);
11576 lbl2 =newiTempLabel(NULL);
11578 /* now for the actual compare */
11579 if (AOP_TYPE(count) == AOP_LIT &&
11580 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11581 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11583 emitcode("lcall","__bi_memcmpc2x_s");
11585 emitcode("lcall","__bi_memcmpx2x_s");
11586 freeAsmop (count, NULL, ic, FALSE);
11587 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11588 aopPut(AOP(IC_RESULT(ic)),"a",0);
11589 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11591 symbol *lbl1 = newiTempLabel(NULL);
11593 emitcode("push","ar0");
11594 emitcode (";"," Auto increment but no djnz");
11595 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11596 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11597 freeAsmop (count, NULL, ic, FALSE);
11598 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11599 emitcode ("","!tlabeldef",lbl->key+100);
11601 emitcode ("clr","a");
11602 emitcode ("movc", "a,@a+dptr");
11604 emitcode ("movx", "a,@dptr");
11605 emitcode ("mov","r0,a");
11606 emitcode ("movx", "a,@dptr");
11607 emitcode ("clr","c");
11608 emitcode ("subb","a,r0");
11609 emitcode ("jnz","!tlabel",lbl2->key+100);
11610 emitcode ("inc", "dptr");
11611 emitcode ("inc", "dptr");
11612 emitcode ("mov","a,b");
11613 emitcode ("orl","a,_ap");
11614 emitcode ("jz","!tlabel",lbl1->key+100);
11615 emitcode ("mov","a,_ap");
11616 emitcode ("add","a,#!constbyte",0xFF);
11617 emitcode ("mov","_ap,a");
11618 emitcode ("mov","a,b");
11619 emitcode ("addc","a,#!constbyte",0xFF);
11620 emitcode ("mov","b,a");
11621 emitcode ("sjmp","!tlabel",lbl->key+100);
11622 emitcode ("","!tlabeldef",lbl1->key+100);
11623 emitcode ("clr","a");
11624 emitcode ("","!tlabeldef",lbl2->key+100);
11625 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11626 aopPut(AOP(IC_RESULT(ic)),"a",0);
11627 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11628 emitcode("pop","ar0");
11629 emitcode ("mov", "dps,#0");
11631 _G.dptrInUse = _G.dptr1InUse = 0;
11632 unsavermask(rsave);
11636 /*-----------------------------------------------------------------*/
11637 /* genInp - gen code for __builtin_inp read data from a mem mapped */
11638 /* port, first parameter output area second parameter pointer to */
11639 /* port third parameter count */
11640 /*-----------------------------------------------------------------*/
11641 static void genInp( iCode *ic, int nparms, operand **parms)
11643 operand *from , *to , *count;
11648 /* we know it has to be 3 parameters */
11649 assert (nparms == 3);
11651 rsave = newBitVect(16);
11652 /* save DPTR if it needs to be saved */
11653 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11654 if (bitVectBitValue(ic->rMask,i))
11655 rsave = bitVectSetBit(rsave,i);
11657 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11658 ds390_rUmaskForOp (IC_RESULT(ic))));
11665 aopOp (from, ic->next, FALSE, FALSE);
11667 /* get from into DPTR1 */
11668 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11669 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11670 if (options.model == MODEL_FLAT24) {
11671 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11674 freeAsmop (from, NULL, ic, FALSE);
11675 aopOp (to, ic, FALSE, FALSE);
11676 /* get "to" into DPTR */
11677 /* if the operand is already in dptr
11678 then we do nothing else we move the value to dptr */
11679 if (AOP_TYPE (to) != AOP_STR) {
11680 /* if already in DPTR then we need to push */
11681 if (AOP_TYPE(to) == AOP_DPTR) {
11682 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11683 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11684 if (options.model == MODEL_FLAT24)
11685 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11686 emitcode ("pop", "dph");
11687 emitcode ("pop", "dpl");
11689 _startLazyDPSEvaluation ();
11690 /* if this is remateriazable */
11691 if (AOP_TYPE (to) == AOP_IMMD) {
11692 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11693 } else { /* we need to get it byte by byte */
11694 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11695 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11696 if (options.model == MODEL_FLAT24) {
11697 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11700 _endLazyDPSEvaluation ();
11703 freeAsmop (to, NULL, ic, FALSE);
11705 _G.dptrInUse = _G.dptr1InUse = 1;
11706 aopOp (count, ic->next->next, FALSE,FALSE);
11707 lbl =newiTempLabel(NULL);
11709 /* now for the actual copy */
11710 if (AOP_TYPE(count) == AOP_LIT &&
11711 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11712 emitcode (";","OH JOY auto increment with djnz (very fast)");
11713 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11714 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11715 freeAsmop (count, NULL, ic, FALSE);
11716 emitcode ("","!tlabeldef",lbl->key+100);
11717 emitcode ("movx", "a,@dptr"); /* read data from port */
11718 emitcode ("dec","dps"); /* switch to DPTR */
11719 emitcode ("movx", "@dptr,a"); /* save into location */
11720 emitcode ("inc", "dptr"); /* point to next area */
11721 emitcode ("inc","dps"); /* switch to DPTR2 */
11722 emitcode ("djnz","b,!tlabel",lbl->key+100);
11724 symbol *lbl1 = newiTempLabel(NULL);
11726 emitcode (";"," Auto increment but no djnz");
11727 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11728 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11729 freeAsmop (count, NULL, ic, FALSE);
11730 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11731 emitcode ("","!tlabeldef",lbl->key+100);
11732 emitcode ("movx", "a,@dptr");
11733 emitcode ("dec","dps"); /* switch to DPTR */
11734 emitcode ("movx", "@dptr,a");
11735 emitcode ("inc", "dptr");
11736 emitcode ("inc","dps"); /* switch to DPTR2 */
11737 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
11738 /* emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
11739 emitcode ("mov","a,b");
11740 emitcode ("orl","a,_ap");
11741 emitcode ("jz","!tlabel",lbl1->key+100);
11742 emitcode ("mov","a,_ap");
11743 emitcode ("add","a,#!constbyte",0xFF);
11744 emitcode ("mov","_ap,a");
11745 emitcode ("mov","a,b");
11746 emitcode ("addc","a,#!constbyte",0xFF);
11747 emitcode ("mov","b,a");
11748 emitcode ("sjmp","!tlabel",lbl->key+100);
11749 emitcode ("","!tlabeldef",lbl1->key+100);
11751 emitcode ("mov", "dps,#0");
11752 _G.dptrInUse = _G.dptr1InUse = 0;
11753 unsavermask(rsave);
11757 /*-----------------------------------------------------------------*/
11758 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
11759 /* port, first parameter output area second parameter pointer to */
11760 /* port third parameter count */
11761 /*-----------------------------------------------------------------*/
11762 static void genOutp( iCode *ic, int nparms, operand **parms)
11764 operand *from , *to , *count;
11769 /* we know it has to be 3 parameters */
11770 assert (nparms == 3);
11772 rsave = newBitVect(16);
11773 /* save DPTR if it needs to be saved */
11774 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11775 if (bitVectBitValue(ic->rMask,i))
11776 rsave = bitVectSetBit(rsave,i);
11778 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11779 ds390_rUmaskForOp (IC_RESULT(ic))));
11786 aopOp (from, ic->next, FALSE, FALSE);
11788 /* get from into DPTR1 */
11789 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11790 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11791 if (options.model == MODEL_FLAT24) {
11792 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11795 freeAsmop (from, NULL, ic, FALSE);
11796 aopOp (to, ic, FALSE, FALSE);
11797 /* get "to" into DPTR */
11798 /* if the operand is already in dptr
11799 then we do nothing else we move the value to dptr */
11800 if (AOP_TYPE (to) != AOP_STR) {
11801 /* if already in DPTR then we need to push */
11802 if (AOP_TYPE(to) == AOP_DPTR) {
11803 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11804 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11805 if (options.model == MODEL_FLAT24)
11806 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11807 emitcode ("pop", "dph");
11808 emitcode ("pop", "dpl");
11810 _startLazyDPSEvaluation ();
11811 /* if this is remateriazable */
11812 if (AOP_TYPE (to) == AOP_IMMD) {
11813 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11814 } else { /* we need to get it byte by byte */
11815 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11816 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11817 if (options.model == MODEL_FLAT24) {
11818 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11821 _endLazyDPSEvaluation ();
11824 freeAsmop (to, NULL, ic, FALSE);
11826 _G.dptrInUse = _G.dptr1InUse = 1;
11827 aopOp (count, ic->next->next, FALSE,FALSE);
11828 lbl =newiTempLabel(NULL);
11830 /* now for the actual copy */
11831 if (AOP_TYPE(count) == AOP_LIT &&
11832 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11833 emitcode (";","OH JOY auto increment with djnz (very fast)");
11834 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
11835 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11836 emitcode ("","!tlabeldef",lbl->key+100);
11837 emitcode ("movx", "a,@dptr"); /* read data from port */
11838 emitcode ("inc","dps"); /* switch to DPTR2 */
11839 emitcode ("movx", "@dptr,a"); /* save into location */
11840 emitcode ("inc", "dptr"); /* point to next area */
11841 emitcode ("dec","dps"); /* switch to DPTR */
11842 emitcode ("djnz","b,!tlabel",lbl->key+100);
11843 freeAsmop (count, NULL, ic, FALSE);
11845 symbol *lbl1 = newiTempLabel(NULL);
11847 emitcode (";"," Auto increment but no djnz");
11848 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11849 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11850 freeAsmop (count, NULL, ic, FALSE);
11851 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
11852 emitcode ("","!tlabeldef",lbl->key+100);
11853 emitcode ("movx", "a,@dptr");
11854 emitcode ("inc", "dptr");
11855 emitcode ("inc","dps"); /* switch to DPTR2 */
11856 emitcode ("movx", "@dptr,a");
11857 emitcode ("dec","dps"); /* switch to DPTR */
11858 emitcode ("mov","a,b");
11859 emitcode ("orl","a,_ap");
11860 emitcode ("jz","!tlabel",lbl1->key+100);
11861 emitcode ("mov","a,_ap");
11862 emitcode ("add","a,#!constbyte",0xFF);
11863 emitcode ("mov","_ap,a");
11864 emitcode ("mov","a,b");
11865 emitcode ("addc","a,#!constbyte",0xFF);
11866 emitcode ("mov","b,a");
11867 emitcode ("sjmp","!tlabel",lbl->key+100);
11868 emitcode ("","!tlabeldef",lbl1->key+100);
11870 emitcode ("mov", "dps,#0");
11871 _G.dptrInUse = _G.dptr1InUse = 0;
11872 unsavermask(rsave);
11876 /*-----------------------------------------------------------------*/
11877 /* genSwapW - swap lower & high order bytes */
11878 /*-----------------------------------------------------------------*/
11879 static void genSwapW(iCode *ic, int nparms, operand **parms)
11883 assert (nparms==1);
11886 dest=IC_RESULT(ic);
11888 assert(getSize(operandType(src))==2);
11890 aopOp (src, ic, FALSE, FALSE);
11891 emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
11893 MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
11895 freeAsmop (src, NULL, ic, FALSE);
11897 aopOp (dest,ic, FALSE, FALSE);
11898 aopPut(AOP(dest),"b",0);
11899 aopPut(AOP(dest),"a",1);
11900 freeAsmop (dest, NULL, ic, FALSE);
11903 /*-----------------------------------------------------------------*/
11904 /* genMemsetX - gencode for memSetX data */
11905 /*-----------------------------------------------------------------*/
11906 static void genMemsetX(iCode *ic, int nparms, operand **parms)
11908 operand *to , *val , *count;
11914 /* we know it has to be 3 parameters */
11915 assert (nparms == 3);
11921 /* save DPTR if it needs to be saved */
11922 rsave = newBitVect(16);
11923 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11924 if (bitVectBitValue(ic->rMask,i))
11925 rsave = bitVectSetBit(rsave,i);
11927 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11928 ds390_rUmaskForOp (IC_RESULT(ic))));
11931 aopOp (to, ic, FALSE, FALSE);
11932 /* get "to" into DPTR */
11933 /* if the operand is already in dptr
11934 then we do nothing else we move the value to dptr */
11935 if (AOP_TYPE (to) != AOP_STR) {
11936 /* if already in DPTR then we need to push */
11937 if (AOP_TYPE(to) == AOP_DPTR) {
11938 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11939 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11940 if (options.model == MODEL_FLAT24)
11941 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11942 emitcode ("pop", "dph");
11943 emitcode ("pop", "dpl");
11945 _startLazyDPSEvaluation ();
11946 /* if this is remateriazable */
11947 if (AOP_TYPE (to) == AOP_IMMD) {
11948 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11949 } else { /* we need to get it byte by byte */
11950 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11951 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11952 if (options.model == MODEL_FLAT24) {
11953 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11956 _endLazyDPSEvaluation ();
11959 freeAsmop (to, NULL, ic, FALSE);
11961 aopOp (val, ic->next->next, FALSE,FALSE);
11962 aopOp (count, ic->next->next, FALSE,FALSE);
11963 lbl =newiTempLabel(NULL);
11964 /* now for the actual copy */
11965 if (AOP_TYPE(count) == AOP_LIT &&
11966 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11967 l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
11968 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11970 emitcode ("","!tlabeldef",lbl->key+100);
11971 emitcode ("movx", "@dptr,a");
11972 emitcode ("inc", "dptr");
11973 emitcode ("djnz","b,!tlabel",lbl->key+100);
11975 symbol *lbl1 = newiTempLabel(NULL);
11977 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11978 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11979 emitcode ("","!tlabeldef",lbl->key+100);
11980 MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
11981 emitcode ("movx", "@dptr,a");
11982 emitcode ("inc", "dptr");
11983 emitcode ("mov","a,b");
11984 emitcode ("orl","a,_ap");
11985 emitcode ("jz","!tlabel",lbl1->key+100);
11986 emitcode ("mov","a,_ap");
11987 emitcode ("add","a,#!constbyte",0xFF);
11988 emitcode ("mov","_ap,a");
11989 emitcode ("mov","a,b");
11990 emitcode ("addc","a,#!constbyte",0xFF);
11991 emitcode ("mov","b,a");
11992 emitcode ("sjmp","!tlabel",lbl->key+100);
11993 emitcode ("","!tlabeldef",lbl1->key+100);
11995 freeAsmop (count, NULL, ic, FALSE);
11996 unsavermask(rsave);
11999 /*-----------------------------------------------------------------*/
12000 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
12001 /*-----------------------------------------------------------------*/
12002 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
12005 operand *pnum, *result;
12008 assert (nparms==1);
12009 /* save registers that need to be saved */
12010 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12011 ds390_rUmaskForOp (IC_RESULT(ic))));
12014 aopOp (pnum, ic, FALSE, FALSE);
12015 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12016 freeAsmop (pnum, NULL, ic, FALSE);
12017 emitcode ("lcall","NatLib_LoadPrimitive");
12018 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12019 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
12020 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
12021 for (i = (size-1) ; i >= 0 ; i-- ) {
12022 emitcode ("push","a%s",javaRet[i]);
12024 for (i=0; i < size ; i++ ) {
12025 emitcode ("pop","a%s",
12026 aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
12029 for (i = 0 ; i < size ; i++ ) {
12030 aopPut(AOP(result),javaRet[i],i);
12033 freeAsmop (result, NULL, ic, FALSE);
12034 unsavermask(rsave);
12037 /*-----------------------------------------------------------------*/
12038 /* genNatLibLoadPointer - calls TINI api function to load pointer */
12039 /*-----------------------------------------------------------------*/
12040 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
12043 operand *pnum, *result;
12047 assert (nparms==1);
12048 /* save registers that need to be saved */
12049 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12050 ds390_rUmaskForOp (IC_RESULT(ic))));
12053 aopOp (pnum, ic, FALSE, FALSE);
12054 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12055 freeAsmop (pnum, NULL, ic, FALSE);
12056 emitcode ("lcall","NatLib_LoadPointer");
12057 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12058 if (AOP_TYPE(result)!=AOP_STR) {
12059 for (i = 0 ; i < size ; i++ ) {
12060 aopPut(AOP(result),fReturn[i],i);
12063 freeAsmop (result, NULL, ic, FALSE);
12064 unsavermask(rsave);
12067 /*-----------------------------------------------------------------*/
12068 /* genNatLibInstallStateBlock - */
12069 /*-----------------------------------------------------------------*/
12070 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
12071 operand **parms, const char *name)
12074 operand *psb, *handle;
12075 assert (nparms==2);
12077 /* save registers that need to be saved */
12078 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12079 ds390_rUmaskForOp (IC_RESULT(ic))));
12083 /* put pointer to state block into DPTR1 */
12084 aopOp (psb, ic, FALSE, FALSE);
12085 if (AOP_TYPE (psb) == AOP_IMMD) {
12086 emitcode ("mov","dps,#1");
12087 emitcode ("mov", "dptr,%s",
12088 aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12089 emitcode ("mov","dps,#0");
12091 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12092 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12093 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12095 freeAsmop (psb, NULL, ic, FALSE);
12097 /* put libraryID into DPTR */
12098 emitcode ("mov","dptr,#LibraryID");
12100 /* put handle into r3:r2 */
12101 aopOp (handle, ic, FALSE, FALSE);
12102 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12103 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12104 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12105 emitcode ("pop","ar3");
12106 emitcode ("pop","ar2");
12108 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12109 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12111 freeAsmop (psb, NULL, ic, FALSE);
12113 /* make the call */
12114 emitcode ("lcall","NatLib_Install%sStateBlock",name);
12116 /* put return value into place*/
12118 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12120 aopPut(AOP(IC_RESULT(ic)),"a",0);
12121 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12122 unsavermask(rsave);
12125 /*-----------------------------------------------------------------*/
12126 /* genNatLibRemoveStateBlock - */
12127 /*-----------------------------------------------------------------*/
12128 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12134 /* save registers that need to be saved */
12135 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12136 ds390_rUmaskForOp (IC_RESULT(ic))));
12138 /* put libraryID into DPTR */
12139 emitcode ("mov","dptr,#LibraryID");
12140 /* make the call */
12141 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12142 unsavermask(rsave);
12145 /*-----------------------------------------------------------------*/
12146 /* genNatLibGetStateBlock - */
12147 /*-----------------------------------------------------------------*/
12148 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12149 operand **parms,const char *name)
12152 symbol *lbl = newiTempLabel(NULL);
12155 /* save registers that need to be saved */
12156 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12157 ds390_rUmaskForOp (IC_RESULT(ic))));
12159 /* put libraryID into DPTR */
12160 emitcode ("mov","dptr,#LibraryID");
12161 /* make the call */
12162 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12163 emitcode ("jnz","!tlabel",lbl->key+100);
12165 /* put return value into place */
12166 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12167 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12168 emitcode ("push","ar3");
12169 emitcode ("push","ar2");
12170 emitcode ("pop","%s",
12171 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12172 emitcode ("pop","%s",
12173 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12175 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12176 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12178 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12179 emitcode ("","!tlabeldef",lbl->key+100);
12180 unsavermask(rsave);
12183 /*-----------------------------------------------------------------*/
12184 /* genMMMalloc - */
12185 /*-----------------------------------------------------------------*/
12186 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12187 int size, const char *name)
12192 symbol *lbl = newiTempLabel(NULL);
12194 assert (nparms == 1);
12195 /* save registers that need to be saved */
12196 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12197 ds390_rUmaskForOp (IC_RESULT(ic))));
12200 aopOp (bsize,ic,FALSE,FALSE);
12202 /* put the size in R4-R2 */
12203 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12204 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12205 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12207 emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12208 emitcode("pop","ar4");
12210 emitcode("pop","ar3");
12211 emitcode("pop","ar2");
12213 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12214 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12216 emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12219 freeAsmop (bsize, NULL, ic, FALSE);
12221 /* make the call */
12222 emitcode ("lcall","MM_%s",name);
12223 emitcode ("jz","!tlabel",lbl->key+100);
12224 emitcode ("mov","r2,#!constbyte",0xff);
12225 emitcode ("mov","r3,#!constbyte",0xff);
12226 emitcode ("","!tlabeldef",lbl->key+100);
12227 /* we don't care about the pointer : we just save the handle */
12228 rsym = OP_SYMBOL(IC_RESULT(ic));
12229 if (rsym->liveFrom != rsym->liveTo) {
12230 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12231 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12232 emitcode ("push","ar3");
12233 emitcode ("push","ar2");
12234 emitcode ("pop","%s",
12235 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12236 emitcode ("pop","%s",
12237 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12239 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12240 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12242 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12244 unsavermask(rsave);
12247 /*-----------------------------------------------------------------*/
12249 /*-----------------------------------------------------------------*/
12250 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12255 assert (nparms == 1);
12256 /* save registers that need to be saved */
12257 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12258 ds390_rUmaskForOp (IC_RESULT(ic))));
12261 aopOp (handle,ic,FALSE,FALSE);
12263 /* put the size in R4-R2 */
12264 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12265 emitcode("push","%s",
12266 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12267 emitcode("push","%s",
12268 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12269 emitcode("pop","ar3");
12270 emitcode("pop","ar2");
12272 emitcode ("mov","r2,%s",
12273 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12274 emitcode ("mov","r3,%s",
12275 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12277 freeAsmop (handle, NULL, ic, FALSE);
12279 /* make the call */
12280 emitcode ("lcall","MM_Deref");
12283 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12284 if (rsym->liveFrom != rsym->liveTo) {
12285 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12286 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12287 _startLazyDPSEvaluation ();
12289 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12290 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12291 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12293 _endLazyDPSEvaluation ();
12298 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12299 unsavermask(rsave);
12302 /*-----------------------------------------------------------------*/
12303 /* genMMUnrestrictedPersist - */
12304 /*-----------------------------------------------------------------*/
12305 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12310 assert (nparms == 1);
12311 /* save registers that need to be saved */
12312 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12313 ds390_rUmaskForOp (IC_RESULT(ic))));
12316 aopOp (handle,ic,FALSE,FALSE);
12318 /* put the size in R3-R2 */
12319 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12320 emitcode("push","%s",
12321 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12322 emitcode("push","%s",
12323 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12324 emitcode("pop","ar3");
12325 emitcode("pop","ar2");
12327 emitcode ("mov","r2,%s",
12328 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12329 emitcode ("mov","r3,%s",
12330 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12332 freeAsmop (handle, NULL, ic, FALSE);
12334 /* make the call */
12335 emitcode ("lcall","MM_UnrestrictedPersist");
12338 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12339 if (rsym->liveFrom != rsym->liveTo) {
12340 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12341 aopPut(AOP(IC_RESULT(ic)),"a",0);
12342 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12345 unsavermask(rsave);
12348 /*-----------------------------------------------------------------*/
12349 /* genSystemExecJavaProcess - */
12350 /*-----------------------------------------------------------------*/
12351 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12354 operand *handle, *pp;
12356 assert (nparms==2);
12357 /* save registers that need to be saved */
12358 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12359 ds390_rUmaskForOp (IC_RESULT(ic))));
12364 /* put the handle in R3-R2 */
12365 aopOp (handle,ic,FALSE,FALSE);
12366 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12367 emitcode("push","%s",
12368 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12369 emitcode("push","%s",
12370 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12371 emitcode("pop","ar3");
12372 emitcode("pop","ar2");
12374 emitcode ("mov","r2,%s",
12375 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12376 emitcode ("mov","r3,%s",
12377 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12379 freeAsmop (handle, NULL, ic, FALSE);
12381 /* put pointer in DPTR */
12382 aopOp (pp,ic,FALSE,FALSE);
12383 if (AOP_TYPE(pp) == AOP_IMMD) {
12384 emitcode ("mov", "dptr,%s",
12385 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12386 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12387 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12388 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12389 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12391 freeAsmop (handle, NULL, ic, FALSE);
12393 /* make the call */
12394 emitcode ("lcall","System_ExecJavaProcess");
12396 /* put result in place */
12398 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12399 if (rsym->liveFrom != rsym->liveTo) {
12400 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12401 aopPut(AOP(IC_RESULT(ic)),"a",0);
12402 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12406 unsavermask(rsave);
12409 /*-----------------------------------------------------------------*/
12410 /* genSystemRTCRegisters - */
12411 /*-----------------------------------------------------------------*/
12412 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12418 assert (nparms==1);
12419 /* save registers that need to be saved */
12420 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12421 ds390_rUmaskForOp (IC_RESULT(ic))));
12424 /* put pointer in DPTR */
12425 aopOp (pp,ic,FALSE,FALSE);
12426 if (AOP_TYPE (pp) == AOP_IMMD) {
12427 emitcode ("mov","dps,#1");
12428 emitcode ("mov", "dptr,%s",
12429 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12430 emitcode ("mov","dps,#0");
12432 emitcode ("mov","dpl1,%s",
12433 aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12434 emitcode ("mov","dph1,%s",
12435 aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12436 emitcode ("mov","dpx1,%s",
12437 aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12439 freeAsmop (pp, NULL, ic, FALSE);
12441 /* make the call */
12442 emitcode ("lcall","System_%sRTCRegisters",name);
12444 unsavermask(rsave);
12447 /*-----------------------------------------------------------------*/
12448 /* genSystemThreadSleep - */
12449 /*-----------------------------------------------------------------*/
12450 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12455 assert (nparms==1);
12456 /* save registers that need to be saved */
12457 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12458 ds390_rUmaskForOp (IC_RESULT(ic))));
12461 aopOp(to,ic,FALSE,FALSE);
12462 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12463 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12464 emitcode ("push","%s",
12465 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12466 emitcode ("push","%s",
12467 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12468 emitcode ("push","%s",
12469 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12470 emitcode ("push","%s",
12471 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12472 emitcode ("pop","ar3");
12473 emitcode ("pop","ar2");
12474 emitcode ("pop","ar1");
12475 emitcode ("pop","ar0");
12477 emitcode ("mov","r0,%s",
12478 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12479 emitcode ("mov","r1,%s",
12480 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12481 emitcode ("mov","r2,%s",
12482 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12483 emitcode ("mov","r3,%s",
12484 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12486 freeAsmop (to, NULL, ic, FALSE);
12488 /* suspend in acc */
12490 aopOp(s,ic,FALSE,FALSE);
12491 emitcode ("mov","a,%s",
12492 aopGet(AOP(s),0,FALSE,TRUE,NULL));
12493 freeAsmop (s, NULL, ic, FALSE);
12495 /* make the call */
12496 emitcode ("lcall","System_%s",name);
12498 unsavermask(rsave);
12501 /*-----------------------------------------------------------------*/
12502 /* genSystemThreadResume - */
12503 /*-----------------------------------------------------------------*/
12504 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12509 assert (nparms==2);
12510 /* save registers that need to be saved */
12511 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12512 ds390_rUmaskForOp (IC_RESULT(ic))));
12518 aopOp(pid,ic,FALSE,FALSE);
12519 emitcode ("mov","r0,%s",
12520 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12521 freeAsmop (pid, NULL, ic, FALSE);
12524 aopOp(tid,ic,FALSE,FALSE);
12525 emitcode ("mov","a,%s",
12526 aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
12527 freeAsmop (tid, NULL, ic, FALSE);
12529 emitcode ("lcall","System_ThreadResume");
12531 /* put result into place */
12533 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12534 if (rsym->liveFrom != rsym->liveTo) {
12535 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12536 aopPut(AOP(IC_RESULT(ic)),"a",0);
12537 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12540 unsavermask(rsave);
12543 /*-----------------------------------------------------------------*/
12544 /* genSystemProcessResume - */
12545 /*-----------------------------------------------------------------*/
12546 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
12551 assert (nparms==1);
12552 /* save registers that need to be saved */
12553 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12554 ds390_rUmaskForOp (IC_RESULT(ic))));
12559 aopOp(pid,ic,FALSE,FALSE);
12560 emitcode ("mov","a,%s",
12561 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12562 freeAsmop (pid, NULL, ic, FALSE);
12564 emitcode ("lcall","System_ProcessResume");
12566 unsavermask(rsave);
12569 /*-----------------------------------------------------------------*/
12571 /*-----------------------------------------------------------------*/
12572 static void genSystem (iCode *ic,int nparms,char *name)
12574 assert(nparms == 0);
12576 emitcode ("lcall","System_%s",name);
12579 /*-----------------------------------------------------------------*/
12580 /* genSystemPoll - */
12581 /*-----------------------------------------------------------------*/
12582 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
12587 assert (nparms==1);
12588 /* save registers that need to be saved */
12589 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12590 ds390_rUmaskForOp (IC_RESULT(ic))));
12593 aopOp (fp,ic,FALSE,FALSE);
12594 if (AOP_TYPE (fp) == AOP_IMMD) {
12595 emitcode ("mov", "dptr,%s",
12596 aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
12597 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
12598 emitcode ("mov","dpl,%s",
12599 aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
12600 emitcode ("mov","dph,%s",
12601 aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
12602 emitcode ("mov","dpx,%s",
12603 aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
12605 freeAsmop (fp, NULL, ic, FALSE);
12607 emitcode ("lcall","System_%sPoll",name);
12609 /* put result into place */
12611 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12612 if (rsym->liveFrom != rsym->liveTo) {
12613 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12614 aopPut(AOP(IC_RESULT(ic)),"a",0);
12615 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12618 unsavermask(rsave);
12621 /*-----------------------------------------------------------------*/
12622 /* genSystemGetCurrentID - */
12623 /*-----------------------------------------------------------------*/
12624 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
12626 assert (nparms==0);
12628 emitcode ("lcall","System_GetCurrent%sId",name);
12629 /* put result into place */
12631 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12632 if (rsym->liveFrom != rsym->liveTo) {
12633 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12634 aopPut(AOP(IC_RESULT(ic)),"a",0);
12635 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12640 /*-----------------------------------------------------------------*/
12641 /* genDummyRead - generate code for dummy read of volatiles */
12642 /*-----------------------------------------------------------------*/
12644 genDummyRead (iCode * ic)
12649 D(emitcode("; genDummyRead",""));
12651 right = IC_RIGHT (ic);
12653 aopOp (right, ic, FALSE, FALSE);
12655 /* if the result is a bit */
12656 if (AOP_TYPE (right) == AOP_CRY)
12658 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
12662 /* bit variables done */
12664 size = AOP_SIZE (right);
12668 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
12673 freeAsmop (right, NULL, ic, TRUE);
12676 /*-----------------------------------------------------------------*/
12677 /* genBuiltIn - calls the appropriate function to generating code */
12678 /* for a built in function */
12679 /*-----------------------------------------------------------------*/
12680 static void genBuiltIn (iCode *ic)
12682 operand *bi_parms[MAX_BUILTIN_ARGS];
12687 /* get all the arguments for a built in function */
12688 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
12690 /* which function is it */
12691 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
12692 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
12693 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
12694 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
12695 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
12696 } else if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
12697 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
12698 } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
12699 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
12700 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
12701 genMemsetX(bi_iCode,nbi_parms,bi_parms);
12702 } else if (strcmp(bif->name,"__builtin_inp")==0) {
12703 genInp(bi_iCode,nbi_parms,bi_parms);
12704 } else if (strcmp(bif->name,"__builtin_outp")==0) {
12705 genOutp(bi_iCode,nbi_parms,bi_parms);
12706 } else if (strcmp(bif->name,"__builtin_swapw")==0) {
12707 genSwapW(bi_iCode,nbi_parms,bi_parms);
12708 /* JavaNative builtIns */
12709 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
12710 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
12711 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
12712 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
12713 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
12714 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
12715 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
12716 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
12717 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
12718 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12719 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
12720 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12721 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
12722 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
12723 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
12724 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
12725 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
12726 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12727 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
12728 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12729 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
12730 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
12731 } else if (strcmp(bif->name,"MM_Malloc")==0) {
12732 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
12733 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
12734 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
12735 } else if (strcmp(bif->name,"MM_Free")==0) {
12736 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
12737 } else if (strcmp(bif->name,"MM_Deref")==0) {
12738 genMMDeref(bi_iCode,nbi_parms,bi_parms);
12739 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
12740 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
12741 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
12742 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
12743 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
12744 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
12745 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
12746 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
12747 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
12748 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
12749 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
12750 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
12751 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
12752 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
12753 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
12754 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
12755 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12756 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12757 } else if (strcmp(bif->name,"System_SaveThread")==0) {
12758 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12759 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12760 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12761 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
12762 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
12763 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
12764 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
12765 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
12766 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
12767 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
12768 genSystem(bi_iCode,nbi_parms,"ProcessYield");
12769 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
12770 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
12771 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
12772 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
12773 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
12774 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
12775 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
12776 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
12777 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
12778 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
12780 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
12786 /*-----------------------------------------------------------------*/
12787 /* gen390Code - generate code for Dallas 390 based controllers */
12788 /*-----------------------------------------------------------------*/
12790 gen390Code (iCode * lic)
12795 lineHead = lineCurr = NULL;
12796 dptrn[1][0] = "dpl1";
12797 dptrn[1][1] = "dph1";
12798 dptrn[1][2] = "dpx1";
12800 if (options.model == MODEL_FLAT24) {
12801 fReturnSizeDS390 = 5;
12802 fReturn = fReturn24;
12804 fReturnSizeDS390 = 4;
12805 fReturn = fReturn16;
12806 options.stack10bit=0;
12809 /* print the allocation information */
12810 if (allocInfo && currFunc)
12811 printAllocInfo (currFunc, codeOutFile);
12813 /* if debug information required */
12814 if (options.debug && currFunc)
12816 debugFile->writeFunction(currFunc);
12818 if (IS_STATIC (currFunc->etype))
12819 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
12821 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
12824 /* stack pointer name */
12825 if (options.useXstack)
12831 for (ic = lic; ic; ic = ic->next)
12834 if (ic->lineno && cln != ic->lineno)
12839 emitcode ("", "C$%s$%d$%d$%d ==.",
12840 FileBaseName (ic->filename), ic->lineno,
12841 ic->level, ic->block);
12844 if (!options.noCcodeInAsm) {
12845 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
12846 printCLine(ic->filename, ic->lineno));
12850 if (options.iCodeInAsm) {
12851 emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
12853 /* if the result is marked as
12854 spilt and rematerializable or code for
12855 this has already been generated then
12857 if (resultRemat (ic) || ic->generated)
12860 /* depending on the operation */
12880 /* IPOP happens only when trying to restore a
12881 spilt live range, if there is an ifx statement
12882 following this pop then the if statement might
12883 be using some of the registers being popped which
12884 would destory the contents of the register so
12885 we need to check for this condition and handle it */
12887 ic->next->op == IFX &&
12888 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
12889 genIfx (ic->next, ic);
12907 genEndFunction (ic);
12927 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
12944 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
12948 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
12955 /* note these two are xlated by algebraic equivalence
12956 during parsing SDCC.y */
12957 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12958 "got '>=' or '<=' shouldn't have come here");
12962 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
12974 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
12978 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
12982 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
13006 genRightShift (ic);
13009 case GET_VALUE_AT_ADDRESS:
13010 genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
13014 if (POINTER_SET (ic))
13015 genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
13041 if (ic->builtinSEND) genBuiltIn(ic);
13042 else addSet (&_G.sendSet, ic);
13045 case DUMMY_READ_VOLATILE:
13049 #if 0 // obsolete, and buggy for != xdata
13061 /* now we are ready to call the
13062 peep hole optimizer */
13063 if (!options.nopeep)
13064 peepHole (&lineHead);
13066 /* now do the actual printing */
13067 printLine (lineHead, codeOutFile);