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;
1009 /* else spill location */
1010 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1011 /* force a new aop if sizes differ */
1012 sym->usl.spillLoc->aop = NULL;
1014 sym->aop = op->aop = aop =
1015 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
1016 aop->size = getSize (sym->type);
1020 /* must be in a register */
1021 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1022 aop->size = sym->nRegs;
1023 for (i = 0; i < sym->nRegs; i++)
1024 aop->aopu.aop_reg[i] = sym->regs[i];
1027 /*-----------------------------------------------------------------*/
1028 /* freeAsmop - free up the asmop given to an operand */
1029 /*----------------------------------------------------------------*/
1031 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1048 /* depending on the asmop type only three cases need work AOP_RO
1049 , AOP_R1 && AOP_STK */
1057 emitcode ("pop", "ar0");
1061 bitVectUnSetBit (ic->rUsed, R0_IDX);
1069 emitcode ("pop", "ar1");
1073 bitVectUnSetBit (ic->rUsed, R1_IDX);
1079 int stk = aop->aopu.aop_stk + aop->size;
1080 bitVectUnSetBit (ic->rUsed, R0_IDX);
1081 bitVectUnSetBit (ic->rUsed, R1_IDX);
1083 getFreePtr (ic, &aop, FALSE);
1085 if (options.stack10bit)
1087 /* I'm not sure what to do here yet... */
1090 "*** Warning: probably generating bad code for "
1091 "10 bit stack mode.\n");
1096 emitcode ("mov", "a,_bp");
1097 emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
1098 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1102 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1107 emitcode ("pop", "acc");
1108 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1111 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1114 freeAsmop (op, NULL, ic, TRUE);
1117 emitcode ("pop", "ar0");
1123 emitcode ("pop", "ar1");
1128 if (_G.dptr1InUse) {
1129 emitcode ("pop","dpx1");
1130 emitcode ("pop","dph1");
1131 emitcode ("pop","dpl1");
1136 emitcode ("pop","dpx");
1137 emitcode ("pop","dph");
1138 emitcode ("pop","dpl");
1143 /* all other cases just dealloc */
1149 OP_SYMBOL (op)->aop = NULL;
1150 /* if the symbol has a spill */
1152 SPIL_LOC (op)->aop = NULL;
1157 #define DEFAULT_ACC_WARNING 0
1158 static int saveAccWarn = DEFAULT_ACC_WARNING;
1160 /*-------------------------------------------------------------------*/
1161 /* aopGet - for fetching value of the aop */
1163 /* Set saveAcc to NULL if you are sure it is OK to clobber the value */
1164 /* in the accumulator. Set it to the name of a free register */
1165 /* if acc must be preserved; the register will be used to preserve */
1166 /* acc temporarily and to return the result byte. */
1167 /*-------------------------------------------------------------------*/
1176 /* offset is greater than
1178 if (offset > (aop->size - 1) &&
1179 aop->type != AOP_LIT)
1182 /* depending on type */
1188 /* if we need to increment it */
1189 while (offset > aop->coff)
1191 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1195 while (offset < aop->coff)
1197 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1204 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1205 return (dname ? "acc" : "a");
1207 SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1208 return Safe_strdup(buffer);
1211 assert(offset <= 3);
1212 return dptrn[aop->aopu.dptr][offset];
1217 if (aop->type == AOP_DPTR2)
1225 // if (aop->type != AOP_DPTR2)
1227 // if (saveAccWarn) { fprintf(stderr, "saveAcc for DPTR...\n"); }
1228 // emitcode(";", "spanky: saveAcc for DPTR");
1231 emitcode ("xch", "a, %s", saveAcc);
1236 while (offset > aop->coff)
1238 emitcode ("inc", "dptr");
1242 while (offset < aop->coff)
1244 emitcode ("lcall", "__decdptr");
1251 emitcode ("clr", "a");
1252 emitcode ("movc", "a,@a+dptr");
1256 emitcode ("movx", "a,@dptr");
1259 if (aop->type == AOP_DPTR2)
1267 emitcode ("xch", "a, %s", saveAcc);
1268 // if (strcmp(saveAcc, "_ap"))
1270 // emitcode(";", "spiffy: non _ap return from aopGet.");
1275 return (dname ? "acc" : "a");
1278 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1280 SNPRINTF(buffer, sizeof(buffer),
1281 "%s",aop->aopu.aop_immd.aop_immd2);
1285 SNPRINTF(buffer, sizeof(buffer),
1286 "#%s", aop->aopu.aop_immd.aop_immd1);
1292 tsprintf(buffer, sizeof(buffer),
1293 "#!his",aop->aopu.aop_immd.aop_immd1);
1296 tsprintf(buffer, sizeof(buffer),
1297 "#!hihis",aop->aopu.aop_immd.aop_immd1);
1300 tsprintf(buffer, sizeof(buffer),
1301 "#!hihihis",aop->aopu.aop_immd.aop_immd1);
1303 default: /* should not need this (just in case) */
1304 SNPRINTF (buffer, sizeof(buffer),
1306 aop->aopu.aop_immd.aop_immd1,
1312 SNPRINTF (buffer, sizeof(buffer),
1313 "#%s", aop->aopu.aop_immd.aop_immd1);
1315 return Safe_strdup(buffer);
1320 SNPRINTF (buffer, sizeof(buffer),
1327 SNPRINTF(buffer, sizeof(buffer),
1328 "%s", aop->aopu.aop_dir);
1331 return Safe_strdup(buffer);
1335 return aop->aopu.aop_reg[offset]->dname;
1337 return aop->aopu.aop_reg[offset]->name;
1340 emitcode ("clr", "a");
1341 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1342 emitcode ("rlc", "a");
1343 return (dname ? "acc" : "a");
1346 if (!offset && dname)
1348 return aop->aopu.aop_str[offset];
1351 return aopLiteral (aop->aopu.aop_lit, offset);
1355 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1359 return aop->aopu.aop_str[offset];
1363 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1364 "aopget got unsupported aop->type");
1367 return NULL; // not reached, but makes compiler happy.
1369 /*-----------------------------------------------------------------*/
1370 /* aopPut - puts a string for a aop */
1371 /*-----------------------------------------------------------------*/
1373 aopPut (asmop * aop, char *s, int offset)
1375 if (aop->size && offset > (aop->size - 1))
1377 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1378 "aopPut got offset > aop->size");
1382 /* will assign value to value */
1383 /* depending on where it is ofcourse */
1389 SNPRINTF (buffer, sizeof(buffer),
1391 aop->aopu.aop_dir, offset);
1395 SNPRINTF (buffer, sizeof(buffer),
1396 "%s", aop->aopu.aop_dir);
1400 if (strcmp (buffer, s))
1402 emitcode ("mov", "%s,%s", buffer, s);
1407 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1408 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1411 strcmp (s, "r0") == 0 ||
1412 strcmp (s, "r1") == 0 ||
1413 strcmp (s, "r2") == 0 ||
1414 strcmp (s, "r3") == 0 ||
1415 strcmp (s, "r4") == 0 ||
1416 strcmp (s, "r5") == 0 ||
1417 strcmp (s, "r6") == 0 ||
1418 strcmp (s, "r7") == 0)
1420 emitcode ("mov", "%s,%s",
1421 aop->aopu.aop_reg[offset]->dname, s);
1425 emitcode ("mov", "%s,%s",
1426 aop->aopu.aop_reg[offset]->name, s);
1432 emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1438 if (aop->type == AOP_DPTR2)
1446 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1447 "aopPut writting to code space");
1451 while (offset > aop->coff)
1454 emitcode ("inc", "dptr");
1457 while (offset < aop->coff)
1460 emitcode ("lcall", "__decdptr");
1465 /* if not in accumulater */
1468 emitcode ("movx", "@dptr,a");
1470 if (aop->type == AOP_DPTR2)
1478 while (offset > aop->coff)
1481 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1483 while (offset < aop->coff)
1486 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1493 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1499 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1501 else if (strcmp (s, "r0") == 0 ||
1502 strcmp (s, "r1") == 0 ||
1503 strcmp (s, "r2") == 0 ||
1504 strcmp (s, "r3") == 0 ||
1505 strcmp (s, "r4") == 0 ||
1506 strcmp (s, "r5") == 0 ||
1507 strcmp (s, "r6") == 0 ||
1508 strcmp (s, "r7") == 0)
1511 SNPRINTF(buff, sizeof(buff),
1513 emitcode ("mov", "@%s,%s",
1514 aop->aopu.aop_ptr->name, buff);
1518 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1523 if (strcmp (s, "a") == 0)
1524 emitcode ("push", "acc");
1528 emitcode ("push", "acc");
1530 emitcode ("push", s);
1536 /* if bit variable */
1537 if (!aop->aopu.aop_dir)
1539 emitcode ("clr", "a");
1540 emitcode ("rlc", "a");
1545 emitcode ("clr", "%s", aop->aopu.aop_dir);
1547 emitcode ("setb", "%s", aop->aopu.aop_dir);
1548 else if (!strcmp (s, "c"))
1549 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1552 if (strcmp (s, "a"))
1557 /* set C, if a >= 1 */
1558 emitcode ("add", "a,#!constbyte",0xff);
1559 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1567 if (strcmp (aop->aopu.aop_str[offset], s))
1568 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1573 if (!offset && (strcmp (s, "acc") == 0))
1576 if (strcmp (aop->aopu.aop_str[offset], s))
1577 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1581 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1582 "aopPut got unsupported aop->type");
1589 /*--------------------------------------------------------------------*/
1590 /* reAdjustPreg - points a register back to where it should (coff==0) */
1591 /*--------------------------------------------------------------------*/
1593 reAdjustPreg (asmop * aop)
1595 if ((aop->coff==0) || (aop->size <= 1)) {
1604 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1608 if (aop->type == AOP_DPTR2)
1615 emitcode ("lcall", "__decdptr");
1618 if (aop->type == AOP_DPTR2)
1628 #define AOP(op) op->aop
1629 #define AOP_TYPE(op) AOP(op)->type
1630 #define AOP_SIZE(op) AOP(op)->size
1631 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1632 AOP_TYPE(x) == AOP_R0))
1634 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1635 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1638 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1639 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1640 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1641 #define AOP_INDPTRn(x) (AOP_TYPE(x) == AOP_DPTRn)
1642 #define AOP_USESDPTR(x) ((AOP_TYPE(x) == AOP_DPTR) || (AOP_TYPE(x) == AOP_STR))
1643 #define AOP_USESDPTR2(x) ((AOP_TYPE(x) == AOP_DPTR2) || (AOP_TYPE(x) == AOP_DPTRn))
1645 // The following two macros can be used even if the aop has not yet been aopOp'd.
1646 #define AOP_IS_STR(x) (IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
1647 #define AOP_IS_DPTRn(x) (IS_SYMOP(x) && OP_SYMBOL(x)->dptr)
1649 /* Workaround for DS80C390 bug: div ab may return bogus results
1650 * if A is accessed in instruction immediately before the div.
1652 * Will be fixed in B4 rev of processor, Dallas claims.
1655 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1656 if (!AOP_NEEDSACC(RIGHT)) \
1658 /* We can load A first, then B, since \
1659 * B (the RIGHT operand) won't clobber A, \
1660 * thus avoiding touching A right before the div. \
1662 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1663 L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL); \
1665 L = aopGet(AOP(RIGHT),0,FALSE,FALSE,"b"); \
1670 /* Just stuff in a nop after loading A. */ \
1671 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,NULL));\
1672 L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL); \
1674 emitcode("nop", "; workaround for DS80C390 div bug."); \
1678 /*-----------------------------------------------------------------*/
1679 /* opIsGptr: returns non-zero if the passed operand is */
1680 /* a generic pointer type. */
1681 /*-----------------------------------------------------------------*/
1683 opIsGptr (operand * op)
1685 sym_link *type = operandType (op);
1687 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1694 /*-----------------------------------------------------------------*/
1695 /* getDataSize - get the operand data size */
1696 /*-----------------------------------------------------------------*/
1698 getDataSize (operand * op)
1701 size = AOP_SIZE (op);
1702 if (size == GPTRSIZE)
1704 sym_link *type = operandType (op);
1705 if (IS_GENPTR (type))
1707 /* generic pointer; arithmetic operations
1708 * should ignore the high byte (pointer type).
1716 /*-----------------------------------------------------------------*/
1717 /* outAcc - output Acc */
1718 /*-----------------------------------------------------------------*/
1720 outAcc (operand * result)
1723 size = getDataSize (result);
1726 aopPut (AOP (result), "a", 0);
1729 /* unsigned or positive */
1732 aopPut (AOP (result), zero, offset++);
1737 /*-----------------------------------------------------------------*/
1738 /* outBitC - output a bit C */
1739 /*-----------------------------------------------------------------*/
1741 outBitC (operand * result)
1743 /* if the result is bit */
1744 if (AOP_TYPE (result) == AOP_CRY)
1746 aopPut (AOP (result), "c", 0);
1750 emitcode ("clr", "a");
1751 emitcode ("rlc", "a");
1756 /*-----------------------------------------------------------------*/
1757 /* toBoolean - emit code for orl a,operator(sizeop) */
1758 /*-----------------------------------------------------------------*/
1760 toBoolean (operand * oper)
1762 int size = AOP_SIZE (oper) - 1;
1766 /* The generic part of a generic pointer should
1767 * not participate in it's truth value.
1769 * i.e. 0x10000000 is zero.
1771 if (opIsGptr (oper))
1773 D (emitcode (";", "toBoolean: generic ptr special case."););
1777 _startLazyDPSEvaluation ();
1778 if (AOP_NEEDSACC (oper) && size)
1783 emitcode ("push", "b");
1785 MOVB (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1789 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1796 emitcode ("orl", "b,%s",
1797 aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1801 emitcode ("orl", "a,%s",
1802 aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1805 _endLazyDPSEvaluation ();
1809 emitcode ("mov", "a,b");
1812 emitcode ("pop", "b");
1819 /*-----------------------------------------------------------------*/
1820 /* genNot - generate code for ! operation */
1821 /*-----------------------------------------------------------------*/
1827 D (emitcode (";", "genNot "););
1829 /* assign asmOps to operand & result */
1830 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1831 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1833 /* if in bit space then a special case */
1834 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1836 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1837 emitcode ("cpl", "c");
1838 outBitC (IC_RESULT (ic));
1842 toBoolean (IC_LEFT (ic));
1844 tlbl = newiTempLabel (NULL);
1845 emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1846 emitcode ("", "!tlabeldef", tlbl->key + 100);
1847 outBitC (IC_RESULT (ic));
1850 /* release the aops */
1851 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1852 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1856 /*-----------------------------------------------------------------*/
1857 /* genCpl - generate code for complement */
1858 /*-----------------------------------------------------------------*/
1866 D (emitcode (";", "genCpl "););
1869 /* assign asmOps to operand & result */
1870 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1871 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1873 /* special case if in bit space */
1874 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1875 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1876 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1877 emitcode ("cpl", "c");
1878 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1881 tlbl=newiTempLabel(NULL);
1882 emitcode ("cjne", "%s,#0x01,%05d$",
1883 aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE,NULL), tlbl->key+100);
1884 emitcode ("", "%05d$:", tlbl->key+100);
1885 outBitC (IC_RESULT(ic));
1889 size = AOP_SIZE (IC_RESULT (ic));
1890 _startLazyDPSEvaluation ();
1893 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
1894 emitcode ("cpl", "a");
1895 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1897 _endLazyDPSEvaluation ();
1901 /* release the aops */
1902 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1903 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1906 /*-----------------------------------------------------------------*/
1907 /* genUminusFloat - unary minus for floating points */
1908 /*-----------------------------------------------------------------*/
1910 genUminusFloat (operand * op, operand * result)
1912 int size, offset = 0;
1914 D(emitcode (";", "genUminusFloat"););
1916 /* for this we just copy and then flip the bit */
1918 _startLazyDPSEvaluation ();
1919 size = AOP_SIZE (op) - 1;
1923 aopPut (AOP (result),
1924 aopGet (AOP (op), offset, FALSE, FALSE, NULL),
1929 MOVA(aopGet (AOP (op), offset, FALSE, FALSE, NULL));
1931 emitcode ("cpl", "acc.7");
1932 aopPut (AOP (result), "a", offset);
1933 _endLazyDPSEvaluation ();
1936 /*-----------------------------------------------------------------*/
1937 /* genUminus - unary minus code generation */
1938 /*-----------------------------------------------------------------*/
1940 genUminus (iCode * ic)
1945 D (emitcode (";", "genUminus "););
1948 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1949 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1951 /* if both in bit space then special
1953 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1954 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1957 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1958 emitcode ("cpl", "c");
1959 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1963 optype = operandType (IC_LEFT (ic));
1965 /* if float then do float stuff */
1966 if (IS_FLOAT (optype))
1968 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1972 /* otherwise subtract from zero */
1973 size = AOP_SIZE (IC_LEFT (ic));
1975 _startLazyDPSEvaluation ();
1978 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL);
1979 if (!strcmp (l, "a"))
1983 emitcode ("cpl", "a");
1984 emitcode ("addc", "a,#0");
1990 emitcode ("clr", "a");
1991 emitcode ("subb", "a,%s", l);
1993 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1995 _endLazyDPSEvaluation ();
1997 /* if any remaining bytes in the result */
1998 /* we just need to propagate the sign */
1999 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic)))) != 0)
2001 emitcode ("rlc", "a");
2002 emitcode ("subb", "a,acc");
2004 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2008 /* release the aops */
2009 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2010 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2013 /*-----------------------------------------------------------------*/
2014 /* savermask - saves registers in the mask */
2015 /*-----------------------------------------------------------------*/
2016 static void savermask(bitVect *rs_mask)
2019 if (options.useXstack) {
2020 if (bitVectBitValue (rs_mask, R0_IDX))
2021 emitcode ("mov", "b,r0");
2022 emitcode ("mov", "r0,%s", spname);
2023 for (i = 0; i < ds390_nRegs; i++) {
2024 if (bitVectBitValue (rs_mask, i)) {
2026 emitcode ("mov", "a,b");
2028 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
2029 emitcode ("movx", "@r0,a");
2030 emitcode ("inc", "r0");
2033 emitcode ("mov", "%s,r0", spname);
2034 if (bitVectBitValue (rs_mask, R0_IDX))
2035 emitcode ("mov", "r0,b");
2037 for (i = 0; i < ds390_nRegs; i++) {
2038 if (bitVectBitValue (rs_mask, i))
2039 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2044 /*-----------------------------------------------------------------*/
2045 /* saveRegisters - will look for a call and save the registers */
2046 /*-----------------------------------------------------------------*/
2048 saveRegisters (iCode * lic)
2054 for (ic = lic; ic; ic = ic->next)
2055 if (ic->op == CALL || ic->op == PCALL)
2060 fprintf (stderr, "found parameter push with no function call\n");
2064 /* if the registers have been saved already then
2067 || (IS_SYMOP(IC_LEFT(ic)) && IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))) && !TARGET_IS_DS400) )
2070 /* special case if DPTR alive across a function call then must save it
2071 even though callee saves */
2072 if (IS_SYMOP(IC_LEFT(ic)) &&
2073 IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2075 rsave = newBitVect(ic->rMask->size);
2076 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2077 if (bitVectBitValue(ic->rMask,i))
2078 rsave = bitVectSetBit(rsave,i);
2080 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2082 /* safe the registers in use at this time but skip the
2083 ones for the result */
2084 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2085 ds390_rUmaskForOp (IC_RESULT(ic)));
2091 /*-----------------------------------------------------------------*/
2092 /* usavermask - restore registers with mask */
2093 /*-----------------------------------------------------------------*/
2094 static void unsavermask(bitVect *rs_mask)
2097 if (options.useXstack) {
2098 emitcode ("mov", "r0,%s", spname);
2099 for (i = ds390_nRegs; i >= 0; i--) {
2100 if (bitVectBitValue (rs_mask, i)) {
2101 emitcode ("dec", "r0");
2102 emitcode ("movx", "a,@r0");
2104 emitcode ("mov", "b,a");
2106 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
2109 emitcode ("mov", "%s,r0", spname);
2110 if (bitVectBitValue (rs_mask, R0_IDX))
2111 emitcode ("mov", "r0,b");
2113 for (i = ds390_nRegs; i >= 0; i--) {
2114 if (bitVectBitValue (rs_mask, i))
2115 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2120 /*-----------------------------------------------------------------*/
2121 /* unsaveRegisters - pop the pushed registers */
2122 /*-----------------------------------------------------------------*/
2124 unsaveRegisters (iCode * ic)
2128 if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2130 rsave = newBitVect(ic->rMask->size);
2131 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2132 if (bitVectBitValue(ic->rMask,i))
2133 rsave = bitVectSetBit(rsave,i);
2135 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2137 /* restore the registers in use at this time but skip the
2138 ones for the result */
2139 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2140 ds390_rUmaskForOp (IC_RESULT(ic)));
2146 /*-----------------------------------------------------------------*/
2148 /*-----------------------------------------------------------------*/
2150 pushSide (operand * oper, int size)
2153 _startLazyDPSEvaluation ();
2156 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, NULL);
2157 if (AOP_TYPE (oper) != AOP_REG &&
2158 AOP_TYPE (oper) != AOP_DIR &&
2161 emitcode ("mov", "a,%s", l);
2162 emitcode ("push", "acc");
2165 emitcode ("push", "%s", l);
2167 _endLazyDPSEvaluation ();
2170 /*-----------------------------------------------------------------*/
2171 /* assignResultValue - */
2172 /*-----------------------------------------------------------------*/
2174 assignResultValue (operand * oper)
2177 int size = AOP_SIZE (oper);
2178 bool pushedAcc = FALSE;
2180 if (size == fReturnSizeDS390)
2182 /* I don't think this case can ever happen... */
2183 /* ACC is the last part of this. If writing the result
2184 * uses AC, we must preserve it.
2186 if (AOP_NEEDSACC(oper))
2188 emitcode(";", "assignResultValue special case for ACC.");
2189 emitcode("push", "acc");
2196 _startLazyDPSEvaluation ();
2199 aopPut (AOP (oper), fReturn[offset], offset);
2202 _endLazyDPSEvaluation ();
2206 emitcode("pop", "acc");
2207 aopPut(AOP(oper), "a", offset);
2212 /*-----------------------------------------------------------------*/
2213 /* genXpush - pushes onto the external stack */
2214 /*-----------------------------------------------------------------*/
2216 genXpush (iCode * ic)
2218 asmop *aop = newAsmop (0);
2220 int size, offset = 0;
2222 D (emitcode (";", "genXpush ");
2225 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2226 r = getFreePtr (ic, &aop, FALSE);
2229 emitcode ("mov", "%s,_spx", r->name);
2231 size = AOP_SIZE (IC_LEFT (ic));
2232 _startLazyDPSEvaluation ();
2236 MOVA (aopGet (AOP (IC_LEFT (ic)),
2237 offset++, FALSE, FALSE, NULL));
2238 emitcode ("movx", "@%s,a", r->name);
2239 emitcode ("inc", "%s", r->name);
2242 _endLazyDPSEvaluation ();
2245 emitcode ("mov", "_spx,%s", r->name);
2247 freeAsmop (NULL, aop, ic, TRUE);
2248 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2251 /*-----------------------------------------------------------------*/
2252 /* genIpush - generate code for pushing this gets a little complex */
2253 /*-----------------------------------------------------------------*/
2255 genIpush (iCode * ic)
2257 int size, offset = 0;
2260 D (emitcode (";", "genIpush ");
2263 /* if this is not a parm push : ie. it is spill push
2264 and spill push is always done on the local stack */
2268 /* and the item is spilt then do nothing */
2269 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2272 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2273 size = AOP_SIZE (IC_LEFT (ic));
2274 /* push it on the stack */
2275 _startLazyDPSEvaluation ();
2278 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2284 emitcode ("push", "%s", l);
2286 _endLazyDPSEvaluation ();
2290 /* this is a paramter push: in this case we call
2291 the routine to find the call and save those
2292 registers that need to be saved */
2295 /* if use external stack then call the external
2296 stack pushing routine */
2297 if (options.useXstack)
2303 /* then do the push */
2304 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2306 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2307 size = AOP_SIZE (IC_LEFT (ic));
2309 _startLazyDPSEvaluation ();
2312 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2313 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2314 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2317 emitcode ("mov", "a,%s", l);
2318 emitcode ("push", "acc");
2322 emitcode ("push", "%s", l);
2325 _endLazyDPSEvaluation ();
2327 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2330 /*-----------------------------------------------------------------*/
2331 /* genIpop - recover the registers: can happen only for spilling */
2332 /*-----------------------------------------------------------------*/
2334 genIpop (iCode * ic)
2338 D (emitcode (";", "genIpop ");
2342 /* if the temp was not pushed then */
2343 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2346 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2347 size = AOP_SIZE (IC_LEFT (ic));
2348 offset = (size - 1);
2349 _startLazyDPSEvaluation ();
2352 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2353 FALSE, TRUE, NULL));
2355 _endLazyDPSEvaluation ();
2357 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2360 /*-----------------------------------------------------------------*/
2361 /* unsaveRBank - restores the resgister bank from stack */
2362 /*-----------------------------------------------------------------*/
2364 unsaveRBank (int bank, iCode * ic, bool popPsw)
2370 if (options.useXstack)
2374 /* Assume r0 is available for use. */
2375 r = ds390_regWithIdx (R0_IDX);;
2380 r = getFreePtr (ic, &aop, FALSE);
2382 emitcode ("mov", "%s,_spx", r->name);
2387 if (options.useXstack)
2389 emitcode ("movx", "a,@%s", r->name);
2390 emitcode ("mov", "psw,a");
2391 emitcode ("dec", "%s", r->name);
2395 emitcode ("pop", "psw");
2399 for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2401 if (options.useXstack)
2403 emitcode ("movx", "a,@%s", r->name);
2404 emitcode ("mov", "(%s+%d),a",
2405 regs390[i].base, 8 * bank + regs390[i].offset);
2406 emitcode ("dec", "%s", r->name);
2410 emitcode ("pop", "(%s+%d)",
2411 regs390[i].base, 8 * bank + regs390[i].offset);
2414 if (options.useXstack)
2416 emitcode ("mov", "_spx,%s", r->name);
2421 freeAsmop (NULL, aop, ic, TRUE);
2425 /*-----------------------------------------------------------------*/
2426 /* saveRBank - saves an entire register bank on the stack */
2427 /*-----------------------------------------------------------------*/
2429 saveRBank (int bank, iCode * ic, bool pushPsw)
2435 if (options.useXstack)
2439 /* Assume r0 is available for use. */
2440 r = ds390_regWithIdx (R0_IDX);;
2445 r = getFreePtr (ic, &aop, FALSE);
2447 emitcode ("mov", "%s,_spx", r->name);
2450 for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2452 if (options.useXstack)
2454 emitcode ("inc", "%s", r->name);
2455 emitcode ("mov", "a,(%s+%d)",
2456 regs390[i].base, 8 * bank + regs390[i].offset);
2457 emitcode ("movx", "@%s,a", r->name);
2460 emitcode ("push", "(%s+%d)",
2461 regs390[i].base, 8 * bank + regs390[i].offset);
2466 if (options.useXstack)
2468 emitcode ("mov", "a,psw");
2469 emitcode ("movx", "@%s,a", r->name);
2470 emitcode ("inc", "%s", r->name);
2471 emitcode ("mov", "_spx,%s", r->name);
2475 emitcode ("push", "psw");
2478 emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2483 freeAsmop (NULL, aop, ic, TRUE);
2492 /*-----------------------------------------------------------------*/
2493 /* genSend - gen code for SEND */
2494 /*-----------------------------------------------------------------*/
2495 static void genSend(set *sendSet)
2499 static int rb1_count = 0;
2501 for (sic = setFirstItem (sendSet); sic;
2502 sic = setNextItem (sendSet)) {
2503 int size, offset = 0;
2505 size=getSize(operandType(IC_LEFT(sic)));
2506 D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2507 if (sendCount == 0) { /* first parameter */
2508 // we know that dpl(hxb) is the result, so
2510 _startLazyDPSEvaluation ();
2512 aopOp (IC_LEFT (sic), sic, FALSE,
2513 (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2515 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2518 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2519 FALSE, FALSE, NULL);
2520 if (strcmp (l, fReturn[offset])) {
2521 emitcode ("mov", "%s,%s",
2527 _endLazyDPSEvaluation ();
2528 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2530 } else { /* if more parameter in registers */
2531 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2533 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
2534 FALSE, FALSE, NULL));
2536 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2543 adjustEsp(const char *reg)
2545 emitcode ("anl","%s,#3", reg);
2546 if (TARGET_IS_DS400)
2548 emitcode ("orl","%s,#!constbyte",
2550 (options.stack_loc >> 8) & 0xff);
2554 /*-----------------------------------------------------------------*/
2555 /* genCall - generates a call statement */
2556 /*-----------------------------------------------------------------*/
2558 genCall (iCode * ic)
2561 bool restoreBank = FALSE;
2562 bool swapBanks = FALSE;
2564 D (emitcode (";", "genCall "););
2566 /* if we are calling a not _naked function that is not using
2567 the same register bank then we need to save the
2568 destination registers on the stack */
2569 dtype = operandType (IC_LEFT (ic));
2570 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2571 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2572 IFFUNC_ISISR (currFunc->type))
2576 /* This is unexpected; the bank should have been saved in
2579 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2585 /* if caller saves & we have not saved then */
2589 /* if send set is not empty the assign */
2590 /* We've saved all the registers we care about;
2591 * therefore, we may clobber any register not used
2592 * in the calling convention (i.e. anything not in
2597 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2598 genSend(reverseSet(_G.sendSet));
2600 genSend(_G.sendSet);
2607 emitcode ("mov", "psw,#!constbyte",
2608 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2612 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2613 OP_SYMBOL (IC_LEFT (ic))->rname :
2614 OP_SYMBOL (IC_LEFT (ic))->name));
2618 emitcode ("mov", "psw,#!constbyte",
2619 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2622 /* if we need assign a result value */
2623 if ((IS_ITEMP (IC_RESULT (ic)) &&
2624 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2625 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2626 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2627 IS_TRUE_SYMOP (IC_RESULT (ic)))
2629 if (isOperandInFarSpace (IC_RESULT (ic))
2630 && getSize (operandType (IC_RESULT (ic))) <= 2)
2632 int size = getSize (operandType (IC_RESULT (ic)));
2634 /* Special case for 1 or 2 byte return in far space. */
2638 emitcode ("mov", "b,%s", fReturn[1]);
2641 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2642 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2646 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2648 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2653 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2656 assignResultValue (IC_RESULT (ic));
2658 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2662 /* adjust the stack for parameters if
2664 if (ic->parmBytes) {
2666 if (options.stack10bit) {
2667 if (ic->parmBytes <= 10) {
2668 emitcode(";","stack adjustment for parms");
2669 for (i=0; i < ic->parmBytes ; i++) {
2670 emitcode("pop","acc");
2674 emitcode ("clr","c");
2675 emitcode ("mov","a,sp");
2676 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2677 emitcode ("mov","sp,a");
2678 emitcode ("mov","a,esp");
2680 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2681 emitcode ("mov","esp,a");
2685 if (ic->parmBytes > 3) {
2686 emitcode ("mov", "a,%s", spname);
2687 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2688 emitcode ("mov", "%s,a", spname);
2690 for (i = 0; i < ic->parmBytes; i++)
2691 emitcode ("dec", "%s", spname);
2695 /* if we hade saved some registers then unsave them */
2697 unsaveRegisters (ic);
2699 /* if register bank was saved then pop them */
2701 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2704 /*-----------------------------------------------------------------*/
2705 /* genPcall - generates a call by pointer statement */
2706 /*-----------------------------------------------------------------*/
2708 genPcall (iCode * ic)
2711 symbol *rlbl = newiTempLabel (NULL);
2712 bool restoreBank=FALSE;
2714 D (emitcode (";", "genPcall ");
2718 /* if caller saves & we have not saved then */
2722 /* if we are calling a function that is not using
2723 the same register bank then we need to save the
2724 destination registers on the stack */
2725 dtype = operandType (IC_LEFT (ic));
2726 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2727 IFFUNC_ISISR (currFunc->type) &&
2728 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2729 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2733 /* push the return address on to the stack */
2734 emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2735 emitcode ("push", "acc");
2736 emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2737 emitcode ("push", "acc");
2739 if (options.model == MODEL_FLAT24)
2741 emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2742 emitcode ("push", "acc");
2745 /* now push the calling address */
2746 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2748 pushSide (IC_LEFT (ic), FPTRSIZE);
2750 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2752 /* if send set is not empty the assign */
2755 genSend(reverseSet(_G.sendSet));
2759 emitcode ("ret", "");
2760 emitcode ("", "!tlabeldef", (rlbl->key + 100));
2763 /* if we need assign a result value */
2764 if ((IS_ITEMP (IC_RESULT (ic)) &&
2765 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2766 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2767 IS_TRUE_SYMOP (IC_RESULT (ic)))
2771 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2774 assignResultValue (IC_RESULT (ic));
2776 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2779 /* adjust the stack for parameters if
2784 if (options.stack10bit) {
2785 if (ic->parmBytes <= 10) {
2786 emitcode(";","stack adjustment for parms");
2787 for (i=0; i < ic->parmBytes ; i++) {
2788 emitcode("pop","acc");
2792 emitcode ("clr","c");
2793 emitcode ("mov","a,sp");
2794 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2795 emitcode ("mov","sp,a");
2796 emitcode ("mov","a,esp");
2798 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2799 emitcode ("mov","esp,a");
2803 if (ic->parmBytes > 3) {
2804 emitcode ("mov", "a,%s", spname);
2805 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2806 emitcode ("mov", "%s,a", spname);
2809 for (i = 0; i < ic->parmBytes; i++)
2810 emitcode ("dec", "%s", spname);
2814 /* if register bank was saved then unsave them */
2816 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2818 /* if we hade saved some registers then
2821 unsaveRegisters (ic);
2825 /*-----------------------------------------------------------------*/
2826 /* resultRemat - result is rematerializable */
2827 /*-----------------------------------------------------------------*/
2829 resultRemat (iCode * ic)
2831 if (SKIP_IC (ic) || ic->op == IFX)
2834 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2836 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2837 if (sym->remat && !POINTER_SET (ic))
2844 #if defined(__BORLANDC__) || defined(_MSC_VER)
2845 #define STRCASECMP stricmp
2847 #define STRCASECMP strcasecmp
2850 /*-----------------------------------------------------------------*/
2851 /* inExcludeList - return 1 if the string is in exclude Reg list */
2852 /*-----------------------------------------------------------------*/
2854 regsCmp(void *p1, void *p2)
2856 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2860 inExcludeList (char *s)
2862 const char *p = setFirstItem(options.excludeRegsSet);
2864 if (p == NULL || STRCASECMP(p, "none") == 0)
2868 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2871 /*-----------------------------------------------------------------*/
2872 /* genFunction - generated code for function entry */
2873 /*-----------------------------------------------------------------*/
2875 genFunction (iCode * ic)
2879 bool switchedPSW = FALSE;
2881 D (emitcode (";", "genFunction "););
2884 /* create the function header */
2885 emitcode (";", "-----------------------------------------");
2886 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2887 emitcode (";", "-----------------------------------------");
2889 emitcode ("", "%s:", sym->rname);
2890 ftype = operandType (IC_LEFT (ic));
2892 if (IFFUNC_ISNAKED(ftype))
2894 emitcode(";", "naked function: no prologue.");
2898 if (options.stack_probe)
2899 emitcode ("lcall","__stack_probe");
2900 /* if critical function then turn interrupts off */
2901 if (IFFUNC_ISCRITICAL (ftype))
2903 emitcode ("mov", "c,ea");
2904 emitcode ("push", "psw"); /* save old ea via c in psw */
2905 emitcode ("clr", "ea");
2908 /* here we need to generate the equates for the
2909 register bank if required */
2910 if (FUNC_REGBANK (ftype) != rbank)
2914 rbank = FUNC_REGBANK (ftype);
2915 for (i = 0; i < ds390_nRegs; i++)
2917 if (regs390[i].print) {
2918 if (strcmp (regs390[i].base, "0") == 0)
2919 emitcode ("", "%s !equ !constbyte",
2921 8 * rbank + regs390[i].offset);
2923 emitcode ("", "%s !equ %s + !constbyte",
2926 8 * rbank + regs390[i].offset);
2931 /* if this is an interrupt service routine then
2932 save acc, b, dpl, dph */
2933 if (IFFUNC_ISISR (sym->type))
2935 if (!inExcludeList ("acc"))
2936 emitcode ("push", "acc");
2937 if (!inExcludeList ("b"))
2938 emitcode ("push", "b");
2939 if (!inExcludeList ("dpl"))
2940 emitcode ("push", "dpl");
2941 if (!inExcludeList ("dph"))
2942 emitcode ("push", "dph");
2943 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2945 emitcode ("push", "dpx");
2946 /* Make sure we're using standard DPTR */
2947 emitcode ("push", "dps");
2948 emitcode ("mov", "dps,#0");
2949 if (options.stack10bit)
2951 /* This ISR could conceivably use DPTR2. Better save it. */
2952 emitcode ("push", "dpl1");
2953 emitcode ("push", "dph1");
2954 emitcode ("push", "dpx1");
2955 emitcode ("push", DP2_RESULT_REG);
2958 /* if this isr has no bank i.e. is going to
2959 run with bank 0 , then we need to save more
2961 if (!FUNC_REGBANK (sym->type))
2965 /* if this function does not call any other
2966 function then we can be economical and
2967 save only those registers that are used */
2968 if (!IFFUNC_HASFCALL(sym->type))
2971 /* if any registers used */
2974 /* save the registers used */
2975 for (i = 0; i < sym->regsUsed->size; i++)
2977 if (bitVectBitValue (sym->regsUsed, i) ||
2978 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2979 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2986 /* this function has a function call cannot
2987 determines register usage so we will have to push the
2989 saveRBank (0, ic, FALSE);
2990 if (options.parms_in_bank1) {
2991 for (i=0; i < 8 ; i++ ) {
2992 emitcode ("push","%s",rb1regs[i]);
2999 /* This ISR uses a non-zero bank.
3001 * We assume that the bank is available for our
3004 * However, if this ISR calls a function which uses some
3005 * other bank, we must save that bank entirely.
3007 unsigned long banksToSave = 0;
3009 if (IFFUNC_HASFCALL(sym->type))
3012 #define MAX_REGISTER_BANKS 4
3017 for (i = ic; i; i = i->next)
3019 if (i->op == ENDFUNCTION)
3021 /* we got to the end OK. */
3029 dtype = operandType (IC_LEFT(i));
3031 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3033 /* Mark this bank for saving. */
3034 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3036 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3040 banksToSave |= (1 << FUNC_REGBANK(dtype));
3043 /* And note that we don't need to do it in
3051 /* This is a mess; we have no idea what
3052 * register bank the called function might
3055 * The only thing I can think of to do is
3056 * throw a warning and hope.
3058 werror(W_FUNCPTR_IN_USING_ISR);
3062 if (banksToSave && options.useXstack)
3064 /* Since we aren't passing it an ic,
3065 * saveRBank will assume r0 is available to abuse.
3067 * So switch to our (trashable) bank now, so
3068 * the caller's R0 isn't trashed.
3070 emitcode ("push", "psw");
3071 emitcode ("mov", "psw,#!constbyte",
3072 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3076 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3078 if (banksToSave & (1 << ix))
3080 saveRBank(ix, NULL, FALSE);
3084 // TODO: this needs a closer look
3085 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3090 /* if callee-save to be used for this function
3091 then save the registers being used in this function */
3092 if (IFFUNC_CALLEESAVES(sym->type))
3096 /* if any registers used */
3099 /* save the registers used */
3100 for (i = 0; i < sym->regsUsed->size; i++)
3102 if (bitVectBitValue (sym->regsUsed, i) ||
3103 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3105 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3113 /* set the register bank to the desired value */
3114 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3117 emitcode ("push", "psw");
3118 emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3121 if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3122 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3123 if (options.stack10bit) {
3124 emitcode ("push","_bpx");
3125 emitcode ("push","_bpx+1");
3126 emitcode ("mov","_bpx,%s",spname);
3127 emitcode ("mov","_bpx+1,esp");
3128 adjustEsp("_bpx+1");
3130 if (options.useXstack) {
3131 emitcode ("mov", "r0,%s", spname);
3132 emitcode ("mov", "a,_bp");
3133 emitcode ("movx", "@r0,a");
3134 emitcode ("inc", "%s", spname);
3136 /* set up the stack */
3137 emitcode ("push", "_bp"); /* save the callers stack */
3139 emitcode ("mov", "_bp,%s", spname);
3143 /* adjust the stack for the function */
3146 if (options.stack10bit) {
3147 if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
3148 assert (sym->recvSize <= 4);
3149 if (sym->stack <= 8) {
3150 while (i--) emitcode ("push","acc");
3153 emitcode ("mov","a,sp");
3154 emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3155 emitcode ("mov","sp,a");
3156 emitcode ("mov","a,esp");
3158 emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3159 emitcode ("mov","esp,a");
3164 werror (W_STACK_OVERFLOW, sym->name);
3166 if (i > 3 && sym->recvSize < 4) {
3168 emitcode ("mov", "a,sp");
3169 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3170 emitcode ("mov", "sp,a");
3174 emitcode ("inc", "sp");
3181 emitcode ("mov", "a,_spx");
3182 emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3183 emitcode ("mov", "_spx,a");
3188 /*-----------------------------------------------------------------*/
3189 /* genEndFunction - generates epilogue for functions */
3190 /*-----------------------------------------------------------------*/
3192 genEndFunction (iCode * ic)
3194 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3196 D (emitcode (";", "genEndFunction "););
3198 if (IFFUNC_ISNAKED(sym->type))
3200 emitcode(";", "naked function: no epilogue.");
3204 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3205 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3207 if (options.stack10bit) {
3209 emitcode ("mov", "sp,_bpx", spname);
3210 emitcode ("mov", "esp,_bpx+1", spname);
3213 emitcode ("mov", "%s,_bp", spname);
3217 /* if use external stack but some variables were
3218 added to the local stack then decrement the
3220 if (options.useXstack && sym->stack) {
3221 emitcode ("mov", "a,sp");
3222 emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3223 emitcode ("mov", "sp,a");
3227 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3228 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3230 if (options.useXstack) {
3231 emitcode ("mov", "r0,%s", spname);
3232 emitcode ("movx", "a,@r0");
3233 emitcode ("mov", "_bp,a");
3234 emitcode ("dec", "%s", spname);
3236 if (options.stack10bit) {
3237 emitcode ("pop", "_bpx+1");
3238 emitcode ("pop", "_bpx");
3240 emitcode ("pop", "_bp");
3245 /* restore the register bank */
3246 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3248 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3249 || !options.useXstack)
3251 /* Special case of ISR using non-zero bank with useXstack
3254 emitcode ("pop", "psw");
3258 if (IFFUNC_ISISR (sym->type))
3261 /* now we need to restore the registers */
3262 /* if this isr has no bank i.e. is going to
3263 run with bank 0 , then we need to save more
3265 if (!FUNC_REGBANK (sym->type))
3268 /* if this function does not call any other
3269 function then we can be economical and
3270 save only those registers that are used */
3271 if (!IFFUNC_HASFCALL(sym->type))
3274 /* if any registers used */
3277 /* save the registers used */
3278 for (i = sym->regsUsed->size; i >= 0; i--)
3280 if (bitVectBitValue (sym->regsUsed, i) ||
3281 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3282 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3289 /* this function has a function call cannot
3290 determines register usage so we will have to pop the
3292 if (options.parms_in_bank1) {
3293 for (i = 7 ; i >= 0 ; i-- ) {
3294 emitcode ("pop","%s",rb1regs[i]);
3297 unsaveRBank (0, ic, FALSE);
3302 /* This ISR uses a non-zero bank.
3304 * Restore any register banks saved by genFunction
3307 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3310 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3312 if (savedBanks & (1 << ix))
3314 unsaveRBank(ix, NULL, FALSE);
3318 if (options.useXstack)
3320 /* Restore bank AFTER calling unsaveRBank,
3321 * since it can trash r0.
3323 emitcode ("pop", "psw");
3327 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3329 if (options.stack10bit)
3331 emitcode ("pop", DP2_RESULT_REG);
3332 emitcode ("pop", "dpx1");
3333 emitcode ("pop", "dph1");
3334 emitcode ("pop", "dpl1");
3336 emitcode ("pop", "dps");
3337 emitcode ("pop", "dpx");
3339 if (!inExcludeList ("dph"))
3340 emitcode ("pop", "dph");
3341 if (!inExcludeList ("dpl"))
3342 emitcode ("pop", "dpl");
3343 if (!inExcludeList ("b"))
3344 emitcode ("pop", "b");
3345 if (!inExcludeList ("acc"))
3346 emitcode ("pop", "acc");
3348 if (IFFUNC_ISCRITICAL (sym->type))
3350 emitcode ("pop", "psw"); /* restore ea via c in psw */
3351 emitcode ("mov", "ea,c");
3354 /* if debug then send end of function */
3355 if (options.debug && currFunc) {
3357 emitcode ("", "C$%s$%d$%d$%d ==.",
3358 FileBaseName (ic->filename), currFunc->lastLine,
3359 ic->level, ic->block);
3360 if (IS_STATIC (currFunc->etype))
3361 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3363 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3367 emitcode ("reti", "");
3371 if (IFFUNC_ISCRITICAL (sym->type))
3373 emitcode ("pop", "psw"); /* restore ea via c in psw */
3374 emitcode ("mov", "ea,c");
3377 if (IFFUNC_CALLEESAVES(sym->type))
3381 /* if any registers used */
3384 /* save the registers used */
3385 for (i = sym->regsUsed->size; i >= 0; i--)
3387 if (bitVectBitValue (sym->regsUsed, i) ||
3388 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3389 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3395 /* if debug then send end of function */
3396 if (options.debug && currFunc)
3399 emitcode ("", "C$%s$%d$%d$%d ==.",
3400 FileBaseName (ic->filename), currFunc->lastLine,
3401 ic->level, ic->block);
3402 if (IS_STATIC (currFunc->etype))
3403 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3405 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3409 emitcode ("ret", "");
3414 /*-----------------------------------------------------------------*/
3415 /* genJavaNativeRet - generate code for return JavaNative */
3416 /*-----------------------------------------------------------------*/
3417 static void genJavaNativeRet(iCode *ic)
3421 aopOp (IC_LEFT (ic), ic, FALSE,
3422 AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
3423 size = AOP_SIZE (IC_LEFT (ic));
3427 /* it is assigned to GPR0-R3 then push them */
3428 if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3429 aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3430 for (i = 0 ; i < size ; i++ ) {
3431 emitcode ("push","%s",
3432 aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3434 for (i = (size-1) ; i >= 0 ; i--) {
3435 emitcode ("pop","a%s",javaRet[i]);
3438 for (i = 0 ; i < size ; i++)
3439 emitcode ("mov","%s,%s",javaRet[i],
3440 aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3442 for (i = size ; i < 4 ; i++ )
3443 emitcode ("mov","%s,#0",javaRet[i]);
3447 /*-----------------------------------------------------------------*/
3448 /* genRet - generate code for return statement */
3449 /*-----------------------------------------------------------------*/
3453 int size, offset = 0, pushed = 0;
3455 D (emitcode (";", "genRet "););
3457 /* if we have no return value then
3458 just generate the "ret" */
3462 /* if this is a JavaNative function then return
3463 value in different register */
3464 if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3465 genJavaNativeRet(ic);
3468 /* we have something to return then
3469 move the return value into place */
3470 aopOp (IC_LEFT (ic), ic, FALSE,
3471 (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
3472 size = AOP_SIZE (IC_LEFT (ic));
3474 _startLazyDPSEvaluation ();
3478 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3480 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3482 emitcode ("push", "%s", l);
3487 /* Since A is the last element of fReturn,
3488 * is is OK to clobber it in the aopGet.
3490 l = aopGet (AOP (IC_LEFT (ic)), offset,
3491 FALSE, FALSE, NULL);
3492 if (strcmp (fReturn[offset], l))
3493 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3496 _endLazyDPSEvaluation ();
3503 if (strcmp (fReturn[pushed], "a"))
3504 emitcode ("pop", fReturn[pushed]);
3506 emitcode ("pop", "acc");
3509 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3512 /* generate a jump to the return label
3513 if the next is not the return statement */
3514 if (!(ic->next && ic->next->op == LABEL &&
3515 IC_LABEL (ic->next) == returnLabel))
3517 emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3521 /*-----------------------------------------------------------------*/
3522 /* genLabel - generates a label */
3523 /*-----------------------------------------------------------------*/
3525 genLabel (iCode * ic)
3527 /* special case never generate */
3528 if (IC_LABEL (ic) == entryLabel)
3531 D (emitcode (";", "genLabel ");
3534 emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3537 /*-----------------------------------------------------------------*/
3538 /* genGoto - generates a ljmp */
3539 /*-----------------------------------------------------------------*/
3541 genGoto (iCode * ic)
3543 D (emitcode (";", "genGoto ");
3545 emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3548 /*-----------------------------------------------------------------*/
3549 /* findLabelBackwards: walks back through the iCode chain looking */
3550 /* for the given label. Returns number of iCode instructions */
3551 /* between that label and given ic. */
3552 /* Returns zero if label not found. */
3553 /*-----------------------------------------------------------------*/
3555 findLabelBackwards (iCode * ic, int key)
3564 /* If we have any pushes or pops, we cannot predict the distance.
3565 I don't like this at all, this should be dealt with in the
3567 if (ic->op == IPUSH || ic->op == IPOP) {
3571 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3573 /* printf("findLabelBackwards = %d\n", count); */
3581 /*-----------------------------------------------------------------*/
3582 /* genPlusIncr :- does addition with increment if possible */
3583 /*-----------------------------------------------------------------*/
3585 genPlusIncr (iCode * ic)
3587 unsigned int icount;
3588 unsigned int size = getDataSize (IC_RESULT (ic));
3590 /* will try to generate an increment */
3591 /* if the right side is not a literal
3593 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3596 /* if the literal value of the right hand side
3597 is greater than 4 then it is not worth it */
3598 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3601 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3602 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3604 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
3608 /* if increment 16 bits in register */
3610 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3611 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3612 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3621 /* If the next instruction is a goto and the goto target
3622 * is <= 5 instructions previous to this, we can generate
3623 * jumps straight to that target.
3625 if (ic->next && ic->next->op == GOTO
3626 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3629 D(emitcode (";", "tail increment optimized (range %d)", labelRange););
3630 tlbl = IC_LABEL (ic->next);
3635 tlbl = newiTempLabel (NULL);
3639 l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
3640 emitcode ("inc", "%s", l);
3642 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3643 IS_AOP_PREG (IC_RESULT (ic)))
3645 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3649 emitcode ("clr", "a");
3650 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3653 l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
3654 emitcode ("inc", "%s", l);
3657 if (!strcmp(l, "acc"))
3659 emitcode("jnz", "!tlabel", tlbl->key + 100);
3661 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3662 IS_AOP_PREG (IC_RESULT (ic)))
3664 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3668 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3671 l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
3672 emitcode ("inc", "%s", l);
3676 if (!strcmp(l, "acc"))
3678 emitcode("jnz", "!tlabel", tlbl->key + 100);
3680 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3681 IS_AOP_PREG (IC_RESULT (ic)))
3683 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3687 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3690 l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
3691 emitcode ("inc", "%s", l); }
3695 emitcode ("", "!tlabeldef", tlbl->key + 100);
3700 if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3701 !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 &&
3702 options.model == MODEL_FLAT24 ) {
3706 emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, NULL));
3708 emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, NULL));
3710 emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3713 while (icount--) emitcode ("inc","dptr");
3717 if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3718 AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3720 emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3721 while (icount--) emitcode ("inc","dptr");
3722 emitcode ("mov","dps,#0");
3726 /* if the sizes are greater than 1 then we cannot */
3727 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3728 AOP_SIZE (IC_LEFT (ic)) > 1)
3731 /* we can if the aops of the left & result match or
3732 if they are in registers and the registers are the
3735 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3736 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3737 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3742 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3743 emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3744 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3749 _startLazyDPSEvaluation ();
3752 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3754 _endLazyDPSEvaluation ();
3763 /*-----------------------------------------------------------------*/
3764 /* outBitAcc - output a bit in acc */
3765 /*-----------------------------------------------------------------*/
3767 outBitAcc (operand * result)
3769 symbol *tlbl = newiTempLabel (NULL);
3770 /* if the result is a bit */
3771 if (AOP_TYPE (result) == AOP_CRY)
3773 aopPut (AOP (result), "a", 0);
3777 emitcode ("jz", "!tlabel", tlbl->key + 100);
3778 emitcode ("mov", "a,%s", one);
3779 emitcode ("", "!tlabeldef", tlbl->key + 100);
3784 /*-----------------------------------------------------------------*/
3785 /* genPlusBits - generates code for addition of two bits */
3786 /*-----------------------------------------------------------------*/
3788 genPlusBits (iCode * ic)
3790 D (emitcode (";", "genPlusBits "););
3792 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3794 symbol *lbl = newiTempLabel (NULL);
3795 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3796 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3797 emitcode ("cpl", "c");
3798 emitcode ("", "!tlabeldef", (lbl->key + 100));
3799 outBitC (IC_RESULT (ic));
3803 emitcode ("clr", "a");
3804 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3805 emitcode ("rlc", "a");
3806 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3807 emitcode ("addc", "a,#0");
3808 outAcc (IC_RESULT (ic));
3813 adjustArithmeticResult (iCode * ic)
3815 if (opIsGptr (IC_RESULT (ic)) &&
3816 opIsGptr (IC_LEFT (ic)) &&
3817 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3819 aopPut (AOP (IC_RESULT (ic)),
3820 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3824 if (opIsGptr (IC_RESULT (ic)) &&
3825 opIsGptr (IC_RIGHT (ic)) &&
3826 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3828 aopPut (AOP (IC_RESULT (ic)),
3829 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3833 if (opIsGptr (IC_RESULT (ic)) &&
3834 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3835 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3836 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3837 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3840 SNPRINTF (buff, sizeof(buff),
3841 "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3842 aopPut (AOP (IC_RESULT (ic)), buff, GPTRSIZE - 1);
3846 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
3847 // generates the result if possible. If result is generated, returns TRUE; otherwise
3848 // returns false and caller must deal with fact that result isn't aopOp'd.
3849 bool aopOp3(iCode * ic)
3851 bool dp1InUse, dp2InUse;
3854 // First, generate the right opcode. DPTR may be used if neither left nor result are
3857 // D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
3858 // AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
3859 // AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
3860 // AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
3862 // D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
3863 // AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
3864 // AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
3865 // AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
3868 // Right uses DPTR unless left or result is an AOP_STR; however,
3869 // if right is an AOP_STR, it must use DPTR regardless.
3870 if ((AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)))
3871 && !AOP_IS_STR(IC_RIGHT(ic)))
3880 aopOp (IC_RIGHT(ic),ic,FALSE, useDp2);
3882 // if the right used DPTR, left MUST use DPTR2.
3883 // if the right used DPTR2, left MUST use DPTR.
3884 // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
3885 // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
3886 // enabling us to assign DPTR to result.
3888 if (AOP_USESDPTR(IC_RIGHT(ic)))
3892 else if (AOP_USESDPTR2(IC_RIGHT(ic)))
3898 if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
3908 aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
3910 // We've op'd the left & right. So, if left or right are the same operand as result,
3911 // we know aopOp will succeed, and we can just do it & bail.
3912 if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)) ||
3913 isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
3915 // D(emitcode(";", "aopOp3: (left | right) & result equal"););
3916 aopOp(IC_RESULT(ic),ic,TRUE, FALSE);
3920 // Note which dptrs are currently in use.
3921 dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
3922 dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
3924 // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot
3926 if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
3931 // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
3932 if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
3937 // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck
3938 if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
3943 aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
3945 // Some sanity checking...
3946 if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
3949 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
3950 __FILE__, __LINE__, ic->filename, ic->lineno);
3951 emitcode(";", ">>> unexpected DPTR here.");
3954 if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
3957 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
3958 __FILE__, __LINE__, ic->filename, ic->lineno);
3959 emitcode(";", ">>> unexpected DPTR2 here.");
3965 // Macro to aopOp all three operands of an ic. If this cannot be done,
3966 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3967 // will be set TRUE. The caller must then handle the case specially, noting
3968 // that the IC_RESULT operand is not aopOp'd.
3970 #define AOP_OP_3_NOFATAL(ic, rc) \
3971 do { rc = !aopOp3(ic); } while (0)
3973 // aopOp the left & right operands of an ic.
3974 #define AOP_OP_2(ic) \
3975 aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
3976 aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
3978 // convienience macro.
3979 #define AOP_SET_LOCALS(ic) \
3980 left = IC_LEFT(ic); \
3981 right = IC_RIGHT(ic); \
3982 result = IC_RESULT(ic);
3985 // Given an integer value of pushedSize bytes on the stack,
3986 // adjust it to be resultSize bytes, either by discarding
3987 // the most significant bytes or by zero-padding.
3989 // On exit from this macro, pushedSize will have been adjusted to
3990 // equal resultSize, and ACC may be trashed.
3991 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3992 /* If the pushed data is bigger than the result, \
3993 * simply discard unused bytes. Icky, but works. \
3995 while (pushedSize > resultSize) \
3997 D (emitcode (";", "discarding unused result byte."););\
3998 emitcode ("pop", "acc"); \
4001 if (pushedSize < resultSize) \
4003 emitcode ("clr", "a"); \
4004 /* Conversly, we haven't pushed enough here. \
4005 * just zero-pad, and all is well. \
4007 while (pushedSize < resultSize) \
4009 emitcode("push", "acc"); \
4013 assert(pushedSize == resultSize);
4015 /*-----------------------------------------------------------------*/
4016 /* genPlus - generates code for addition */
4017 /*-----------------------------------------------------------------*/
4019 genPlus (iCode * ic)
4021 int size, offset = 0;
4025 D (emitcode (";", "genPlus "););
4027 /* special cases :- */
4028 if ( AOP_IS_STR(IC_LEFT(ic)) &&
4029 isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
4030 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
4031 size = (int)floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
4033 while (size--) emitcode ("inc","dptr");
4035 emitcode ("mov","a,dpl");
4036 emitcode ("add","a,#!constbyte",size & 0xff);
4037 emitcode ("mov","dpl,a");
4038 emitcode ("mov","a,dph");
4039 emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
4040 emitcode ("mov","dph,a");
4041 emitcode ("mov","a,dpx");
4042 emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
4043 emitcode ("mov","dpx,a");
4045 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
4048 if ( IS_SYMOP(IC_LEFT(ic)) &&
4049 OP_SYMBOL(IC_LEFT(ic))->remat &&
4050 isOperandInFarSpace(IC_RIGHT(ic))) {
4051 operand *op = IC_RIGHT(ic);
4052 IC_RIGHT(ic) = IC_LEFT(ic);
4056 AOP_OP_3_NOFATAL (ic, pushResult);
4060 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
4065 /* if literal, literal on the right or
4066 if left requires ACC or right is already
4068 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4069 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
4070 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4072 operand *t = IC_RIGHT (ic);
4073 IC_RIGHT (ic) = IC_LEFT (ic);
4075 emitcode (";", "Swapped plus args.");
4078 /* if both left & right are in bit
4080 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4081 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4087 /* if left in bit space & right literal */
4088 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4089 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4091 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4092 /* if result in bit space */
4093 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4095 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4096 emitcode ("cpl", "c");
4097 outBitC (IC_RESULT (ic));
4101 size = getDataSize (IC_RESULT (ic));
4102 _startLazyDPSEvaluation ();
4105 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4106 emitcode ("addc", "a,#0");
4107 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4109 _endLazyDPSEvaluation ();
4114 /* if I can do an increment instead
4115 of add then GOOD for ME */
4116 if (genPlusIncr (ic) == TRUE)
4118 emitcode (";", "did genPlusIncr");
4123 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4125 _startLazyDPSEvaluation ();
4128 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4130 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4132 emitcode ("add", "a,%s",
4133 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4135 emitcode ("addc", "a,%s",
4136 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4140 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4142 /* right is going to use ACC or we would have taken the
4145 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4147 D(emitcode(";", "+ AOP_ACC special case."););
4148 emitcode("xch", "a, %s", DP2_RESULT_REG);
4150 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4153 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4156 emitcode("add", "a, %s", DP2_RESULT_REG);
4160 emitcode ("add", "a,%s",
4161 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE,
4167 emitcode ("addc", "a,%s",
4168 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE,
4174 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4178 emitcode ("push", "acc");
4182 _endLazyDPSEvaluation ();
4186 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4188 size = getDataSize (IC_LEFT (ic));
4189 rSize = getDataSize (IC_RESULT (ic));
4191 ADJUST_PUSHED_RESULT(size, rSize);
4193 _startLazyDPSEvaluation ();
4196 emitcode ("pop", "acc");
4197 aopPut (AOP (IC_RESULT (ic)), "a", size);
4199 _endLazyDPSEvaluation ();
4202 adjustArithmeticResult (ic);
4205 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4206 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4207 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4210 /*-----------------------------------------------------------------*/
4211 /* genMinusDec :- does subtraction with deccrement if possible */
4212 /*-----------------------------------------------------------------*/
4214 genMinusDec (iCode * ic)
4216 unsigned int icount;
4217 unsigned int size = getDataSize (IC_RESULT (ic));
4219 /* will try to generate an increment */
4220 /* if the right side is not a literal
4222 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4225 /* if the literal value of the right hand side
4226 is greater than 4 then it is not worth it */
4227 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4230 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4231 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4233 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
4237 /* if decrement 16 bits in register */
4238 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4239 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4240 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4249 /* If the next instruction is a goto and the goto target
4250 * is <= 5 instructions previous to this, we can generate
4251 * jumps straight to that target.
4253 if (ic->next && ic->next->op == GOTO
4254 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4257 emitcode (";", "tail decrement optimized (range %d)", labelRange);
4258 tlbl = IC_LABEL (ic->next);
4263 tlbl = newiTempLabel (NULL);
4267 l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
4268 emitcode ("dec", "%s", l);
4270 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4271 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4272 IS_AOP_PREG (IC_RESULT (ic)))
4274 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4278 emitcode ("mov", "a,#!constbyte",0xff);
4279 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4281 l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
4282 emitcode ("dec", "%s", l);
4285 if (!strcmp(l, "acc"))
4287 emitcode("jnz", "!tlabel", tlbl->key + 100);
4289 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4290 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4291 IS_AOP_PREG (IC_RESULT (ic)))
4293 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4297 emitcode ("mov", "a,#!constbyte",0xff);
4298 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4300 l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
4301 emitcode ("dec", "%s", l);
4305 if (!strcmp(l, "acc"))
4307 emitcode("jnz", "!tlabel", tlbl->key + 100);
4309 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4310 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4311 IS_AOP_PREG (IC_RESULT (ic)))
4313 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4317 emitcode ("mov", "a,#!constbyte",0xff);
4318 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4320 l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
4321 emitcode ("dec", "%s", l);
4325 emitcode ("", "!tlabeldef", tlbl->key + 100);
4330 /* if the sizes are greater than 1 then we cannot */
4331 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4332 AOP_SIZE (IC_LEFT (ic)) > 1)
4335 /* we can if the aops of the left & result match or
4336 if they are in registers and the registers are the
4339 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4340 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4341 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4344 _startLazyDPSEvaluation ();
4347 emitcode ("dec", "%s",
4348 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
4350 _endLazyDPSEvaluation ();
4358 /*-----------------------------------------------------------------*/
4359 /* addSign - complete with sign */
4360 /*-----------------------------------------------------------------*/
4362 addSign (operand * result, int offset, int sign)
4364 int size = (getDataSize (result) - offset);
4367 _startLazyDPSEvaluation();
4370 emitcode ("rlc", "a");
4371 emitcode ("subb", "a,acc");
4374 aopPut (AOP (result), "a", offset++);
4381 aopPut (AOP (result), zero, offset++);
4384 _endLazyDPSEvaluation();
4388 /*-----------------------------------------------------------------*/
4389 /* genMinusBits - generates code for subtraction of two bits */
4390 /*-----------------------------------------------------------------*/
4392 genMinusBits (iCode * ic)
4394 symbol *lbl = newiTempLabel (NULL);
4396 D (emitcode (";", "genMinusBits "););
4398 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4400 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4401 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4402 emitcode ("cpl", "c");
4403 emitcode ("", "!tlabeldef", (lbl->key + 100));
4404 outBitC (IC_RESULT (ic));
4408 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4409 emitcode ("subb", "a,acc");
4410 emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4411 emitcode ("inc", "a");
4412 emitcode ("", "!tlabeldef", (lbl->key + 100));
4413 aopPut (AOP (IC_RESULT (ic)), "a", 0);
4414 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4418 /*-----------------------------------------------------------------*/
4419 /* genMinus - generates code for subtraction */
4420 /*-----------------------------------------------------------------*/
4422 genMinus (iCode * ic)
4424 int size, offset = 0;
4429 D (emitcode (";", "genMinus "););
4431 AOP_OP_3_NOFATAL(ic, pushResult);
4435 /* special cases :- */
4436 /* if both left & right are in bit space */
4437 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4438 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4444 /* if I can do an decrement instead
4445 of subtract then GOOD for ME */
4446 if (genMinusDec (ic) == TRUE)
4451 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4453 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4459 lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4464 /* if literal, add a,#-lit, else normal subb */
4465 _startLazyDPSEvaluation ();
4467 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4468 if (AOP_USESDPTR(IC_RIGHT(ic))) {
4469 emitcode ("mov","b,%s",
4470 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4471 MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4472 emitcode ("subb","a,b");
4474 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4475 emitcode ("subb", "a,%s",
4476 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE,
4480 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4481 /* first add without previous c */
4483 if (!size && lit==-1) {
4484 emitcode ("dec", "a");
4486 emitcode ("add", "a,#!constbyte",
4487 (unsigned int) (lit & 0x0FFL));
4490 emitcode ("addc", "a,#!constbyte",
4491 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4496 emitcode ("push", "acc");
4498 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4502 _endLazyDPSEvaluation ();
4506 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4508 size = getDataSize (IC_LEFT (ic));
4509 rSize = getDataSize (IC_RESULT (ic));
4511 ADJUST_PUSHED_RESULT(size, rSize);
4513 _startLazyDPSEvaluation ();
4516 emitcode ("pop", "acc");
4517 aopPut (AOP (IC_RESULT (ic)), "a", size);
4519 _endLazyDPSEvaluation ();
4522 adjustArithmeticResult (ic);
4525 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4526 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4527 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4531 /*-----------------------------------------------------------------*/
4532 /* genMultbits :- multiplication of bits */
4533 /*-----------------------------------------------------------------*/
4535 genMultbits (operand * left,
4540 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4541 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4542 aopOp(result, ic, TRUE, FALSE);
4547 /*-----------------------------------------------------------------*/
4548 /* genMultOneByte : 8*8=8/16 bit multiplication */
4549 /*-----------------------------------------------------------------*/
4551 genMultOneByte (operand * left,
4556 sym_link *opetype = operandType (result);
4560 /* (if two literals: the value is computed before) */
4561 /* if one literal, literal on the right */
4562 if (AOP_TYPE (left) == AOP_LIT)
4567 emitcode (";", "swapped left and right");
4570 if (SPEC_USIGN(opetype)
4571 // ignore the sign of left and right, what else can we do?
4572 || (SPEC_USIGN(operandType(left)) &&
4573 SPEC_USIGN(operandType(right)))) {
4574 // just an unsigned 8*8=8/16 multiply
4575 //emitcode (";","unsigned");
4576 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4577 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4578 emitcode ("mul", "ab");
4580 _G.accInUse++; _G.bInUse++;
4581 aopOp(result, ic, TRUE, FALSE);
4583 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4585 // this should never happen
4586 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4587 AOP_SIZE(result), __FILE__, lineno);
4591 aopPut (AOP (result), "a", 0);
4592 _G.accInUse--; _G.bInUse--;
4593 if (AOP_SIZE(result)==2)
4595 aopPut (AOP (result), "b", 1);
4600 // we have to do a signed multiply
4602 emitcode (";", "signed");
4603 emitcode ("clr", "F0"); // reset sign flag
4604 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4606 lbl=newiTempLabel(NULL);
4607 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4608 // left side is negative, 8-bit two's complement, this fails for -128
4609 emitcode ("setb", "F0"); // set sign flag
4610 emitcode ("cpl", "a");
4611 emitcode ("inc", "a");
4613 emitcode ("", "!tlabeldef", lbl->key+100);
4616 if (AOP_TYPE(right)==AOP_LIT) {
4617 signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
4618 /* AND literal negative */
4619 if ((int) val < 0) {
4620 emitcode ("cpl", "F0"); // complement sign flag
4621 emitcode ("mov", "b,#!constbyte", -val);
4623 emitcode ("mov", "b,#!constbyte", val);
4626 lbl=newiTempLabel(NULL);
4627 emitcode ("mov", "b,a");
4628 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4629 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4630 // right side is negative, 8-bit two's complement
4631 emitcode ("cpl", "F0"); // complement sign flag
4632 emitcode ("cpl", "a");
4633 emitcode ("inc", "a");
4634 emitcode ("", "!tlabeldef", lbl->key+100);
4636 emitcode ("mul", "ab");
4638 _G.accInUse++;_G.bInUse++;
4639 aopOp(result, ic, TRUE, FALSE);
4641 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4643 // this should never happen
4644 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4645 AOP_SIZE(result), __FILE__, lineno);
4649 lbl=newiTempLabel(NULL);
4650 emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4651 // only ONE op was negative, we have to do a 8/16-bit two's complement
4652 emitcode ("cpl", "a"); // lsb
4653 if (AOP_SIZE(result)==1) {
4654 emitcode ("inc", "a");
4656 emitcode ("add", "a,#1");
4657 emitcode ("xch", "a,b");
4658 emitcode ("cpl", "a"); // msb
4659 emitcode ("addc", "a,#0");
4660 emitcode ("xch", "a,b");
4663 emitcode ("", "!tlabeldef", lbl->key+100);
4664 aopPut (AOP (result), "a", 0);
4665 _G.accInUse--;_G.bInUse--;
4666 if (AOP_SIZE(result)==2) {
4667 aopPut (AOP (result), "b", 1);
4671 /*-----------------------------------------------------------------*/
4672 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
4673 /*-----------------------------------------------------------------*/
4674 static void genMultTwoByte (operand *left, operand *right,
4675 operand *result, iCode *ic)
4677 sym_link *retype = getSpec(operandType(right));
4678 sym_link *letype = getSpec(operandType(left));
4679 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4682 if (AOP_TYPE (left) == AOP_LIT) {
4687 /* save EA bit in F1 */
4688 lbl = newiTempLabel(NULL);
4689 emitcode ("setb","F1");
4690 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4691 emitcode ("clr","F1");
4692 emitcode("","!tlabeldef",lbl->key+100);
4694 /* load up MB with right */
4696 emitcode("clr","F0");
4697 if (AOP_TYPE(right) == AOP_LIT) {
4698 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
4700 emitcode("setb","F0");
4703 emitcode ("mov","mb,#!constbyte",val & 0xff);
4704 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4706 lbl = newiTempLabel(NULL);
4707 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4708 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4709 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4710 emitcode ("xch", "a,b");
4711 emitcode ("cpl","a");
4712 emitcode ("add", "a,#1");
4713 emitcode ("xch", "a,b");
4714 emitcode ("cpl", "a"); // msb
4715 emitcode ("addc", "a,#0");
4716 emitcode ("setb","F0");
4717 emitcode ("","!tlabeldef",lbl->key+100);
4718 emitcode ("mov","mb,b");
4719 emitcode ("mov","mb,a");
4722 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4723 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4725 /* load up MA with left */
4727 lbl = newiTempLabel(NULL);
4728 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4729 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4730 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4731 emitcode ("xch", "a,b");
4732 emitcode ("cpl","a");
4733 emitcode ("add", "a,#1");
4734 emitcode ("xch", "a,b");
4735 emitcode ("cpl", "a"); // msb
4736 emitcode ("addc","a,#0");
4737 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4738 emitcode ("setb","F0");
4739 emitcode ("","!tlabeldef",lbl->key+100);
4740 emitcode ("mov","ma,b");
4741 emitcode ("mov","ma,a");
4743 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4744 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4746 /* wait for multiplication to finish */
4747 lbl = newiTempLabel(NULL);
4748 emitcode("","!tlabeldef", lbl->key+100);
4749 emitcode("mov","a,mcnt1");
4750 emitcode("anl","a,#!constbyte",0x80);
4751 emitcode("jnz","!tlabel",lbl->key+100);
4753 freeAsmop (left, NULL, ic, TRUE);
4754 freeAsmop (right, NULL, ic,TRUE);
4755 aopOp(result, ic, TRUE, FALSE);
4757 /* if unsigned then simple */
4759 emitcode ("mov","a,ma");
4760 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4761 emitcode ("mov","a,ma");
4762 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4763 aopPut(AOP(result),"ma",1);
4764 aopPut(AOP(result),"ma",0);
4766 emitcode("push","ma");
4767 emitcode("push","ma");
4768 emitcode("push","ma");
4770 /* negate result if needed */
4771 lbl = newiTempLabel(NULL);
4772 emitcode("jnb","F0,!tlabel",lbl->key+100);
4773 emitcode("cpl","a");
4774 emitcode("add","a,#1");
4775 emitcode("","!tlabeldef", lbl->key+100);
4776 if (AOP_TYPE(result) == AOP_ACC)
4778 D(emitcode(";", "ACC special case."););
4779 /* We know result is the only live aop, and
4780 * it's obviously not a DPTR2, so AP is available.
4782 emitcode("mov", "%s,acc", DP2_RESULT_REG);
4786 aopPut(AOP(result),"a",0);
4789 emitcode("pop","acc");
4790 lbl = newiTempLabel(NULL);
4791 emitcode("jnb","F0,!tlabel",lbl->key+100);
4792 emitcode("cpl","a");
4793 emitcode("addc","a,#0");
4794 emitcode("","!tlabeldef", lbl->key+100);
4795 aopPut(AOP(result),"a",1);
4796 emitcode("pop","acc");
4797 if (AOP_SIZE(result) >= 3) {
4798 lbl = newiTempLabel(NULL);
4799 emitcode("jnb","F0,!tlabel",lbl->key+100);
4800 emitcode("cpl","a");
4801 emitcode("addc","a,#0");
4802 emitcode("","!tlabeldef", lbl->key+100);
4803 aopPut(AOP(result),"a",2);
4805 emitcode("pop","acc");
4806 if (AOP_SIZE(result) >= 4) {
4807 lbl = newiTempLabel(NULL);
4808 emitcode("jnb","F0,!tlabel",lbl->key+100);
4809 emitcode("cpl","a");
4810 emitcode("addc","a,#0");
4811 emitcode("","!tlabeldef", lbl->key+100);
4812 aopPut(AOP(result),"a",3);
4814 if (AOP_TYPE(result) == AOP_ACC)
4816 /* We stashed the result away above. */
4817 emitcode("mov", "acc,%s", DP2_RESULT_REG);
4821 freeAsmop (result, NULL, ic, TRUE);
4823 /* restore EA bit in F1 */
4824 lbl = newiTempLabel(NULL);
4825 emitcode ("jnb","F1,!tlabel",lbl->key+100);
4826 emitcode ("setb","EA");
4827 emitcode("","!tlabeldef",lbl->key+100);
4831 /*-----------------------------------------------------------------*/
4832 /* genMult - generates code for multiplication */
4833 /*-----------------------------------------------------------------*/
4835 genMult (iCode * ic)
4837 operand *left = IC_LEFT (ic);
4838 operand *right = IC_RIGHT (ic);
4839 operand *result = IC_RESULT (ic);
4841 D (emitcode (";", "genMult "););
4843 /* assign the amsops */
4846 /* special cases first */
4848 if (AOP_TYPE (left) == AOP_CRY &&
4849 AOP_TYPE (right) == AOP_CRY)
4851 genMultbits (left, right, result, ic);
4855 /* if both are of size == 1 */
4856 if (AOP_SIZE (left) == 1 &&
4857 AOP_SIZE (right) == 1)
4859 genMultOneByte (left, right, result, ic);
4863 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4864 /* use the ds390 ARITHMETIC accel UNIT */
4865 genMultTwoByte (left, right, result, ic);
4868 /* should have been converted to function call */
4872 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4873 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4874 freeAsmop (result, NULL, ic, TRUE);
4877 /*-----------------------------------------------------------------*/
4878 /* genDivbits :- division of bits */
4879 /*-----------------------------------------------------------------*/
4881 genDivbits (operand * left,
4889 /* the result must be bit */
4890 LOAD_AB_FOR_DIV (left, right, l);
4891 emitcode ("div", "ab");
4892 emitcode ("rrc", "a");
4893 aopOp(result, ic, TRUE, FALSE);
4895 aopPut (AOP (result), "c", 0);
4898 /*-----------------------------------------------------------------*/
4899 /* genDivOneByte : 8 bit division */
4900 /*-----------------------------------------------------------------*/
4902 genDivOneByte (operand * left,
4907 sym_link *opetype = operandType (result);
4913 /* signed or unsigned */
4914 if (SPEC_USIGN (opetype))
4916 /* unsigned is easy */
4917 LOAD_AB_FOR_DIV (left, right, l);
4918 emitcode ("div", "ab");
4921 aopOp(result, ic, TRUE, FALSE);
4922 aopPut (AOP (result), "a", 0);
4925 size = AOP_SIZE (result) - 1;
4929 aopPut (AOP (result), zero, offset++);
4934 /* signed is a little bit more difficult */
4936 /* save the signs of the operands */
4937 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4938 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4939 emitcode ("push", "acc"); /* save it on the stack */
4941 /* now sign adjust for both left & right */
4942 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4943 lbl = newiTempLabel (NULL);
4944 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4945 emitcode ("cpl", "a");
4946 emitcode ("inc", "a");
4947 emitcode ("", "!tlabeldef", (lbl->key + 100));
4948 emitcode ("mov", "b,a");
4950 /* sign adjust left side */
4951 MOVA( aopGet (AOP (left), 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));
4959 /* now the division */
4960 emitcode ("nop", "; workaround for DS80C390 div bug.");
4961 emitcode ("div", "ab");
4962 /* we are interested in the lower order
4964 emitcode ("mov", "b,a");
4965 lbl = newiTempLabel (NULL);
4966 emitcode ("pop", "acc");
4967 /* if there was an over flow we don't
4968 adjust the sign of the result */
4969 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4970 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4972 emitcode ("clr", "a");
4973 emitcode ("subb", "a,b");
4974 emitcode ("mov", "b,a");
4975 emitcode ("", "!tlabeldef", (lbl->key + 100));
4977 /* now we are done */
4978 _G.accInUse++; _G.bInUse++;
4979 aopOp(result, ic, TRUE, FALSE);
4981 aopPut (AOP (result), "b", 0);
4983 size = AOP_SIZE (result) - 1;
4987 emitcode ("mov", "c,b.7");
4988 emitcode ("subb", "a,acc");
4992 aopPut (AOP (result), "a", offset++);
4994 _G.accInUse--; _G.bInUse--;
4998 /*-----------------------------------------------------------------*/
4999 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
5000 /*-----------------------------------------------------------------*/
5001 static void genDivTwoByte (operand *left, operand *right,
5002 operand *result, iCode *ic)
5004 sym_link *retype = getSpec(operandType(right));
5005 sym_link *letype = getSpec(operandType(left));
5006 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5009 /* save EA bit in F1 */
5010 lbl = newiTempLabel(NULL);
5011 emitcode ("setb","F1");
5012 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5013 emitcode ("clr","F1");
5014 emitcode("","!tlabeldef",lbl->key+100);
5016 /* load up MA with left */
5018 emitcode("clr","F0");
5019 lbl = newiTempLabel(NULL);
5020 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5021 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5022 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5023 emitcode ("xch", "a,b");
5024 emitcode ("cpl","a");
5025 emitcode ("add", "a,#1");
5026 emitcode ("xch", "a,b");
5027 emitcode ("cpl", "a"); // msb
5028 emitcode ("addc","a,#0");
5029 emitcode ("setb","F0");
5030 emitcode ("","!tlabeldef",lbl->key+100);
5031 emitcode ("mov","ma,b");
5032 emitcode ("mov","ma,a");
5034 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5035 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5038 /* load up MB with right */
5040 if (AOP_TYPE(right) == AOP_LIT) {
5041 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5043 lbl = newiTempLabel(NULL);
5044 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5045 emitcode("setb","F0");
5046 emitcode ("","!tlabeldef",lbl->key+100);
5049 emitcode ("mov","mb,#!constbyte",val & 0xff);
5050 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5052 lbl = newiTempLabel(NULL);
5053 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5054 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5055 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5056 emitcode ("xch", "a,b");
5057 emitcode ("cpl","a");
5058 emitcode ("add", "a,#1");
5059 emitcode ("xch", "a,b");
5060 emitcode ("cpl", "a"); // msb
5061 emitcode ("addc", "a,#0");
5062 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5063 emitcode ("setb","F0");
5064 emitcode ("","!tlabeldef",lbl->key+100);
5065 emitcode ("mov","mb,b");
5066 emitcode ("mov","mb,a");
5069 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5070 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5073 /* wait for multiplication to finish */
5074 lbl = newiTempLabel(NULL);
5075 emitcode("","!tlabeldef", lbl->key+100);
5076 emitcode("mov","a,mcnt1");
5077 emitcode("anl","a,#!constbyte",0x80);
5078 emitcode("jnz","!tlabel",lbl->key+100);
5080 freeAsmop (left, NULL, ic, TRUE);
5081 freeAsmop (right, NULL, ic,TRUE);
5082 aopOp(result, ic, TRUE, FALSE);
5084 /* if unsigned then simple */
5086 aopPut(AOP(result),"ma",1);
5087 aopPut(AOP(result),"ma",0);
5089 emitcode("push","ma");
5091 /* negate result if needed */
5092 lbl = newiTempLabel(NULL);
5093 emitcode("jnb","F0,!tlabel",lbl->key+100);
5094 emitcode("cpl","a");
5095 emitcode("add","a,#1");
5096 emitcode("","!tlabeldef", lbl->key+100);
5097 aopPut(AOP(result),"a",0);
5098 emitcode("pop","acc");
5099 lbl = newiTempLabel(NULL);
5100 emitcode("jnb","F0,!tlabel",lbl->key+100);
5101 emitcode("cpl","a");
5102 emitcode("addc","a,#0");
5103 emitcode("","!tlabeldef", lbl->key+100);
5104 aopPut(AOP(result),"a",1);
5106 freeAsmop (result, NULL, ic, TRUE);
5107 /* restore EA bit in F1 */
5108 lbl = newiTempLabel(NULL);
5109 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5110 emitcode ("setb","EA");
5111 emitcode("","!tlabeldef",lbl->key+100);
5115 /*-----------------------------------------------------------------*/
5116 /* genDiv - generates code for division */
5117 /*-----------------------------------------------------------------*/
5121 operand *left = IC_LEFT (ic);
5122 operand *right = IC_RIGHT (ic);
5123 operand *result = IC_RESULT (ic);
5125 D (emitcode (";", "genDiv "););
5127 /* assign the amsops */
5130 /* special cases first */
5132 if (AOP_TYPE (left) == AOP_CRY &&
5133 AOP_TYPE (right) == AOP_CRY)
5135 genDivbits (left, right, result, ic);
5139 /* if both are of size == 1 */
5140 if (AOP_SIZE (left) == 1 &&
5141 AOP_SIZE (right) == 1)
5143 genDivOneByte (left, right, result, ic);
5147 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5148 /* use the ds390 ARITHMETIC accel UNIT */
5149 genDivTwoByte (left, right, result, ic);
5152 /* should have been converted to function call */
5155 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5156 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5157 freeAsmop (result, NULL, ic, TRUE);
5160 /*-----------------------------------------------------------------*/
5161 /* genModbits :- modulus of bits */
5162 /*-----------------------------------------------------------------*/
5164 genModbits (operand * left,
5172 /* the result must be bit */
5173 LOAD_AB_FOR_DIV (left, right, l);
5174 emitcode ("div", "ab");
5175 emitcode ("mov", "a,b");
5176 emitcode ("rrc", "a");
5177 aopOp(result, ic, TRUE, FALSE);
5178 aopPut (AOP (result), "c", 0);
5181 /*-----------------------------------------------------------------*/
5182 /* genModOneByte : 8 bit modulus */
5183 /*-----------------------------------------------------------------*/
5185 genModOneByte (operand * left,
5190 sym_link *opetype = operandType (result);
5194 /* signed or unsigned */
5195 if (SPEC_USIGN (opetype))
5197 /* unsigned is easy */
5198 LOAD_AB_FOR_DIV (left, right, l);
5199 emitcode ("div", "ab");
5200 aopOp(result, ic, TRUE, FALSE);
5201 aopPut (AOP (result), "b", 0);
5205 /* signed is a little bit more difficult */
5207 /* save the signs of the operands */
5208 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5210 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
5211 emitcode ("push", "acc"); /* save it on the stack */
5213 /* now sign adjust for both left & right */
5214 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5216 lbl = newiTempLabel (NULL);
5217 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5218 emitcode ("cpl", "a");
5219 emitcode ("inc", "a");
5220 emitcode ("", "!tlabeldef", (lbl->key + 100));
5221 emitcode ("mov", "b,a");
5223 /* sign adjust left side */
5224 MOVA (aopGet (AOP (left), 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));
5232 /* now the multiplication */
5233 emitcode ("nop", "; workaround for DS80C390 div bug.");
5234 emitcode ("div", "ab");
5235 /* we are interested in the lower order
5237 lbl = newiTempLabel (NULL);
5238 emitcode ("pop", "acc");
5239 /* if there was an over flow we don't
5240 adjust the sign of the result */
5241 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
5242 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5244 emitcode ("clr", "a");
5245 emitcode ("subb", "a,b");
5246 emitcode ("mov", "b,a");
5247 emitcode ("", "!tlabeldef", (lbl->key + 100));
5250 /* now we are done */
5251 aopOp(result, ic, TRUE, FALSE);
5252 aopPut (AOP (result), "b", 0);
5257 /*-----------------------------------------------------------------*/
5258 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
5259 /*-----------------------------------------------------------------*/
5260 static void genModTwoByte (operand *left, operand *right,
5261 operand *result, iCode *ic)
5263 sym_link *retype = getSpec(operandType(right));
5264 sym_link *letype = getSpec(operandType(left));
5265 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5268 /* load up MA with left */
5269 /* save EA bit in F1 */
5270 lbl = newiTempLabel(NULL);
5271 emitcode ("setb","F1");
5272 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5273 emitcode ("clr","F1");
5274 emitcode("","!tlabeldef",lbl->key+100);
5277 lbl = newiTempLabel(NULL);
5278 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5279 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5280 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5281 emitcode ("xch", "a,b");
5282 emitcode ("cpl","a");
5283 emitcode ("add", "a,#1");
5284 emitcode ("xch", "a,b");
5285 emitcode ("cpl", "a"); // msb
5286 emitcode ("addc","a,#0");
5287 emitcode ("","!tlabeldef",lbl->key+100);
5288 emitcode ("mov","ma,b");
5289 emitcode ("mov","ma,a");
5291 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5292 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5295 /* load up MB with right */
5297 if (AOP_TYPE(right) == AOP_LIT) {
5298 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5302 emitcode ("mov","mb,#!constbyte",val & 0xff);
5303 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5305 lbl = newiTempLabel(NULL);
5306 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5307 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5308 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5309 emitcode ("xch", "a,b");
5310 emitcode ("cpl","a");
5311 emitcode ("add", "a,#1");
5312 emitcode ("xch", "a,b");
5313 emitcode ("cpl", "a"); // msb
5314 emitcode ("addc", "a,#0");
5315 emitcode ("","!tlabeldef",lbl->key+100);
5316 emitcode ("mov","mb,b");
5317 emitcode ("mov","mb,a");
5320 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5321 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5324 /* wait for multiplication to finish */
5325 lbl = newiTempLabel(NULL);
5326 emitcode("","!tlabeldef", lbl->key+100);
5327 emitcode("mov","a,mcnt1");
5328 emitcode("anl","a,#!constbyte",0x80);
5329 emitcode("jnz","!tlabel",lbl->key+100);
5331 freeAsmop (left, NULL, ic, TRUE);
5332 freeAsmop (right, NULL, ic,TRUE);
5333 aopOp(result, ic, TRUE, FALSE);
5335 aopPut(AOP(result),"mb",1);
5336 aopPut(AOP(result),"mb",0);
5337 freeAsmop (result, NULL, ic, TRUE);
5339 /* restore EA bit in F1 */
5340 lbl = newiTempLabel(NULL);
5341 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5342 emitcode ("setb","EA");
5343 emitcode("","!tlabeldef",lbl->key+100);
5347 /*-----------------------------------------------------------------*/
5348 /* genMod - generates code for division */
5349 /*-----------------------------------------------------------------*/
5353 operand *left = IC_LEFT (ic);
5354 operand *right = IC_RIGHT (ic);
5355 operand *result = IC_RESULT (ic);
5357 D (emitcode (";", "genMod "); );
5359 /* assign the amsops */
5362 /* special cases first */
5364 if (AOP_TYPE (left) == AOP_CRY &&
5365 AOP_TYPE (right) == AOP_CRY)
5367 genModbits (left, right, result, ic);
5371 /* if both are of size == 1 */
5372 if (AOP_SIZE (left) == 1 &&
5373 AOP_SIZE (right) == 1)
5375 genModOneByte (left, right, result, ic);
5379 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5380 /* use the ds390 ARITHMETIC accel UNIT */
5381 genModTwoByte (left, right, result, ic);
5385 /* should have been converted to function call */
5389 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5390 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5391 freeAsmop (result, NULL, ic, TRUE);
5394 /*-----------------------------------------------------------------*/
5395 /* genIfxJump :- will create a jump depending on the ifx */
5396 /*-----------------------------------------------------------------*/
5398 genIfxJump (iCode * ic, char *jval)
5401 symbol *tlbl = newiTempLabel (NULL);
5404 D (emitcode (";", "genIfxJump"););
5406 /* if true label then we jump if condition
5410 jlbl = IC_TRUE (ic);
5411 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5412 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5416 /* false label is present */
5417 jlbl = IC_FALSE (ic);
5418 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5419 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5421 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5422 emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5424 emitcode (inst, "!tlabel", tlbl->key + 100);
5425 emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5426 emitcode ("", "!tlabeldef", tlbl->key + 100);
5428 /* mark the icode as generated */
5432 /*-----------------------------------------------------------------*/
5433 /* genCmp :- greater or less than comparison */
5434 /*-----------------------------------------------------------------*/
5436 genCmp (operand * left, operand * right,
5437 iCode * ic, iCode * ifx, int sign)
5439 int size, offset = 0;
5440 unsigned long lit = 0L;
5443 D (emitcode (";", "genCmp"););
5445 result = IC_RESULT (ic);
5447 /* if left & right are bit variables */
5448 if (AOP_TYPE (left) == AOP_CRY &&
5449 AOP_TYPE (right) == AOP_CRY)
5451 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5452 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5456 /* subtract right from left if at the
5457 end the carry flag is set then we know that
5458 left is greater than right */
5459 size = max (AOP_SIZE (left), AOP_SIZE (right));
5461 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5462 if ((size == 1) && !sign
5463 && (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5465 symbol *lbl = newiTempLabel (NULL);
5466 emitcode ("cjne", "%s,%s,!tlabel",
5467 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
5468 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5470 emitcode ("", "!tlabeldef", lbl->key + 100);
5474 if (AOP_TYPE (right) == AOP_LIT)
5476 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5477 /* optimize if(x < 0) or if(x >= 0) */
5486 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
5488 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5489 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5491 aopOp (result, ic, FALSE, FALSE);
5493 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5495 freeAsmop (result, NULL, ic, TRUE);
5496 genIfxJump (ifx, "acc.7");
5501 emitcode ("rlc", "a");
5503 goto release_freedLR;
5511 // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5512 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5513 // emitcode (";", "genCmp #2");
5514 if (sign && (size == 0))
5516 // emitcode (";", "genCmp #3");
5517 emitcode ("xrl", "a,#!constbyte",0x80);
5518 if (AOP_TYPE (right) == AOP_LIT)
5520 unsigned long lit = (unsigned long)
5521 floatFromVal (AOP (right)->aopu.aop_lit);
5522 // emitcode (";", "genCmp #3.1");
5523 emitcode ("subb", "a,#!constbyte",
5524 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5528 // emitcode (";", "genCmp #3.2");
5530 MOVB(aopGet (AOP (right), offset++, FALSE, FALSE, "b"));
5531 saveAccWarn = DEFAULT_ACC_WARNING;
5532 emitcode ("xrl", "b,#!constbyte",0x80);
5533 emitcode ("subb", "a,b");
5540 // emitcode (";", "genCmp #4");
5542 s = aopGet (AOP (right), offset++, FALSE, FALSE, "b");
5543 saveAccWarn = DEFAULT_ACC_WARNING;
5545 emitcode ("subb", "a,%s", s);
5552 /* Don't need the left & right operands any more; do need the result. */
5553 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5554 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5556 aopOp (result, ic, FALSE, FALSE);
5560 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5566 /* if the result is used in the next
5567 ifx conditional branch then generate
5568 code a little differently */
5571 genIfxJump (ifx, "c");
5577 /* leave the result in acc */
5579 freeAsmop (result, NULL, ic, TRUE);
5582 /*-----------------------------------------------------------------*/
5583 /* genCmpGt :- greater than comparison */
5584 /*-----------------------------------------------------------------*/
5586 genCmpGt (iCode * ic, iCode * ifx)
5588 operand *left, *right;
5589 sym_link *letype, *retype;
5592 D (emitcode (";", "genCmpGt ");
5595 left = IC_LEFT (ic);
5596 right = IC_RIGHT (ic);
5598 letype = getSpec (operandType (left));
5599 retype = getSpec (operandType (right));
5600 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5602 /* assign the left & right amsops */
5605 genCmp (right, left, ic, ifx, sign);
5608 /*-----------------------------------------------------------------*/
5609 /* genCmpLt - less than comparisons */
5610 /*-----------------------------------------------------------------*/
5612 genCmpLt (iCode * ic, iCode * ifx)
5614 operand *left, *right;
5615 sym_link *letype, *retype;
5618 D (emitcode (";", "genCmpLt "););
5620 left = IC_LEFT (ic);
5621 right = IC_RIGHT (ic);
5623 letype = getSpec (operandType (left));
5624 retype = getSpec (operandType (right));
5625 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5627 /* assign the left & right amsops */
5630 genCmp (left, right, ic, ifx, sign);
5633 /*-----------------------------------------------------------------*/
5634 /* gencjneshort - compare and jump if not equal */
5635 /*-----------------------------------------------------------------*/
5637 gencjneshort (operand * left, operand * right, symbol * lbl)
5639 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5641 unsigned long lit = 0L;
5643 D (emitcode (";", "gencjneshort");
5646 /* if the left side is a literal or
5647 if the right is in a pointer register and left
5649 if ((AOP_TYPE (left) == AOP_LIT) ||
5650 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5657 if (AOP_TYPE (right) == AOP_LIT)
5658 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5660 if (opIsGptr (left) || opIsGptr (right))
5662 /* We are comparing a generic pointer to something.
5663 * Exclude the generic type byte from the comparison.
5666 D (emitcode (";", "cjneshort: generic ptr special case."););
5670 /* if the right side is a literal then anything goes */
5671 if (AOP_TYPE (right) == AOP_LIT &&
5672 AOP_TYPE (left) != AOP_DIR)
5676 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5677 emitcode ("cjne", "a,%s,!tlabel",
5678 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5684 /* if the right side is in a register or in direct space or
5685 if the left is a pointer register & right is not */
5686 else if (AOP_TYPE (right) == AOP_REG ||
5687 AOP_TYPE (right) == AOP_DIR ||
5688 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5689 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5693 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5694 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5695 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5696 emitcode ("jnz", "!tlabel", lbl->key + 100);
5698 emitcode ("cjne", "a,%s,!tlabel",
5699 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
5706 /* right is a pointer reg need both a & b */
5709 MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5710 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
5711 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5717 /*-----------------------------------------------------------------*/
5718 /* gencjne - compare and jump if not equal */
5719 /*-----------------------------------------------------------------*/
5721 gencjne (operand * left, operand * right, symbol * lbl)
5723 symbol *tlbl = newiTempLabel (NULL);
5725 D (emitcode (";", "gencjne");
5728 gencjneshort (left, right, lbl);
5730 emitcode ("mov", "a,%s", one);
5731 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5732 emitcode ("", "!tlabeldef", lbl->key + 100);
5733 emitcode ("clr", "a");
5734 emitcode ("", "!tlabeldef", tlbl->key + 100);
5737 /*-----------------------------------------------------------------*/
5738 /* genCmpEq - generates code for equal to */
5739 /*-----------------------------------------------------------------*/
5741 genCmpEq (iCode * ic, iCode * ifx)
5743 operand *left, *right, *result;
5745 D (emitcode (";", "genCmpEq ");
5749 AOP_SET_LOCALS (ic);
5751 /* if literal, literal on the right or
5752 if the right is in a pointer register and left
5754 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5755 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5757 operand *t = IC_RIGHT (ic);
5758 IC_RIGHT (ic) = IC_LEFT (ic);
5762 if (ifx && /* !AOP_SIZE(result) */
5763 OP_SYMBOL (result) &&
5764 OP_SYMBOL (result)->regType == REG_CND)
5767 /* if they are both bit variables */
5768 if (AOP_TYPE (left) == AOP_CRY &&
5769 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5771 if (AOP_TYPE (right) == AOP_LIT)
5773 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5776 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5777 emitcode ("cpl", "c");
5781 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5785 emitcode ("clr", "c");
5787 /* AOP_TYPE(right) == AOP_CRY */
5791 symbol *lbl = newiTempLabel (NULL);
5792 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5793 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5794 emitcode ("cpl", "c");
5795 emitcode ("", "!tlabeldef", (lbl->key + 100));
5797 /* if true label then we jump if condition
5799 tlbl = newiTempLabel (NULL);
5802 emitcode ("jnc", "!tlabel", tlbl->key + 100);
5803 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5807 emitcode ("jc", "!tlabel", tlbl->key + 100);
5808 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5810 emitcode ("", "!tlabeldef", tlbl->key + 100);
5814 tlbl = newiTempLabel (NULL);
5815 gencjneshort (left, right, tlbl);
5818 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5819 emitcode ("", "!tlabeldef", tlbl->key + 100);
5823 symbol *lbl = newiTempLabel (NULL);
5824 emitcode ("sjmp", "!tlabel", lbl->key + 100);
5825 emitcode ("", "!tlabeldef", tlbl->key + 100);
5826 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5827 emitcode ("", "!tlabeldef", lbl->key + 100);
5830 /* mark the icode as generated */
5833 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5834 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5838 /* if they are both bit variables */
5839 if (AOP_TYPE (left) == AOP_CRY &&
5840 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5842 if (AOP_TYPE (right) == AOP_LIT)
5844 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5847 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5848 emitcode ("cpl", "c");
5852 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5856 emitcode ("clr", "c");
5858 /* AOP_TYPE(right) == AOP_CRY */
5862 symbol *lbl = newiTempLabel (NULL);
5863 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5864 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5865 emitcode ("cpl", "c");
5866 emitcode ("", "!tlabeldef", (lbl->key + 100));
5869 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5870 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5872 aopOp (result, ic, TRUE, FALSE);
5875 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5882 genIfxJump (ifx, "c");
5885 /* if the result is used in an arithmetic operation
5886 then put the result in place */
5891 gencjne (left, right, newiTempLabel (NULL));
5893 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5894 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5896 aopOp (result, ic, TRUE, FALSE);
5898 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5900 aopPut (AOP (result), "a", 0);
5905 genIfxJump (ifx, "a");
5908 /* if the result is used in an arithmetic operation
5909 then put the result in place */
5910 if (AOP_TYPE (result) != AOP_CRY)
5912 /* leave the result in acc */
5916 freeAsmop (result, NULL, ic, TRUE);
5919 /*-----------------------------------------------------------------*/
5920 /* ifxForOp - returns the icode containing the ifx for operand */
5921 /*-----------------------------------------------------------------*/
5923 ifxForOp (operand * op, iCode * ic)
5925 /* if true symbol then needs to be assigned */
5926 if (IS_TRUE_SYMOP (op))
5929 /* if this has register type condition and
5930 the next instruction is ifx with the same operand
5931 and live to of the operand is upto the ifx only then */
5933 ic->next->op == IFX &&
5934 IC_COND (ic->next)->key == op->key &&
5935 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5940 /*-----------------------------------------------------------------*/
5941 /* hasInc - operand is incremented before any other use */
5942 /*-----------------------------------------------------------------*/
5944 hasInc (operand *op, iCode *ic, int osize)
5946 sym_link *type = operandType(op);
5947 sym_link *retype = getSpec (type);
5948 iCode *lic = ic->next;
5951 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5952 if (!IS_SYMOP(op)) return NULL;
5954 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5955 if (IS_AGGREGATE(type->next)) return NULL;
5956 if (osize != (isize = getSize(type->next))) return NULL;
5959 /* if operand of the form op = op + <sizeof *op> */
5960 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5961 isOperandEqual(IC_RESULT(lic),op) &&
5962 isOperandLiteral(IC_RIGHT(lic)) &&
5963 operandLitValue(IC_RIGHT(lic)) == isize) {
5966 /* if the operand used or deffed */
5967 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5970 /* if GOTO or IFX */
5971 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5977 /*-----------------------------------------------------------------*/
5978 /* genAndOp - for && operation */
5979 /*-----------------------------------------------------------------*/
5981 genAndOp (iCode * ic)
5983 operand *left, *right, *result;
5986 D (emitcode (";", "genAndOp "););
5988 /* note here that && operations that are in an
5989 if statement are taken away by backPatchLabels
5990 only those used in arthmetic operations remain */
5992 AOP_SET_LOCALS (ic);
5994 /* if both are bit variables */
5995 if (AOP_TYPE (left) == AOP_CRY &&
5996 AOP_TYPE (right) == AOP_CRY)
5998 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5999 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6000 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6001 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6003 aopOp (result,ic,FALSE, FALSE);
6008 tlbl = newiTempLabel (NULL);
6010 emitcode ("jz", "!tlabel", tlbl->key + 100);
6012 emitcode ("", "!tlabeldef", tlbl->key + 100);
6013 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6014 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6016 aopOp (result,ic,FALSE, FALSE);
6019 freeAsmop (result, NULL, ic, TRUE);
6023 /*-----------------------------------------------------------------*/
6024 /* genOrOp - for || operation */
6025 /*-----------------------------------------------------------------*/
6027 genOrOp (iCode * ic)
6029 operand *left, *right, *result;
6032 D (emitcode (";", "genOrOp "););
6034 /* note here that || operations that are in an
6035 if statement are taken away by backPatchLabels
6036 only those used in arthmetic operations remain */
6038 AOP_SET_LOCALS (ic);
6040 /* if both are bit variables */
6041 if (AOP_TYPE (left) == AOP_CRY &&
6042 AOP_TYPE (right) == AOP_CRY)
6044 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6045 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6046 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6047 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6049 aopOp (result,ic,FALSE, FALSE);
6055 tlbl = newiTempLabel (NULL);
6057 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6059 emitcode ("", "!tlabeldef", tlbl->key + 100);
6060 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6061 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6063 aopOp (result,ic,FALSE, FALSE);
6068 freeAsmop (result, NULL, ic, TRUE);
6071 /*-----------------------------------------------------------------*/
6072 /* isLiteralBit - test if lit == 2^n */
6073 /*-----------------------------------------------------------------*/
6075 isLiteralBit (unsigned long lit)
6077 unsigned long pw[32] =
6078 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6079 0x100L, 0x200L, 0x400L, 0x800L,
6080 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6081 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6082 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6083 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6084 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6087 for (idx = 0; idx < 32; idx++)
6093 /*-----------------------------------------------------------------*/
6094 /* continueIfTrue - */
6095 /*-----------------------------------------------------------------*/
6097 continueIfTrue (iCode * ic)
6100 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6104 /*-----------------------------------------------------------------*/
6106 /*-----------------------------------------------------------------*/
6108 jumpIfTrue (iCode * ic)
6111 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6115 /*-----------------------------------------------------------------*/
6116 /* jmpTrueOrFalse - */
6117 /*-----------------------------------------------------------------*/
6119 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6121 // ugly but optimized by peephole
6124 symbol *nlbl = newiTempLabel (NULL);
6125 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6126 emitcode ("", "!tlabeldef", tlbl->key + 100);
6127 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6128 emitcode ("", "!tlabeldef", nlbl->key + 100);
6132 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6133 emitcode ("", "!tlabeldef", tlbl->key + 100);
6138 // Generate code to perform a bit-wise logic operation
6139 // on two operands in far space (assumed to already have been
6140 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6141 // in far space. This requires pushing the result on the stack
6142 // then popping it into the result.
6144 genFarFarLogicOp(iCode *ic, char *logicOp)
6146 int size, resultSize, compSize;
6150 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6151 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
6152 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6154 _startLazyDPSEvaluation();
6155 for (size = compSize; (size--); offset++)
6157 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6158 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6159 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6161 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6162 emitcode ("push", "acc");
6164 _endLazyDPSEvaluation();
6166 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6167 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6168 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6170 resultSize = AOP_SIZE(IC_RESULT(ic));
6172 ADJUST_PUSHED_RESULT(compSize, resultSize);
6174 _startLazyDPSEvaluation();
6177 emitcode ("pop", "acc");
6178 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6180 _endLazyDPSEvaluation();
6181 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6185 /*-----------------------------------------------------------------*/
6186 /* genAnd - code for and */
6187 /*-----------------------------------------------------------------*/
6189 genAnd (iCode * ic, iCode * ifx)
6191 operand *left, *right, *result;
6192 int size, offset = 0;
6193 unsigned long lit = 0L;
6198 D (emitcode (";", "genAnd "););
6200 AOP_OP_3_NOFATAL (ic, pushResult);
6201 AOP_SET_LOCALS (ic);
6205 genFarFarLogicOp(ic, "anl");
6210 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6212 AOP_TYPE (left), AOP_TYPE (right));
6213 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6215 AOP_SIZE (left), AOP_SIZE (right));
6218 /* if left is a literal & right is not then exchange them */
6219 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6220 #ifdef LOGIC_OPS_BROKEN
6221 || AOP_NEEDSACC (left)
6225 operand *tmp = right;
6230 /* if result = right then exchange them */
6231 if (sameRegs (AOP (result), AOP (right)))
6233 operand *tmp = right;
6238 /* if right is bit then exchange them */
6239 if (AOP_TYPE (right) == AOP_CRY &&
6240 AOP_TYPE (left) != AOP_CRY)
6242 operand *tmp = right;
6246 if (AOP_TYPE (right) == AOP_LIT)
6247 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6249 size = AOP_SIZE (result);
6252 // result = bit & yy;
6253 if (AOP_TYPE (left) == AOP_CRY)
6255 // c = bit & literal;
6256 if (AOP_TYPE (right) == AOP_LIT)
6260 if (size && sameRegs (AOP (result), AOP (left)))
6263 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6268 if (size && (AOP_TYPE (result) == AOP_CRY))
6270 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6273 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6278 emitcode ("clr", "c");
6283 if (AOP_TYPE (right) == AOP_CRY)
6286 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6287 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6292 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6294 emitcode ("rrc", "a");
6295 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6303 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6304 genIfxJump (ifx, "c");
6308 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6309 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6310 if ((AOP_TYPE (right) == AOP_LIT) &&
6311 (AOP_TYPE (result) == AOP_CRY) &&
6312 (AOP_TYPE (left) != AOP_CRY))
6314 int posbit = isLiteralBit (lit);
6319 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6322 emitcode ("mov", "c,acc.%d", posbit & 0x07);
6328 SNPRINTF (buff, sizeof(buff),
6329 "acc.%d", posbit & 0x07);
6330 genIfxJump (ifx, buff);
6334 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6341 symbol *tlbl = newiTempLabel (NULL);
6342 int sizel = AOP_SIZE (left);
6344 emitcode ("setb", "c");
6347 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6349 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6351 if ((posbit = isLiteralBit (bytelit)) != 0)
6352 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6355 if (bytelit != 0x0FFL)
6356 emitcode ("anl", "a,%s",
6357 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6358 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6363 // bit = left & literal
6366 emitcode ("clr", "c");
6367 emitcode ("", "!tlabeldef", tlbl->key + 100);
6369 // if(left & literal)
6373 jmpTrueOrFalse (ifx, tlbl);
6381 /* if left is same as result */
6382 if (sameRegs (AOP (result), AOP (left)))
6384 for (; size--; offset++)
6386 if (AOP_TYPE (right) == AOP_LIT)
6388 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6390 else if (bytelit == 0)
6391 aopPut (AOP (result), zero, offset);
6392 else if (IS_AOP_PREG (result))
6394 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6395 emitcode ("anl", "a,%s",
6396 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6397 aopPut (AOP (result), "a", offset);
6400 emitcode ("anl", "%s,%s",
6401 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6402 aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6406 if (AOP_TYPE (left) == AOP_ACC)
6407 emitcode ("anl", "a,%s",
6408 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6411 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6412 if (IS_AOP_PREG (result))
6414 emitcode ("anl", "a,%s",
6415 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6416 aopPut (AOP (result), "a", offset);
6419 emitcode ("anl", "%s,a",
6420 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6427 // left & result in different registers
6428 if (AOP_TYPE (result) == AOP_CRY)
6431 // if(size), result in bit
6432 // if(!size && ifx), conditional oper: if(left & right)
6433 symbol *tlbl = newiTempLabel (NULL);
6434 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6436 emitcode ("setb", "c");
6439 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6440 emitcode ("anl", "a,%s",
6441 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6443 if (AOP_TYPE(left)==AOP_ACC) {
6444 emitcode("mov", "b,a");
6445 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6446 emitcode("anl", "a,b");
6448 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6449 emitcode ("anl", "a,%s",
6450 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6453 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6459 emitcode ("", "!tlabeldef", tlbl->key + 100);
6463 jmpTrueOrFalse (ifx, tlbl);
6467 for (; (size--); offset++)
6470 // result = left & right
6471 if (AOP_TYPE (right) == AOP_LIT)
6473 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6475 aopPut (AOP (result),
6476 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6480 else if (bytelit == 0)
6482 aopPut (AOP (result), zero, offset);
6485 D (emitcode (";", "better literal AND."););
6486 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6487 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6488 FALSE, FALSE, DP2_RESULT_REG));
6493 // faster than result <- left, anl result,right
6494 // and better if result is SFR
6495 if (AOP_TYPE (left) == AOP_ACC)
6497 emitcode ("anl", "a,%s",
6498 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6502 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6503 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6505 emitcode("mov", "b,a");
6509 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6510 emitcode ("anl", "a,%s", rOp);
6513 aopPut (AOP (result), "a", offset);
6519 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6520 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6521 freeAsmop (result, NULL, ic, TRUE);
6525 /*-----------------------------------------------------------------*/
6526 /* genOr - code for or */
6527 /*-----------------------------------------------------------------*/
6529 genOr (iCode * ic, iCode * ifx)
6531 operand *left, *right, *result;
6532 int size, offset = 0;
6533 unsigned long lit = 0L;
6536 D (emitcode (";", "genOr "););
6538 AOP_OP_3_NOFATAL (ic, pushResult);
6539 AOP_SET_LOCALS (ic);
6543 genFarFarLogicOp(ic, "orl");
6549 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6551 AOP_TYPE (left), AOP_TYPE (right));
6552 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6554 AOP_SIZE (left), AOP_SIZE (right));
6557 /* if left is a literal & right is not then exchange them */
6558 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6559 #ifdef LOGIC_OPS_BROKEN
6560 || AOP_NEEDSACC (left) // I think this is a net loss now.
6564 operand *tmp = right;
6569 /* if result = right then exchange them */
6570 if (sameRegs (AOP (result), AOP (right)))
6572 operand *tmp = right;
6577 /* if right is bit then exchange them */
6578 if (AOP_TYPE (right) == AOP_CRY &&
6579 AOP_TYPE (left) != AOP_CRY)
6581 operand *tmp = right;
6585 if (AOP_TYPE (right) == AOP_LIT)
6586 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6588 size = AOP_SIZE (result);
6592 if (AOP_TYPE (left) == AOP_CRY)
6594 if (AOP_TYPE (right) == AOP_LIT)
6596 // c = bit & literal;
6599 // lit != 0 => result = 1
6600 if (AOP_TYPE (result) == AOP_CRY)
6603 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6605 continueIfTrue (ifx);
6608 emitcode ("setb", "c");
6612 // lit == 0 => result = left
6613 if (size && sameRegs (AOP (result), AOP (left)))
6615 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6620 if (AOP_TYPE (right) == AOP_CRY)
6623 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6624 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6629 symbol *tlbl = newiTempLabel (NULL);
6630 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6631 emitcode ("setb", "c");
6632 emitcode ("jb", "%s,!tlabel",
6633 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6635 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6636 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6638 jmpTrueOrFalse (ifx, tlbl);
6644 emitcode ("", "!tlabeldef", tlbl->key + 100);
6653 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6654 genIfxJump (ifx, "c");
6658 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6659 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6660 if ((AOP_TYPE (right) == AOP_LIT) &&
6661 (AOP_TYPE (result) == AOP_CRY) &&
6662 (AOP_TYPE (left) != AOP_CRY))
6668 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6670 continueIfTrue (ifx);
6675 // lit = 0, result = boolean(left)
6677 emitcode ("setb", "c");
6681 symbol *tlbl = newiTempLabel (NULL);
6682 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6684 emitcode ("", "!tlabeldef", tlbl->key + 100);
6688 genIfxJump (ifx, "a");
6696 /* if left is same as result */
6697 if (sameRegs (AOP (result), AOP (left)))
6699 for (; size--; offset++)
6701 if (AOP_TYPE (right) == AOP_LIT)
6703 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6709 if (IS_AOP_PREG (left))
6711 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6712 emitcode ("orl", "a,%s",
6713 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6714 aopPut (AOP (result), "a", offset);
6718 emitcode ("orl", "%s,%s",
6719 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6720 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6726 if (AOP_TYPE (left) == AOP_ACC)
6728 emitcode ("orl", "a,%s",
6729 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6733 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6734 if (IS_AOP_PREG (left))
6736 emitcode ("orl", "a,%s",
6737 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6738 aopPut (AOP (result), "a", offset);
6742 emitcode ("orl", "%s,a",
6743 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6751 // left & result in different registers
6752 if (AOP_TYPE (result) == AOP_CRY)
6755 // if(size), result in bit
6756 // if(!size && ifx), conditional oper: if(left | right)
6757 symbol *tlbl = newiTempLabel (NULL);
6758 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6760 emitcode ("setb", "c");
6763 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6764 emitcode ("orl", "a,%s",
6765 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6767 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6768 emitcode ("orl", "a,%s",
6769 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6771 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6777 emitcode ("", "!tlabeldef", tlbl->key + 100);
6781 jmpTrueOrFalse (ifx, tlbl);
6785 _startLazyDPSEvaluation();
6786 for (; (size--); offset++)
6789 // result = left & right
6790 if (AOP_TYPE (right) == AOP_LIT)
6792 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6794 aopPut (AOP (result),
6795 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6799 D (emitcode (";", "better literal OR."););
6800 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6801 emitcode ("orl", "a, %s",
6802 aopGet (AOP (right), offset,
6803 FALSE, FALSE, DP2_RESULT_REG));
6808 // faster than result <- left, anl result,right
6809 // and better if result is SFR
6810 if (AOP_TYPE (left) == AOP_ACC)
6812 emitcode ("orl", "a,%s",
6813 aopGet (AOP (right), offset,
6814 FALSE, FALSE, DP2_RESULT_REG));
6818 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6820 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6822 emitcode("mov", "b,a");
6826 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6827 emitcode ("orl", "a,%s", rOp);
6830 aopPut (AOP (result), "a", offset);
6832 _endLazyDPSEvaluation();
6837 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6838 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6839 freeAsmop (result, NULL, ic, TRUE);
6842 /*-----------------------------------------------------------------*/
6843 /* genXor - code for xclusive or */
6844 /*-----------------------------------------------------------------*/
6846 genXor (iCode * ic, iCode * ifx)
6848 operand *left, *right, *result;
6849 int size, offset = 0;
6850 unsigned long lit = 0L;
6853 D (emitcode (";", "genXor "););
6855 AOP_OP_3_NOFATAL (ic, pushResult);
6856 AOP_SET_LOCALS (ic);
6860 genFarFarLogicOp(ic, "xrl");
6865 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6867 AOP_TYPE (left), AOP_TYPE (right));
6868 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6870 AOP_SIZE (left), AOP_SIZE (right));
6873 /* if left is a literal & right is not ||
6874 if left needs acc & right does not */
6875 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6876 #ifdef LOGIC_OPS_BROKEN
6877 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6881 operand *tmp = right;
6886 /* if result = right then exchange them */
6887 if (sameRegs (AOP (result), AOP (right)))
6889 operand *tmp = right;
6894 /* if right is bit then exchange them */
6895 if (AOP_TYPE (right) == AOP_CRY &&
6896 AOP_TYPE (left) != AOP_CRY)
6898 operand *tmp = right;
6902 if (AOP_TYPE (right) == AOP_LIT)
6903 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6905 size = AOP_SIZE (result);
6909 if (AOP_TYPE (left) == AOP_CRY)
6911 if (AOP_TYPE (right) == AOP_LIT)
6913 // c = bit & literal;
6916 // lit>>1 != 0 => result = 1
6917 if (AOP_TYPE (result) == AOP_CRY)
6920 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6922 continueIfTrue (ifx);
6925 emitcode ("setb", "c");
6932 // lit == 0, result = left
6933 if (size && sameRegs (AOP (result), AOP (left)))
6935 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6939 // lit == 1, result = not(left)
6940 if (size && sameRegs (AOP (result), AOP (left)))
6942 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6947 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6948 emitcode ("cpl", "c");
6957 symbol *tlbl = newiTempLabel (NULL);
6958 if (AOP_TYPE (right) == AOP_CRY)
6961 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6965 int sizer = AOP_SIZE (right);
6967 // if val>>1 != 0, result = 1
6968 emitcode ("setb", "c");
6971 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
6973 // test the msb of the lsb
6974 emitcode ("anl", "a,#!constbyte",0xfe);
6975 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6979 emitcode ("rrc", "a");
6981 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6982 emitcode ("cpl", "c");
6983 emitcode ("", "!tlabeldef", (tlbl->key + 100));
6990 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6991 genIfxJump (ifx, "c");
6995 if (sameRegs (AOP (result), AOP (left)))
6997 /* if left is same as result */
6998 for (; size--; offset++)
7000 if (AOP_TYPE (right) == AOP_LIT)
7002 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7004 else if (IS_AOP_PREG (left))
7006 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7007 emitcode ("xrl", "a,%s",
7008 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7009 aopPut (AOP (result), "a", offset);
7012 emitcode ("xrl", "%s,%s",
7013 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
7014 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7018 if (AOP_TYPE (left) == AOP_ACC)
7019 emitcode ("xrl", "a,%s",
7020 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7023 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7024 if (IS_AOP_PREG (left))
7026 emitcode ("xrl", "a,%s",
7027 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7028 aopPut (AOP (result), "a", offset);
7031 emitcode ("xrl", "%s,a",
7032 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7039 // left & result in different registers
7040 if (AOP_TYPE (result) == AOP_CRY)
7043 // if(size), result in bit
7044 // if(!size && ifx), conditional oper: if(left ^ right)
7045 symbol *tlbl = newiTempLabel (NULL);
7046 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7049 emitcode ("setb", "c");
7052 if ((AOP_TYPE (right) == AOP_LIT) &&
7053 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7055 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7059 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7060 emitcode ("xrl", "a,%s",
7061 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7063 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7064 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7066 emitcode("mov", "b,a");
7070 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7071 emitcode ("xrl", "a,%s", rOp);
7074 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7080 emitcode ("", "!tlabeldef", tlbl->key + 100);
7084 jmpTrueOrFalse (ifx, tlbl);
7088 for (; (size--); offset++)
7091 // result = left & right
7092 if (AOP_TYPE (right) == AOP_LIT)
7094 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7096 aopPut (AOP (result),
7097 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7101 D (emitcode (";", "better literal XOR."););
7102 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7103 emitcode ("xrl", "a, %s",
7104 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7108 // faster than result <- left, anl result,right
7109 // and better if result is SFR
7110 if (AOP_TYPE (left) == AOP_ACC)
7112 emitcode ("xrl", "a,%s",
7113 aopGet (AOP (right), offset,
7114 FALSE, FALSE, DP2_RESULT_REG));
7118 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7119 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7121 emitcode("mov", "b,a");
7125 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7126 emitcode ("xrl", "a,%s", rOp);
7129 aopPut (AOP (result), "a", offset);
7136 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7137 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7138 freeAsmop (result, NULL, ic, TRUE);
7141 /*-----------------------------------------------------------------*/
7142 /* genInline - write the inline code out */
7143 /*-----------------------------------------------------------------*/
7145 genInline (iCode * ic)
7147 char *buffer, *bp, *bp1;
7149 D (emitcode (";", "genInline "); );
7151 _G.inLine += (!options.asmpeep);
7153 buffer = Safe_strdup(IC_INLINE(ic));
7157 /* emit each line as a code */
7182 /* emitcode("",buffer); */
7183 _G.inLine -= (!options.asmpeep);
7186 /*-----------------------------------------------------------------*/
7187 /* genRRC - rotate right with carry */
7188 /*-----------------------------------------------------------------*/
7192 operand *left, *result;
7195 D (emitcode (";", "genRRC "););
7197 /* rotate right with carry */
7198 left = IC_LEFT (ic);
7199 result = IC_RESULT (ic);
7200 aopOp (left, ic, FALSE, FALSE);
7201 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7203 /* move it to the result */
7204 size = AOP_SIZE (result);
7208 _startLazyDPSEvaluation ();
7211 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7212 emitcode ("rrc", "a");
7213 if (AOP_SIZE (result) > 1)
7214 aopPut (AOP (result), "a", offset--);
7216 _endLazyDPSEvaluation ();
7218 /* now we need to put the carry into the
7219 highest order byte of the result */
7220 if (AOP_SIZE (result) > 1)
7222 MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7224 emitcode ("mov", "acc.7,c");
7225 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7226 freeAsmop (left, NULL, ic, TRUE);
7227 freeAsmop (result, NULL, ic, TRUE);
7230 /*-----------------------------------------------------------------*/
7231 /* genRLC - generate code for rotate left with carry */
7232 /*-----------------------------------------------------------------*/
7236 operand *left, *result;
7240 D (emitcode (";", "genRLC "););
7242 /* rotate right with carry */
7243 left = IC_LEFT (ic);
7244 result = IC_RESULT (ic);
7245 aopOp (left, ic, FALSE, FALSE);
7246 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7248 /* move it to the result */
7249 size = AOP_SIZE (result);
7253 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7255 emitcode ("add", "a,acc");
7256 if (AOP_SIZE (result) > 1)
7258 aopPut (AOP (result), "a", offset++);
7261 _startLazyDPSEvaluation ();
7264 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7266 emitcode ("rlc", "a");
7267 if (AOP_SIZE (result) > 1)
7268 aopPut (AOP (result), "a", offset++);
7270 _endLazyDPSEvaluation ();
7272 /* now we need to put the carry into the
7273 highest order byte of the result */
7274 if (AOP_SIZE (result) > 1)
7276 l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7279 emitcode ("mov", "acc.0,c");
7280 aopPut (AOP (result), "a", 0);
7281 freeAsmop (left, NULL, ic, TRUE);
7282 freeAsmop (result, NULL, ic, TRUE);
7285 /*-----------------------------------------------------------------*/
7286 /* genGetHbit - generates code get highest order bit */
7287 /*-----------------------------------------------------------------*/
7289 genGetHbit (iCode * ic)
7291 operand *left, *result;
7292 left = IC_LEFT (ic);
7293 result = IC_RESULT (ic);
7294 aopOp (left, ic, FALSE, FALSE);
7295 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7297 D (emitcode (";", "genGetHbit "););
7299 /* get the highest order byte into a */
7300 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7301 if (AOP_TYPE (result) == AOP_CRY)
7303 emitcode ("rlc", "a");
7308 emitcode ("rl", "a");
7309 emitcode ("anl", "a,#1");
7314 freeAsmop (left, NULL, ic, TRUE);
7315 freeAsmop (result, NULL, ic, TRUE);
7318 /*-----------------------------------------------------------------*/
7319 /* AccRol - rotate left accumulator by known count */
7320 /*-----------------------------------------------------------------*/
7322 AccRol (int shCount)
7324 shCount &= 0x0007; // shCount : 0..7
7331 emitcode ("rl", "a");
7334 emitcode ("rl", "a");
7335 emitcode ("rl", "a");
7338 emitcode ("swap", "a");
7339 emitcode ("rr", "a");
7342 emitcode ("swap", "a");
7345 emitcode ("swap", "a");
7346 emitcode ("rl", "a");
7349 emitcode ("rr", "a");
7350 emitcode ("rr", "a");
7353 emitcode ("rr", "a");
7358 /*-----------------------------------------------------------------*/
7359 /* AccLsh - left shift accumulator by known count */
7360 /*-----------------------------------------------------------------*/
7362 AccLsh (int shCount)
7367 emitcode ("add", "a,acc");
7368 else if (shCount == 2)
7370 emitcode ("add", "a,acc");
7371 emitcode ("add", "a,acc");
7375 /* rotate left accumulator */
7377 /* and kill the lower order bits */
7378 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7383 /*-----------------------------------------------------------------*/
7384 /* AccRsh - right shift accumulator by known count */
7385 /*-----------------------------------------------------------------*/
7387 AccRsh (int shCount)
7394 emitcode ("rrc", "a");
7398 /* rotate right accumulator */
7399 AccRol (8 - shCount);
7400 /* and kill the higher order bits */
7401 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7406 #ifdef BETTER_LITERAL_SHIFT
7407 /*-----------------------------------------------------------------*/
7408 /* AccSRsh - signed right shift accumulator by known count */
7409 /*-----------------------------------------------------------------*/
7411 AccSRsh (int shCount)
7418 emitcode ("mov", "c,acc.7");
7419 emitcode ("rrc", "a");
7421 else if (shCount == 2)
7423 emitcode ("mov", "c,acc.7");
7424 emitcode ("rrc", "a");
7425 emitcode ("mov", "c,acc.7");
7426 emitcode ("rrc", "a");
7430 tlbl = newiTempLabel (NULL);
7431 /* rotate right accumulator */
7432 AccRol (8 - shCount);
7433 /* and kill the higher order bits */
7434 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7435 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7436 emitcode ("orl", "a,#!constbyte",
7437 (unsigned char) ~SRMask[shCount]);
7438 emitcode ("", "!tlabeldef", tlbl->key + 100);
7444 #ifdef BETTER_LITERAL_SHIFT
7445 /*-----------------------------------------------------------------*/
7446 /* shiftR1Left2Result - shift right one byte from left to result */
7447 /*-----------------------------------------------------------------*/
7449 shiftR1Left2Result (operand * left, int offl,
7450 operand * result, int offr,
7451 int shCount, int sign)
7453 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7454 /* shift right accumulator */
7459 aopPut (AOP (result), "a", offr);
7463 #ifdef BETTER_LITERAL_SHIFT
7464 /*-----------------------------------------------------------------*/
7465 /* shiftL1Left2Result - shift left one byte from left to result */
7466 /*-----------------------------------------------------------------*/
7468 shiftL1Left2Result (operand * left, int offl,
7469 operand * result, int offr, int shCount)
7471 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7472 /* shift left accumulator */
7474 aopPut (AOP (result), "a", offr);
7478 #ifdef BETTER_LITERAL_SHIFT
7479 /*-----------------------------------------------------------------*/
7480 /* movLeft2Result - move byte from left to result */
7481 /*-----------------------------------------------------------------*/
7483 movLeft2Result (operand * left, int offl,
7484 operand * result, int offr, int sign)
7487 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7489 l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
7491 if (*l == '@' && (IS_AOP_PREG (result)))
7493 emitcode ("mov", "a,%s", l);
7494 aopPut (AOP (result), "a", offr);
7500 aopPut (AOP (result), l, offr);
7504 /* MSB sign in acc.7 ! */
7505 if (getDataSize (left) == offl + 1)
7507 emitcode ("mov", "a,%s", l);
7508 aopPut (AOP (result), "a", offr);
7516 #ifdef BETTER_LITERAL_SHIFT
7517 /*-----------------------------------------------------------------*/
7518 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7519 /*-----------------------------------------------------------------*/
7523 emitcode ("rrc", "a");
7524 emitcode ("xch", "a,%s", x);
7525 emitcode ("rrc", "a");
7526 emitcode ("xch", "a,%s", x);
7530 #ifdef BETTER_LITERAL_SHIFT
7532 /*-----------------------------------------------------------------*/
7533 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7534 /*-----------------------------------------------------------------*/
7538 emitcode ("xch", "a,%s", x);
7539 emitcode ("rlc", "a");
7540 emitcode ("xch", "a,%s", x);
7541 emitcode ("rlc", "a");
7545 #ifdef BETTER_LITERAL_SHIFT
7546 /*-----------------------------------------------------------------*/
7547 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7548 /*-----------------------------------------------------------------*/
7552 emitcode ("xch", "a,%s", x);
7553 emitcode ("add", "a,acc");
7554 emitcode ("xch", "a,%s", x);
7555 emitcode ("rlc", "a");
7559 #ifdef BETTER_LITERAL_SHIFT
7560 /*-----------------------------------------------------------------*/
7561 /* AccAXLsh - left shift a:x by known count (0..7) */
7562 /*-----------------------------------------------------------------*/
7564 AccAXLsh (char *x, int shCount)
7579 case 5: // AAAAABBB:CCCCCDDD
7581 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7583 emitcode ("anl", "a,#!constbyte",
7584 SLMask[shCount]); // BBB00000:CCCCCDDD
7586 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7588 AccRol (shCount); // DDDCCCCC:BBB00000
7590 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7592 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7594 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7596 emitcode ("anl", "a,#!constbyte",
7597 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7599 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7601 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7604 case 6: // AAAAAABB:CCCCCCDD
7605 emitcode ("anl", "a,#!constbyte",
7606 SRMask[shCount]); // 000000BB:CCCCCCDD
7607 emitcode ("mov", "c,acc.0"); // c = B
7608 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7610 AccAXRrl1 (x); // BCCCCCCD:D000000B
7611 AccAXRrl1 (x); // BBCCCCCC:DD000000
7613 emitcode("rrc","a");
7614 emitcode("xch","a,%s", x);
7615 emitcode("rrc","a");
7616 emitcode("mov","c,acc.0"); //<< get correct bit
7617 emitcode("xch","a,%s", x);
7619 emitcode("rrc","a");
7620 emitcode("xch","a,%s", x);
7621 emitcode("rrc","a");
7622 emitcode("xch","a,%s", x);
7625 case 7: // a:x <<= 7
7627 emitcode ("anl", "a,#!constbyte",
7628 SRMask[shCount]); // 0000000B:CCCCCCCD
7630 emitcode ("mov", "c,acc.0"); // c = B
7632 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7634 AccAXRrl1 (x); // BCCCCCCC:D0000000
7643 #ifdef BETTER_LITERAL_SHIFT
7645 /*-----------------------------------------------------------------*/
7646 /* AccAXRsh - right shift a:x known count (0..7) */
7647 /*-----------------------------------------------------------------*/
7649 AccAXRsh (char *x, int shCount)
7657 AccAXRrl1 (x); // 0->a:x
7662 AccAXRrl1 (x); // 0->a:x
7665 AccAXRrl1 (x); // 0->a:x
7670 case 5: // AAAAABBB:CCCCCDDD = a:x
7672 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7674 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7676 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7678 emitcode ("anl", "a,#!constbyte",
7679 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7681 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7683 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7685 emitcode ("anl", "a,#!constbyte",
7686 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7688 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7690 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7692 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7695 case 6: // AABBBBBB:CCDDDDDD
7697 emitcode ("mov", "c,acc.7");
7698 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7700 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7702 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7704 emitcode ("anl", "a,#!constbyte",
7705 SRMask[shCount]); // 000000AA:BBBBBBCC
7708 case 7: // ABBBBBBB:CDDDDDDD
7710 emitcode ("mov", "c,acc.7"); // c = A
7712 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7714 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7716 emitcode ("anl", "a,#!constbyte",
7717 SRMask[shCount]); // 0000000A:BBBBBBBC
7726 #ifdef BETTER_LITERAL_SHIFT
7727 /*-----------------------------------------------------------------*/
7728 /* AccAXRshS - right shift signed a:x known count (0..7) */
7729 /*-----------------------------------------------------------------*/
7731 AccAXRshS (char *x, int shCount)
7739 emitcode ("mov", "c,acc.7");
7740 AccAXRrl1 (x); // s->a:x
7744 emitcode ("mov", "c,acc.7");
7745 AccAXRrl1 (x); // s->a:x
7747 emitcode ("mov", "c,acc.7");
7748 AccAXRrl1 (x); // s->a:x
7753 case 5: // AAAAABBB:CCCCCDDD = a:x
7755 tlbl = newiTempLabel (NULL);
7756 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7758 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7760 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7762 emitcode ("anl", "a,#!constbyte",
7763 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7765 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7767 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7769 emitcode ("anl", "a,#!constbyte",
7770 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7772 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7774 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7776 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7778 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7779 emitcode ("orl", "a,#!constbyte",
7780 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7782 emitcode ("", "!tlabeldef", tlbl->key + 100);
7783 break; // SSSSAAAA:BBBCCCCC
7785 case 6: // AABBBBBB:CCDDDDDD
7787 tlbl = newiTempLabel (NULL);
7788 emitcode ("mov", "c,acc.7");
7789 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7791 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7793 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7795 emitcode ("anl", "a,#!constbyte",
7796 SRMask[shCount]); // 000000AA:BBBBBBCC
7798 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7799 emitcode ("orl", "a,#!constbyte",
7800 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7802 emitcode ("", "!tlabeldef", tlbl->key + 100);
7804 case 7: // ABBBBBBB:CDDDDDDD
7806 tlbl = newiTempLabel (NULL);
7807 emitcode ("mov", "c,acc.7"); // c = A
7809 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7811 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7813 emitcode ("anl", "a,#!constbyte",
7814 SRMask[shCount]); // 0000000A:BBBBBBBC
7816 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7817 emitcode ("orl", "a,#!constbyte",
7818 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7820 emitcode ("", "!tlabeldef", tlbl->key + 100);
7828 #ifdef BETTER_LITERAL_SHIFT
7830 _loadLeftIntoAx(char **lsb,
7836 // Get the initial value from left into a pair of registers.
7837 // MSB must be in A, LSB can be any register.
7839 // If the result is held in registers, it is an optimization
7840 // if the LSB can be held in the register which will hold the,
7841 // result LSB since this saves us from having to copy it into
7842 // the result following AccAXLsh.
7844 // If the result is addressed indirectly, this is not a gain.
7845 if (AOP_NEEDSACC(result))
7849 _startLazyDPSEvaluation();
7850 if (AOP_TYPE(left) == AOP_DPTR2)
7853 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
7854 // get LSB in DP2_RESULT_REG.
7855 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
7856 assert(!strcmp(leftByte, DP2_RESULT_REG));
7860 // get LSB into DP2_RESULT_REG
7861 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
7862 if (strcmp(leftByte, DP2_RESULT_REG))
7865 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7868 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
7869 assert(strcmp(leftByte, DP2_RESULT_REG));
7872 _endLazyDPSEvaluation();
7873 *lsb = DP2_RESULT_REG;
7877 if (sameRegs (AOP (result), AOP (left)) &&
7878 ((offl + MSB16) == offr))
7880 /* don't crash result[offr] */
7881 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
7882 emitcode ("xch", "a,%s",
7883 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
7887 movLeft2Result (left, offl, result, offr, 0);
7888 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
7890 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
7891 assert(strcmp(*lsb,"a"));
7896 _storeAxResults(char *lsb,
7900 _startLazyDPSEvaluation();
7901 if (AOP_NEEDSACC(result))
7903 /* We have to explicitly update the result LSB.
7905 emitcode("xch","a,%s", lsb);
7906 aopPut(AOP(result), "a", offr);
7907 emitcode("mov","a,%s", lsb);
7909 if (getDataSize (result) > 1)
7911 aopPut (AOP (result), "a", offr + MSB16);
7913 _endLazyDPSEvaluation();
7916 /*-----------------------------------------------------------------*/
7917 /* shiftL2Left2Result - shift left two bytes from left to result */
7918 /*-----------------------------------------------------------------*/
7920 shiftL2Left2Result (operand * left, int offl,
7921 operand * result, int offr, int shCount)
7925 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7927 AccAXLsh (lsb, shCount);
7929 _storeAxResults(lsb, result, offr);
7933 #ifdef BETTER_LITERAL_SHIFT
7934 /*-----------------------------------------------------------------*/
7935 /* shiftR2Left2Result - shift right two bytes from left to result */
7936 /*-----------------------------------------------------------------*/
7938 shiftR2Left2Result (operand * left, int offl,
7939 operand * result, int offr,
7940 int shCount, int sign)
7944 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7946 /* a:x >> shCount (x = lsb(result)) */
7949 AccAXRshS(lsb, shCount);
7953 AccAXRsh(lsb, shCount);
7956 _storeAxResults(lsb, result, offr);
7960 /*-----------------------------------------------------------------*/
7961 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7962 /*-----------------------------------------------------------------*/
7964 shiftLLeftOrResult (operand * left, int offl,
7965 operand * result, int offr, int shCount)
7967 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7968 /* shift left accumulator */
7970 /* or with result */
7971 emitcode ("orl", "a,%s",
7972 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7973 /* back to result */
7974 aopPut (AOP (result), "a", offr);
7979 /*-----------------------------------------------------------------*/
7980 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7981 /*-----------------------------------------------------------------*/
7983 shiftRLeftOrResult (operand * left, int offl,
7984 operand * result, int offr, int shCount)
7986 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7987 /* shift right accumulator */
7989 /* or with result */
7990 emitcode ("orl", "a,%s",
7991 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7992 /* back to result */
7993 aopPut (AOP (result), "a", offr);
7997 #ifdef BETTER_LITERAL_SHIFT
7998 /*-----------------------------------------------------------------*/
7999 /* genlshOne - left shift a one byte quantity by known count */
8000 /*-----------------------------------------------------------------*/
8002 genlshOne (operand * result, operand * left, int shCount)
8004 D (emitcode (";", "genlshOne "););
8005 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8009 #ifdef BETTER_LITERAL_SHIFT
8010 /*-----------------------------------------------------------------*/
8011 /* genlshTwo - left shift two bytes by known amount != 0 */
8012 /*-----------------------------------------------------------------*/
8014 genlshTwo (operand * result, operand * left, int shCount)
8018 D (emitcode (";", "genlshTwo "););
8020 size = getDataSize (result);
8022 /* if shCount >= 8 */
8027 _startLazyDPSEvaluation();
8033 _endLazyDPSEvaluation();
8034 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8035 aopPut (AOP (result), zero, LSB);
8039 movLeft2Result (left, LSB, result, MSB16, 0);
8040 aopPut (AOP (result), zero, LSB);
8041 _endLazyDPSEvaluation();
8046 aopPut (AOP (result), zero, LSB);
8047 _endLazyDPSEvaluation();
8051 /* 1 <= shCount <= 7 */
8056 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8060 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8068 /*-----------------------------------------------------------------*/
8069 /* shiftLLong - shift left one long from left to result */
8070 /* offl = LSB or MSB16 */
8071 /*-----------------------------------------------------------------*/
8073 shiftLLong (operand * left, operand * result, int offr)
8076 int size = AOP_SIZE (result);
8078 if (size >= LSB + offr)
8080 l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8082 emitcode ("add", "a,acc");
8083 if (sameRegs (AOP (left), AOP (result)) &&
8084 size >= MSB16 + offr && offr != LSB)
8085 emitcode ("xch", "a,%s",
8086 aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8088 aopPut (AOP (result), "a", LSB + offr);
8091 if (size >= MSB16 + offr)
8093 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8095 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8097 emitcode ("rlc", "a");
8098 if (sameRegs (AOP (left), AOP (result)) &&
8099 size >= MSB24 + offr && offr != LSB)
8100 emitcode ("xch", "a,%s",
8101 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8103 aopPut (AOP (result), "a", MSB16 + offr);
8106 if (size >= MSB24 + offr)
8108 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8110 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8112 emitcode ("rlc", "a");
8113 if (sameRegs (AOP (left), AOP (result)) &&
8114 size >= MSB32 + offr && offr != LSB)
8115 emitcode ("xch", "a,%s",
8116 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8118 aopPut (AOP (result), "a", MSB24 + offr);
8121 if (size > MSB32 + offr)
8123 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8125 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8127 emitcode ("rlc", "a");
8128 aopPut (AOP (result), "a", MSB32 + offr);
8131 aopPut (AOP (result), zero, LSB);
8137 /*-----------------------------------------------------------------*/
8138 /* genlshFour - shift four byte by a known amount != 0 */
8139 /*-----------------------------------------------------------------*/
8141 genlshFour (operand * result, operand * left, int shCount)
8145 D (emitcode (";", "genlshFour ");
8148 size = AOP_SIZE (result);
8150 /* if shifting more that 3 bytes */
8155 /* lowest order of left goes to the highest
8156 order of the destination */
8157 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8159 movLeft2Result (left, LSB, result, MSB32, 0);
8160 aopPut (AOP (result), zero, LSB);
8161 aopPut (AOP (result), zero, MSB16);
8162 aopPut (AOP (result), zero, MSB24);
8166 /* more than two bytes */
8167 else if (shCount >= 16)
8169 /* lower order two bytes goes to higher order two bytes */
8171 /* if some more remaining */
8173 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8176 movLeft2Result (left, MSB16, result, MSB32, 0);
8177 movLeft2Result (left, LSB, result, MSB24, 0);
8179 aopPut (AOP (result), zero, MSB16);
8180 aopPut (AOP (result), zero, LSB);
8184 /* if more than 1 byte */
8185 else if (shCount >= 8)
8187 /* lower order three bytes goes to higher order three bytes */
8192 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8194 movLeft2Result (left, LSB, result, MSB16, 0);
8200 movLeft2Result (left, MSB24, result, MSB32, 0);
8201 movLeft2Result (left, MSB16, result, MSB24, 0);
8202 movLeft2Result (left, LSB, result, MSB16, 0);
8203 aopPut (AOP (result), zero, LSB);
8205 else if (shCount == 1)
8206 shiftLLong (left, result, MSB16);
8209 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8210 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8211 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8212 aopPut (AOP (result), zero, LSB);
8217 /* 1 <= shCount <= 7 */
8218 else if (shCount <= 2)
8220 shiftLLong (left, result, LSB);
8222 shiftLLong (result, result, LSB);
8224 /* 3 <= shCount <= 7, optimize */
8227 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8228 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8229 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8234 #ifdef BETTER_LITERAL_SHIFT
8235 /*-----------------------------------------------------------------*/
8236 /* genLeftShiftLiteral - left shifting by known count */
8237 /*-----------------------------------------------------------------*/
8239 genLeftShiftLiteral (operand * left,
8244 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8247 size = getSize (operandType (result));
8249 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8251 /* We only handle certain easy cases so far. */
8253 && (shCount < (size * 8))
8257 D(emitcode (";", "genLeftShiftLiteral wimping out"););
8261 freeAsmop (right, NULL, ic, TRUE);
8263 aopOp(left, ic, FALSE, FALSE);
8264 aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8267 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8269 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8270 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8272 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8275 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8277 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8278 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8280 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8286 emitcode ("; shift left ", "result %d, left %d", size,
8290 /* I suppose that the left size >= result size */
8293 _startLazyDPSEvaluation();
8296 movLeft2Result (left, size, result, size, 0);
8298 _endLazyDPSEvaluation();
8300 else if (shCount >= (size * 8))
8302 _startLazyDPSEvaluation();
8305 aopPut (AOP (result), zero, size);
8307 _endLazyDPSEvaluation();
8314 genlshOne (result, left, shCount);
8318 genlshTwo (result, left, shCount);
8322 genlshFour (result, left, shCount);
8326 fprintf(stderr, "*** ack! mystery literal shift!\n");
8330 freeAsmop (left, NULL, ic, TRUE);
8331 freeAsmop (result, NULL, ic, TRUE);
8336 /*-----------------------------------------------------------------*/
8337 /* genLeftShift - generates code for left shifting */
8338 /*-----------------------------------------------------------------*/
8340 genLeftShift (iCode * ic)
8342 operand *left, *right, *result;
8345 symbol *tlbl, *tlbl1;
8347 D (emitcode (";", "genLeftShift "););
8349 right = IC_RIGHT (ic);
8350 left = IC_LEFT (ic);
8351 result = IC_RESULT (ic);
8353 aopOp (right, ic, FALSE, FALSE);
8356 #ifdef BETTER_LITERAL_SHIFT
8357 /* if the shift count is known then do it
8358 as efficiently as possible */
8359 if (AOP_TYPE (right) == AOP_LIT)
8361 if (genLeftShiftLiteral (left, right, result, ic))
8368 /* shift count is unknown then we have to form
8369 a loop get the loop count in B : Note: we take
8370 only the lower order byte since shifting
8371 more that 32 bits make no sense anyway, ( the
8372 largest size of an object can be only 32 bits ) */
8374 if (AOP_TYPE (right) == AOP_LIT)
8376 /* Really should be handled by genLeftShiftLiteral,
8377 * but since I'm too lazy to fix that today, at least we can make
8378 * some small improvement.
8380 emitcode("mov", "b,#!constbyte",
8381 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8385 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8386 emitcode ("inc", "b");
8388 freeAsmop (right, NULL, ic, TRUE);
8389 aopOp (left, ic, FALSE, FALSE);
8390 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8392 /* now move the left to the result if they are not the
8394 if (!sameRegs (AOP (left), AOP (result)) &&
8395 AOP_SIZE (result) > 1)
8398 size = AOP_SIZE (result);
8400 _startLazyDPSEvaluation ();
8403 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8404 if (*l == '@' && (IS_AOP_PREG (result)))
8407 emitcode ("mov", "a,%s", l);
8408 aopPut (AOP (result), "a", offset);
8411 aopPut (AOP (result), l, offset);
8414 _endLazyDPSEvaluation ();
8417 tlbl = newiTempLabel (NULL);
8418 size = AOP_SIZE (result);
8420 tlbl1 = newiTempLabel (NULL);
8422 /* if it is only one byte then */
8425 symbol *tlbl1 = newiTempLabel (NULL);
8427 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8428 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8429 emitcode ("", "!tlabeldef", tlbl->key + 100);
8430 emitcode ("add", "a,acc");
8431 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8432 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8433 aopPut (AOP (result), "a", 0);
8437 reAdjustPreg (AOP (result));
8439 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8440 emitcode ("", "!tlabeldef", tlbl->key + 100);
8441 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8442 emitcode ("add", "a,acc");
8443 aopPut (AOP (result), "a", offset++);
8444 _startLazyDPSEvaluation ();
8447 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8448 emitcode ("rlc", "a");
8449 aopPut (AOP (result), "a", offset++);
8451 _endLazyDPSEvaluation ();
8452 reAdjustPreg (AOP (result));
8454 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8455 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8457 freeAsmop (left, NULL, ic, TRUE);
8458 freeAsmop (result, NULL, ic, TRUE);
8461 #ifdef BETTER_LITERAL_SHIFT
8462 /*-----------------------------------------------------------------*/
8463 /* genrshOne - right shift a one byte quantity by known count */
8464 /*-----------------------------------------------------------------*/
8466 genrshOne (operand * result, operand * left,
8467 int shCount, int sign)
8469 D (emitcode (";", "genrshOne"););
8470 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8474 #ifdef BETTER_LITERAL_SHIFT
8475 /*-----------------------------------------------------------------*/
8476 /* genrshTwo - right shift two bytes by known amount != 0 */
8477 /*-----------------------------------------------------------------*/
8479 genrshTwo (operand * result, operand * left,
8480 int shCount, int sign)
8482 D (emitcode (";", "genrshTwo"););
8484 /* if shCount >= 8 */
8488 _startLazyDPSEvaluation();
8491 shiftR1Left2Result (left, MSB16, result, LSB,
8496 movLeft2Result (left, MSB16, result, LSB, sign);
8498 addSign (result, MSB16, sign);
8499 _endLazyDPSEvaluation();
8502 /* 1 <= shCount <= 7 */
8505 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8510 /*-----------------------------------------------------------------*/
8511 /* shiftRLong - shift right one long from left to result */
8512 /* offl = LSB or MSB16 */
8513 /*-----------------------------------------------------------------*/
8515 shiftRLong (operand * left, int offl,
8516 operand * result, int sign)
8518 int isSameRegs=sameRegs(AOP(left),AOP(result));
8520 if (isSameRegs && offl>1) {
8521 // we are in big trouble, but this shouldn't happen
8522 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8525 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8530 emitcode ("rlc", "a");
8531 emitcode ("subb", "a,acc");
8532 emitcode ("xch", "a,%s",
8533 aopGet(AOP(left), MSB32, FALSE, FALSE, DP2_RESULT_REG));
8535 aopPut (AOP(result), zero, MSB32);
8540 emitcode ("clr", "c");
8542 emitcode ("mov", "c,acc.7");
8545 emitcode ("rrc", "a");
8547 if (isSameRegs && offl==MSB16) {
8549 "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE, DP2_RESULT_REG));
8551 aopPut (AOP (result), "a", MSB32);
8552 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8555 emitcode ("rrc", "a");
8556 if (isSameRegs && offl==1) {
8557 emitcode ("xch", "a,%s",
8558 aopGet (AOP (left), MSB16, FALSE, FALSE, DP2_RESULT_REG));
8560 aopPut (AOP (result), "a", MSB24);
8561 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, NULL));
8563 emitcode ("rrc", "a");
8564 aopPut (AOP (result), "a", MSB16 - offl);
8568 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, NULL));
8569 emitcode ("rrc", "a");
8570 aopPut (AOP (result), "a", LSB);
8574 /*-----------------------------------------------------------------*/
8575 /* genrshFour - shift four byte by a known amount != 0 */
8576 /*-----------------------------------------------------------------*/
8578 genrshFour (operand * result, operand * left,
8579 int shCount, int sign)
8581 D (emitcode (";", "genrshFour"););
8583 /* if shifting more that 3 bytes */
8587 _startLazyDPSEvaluation();
8589 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8591 movLeft2Result (left, MSB32, result, LSB, sign);
8592 addSign (result, MSB16, sign);
8593 _endLazyDPSEvaluation();
8595 else if (shCount >= 16)
8598 _startLazyDPSEvaluation();
8600 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8603 movLeft2Result (left, MSB24, result, LSB, 0);
8604 movLeft2Result (left, MSB32, result, MSB16, sign);
8606 addSign (result, MSB24, sign);
8607 _endLazyDPSEvaluation();
8609 else if (shCount >= 8)
8612 _startLazyDPSEvaluation();
8615 shiftRLong (left, MSB16, result, sign);
8617 else if (shCount == 0)
8619 movLeft2Result (left, MSB16, result, LSB, 0);
8620 movLeft2Result (left, MSB24, result, MSB16, 0);
8621 movLeft2Result (left, MSB32, result, MSB24, sign);
8622 addSign (result, MSB32, sign);
8626 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8627 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8628 /* the last shift is signed */
8629 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8630 addSign (result, MSB32, sign);
8632 _endLazyDPSEvaluation();
8636 /* 1 <= shCount <= 7 */
8639 shiftRLong (left, LSB, result, sign);
8641 shiftRLong (result, LSB, result, sign);
8645 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8646 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8647 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8652 #ifdef BETTER_LITERAL_SHIFT
8653 /*-----------------------------------------------------------------*/
8654 /* genRightShiftLiteral - right shifting by known count */
8655 /*-----------------------------------------------------------------*/
8657 genRightShiftLiteral (operand * left,
8663 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8666 size = getSize (operandType (result));
8668 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8670 /* We only handle certain easy cases so far. */
8672 && (shCount < (size * 8))
8677 D(emitcode (";", "genRightShiftLiteral wimping out"););
8681 freeAsmop (right, NULL, ic, TRUE);
8683 aopOp (left, ic, FALSE, FALSE);
8684 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8687 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8691 /* test the LEFT size !!! */
8693 /* I suppose that the left size >= result size */
8696 size = getDataSize (result);
8697 _startLazyDPSEvaluation();
8700 movLeft2Result (left, size, result, size, 0);
8702 _endLazyDPSEvaluation();
8704 else if (shCount >= (size * 8))
8708 /* get sign in acc.7 */
8709 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
8711 addSign (result, LSB, sign);
8718 genrshOne (result, left, shCount, sign);
8722 genrshTwo (result, left, shCount, sign);
8726 genrshFour (result, left, shCount, sign);
8733 freeAsmop (left, NULL, ic, TRUE);
8734 freeAsmop (result, NULL, ic, TRUE);
8740 /*-----------------------------------------------------------------*/
8741 /* genSignedRightShift - right shift of signed number */
8742 /*-----------------------------------------------------------------*/
8744 genSignedRightShift (iCode * ic)
8746 operand *right, *left, *result;
8749 symbol *tlbl, *tlbl1;
8751 D (emitcode (";", "genSignedRightShift "););
8753 /* we do it the hard way put the shift count in b
8754 and loop thru preserving the sign */
8756 right = IC_RIGHT (ic);
8757 left = IC_LEFT (ic);
8758 result = IC_RESULT (ic);
8760 aopOp (right, ic, FALSE, FALSE);
8762 #ifdef BETTER_LITERAL_SHIFT
8763 if (AOP_TYPE (right) == AOP_LIT)
8765 if (genRightShiftLiteral (left, right, result, ic, 1))
8771 /* shift count is unknown then we have to form
8772 a loop get the loop count in B : Note: we take
8773 only the lower order byte since shifting
8774 more that 32 bits make no sense anyway, ( the
8775 largest size of an object can be only 32 bits ) */
8777 if (AOP_TYPE (right) == AOP_LIT)
8779 /* Really should be handled by genRightShiftLiteral,
8780 * but since I'm too lazy to fix that today, at least we can make
8781 * some small improvement.
8783 emitcode("mov", "b,#!constbyte",
8784 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8788 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8789 emitcode ("inc", "b");
8791 freeAsmop (right, NULL, ic, TRUE);
8792 aopOp (left, ic, FALSE, FALSE);
8793 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8795 /* now move the left to the result if they are not the
8797 if (!sameRegs (AOP (left), AOP (result)) &&
8798 AOP_SIZE (result) > 1)
8801 size = AOP_SIZE (result);
8803 _startLazyDPSEvaluation ();
8806 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8807 if (*l == '@' && IS_AOP_PREG (result))
8810 emitcode ("mov", "a,%s", l);
8811 aopPut (AOP (result), "a", offset);
8814 aopPut (AOP (result), l, offset);
8817 _endLazyDPSEvaluation ();
8820 /* mov the highest order bit to OVR */
8821 tlbl = newiTempLabel (NULL);
8822 tlbl1 = newiTempLabel (NULL);
8824 size = AOP_SIZE (result);
8826 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
8827 emitcode ("rlc", "a");
8828 emitcode ("mov", "ov,c");
8829 /* if it is only one byte then */
8832 MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8833 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8834 emitcode ("", "!tlabeldef", tlbl->key + 100);
8835 emitcode ("mov", "c,ov");
8836 emitcode ("rrc", "a");
8837 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8838 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8839 aopPut (AOP (result), "a", 0);
8843 reAdjustPreg (AOP (result));
8844 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8845 emitcode ("", "!tlabeldef", tlbl->key + 100);
8846 emitcode ("mov", "c,ov");
8847 _startLazyDPSEvaluation ();
8850 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8851 emitcode ("rrc", "a");
8852 aopPut (AOP (result), "a", offset--);
8854 _endLazyDPSEvaluation ();
8855 reAdjustPreg (AOP (result));
8856 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8857 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8860 freeAsmop (left, NULL, ic, TRUE);
8861 freeAsmop (result, NULL, ic, TRUE);
8864 /*-----------------------------------------------------------------*/
8865 /* genRightShift - generate code for right shifting */
8866 /*-----------------------------------------------------------------*/
8868 genRightShift (iCode * ic)
8870 operand *right, *left, *result;
8874 symbol *tlbl, *tlbl1;
8876 D (emitcode (";", "genRightShift "););
8878 /* if signed then we do it the hard way preserve the
8879 sign bit moving it inwards */
8880 retype = getSpec (operandType (IC_RESULT (ic)));
8882 if (!SPEC_USIGN (retype))
8884 genSignedRightShift (ic);
8888 /* signed & unsigned types are treated the same : i.e. the
8889 signed is NOT propagated inwards : quoting from the
8890 ANSI - standard : "for E1 >> E2, is equivalent to division
8891 by 2**E2 if unsigned or if it has a non-negative value,
8892 otherwise the result is implementation defined ", MY definition
8893 is that the sign does not get propagated */
8895 right = IC_RIGHT (ic);
8896 left = IC_LEFT (ic);
8897 result = IC_RESULT (ic);
8899 aopOp (right, ic, FALSE, FALSE);
8901 #ifdef BETTER_LITERAL_SHIFT
8902 /* if the shift count is known then do it
8903 as efficiently as possible */
8904 if (AOP_TYPE (right) == AOP_LIT)
8906 if (genRightShiftLiteral (left, right, result, ic, 0))
8913 /* shift count is unknown then we have to form
8914 a loop get the loop count in B : Note: we take
8915 only the lower order byte since shifting
8916 more that 32 bits make no sense anyway, ( the
8917 largest size of an object can be only 32 bits ) */
8919 if (AOP_TYPE (right) == AOP_LIT)
8921 /* Really should be handled by genRightShiftLiteral,
8922 * but since I'm too lazy to fix that today, at least we can make
8923 * some small improvement.
8925 emitcode("mov", "b,#!constbyte",
8926 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8930 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8931 emitcode ("inc", "b");
8933 freeAsmop (right, NULL, ic, TRUE);
8934 aopOp (left, ic, FALSE, FALSE);
8935 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8937 /* now move the left to the result if they are not the
8939 if (!sameRegs (AOP (left), AOP (result)) &&
8940 AOP_SIZE (result) > 1)
8943 size = AOP_SIZE (result);
8945 _startLazyDPSEvaluation ();
8948 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8949 if (*l == '@' && IS_AOP_PREG (result))
8952 emitcode ("mov", "a,%s", l);
8953 aopPut (AOP (result), "a", offset);
8956 aopPut (AOP (result), l, offset);
8959 _endLazyDPSEvaluation ();
8962 tlbl = newiTempLabel (NULL);
8963 tlbl1 = newiTempLabel (NULL);
8964 size = AOP_SIZE (result);
8967 /* if it is only one byte then */
8970 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8971 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8972 emitcode ("", "!tlabeldef", tlbl->key + 100);
8974 emitcode ("rrc", "a");
8975 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8976 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8977 aopPut (AOP (result), "a", 0);
8981 reAdjustPreg (AOP (result));
8982 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8983 emitcode ("", "!tlabeldef", tlbl->key + 100);
8985 _startLazyDPSEvaluation ();
8988 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8989 emitcode ("rrc", "a");
8990 aopPut (AOP (result), "a", offset--);
8992 _endLazyDPSEvaluation ();
8993 reAdjustPreg (AOP (result));
8995 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8996 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8999 freeAsmop (left, NULL, ic, TRUE);
9000 freeAsmop (result, NULL, ic, TRUE);
9004 /*-----------------------------------------------------------------*/
9005 /* emitPtrByteGet - emits code to get a byte into A through a */
9006 /* pointer register (R0, R1, or DPTR). The */
9007 /* original value of A can be preserved in B. */
9008 /*-----------------------------------------------------------------*/
9010 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9017 emitcode ("mov", "b,a");
9018 emitcode ("mov", "a,@%s", rname);
9023 emitcode ("mov", "b,a");
9024 emitcode ("movx", "a,@%s", rname);
9029 emitcode ("mov", "b,a");
9030 emitcode ("movx", "a,@dptr");
9035 emitcode ("mov", "b,a");
9036 emitcode ("clr", "a");
9037 emitcode ("movc", "a,@a+dptr");
9043 emitcode ("push", "b");
9044 emitcode ("push", "acc");
9046 emitcode ("lcall", "__gptrget");
9048 emitcode ("pop", "b");
9053 /*-----------------------------------------------------------------*/
9054 /* emitPtrByteSet - emits code to set a byte from src through a */
9055 /* pointer register (R0, R1, or DPTR). */
9056 /*-----------------------------------------------------------------*/
9058 emitPtrByteSet (char *rname, int p_type, char *src)
9067 emitcode ("mov", "@%s,a", rname);
9070 emitcode ("mov", "@%s,%s", rname, src);
9075 emitcode ("movx", "@%s,a", rname);
9080 emitcode ("movx", "@dptr,a");
9085 emitcode ("lcall", "__gptrput");
9090 /*-----------------------------------------------------------------*/
9091 /* genUnpackBits - generates code for unpacking bits */
9092 /*-----------------------------------------------------------------*/
9094 genUnpackBits (operand * result, char *rname, int ptype)
9096 int offset = 0; /* result byte offset */
9097 int rsize; /* result size */
9098 int rlen = 0; /* remaining bitfield length */
9099 sym_link *etype; /* bitfield type information */
9100 int blen; /* bitfield length */
9101 int bstr; /* bitfield starting bit within byte */
9103 D(emitcode ("; genUnpackBits",""));
9105 etype = getSpec (operandType (result));
9106 rsize = getSize (operandType (result));
9107 blen = SPEC_BLEN (etype);
9108 bstr = SPEC_BSTR (etype);
9110 /* If the bitfield length is less than a byte */
9113 emitPtrByteGet (rname, ptype, FALSE);
9115 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
9116 aopPut (AOP (result), "a", offset++);
9120 /* Bit field did not fit in a byte. Copy all
9121 but the partial byte at the end. */
9122 for (rlen=blen;rlen>=8;rlen-=8)
9124 emitPtrByteGet (rname, ptype, FALSE);
9125 aopPut (AOP (result), "a", offset++);
9127 emitcode ("inc", "%s", rname);
9130 /* Handle the partial byte at the end */
9133 emitPtrByteGet (rname, ptype, FALSE);
9134 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
9135 aopPut (AOP (result), "a", offset++);
9143 aopPut (AOP (result), zero, offset++);
9148 /*-----------------------------------------------------------------*/
9149 /* genDataPointerGet - generates code when ptr offset is known */
9150 /*-----------------------------------------------------------------*/
9152 genDataPointerGet (operand * left,
9158 int size, offset = 0;
9159 aopOp (result, ic, TRUE, FALSE);
9161 /* get the string representation of the name */
9162 l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9163 size = AOP_SIZE (result);
9164 _startLazyDPSEvaluation ();
9169 SNPRINTF (buff, sizeof(buff),
9170 "(%s + %d)", l + 1, offset);
9174 SNPRINTF (buff, sizeof(buff),
9177 aopPut (AOP (result), buff, offset++);
9179 _endLazyDPSEvaluation ();
9181 freeAsmop (left, NULL, ic, TRUE);
9182 freeAsmop (result, NULL, ic, TRUE);
9185 /*-----------------------------------------------------------------*/
9186 /* genNearPointerGet - emitcode for near pointer fetch */
9187 /*-----------------------------------------------------------------*/
9189 genNearPointerGet (operand * left,
9197 sym_link *rtype, *retype, *letype;
9198 sym_link *ltype = operandType (left);
9201 rtype = operandType (result);
9202 retype = getSpec (rtype);
9203 letype = getSpec (ltype);
9205 aopOp (left, ic, FALSE, FALSE);
9207 /* if left is rematerialisable and
9208 result is not bit variable type and
9209 the left is pointer to data space i.e
9210 lower 128 bytes of space */
9211 if (AOP_TYPE (left) == AOP_IMMD &&
9212 !IS_BITVAR (retype) &&
9213 !IS_BITVAR (letype) &&
9214 DCL_TYPE (ltype) == POINTER)
9216 genDataPointerGet (left, result, ic);
9220 /* if the value is already in a pointer register
9221 then don't need anything more */
9222 if (!AOP_INPREG (AOP (left)))
9224 /* otherwise get a free pointer register */
9226 preg = getFreePtr (ic, &aop, FALSE);
9227 emitcode ("mov", "%s,%s",
9229 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9233 rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9235 freeAsmop (left, NULL, ic, TRUE);
9236 aopOp (result, ic, FALSE, FALSE);
9238 /* if bitfield then unpack the bits */
9239 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9240 genUnpackBits (result, rname, POINTER);
9243 /* we have can just get the values */
9244 int size = AOP_SIZE (result);
9249 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9252 emitcode ("mov", "a,@%s", rname);
9253 aopPut (AOP (result), "a", offset);
9257 SNPRINTF (buff, sizeof(buff), "@%s", rname);
9258 aopPut (AOP (result), buff, offset);
9263 emitcode ("inc", "%s", rname);
9268 /* now some housekeeping stuff */
9271 /* we had to allocate for this iCode */
9272 if (pi) { /* post increment present */
9273 aopPut(AOP ( left ),rname,0);
9275 freeAsmop (NULL, aop, ic, TRUE);
9279 /* we did not allocate which means left
9280 already in a pointer register, then
9281 if size > 0 && this could be used again
9282 we have to point it back to where it
9284 if (AOP_SIZE (result) > 1 &&
9285 !OP_SYMBOL (left)->remat &&
9286 (OP_SYMBOL (left)->liveTo > ic->seq ||
9290 int size = AOP_SIZE (result) - 1;
9292 emitcode ("dec", "%s", rname);
9297 freeAsmop (result, NULL, ic, TRUE);
9298 if (pi) pi->generated = 1;
9301 /*-----------------------------------------------------------------*/
9302 /* genPagedPointerGet - emitcode for paged pointer fetch */
9303 /*-----------------------------------------------------------------*/
9305 genPagedPointerGet (operand * left,
9313 sym_link *rtype, *retype, *letype;
9315 rtype = operandType (result);
9316 retype = getSpec (rtype);
9317 letype = getSpec (operandType (left));
9318 aopOp (left, ic, FALSE, FALSE);
9320 /* if the value is already in a pointer register
9321 then don't need anything more */
9322 if (!AOP_INPREG (AOP (left)))
9324 /* otherwise get a free pointer register */
9326 preg = getFreePtr (ic, &aop, FALSE);
9327 emitcode ("mov", "%s,%s",
9329 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9333 rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9335 freeAsmop (left, NULL, ic, TRUE);
9336 aopOp (result, ic, FALSE, FALSE);
9338 /* if bitfield then unpack the bits */
9339 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9340 genUnpackBits (result, rname, PPOINTER);
9343 /* we have can just get the values */
9344 int size = AOP_SIZE (result);
9350 emitcode ("movx", "a,@%s", rname);
9351 aopPut (AOP (result), "a", offset);
9356 emitcode ("inc", "%s", rname);
9360 /* now some housekeeping stuff */
9363 /* we had to allocate for this iCode */
9364 if (pi) aopPut ( AOP (left), rname, 0);
9365 freeAsmop (NULL, aop, ic, TRUE);
9369 /* we did not allocate which means left
9370 already in a pointer register, then
9371 if size > 0 && this could be used again
9372 we have to point it back to where it
9374 if (AOP_SIZE (result) > 1 &&
9375 !OP_SYMBOL (left)->remat &&
9376 (OP_SYMBOL (left)->liveTo > ic->seq ||
9380 int size = AOP_SIZE (result) - 1;
9382 emitcode ("dec", "%s", rname);
9387 freeAsmop (result, NULL, ic, TRUE);
9388 if (pi) pi->generated = 1;
9391 /*-----------------------------------------------------------------*/
9392 /* genFarPointerGet - gget value from far space */
9393 /*-----------------------------------------------------------------*/
9395 genFarPointerGet (operand * left,
9396 operand * result, iCode * ic, iCode *pi)
9398 int size, offset, dopi=1;
9399 sym_link *retype = getSpec (operandType (result));
9400 sym_link *letype = getSpec (operandType (left));
9401 D (emitcode (";", "genFarPointerGet"););
9403 aopOp (left, ic, FALSE, FALSE);
9405 /* if the operand is already in dptr
9406 then we do nothing else we move the value to dptr */
9407 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9409 /* if this is remateriazable */
9410 if (AOP_TYPE (left) == AOP_IMMD)
9412 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9416 /* we need to get it byte by byte */
9417 _startLazyDPSEvaluation ();
9418 if (AOP_TYPE (left) != AOP_DPTR)
9420 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9421 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9422 if (options.model == MODEL_FLAT24)
9423 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9427 /* We need to generate a load to DPTR indirect through DPTR. */
9428 D (emitcode (";", "genFarPointerGet -- indirection special case."););
9429 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9430 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9431 if (options.model == MODEL_FLAT24)
9432 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9433 emitcode ("pop", "dph");
9434 emitcode ("pop", "dpl");
9437 _endLazyDPSEvaluation ();
9440 /* so dptr know contains the address */
9441 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9443 /* if bit then unpack */
9444 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9445 if (AOP_INDPTRn(left)) {
9446 genSetDPTR(AOP(left)->aopu.dptr);
9448 genUnpackBits (result, "dptr", FPOINTER);
9449 if (AOP_INDPTRn(left)) {
9454 size = AOP_SIZE (result);
9457 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9459 genSetDPTR(AOP(left)->aopu.dptr);
9460 emitcode ("movx", "a,@dptr");
9461 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9462 emitcode ("inc", "dptr");
9464 aopPut (AOP (result), "a", offset++);
9467 _startLazyDPSEvaluation ();
9469 if (AOP_INDPTRn(left)) {
9470 genSetDPTR(AOP(left)->aopu.dptr);
9476 emitcode ("movx", "a,@dptr");
9477 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9478 emitcode ("inc", "dptr");
9480 aopPut (AOP (result), "a", offset++);
9482 _endLazyDPSEvaluation ();
9485 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9486 if (!AOP_INDPTRn(left)) {
9487 _startLazyDPSEvaluation ();
9488 aopPut ( AOP (left), "dpl", 0);
9489 aopPut ( AOP (left), "dph", 1);
9490 if (options.model == MODEL_FLAT24)
9491 aopPut ( AOP (left), "dpx", 2);
9492 _endLazyDPSEvaluation ();
9495 } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) &&
9496 AOP_SIZE(result) > 1 &&
9498 (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
9500 size = AOP_SIZE (result) - 1;
9501 if (AOP_INDPTRn(left)) {
9502 genSetDPTR(AOP(left)->aopu.dptr);
9504 while (size--) emitcode ("lcall","__decdptr");
9505 if (AOP_INDPTRn(left)) {
9510 freeAsmop (left, NULL, ic, TRUE);
9511 freeAsmop (result, NULL, ic, TRUE);
9514 /*-----------------------------------------------------------------*/
9515 /* genCodePointerGet - get value from code space */
9516 /*-----------------------------------------------------------------*/
9518 genCodePointerGet (operand * left,
9519 operand * result, iCode * ic, iCode *pi)
9521 int size, offset, dopi=1;
9522 sym_link *retype = getSpec (operandType (result));
9524 aopOp (left, ic, FALSE, FALSE);
9526 /* if the operand is already in dptr
9527 then we do nothing else we move the value to dptr */
9528 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
9530 /* if this is remateriazable */
9531 if (AOP_TYPE (left) == AOP_IMMD)
9533 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9536 { /* we need to get it byte by byte */
9537 _startLazyDPSEvaluation ();
9538 if (AOP_TYPE (left) != AOP_DPTR)
9540 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9541 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9542 if (options.model == MODEL_FLAT24)
9543 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9547 /* We need to generate a load to DPTR indirect through DPTR. */
9548 D (emitcode (";", "gencodePointerGet -- indirection special case."););
9549 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9550 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9551 if (options.model == MODEL_FLAT24)
9552 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9553 emitcode ("pop", "dph");
9554 emitcode ("pop", "dpl");
9557 _endLazyDPSEvaluation ();
9560 /* so dptr know contains the address */
9561 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9563 /* if bit then unpack */
9564 if (IS_BITVAR (retype)) {
9565 if (AOP_INDPTRn(left)) {
9566 genSetDPTR(AOP(left)->aopu.dptr);
9568 genUnpackBits (result, "dptr", CPOINTER);
9569 if (AOP_INDPTRn(left)) {
9574 size = AOP_SIZE (result);
9576 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9578 genSetDPTR(AOP(left)->aopu.dptr);
9579 emitcode ("clr", "a");
9580 emitcode ("movc", "a,@a+dptr");
9581 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9582 emitcode ("inc", "dptr");
9584 aopPut (AOP (result), "a", offset++);
9587 _startLazyDPSEvaluation ();
9590 if (AOP_INDPTRn(left)) {
9591 genSetDPTR(AOP(left)->aopu.dptr);
9597 emitcode ("clr", "a");
9598 emitcode ("movc", "a,@a+dptr");
9599 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9600 emitcode ("inc", "dptr");
9601 aopPut (AOP (result), "a", offset++);
9603 _endLazyDPSEvaluation ();
9606 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9607 if (!AOP_INDPTRn(left)) {
9608 _startLazyDPSEvaluation ();
9610 aopPut ( AOP (left), "dpl", 0);
9611 aopPut ( AOP (left), "dph", 1);
9612 if (options.model == MODEL_FLAT24)
9613 aopPut ( AOP (left), "dpx", 2);
9615 _endLazyDPSEvaluation ();
9618 } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
9619 AOP_SIZE(result) > 1 &&
9620 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9622 size = AOP_SIZE (result) - 1;
9623 if (AOP_INDPTRn(left)) {
9624 genSetDPTR(AOP(left)->aopu.dptr);
9626 while (size--) emitcode ("lcall","__decdptr");
9627 if (AOP_INDPTRn(left)) {
9632 freeAsmop (left, NULL, ic, TRUE);
9633 freeAsmop (result, NULL, ic, TRUE);
9636 /*-----------------------------------------------------------------*/
9637 /* genGenPointerGet - gget value from generic pointer space */
9638 /*-----------------------------------------------------------------*/
9640 genGenPointerGet (operand * left,
9641 operand * result, iCode * ic, iCode * pi)
9644 sym_link *retype = getSpec (operandType (result));
9645 sym_link *letype = getSpec (operandType (left));
9647 D (emitcode (";", "genGenPointerGet "); );
9649 aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
9651 /* if the operand is already in dptr
9652 then we do nothing else we move the value to dptr */
9653 if (AOP_TYPE (left) != AOP_STR)
9655 /* if this is remateriazable */
9656 if (AOP_TYPE (left) == AOP_IMMD)
9658 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9659 if (AOP(left)->aopu.aop_immd.from_cast_remat)
9661 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
9665 emitcode ("mov", "b,#%d", pointerCode (retype));
9669 { /* we need to get it byte by byte */
9670 _startLazyDPSEvaluation ();
9671 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
9672 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
9673 if (options.model == MODEL_FLAT24) {
9674 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9675 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
9677 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9679 _endLazyDPSEvaluation ();
9683 /* so dptr-b now contains the address */
9685 aopOp (result, ic, FALSE, TRUE);
9688 /* if bit then unpack */
9689 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9691 genUnpackBits (result, "dptr", GPOINTER);
9695 size = AOP_SIZE (result);
9702 // Get two bytes at a time, results in _AP & A.
9703 // dptr will be incremented ONCE by __gptrgetWord.
9705 // Note: any change here must be coordinated
9706 // with the implementation of __gptrgetWord
9707 // in device/lib/_gptrget.c
9708 emitcode ("lcall", "__gptrgetWord");
9709 aopPut (AOP (result), DP2_RESULT_REG, offset++);
9710 aopPut (AOP (result), "a", offset++);
9715 // Only one byte to get.
9716 emitcode ("lcall", "__gptrget");
9717 aopPut (AOP (result), "a", offset++);
9720 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9722 emitcode ("inc", "dptr");
9727 if (pi && AOP_TYPE (left) != AOP_IMMD) {
9728 _startLazyDPSEvaluation ();
9730 aopPut ( AOP (left), "dpl", 0);
9731 aopPut ( AOP (left), "dph", 1);
9732 if (options.model == MODEL_FLAT24) {
9733 aopPut ( AOP (left), "dpx", 2);
9734 aopPut ( AOP (left), "b", 3);
9735 } else aopPut ( AOP (left), "b", 2);
9737 _endLazyDPSEvaluation ();
9740 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9741 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9743 size = AOP_SIZE (result) - 1;
9744 while (size--) emitcode ("lcall","__decdptr");
9747 freeAsmop (left, NULL, ic, TRUE);
9748 freeAsmop (result, NULL, ic, TRUE);
9751 /*-----------------------------------------------------------------*/
9752 /* genPointerGet - generate code for pointer get */
9753 /*-----------------------------------------------------------------*/
9755 genPointerGet (iCode * ic, iCode *pi)
9757 operand *left, *result;
9758 sym_link *type, *etype;
9761 D (emitcode (";", "genPointerGet ");
9764 left = IC_LEFT (ic);
9765 result = IC_RESULT (ic);
9767 /* depending on the type of pointer we need to
9768 move it to the correct pointer register */
9769 type = operandType (left);
9770 etype = getSpec (type);
9771 /* if left is of type of pointer then it is simple */
9772 if (IS_PTR (type) && !IS_FUNC (type->next))
9773 p_type = DCL_TYPE (type);
9776 /* we have to go by the storage class */
9777 p_type = PTR_TYPE (SPEC_OCLS (etype));
9779 /* special case when cast remat */
9780 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9781 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9782 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9783 type = operandType (left);
9784 p_type = DCL_TYPE (type);
9786 /* now that we have the pointer type we assign
9787 the pointer values */
9793 genNearPointerGet (left, result, ic, pi);
9797 genPagedPointerGet (left, result, ic, pi);
9801 genFarPointerGet (left, result, ic, pi);
9805 genCodePointerGet (left, result, ic, pi);
9809 genGenPointerGet (left, result, ic, pi);
9815 /*-----------------------------------------------------------------*/
9816 /* genPackBits - generates code for packed bit storage */
9817 /*-----------------------------------------------------------------*/
9819 genPackBits (sym_link * etype,
9821 char *rname, int p_type)
9823 int offset = 0; /* source byte offset */
9824 int rlen = 0; /* remaining bitfield length */
9825 int blen; /* bitfield length */
9826 int bstr; /* bitfield starting bit within byte */
9827 int litval; /* source literal value (if AOP_LIT) */
9828 unsigned char mask; /* bitmask within current byte */
9830 D(emitcode ("; genPackBits",""));
9832 blen = SPEC_BLEN (etype);
9833 bstr = SPEC_BSTR (etype);
9835 /* If the bitfield length is less than a byte */
9838 mask = ((unsigned char) (0xFF << (blen + bstr)) |
9839 (unsigned char) (0xFF >> (8 - bstr)));
9841 if (AOP_TYPE (right) == AOP_LIT)
9843 /* Case with a bitfield length <8 and literal source
9845 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9847 litval &= (~mask) & 0xff;
9848 emitPtrByteGet (rname, p_type, FALSE);
9849 if ((mask|litval)!=0xff)
9850 emitcode ("anl","a,#!constbyte", mask);
9852 emitcode ("orl","a,#!constbyte", litval);
9856 if ((blen==1) && (p_type!=GPOINTER))
9858 /* Case with a bitfield length == 1 and no generic pointer
9860 if (AOP_TYPE (right) == AOP_CRY)
9861 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9864 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
9865 emitcode ("rrc","a");
9867 emitPtrByteGet (rname, p_type, FALSE);
9868 emitcode ("mov","acc.%d,c",bstr);
9872 /* Case with a bitfield length < 8 and arbitrary source
9874 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
9875 /* shift and mask source value */
9877 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
9879 /* transfer A to B and get next byte */
9880 emitPtrByteGet (rname, p_type, TRUE);
9882 emitcode ("anl", "a,#!constbyte", mask);
9883 emitcode ("orl", "a,b");
9884 if (p_type == GPOINTER)
9885 emitcode ("pop", "b");
9889 emitPtrByteSet (rname, p_type, "a");
9893 /* Bit length is greater than 7 bits. In this case, copy */
9894 /* all except the partial byte at the end */
9895 for (rlen=blen;rlen>=8;rlen-=8)
9897 emitPtrByteSet (rname, p_type,
9898 aopGet (AOP (right), offset++, FALSE, TRUE, NULL) );
9900 emitcode ("inc", "%s", rname);
9903 /* If there was a partial byte at the end */
9906 mask = (((unsigned char) -1 << rlen) & 0xff);
9908 if (AOP_TYPE (right) == AOP_LIT)
9910 /* Case with partial byte and literal source
9912 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9913 litval >>= (blen-rlen);
9914 litval &= (~mask) & 0xff;
9915 emitPtrByteGet (rname, p_type, FALSE);
9916 if ((mask|litval)!=0xff)
9917 emitcode ("anl","a,#!constbyte", mask);
9919 emitcode ("orl","a,#!constbyte", litval);
9923 /* Case with partial byte and arbitrary source
9925 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9926 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
9928 /* transfer A to B and get next byte */
9929 emitPtrByteGet (rname, p_type, TRUE);
9931 emitcode ("anl", "a,#!constbyte", mask);
9932 emitcode ("orl", "a,b");
9933 if (p_type == GPOINTER)
9934 emitcode ("pop", "b");
9936 emitPtrByteSet (rname, p_type, "a");
9942 /*-----------------------------------------------------------------*/
9943 /* genDataPointerSet - remat pointer to data space */
9944 /*-----------------------------------------------------------------*/
9946 genDataPointerSet (operand * right,
9950 int size, offset = 0;
9953 aopOp (right, ic, FALSE, FALSE);
9955 l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
9956 size = AOP_SIZE (right);
9961 SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
9965 SNPRINTF (buff, sizeof(buff), "%s", l + 1);
9968 emitcode ("mov", "%s,%s", buff,
9969 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9972 freeAsmop (right, NULL, ic, TRUE);
9973 freeAsmop (result, NULL, ic, TRUE);
9976 /*-----------------------------------------------------------------*/
9977 /* genNearPointerSet - emitcode for near pointer put */
9978 /*-----------------------------------------------------------------*/
9980 genNearPointerSet (operand * right,
9987 sym_link *retype, *letype;
9988 sym_link *ptype = operandType (result);
9990 retype = getSpec (operandType (right));
9991 letype = getSpec (ptype);
9993 aopOp (result, ic, FALSE, FALSE);
9995 /* if the result is rematerializable &
9996 in data space & not a bit variable */
9997 if (AOP_TYPE (result) == AOP_IMMD &&
9998 DCL_TYPE (ptype) == POINTER &&
9999 !IS_BITVAR (retype) &&
10000 !IS_BITVAR (letype))
10002 genDataPointerSet (right, result, ic);
10006 /* if the value is already in a pointer register
10007 then don't need anything more */
10008 if (!AOP_INPREG (AOP (result)))
10010 /* otherwise get a free pointer register */
10013 aop = newAsmop (0);
10014 preg = getFreePtr (ic, &aop, FALSE);
10015 emitcode ("mov", "%s,%s",
10017 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10018 rname = preg->name;
10021 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10023 aopOp (right, ic, FALSE, FALSE);
10025 /* if bitfield then unpack the bits */
10026 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10027 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
10030 /* we have can just get the values */
10031 int size = AOP_SIZE (right);
10036 l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
10040 emitcode ("mov", "@%s,a", rname);
10043 emitcode ("mov", "@%s,%s", rname, l);
10045 emitcode ("inc", "%s", rname);
10050 /* now some housekeeping stuff */
10053 /* we had to allocate for this iCode */
10054 if (pi) aopPut (AOP (result),rname,0);
10055 freeAsmop (NULL, aop, ic, TRUE);
10059 /* we did not allocate which means left
10060 already in a pointer register, then
10061 if size > 0 && this could be used again
10062 we have to point it back to where it
10064 if (AOP_SIZE (right) > 1 &&
10065 !OP_SYMBOL (result)->remat &&
10066 (OP_SYMBOL (result)->liveTo > ic->seq ||
10070 int size = AOP_SIZE (right) - 1;
10072 emitcode ("dec", "%s", rname);
10077 if (pi) pi->generated = 1;
10078 freeAsmop (result, NULL, ic, TRUE);
10079 freeAsmop (right, NULL, ic, TRUE);
10084 /*-----------------------------------------------------------------*/
10085 /* genPagedPointerSet - emitcode for Paged pointer put */
10086 /*-----------------------------------------------------------------*/
10088 genPagedPointerSet (operand * right,
10095 sym_link *retype, *letype;
10097 retype = getSpec (operandType (right));
10098 letype = getSpec (operandType (result));
10100 aopOp (result, ic, FALSE, FALSE);
10102 /* if the value is already in a pointer register
10103 then don't need anything more */
10104 if (!AOP_INPREG (AOP (result)))
10106 /* otherwise get a free pointer register */
10109 aop = newAsmop (0);
10110 preg = getFreePtr (ic, &aop, FALSE);
10111 emitcode ("mov", "%s,%s",
10113 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10114 rname = preg->name;
10117 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10119 aopOp (right, ic, FALSE, FALSE);
10121 /* if bitfield then unpack the bits */
10122 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10123 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
10126 /* we have can just get the values */
10127 int size = AOP_SIZE (right);
10132 MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10134 emitcode ("movx", "@%s,a", rname);
10137 emitcode ("inc", "%s", rname);
10143 /* now some housekeeping stuff */
10146 if (pi) aopPut (AOP (result),rname,0);
10147 /* we had to allocate for this iCode */
10148 freeAsmop (NULL, aop, ic, TRUE);
10152 /* we did not allocate which means left
10153 already in a pointer register, then
10154 if size > 0 && this could be used again
10155 we have to point it back to where it
10157 if (AOP_SIZE (right) > 1 &&
10158 !OP_SYMBOL (result)->remat &&
10159 (OP_SYMBOL (result)->liveTo > ic->seq ||
10163 int size = AOP_SIZE (right) - 1;
10165 emitcode ("dec", "%s", rname);
10170 if (pi) pi->generated = 1;
10171 freeAsmop (result, NULL, ic, TRUE);
10172 freeAsmop (right, NULL, ic, TRUE);
10177 /*-----------------------------------------------------------------*/
10178 /* genFarPointerSet - set value from far space */
10179 /*-----------------------------------------------------------------*/
10181 genFarPointerSet (operand * right,
10182 operand * result, iCode * ic, iCode *pi)
10184 int size, offset, dopi=1;
10185 sym_link *retype = getSpec (operandType (right));
10186 sym_link *letype = getSpec (operandType (result));
10188 aopOp (result, ic, FALSE, FALSE);
10190 /* if the operand is already in dptr
10191 then we do nothing else we move the value to dptr */
10192 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10194 /* if this is remateriazable */
10195 if (AOP_TYPE (result) == AOP_IMMD)
10196 emitcode ("mov", "dptr,%s",
10197 aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10200 /* we need to get it byte by byte */
10201 _startLazyDPSEvaluation ();
10202 if (AOP_TYPE (result) != AOP_DPTR)
10204 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10205 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10206 if (options.model == MODEL_FLAT24)
10207 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10211 /* We need to generate a load to DPTR indirect through DPTR. */
10212 D (emitcode (";", "genFarPointerSet -- indirection special case."););
10214 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10215 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10216 if (options.model == MODEL_FLAT24)
10217 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10218 emitcode ("pop", "dph");
10219 emitcode ("pop", "dpl");
10222 _endLazyDPSEvaluation ();
10225 /* so dptr know contains the address */
10226 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10228 /* if bit then unpack */
10229 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
10230 if (AOP_INDPTRn(result)) {
10231 genSetDPTR(AOP(result)->aopu.dptr);
10233 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
10234 if (AOP_INDPTRn(result)) {
10238 size = AOP_SIZE (right);
10240 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10242 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10244 genSetDPTR(AOP(result)->aopu.dptr);
10245 emitcode ("movx", "@dptr,a");
10246 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10247 emitcode ("inc", "dptr");
10251 _startLazyDPSEvaluation ();
10253 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10255 if (AOP_INDPTRn(result)) {
10256 genSetDPTR(AOP(result)->aopu.dptr);
10262 emitcode ("movx", "@dptr,a");
10263 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10264 emitcode ("inc", "dptr");
10266 _endLazyDPSEvaluation ();
10270 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10271 if (!AOP_INDPTRn(result)) {
10272 _startLazyDPSEvaluation ();
10274 aopPut (AOP(result),"dpl",0);
10275 aopPut (AOP(result),"dph",1);
10276 if (options.model == MODEL_FLAT24)
10277 aopPut (AOP(result),"dpx",2);
10279 _endLazyDPSEvaluation ();
10282 } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
10283 AOP_SIZE(right) > 1 &&
10284 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10286 size = AOP_SIZE (right) - 1;
10287 if (AOP_INDPTRn(result)) {
10288 genSetDPTR(AOP(result)->aopu.dptr);
10290 while (size--) emitcode ("lcall","__decdptr");
10291 if (AOP_INDPTRn(result)) {
10295 freeAsmop (result, NULL, ic, TRUE);
10296 freeAsmop (right, NULL, ic, TRUE);
10299 /*-----------------------------------------------------------------*/
10300 /* genGenPointerSet - set value from generic pointer space */
10301 /*-----------------------------------------------------------------*/
10303 genGenPointerSet (operand * right,
10304 operand * result, iCode * ic, iCode *pi)
10307 sym_link *retype = getSpec (operandType (right));
10308 sym_link *letype = getSpec (operandType (result));
10310 aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10312 /* if the operand is already in dptr
10313 then we do nothing else we move the value to dptr */
10314 if (AOP_TYPE (result) != AOP_STR)
10316 _startLazyDPSEvaluation ();
10317 /* if this is remateriazable */
10318 if (AOP_TYPE (result) == AOP_IMMD)
10320 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10321 if (AOP(result)->aopu.aop_immd.from_cast_remat)
10323 MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10328 "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10332 { /* we need to get it byte by byte */
10333 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10334 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10335 if (options.model == MODEL_FLAT24) {
10336 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10337 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10339 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10342 _endLazyDPSEvaluation ();
10344 /* so dptr + b now contains the address */
10346 aopOp (right, ic, FALSE, TRUE);
10350 /* if bit then unpack */
10351 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10353 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
10357 size = AOP_SIZE (right);
10360 _startLazyDPSEvaluation ();
10365 // Set two bytes at a time, passed in _AP & A.
10366 // dptr will be incremented ONCE by __gptrputWord.
10368 // Note: any change here must be coordinated
10369 // with the implementation of __gptrputWord
10370 // in device/lib/_gptrput.c
10371 emitcode("mov", "_ap, %s",
10372 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10373 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10377 emitcode ("lcall", "__gptrputWord");
10382 // Only one byte to put.
10383 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10387 emitcode ("lcall", "__gptrput");
10390 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10392 emitcode ("inc", "dptr");
10395 _endLazyDPSEvaluation ();
10398 if (pi && AOP_TYPE (result) != AOP_IMMD) {
10399 _startLazyDPSEvaluation ();
10401 aopPut (AOP(result),"dpl",0);
10402 aopPut (AOP(result),"dph",1);
10403 if (options.model == MODEL_FLAT24) {
10404 aopPut (AOP(result),"dpx",2);
10405 aopPut (AOP(result),"b",3);
10407 aopPut (AOP(result),"b",2);
10409 _endLazyDPSEvaluation ();
10412 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10413 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10415 size = AOP_SIZE (right) - 1;
10416 while (size--) emitcode ("lcall","__decdptr");
10418 freeAsmop (result, NULL, ic, TRUE);
10419 freeAsmop (right, NULL, ic, TRUE);
10422 /*-----------------------------------------------------------------*/
10423 /* genPointerSet - stores the value into a pointer location */
10424 /*-----------------------------------------------------------------*/
10426 genPointerSet (iCode * ic, iCode *pi)
10428 operand *right, *result;
10429 sym_link *type, *etype;
10432 D (emitcode (";", "genPointerSet "););
10434 right = IC_RIGHT (ic);
10435 result = IC_RESULT (ic);
10437 /* depending on the type of pointer we need to
10438 move it to the correct pointer register */
10439 type = operandType (result);
10440 etype = getSpec (type);
10441 /* if left is of type of pointer then it is simple */
10442 if (IS_PTR (type) && !IS_FUNC (type->next))
10444 p_type = DCL_TYPE (type);
10448 /* we have to go by the storage class */
10449 p_type = PTR_TYPE (SPEC_OCLS (etype));
10451 /* special case when cast remat */
10452 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10453 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10454 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10455 type = operandType (result);
10456 p_type = DCL_TYPE (type);
10459 /* now that we have the pointer type we assign
10460 the pointer values */
10466 genNearPointerSet (right, result, ic, pi);
10470 genPagedPointerSet (right, result, ic, pi);
10474 genFarPointerSet (right, result, ic, pi);
10478 genGenPointerSet (right, result, ic, pi);
10482 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10483 "genPointerSet: illegal pointer type");
10488 /*-----------------------------------------------------------------*/
10489 /* genIfx - generate code for Ifx statement */
10490 /*-----------------------------------------------------------------*/
10492 genIfx (iCode * ic, iCode * popIc)
10494 operand *cond = IC_COND (ic);
10497 D (emitcode (";", "genIfx "););
10499 aopOp (cond, ic, FALSE, FALSE);
10501 /* get the value into acc */
10502 if (AOP_TYPE (cond) != AOP_CRY)
10511 /* the result is now in the accumulator */
10512 freeAsmop (cond, NULL, ic, TRUE);
10514 /* if there was something to be popped then do it */
10518 /* if the condition is a bit variable */
10519 if (isbit && IS_ITEMP (cond) &&
10522 genIfxJump (ic, SPIL_LOC (cond)->rname);
10524 else if (isbit && !IS_ITEMP (cond))
10526 genIfxJump (ic, OP_SYMBOL (cond)->rname);
10530 genIfxJump (ic, "a");
10536 /*-----------------------------------------------------------------*/
10537 /* genAddrOf - generates code for address of */
10538 /*-----------------------------------------------------------------*/
10540 genAddrOf (iCode * ic)
10542 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10545 D (emitcode (";", "genAddrOf ");
10548 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10550 /* if the operand is on the stack then we
10551 need to get the stack offset of this
10553 if (sym->onStack) {
10555 /* if 10 bit stack */
10556 if (options.stack10bit) {
10560 tsprintf(buff, sizeof(buff),
10561 "#!constbyte",(options.stack_loc >> 16) & 0xff);
10562 /* if it has an offset then we need to compute it */
10563 /* emitcode ("subb", "a,#!constbyte", */
10564 /* -((sym->stack < 0) ? */
10565 /* ((short) (sym->stack - _G.nRegsSaved)) : */
10566 /* ((short) sym->stack)) & 0xff); */
10567 /* emitcode ("mov","b,a"); */
10568 /* emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
10569 /* ((short) (sym->stack - _G.nRegsSaved)) : */
10570 /* ((short) sym->stack)) >> 8) & 0xff); */
10572 emitcode ("mov", "a,_bpx");
10573 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
10574 ((char) (sym->stack - _G.nRegsSaved)) :
10575 ((char) sym->stack )) & 0xff);
10576 emitcode ("mov", "b,a");
10577 emitcode ("mov", "a,_bpx+1");
10579 offset = (((sym->stack < 0) ?
10580 ((short) (sym->stack - _G.nRegsSaved)) :
10581 ((short) sym->stack )) >> 8) & 0xff;
10583 emitcode ("addc","a,#!constbyte", offset);
10585 aopPut (AOP (IC_RESULT (ic)), "b", 0);
10586 aopPut (AOP (IC_RESULT (ic)), "a", 1);
10587 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10589 /* we can just move _bp */
10590 aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10591 aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10592 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10595 /* if it has an offset then we need to compute it */
10597 emitcode ("mov", "a,_bp");
10598 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10599 aopPut (AOP (IC_RESULT (ic)), "a", 0);
10601 /* we can just move _bp */
10602 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10604 /* fill the result with zero */
10605 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10608 if (options.stack10bit && size < (FPTRSIZE - 1)) {
10610 "*** warning: pointer to stack var truncated.\n");
10615 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10621 /* object not on stack then we need the name */
10622 size = AOP_SIZE (IC_RESULT (ic));
10627 char s[SDCC_NAME_MAX];
10631 tsprintf(s, sizeof(s), "#!his",sym->rname);
10634 tsprintf(s, sizeof(s), "#!hihis",sym->rname);
10637 tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
10639 default: /* should not need this (just in case) */
10640 SNPRINTF (s, sizeof(s), "#(%s >> %d)",
10647 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10650 aopPut (AOP (IC_RESULT (ic)), s, offset++);
10654 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10658 #if 0 // obsolete, and buggy for != xdata
10659 /*-----------------------------------------------------------------*/
10660 /* genArrayInit - generates code for address of */
10661 /*-----------------------------------------------------------------*/
10663 genArrayInit (iCode * ic)
10665 literalList *iLoop;
10667 int elementSize = 0, eIndex;
10668 unsigned val, lastVal;
10670 operand *left=IC_LEFT(ic);
10672 D (emitcode (";", "genArrayInit "););
10674 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10676 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10678 // Load immediate value into DPTR.
10679 emitcode("mov", "dptr, %s",
10680 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
10682 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10685 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10686 "Unexpected operand to genArrayInit.\n");
10689 // a regression because of SDCCcse.c:1.52
10690 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10691 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10692 if (options.model == MODEL_FLAT24)
10693 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10697 type = operandType(IC_LEFT(ic));
10699 if (type && type->next)
10701 elementSize = getSize(type->next);
10705 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10706 "can't determine element size in genArrayInit.\n");
10710 iLoop = IC_ARRAYILIST(ic);
10715 bool firstpass = TRUE;
10717 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
10718 iLoop->count, (int)iLoop->literalValue, elementSize);
10724 symbol *tlbl = NULL;
10726 count = ix > 256 ? 256 : ix;
10730 tlbl = newiTempLabel (NULL);
10731 if (firstpass || (count & 0xff))
10733 emitcode("mov", "b, #!constbyte", count & 0xff);
10736 emitcode ("", "!tlabeldef", tlbl->key + 100);
10741 for (eIndex = 0; eIndex < elementSize; eIndex++)
10743 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10744 if (val != lastVal)
10746 emitcode("mov", "a, #!constbyte", val);
10750 emitcode("movx", "@dptr, a");
10751 emitcode("inc", "dptr");
10756 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10762 iLoop = iLoop->next;
10765 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10769 /*-----------------------------------------------------------------*/
10770 /* genFarFarAssign - assignment when both are in far space */
10771 /*-----------------------------------------------------------------*/
10773 genFarFarAssign (operand * result, operand * right, iCode * ic)
10775 int size = AOP_SIZE (right);
10777 symbol *rSym = NULL;
10781 /* quick & easy case. */
10782 D(emitcode(";","genFarFarAssign (1 byte case)"););
10783 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
10784 freeAsmop (right, NULL, ic, FALSE);
10785 /* now assign DPTR to result */
10787 aopOp(result, ic, FALSE, FALSE);
10789 aopPut(AOP(result), "a", 0);
10790 freeAsmop(result, NULL, ic, FALSE);
10794 /* See if we've got an underlying symbol to abuse. */
10795 if (IS_SYMOP(result) && OP_SYMBOL(result))
10797 if (IS_TRUE_SYMOP(result))
10799 rSym = OP_SYMBOL(result);
10801 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10803 rSym = OP_SYMBOL(result)->usl.spillLoc;
10807 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10809 /* We can use the '390 auto-toggle feature to good effect here. */
10811 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10812 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
10813 emitcode ("mov", "dptr,#%s", rSym->rname);
10814 /* DP2 = result, DP1 = right, DP1 is current. */
10817 emitcode("movx", "a,@dptr");
10818 emitcode("movx", "@dptr,a");
10821 emitcode("inc", "dptr");
10822 emitcode("inc", "dptr");
10825 emitcode("mov", "dps,#0");
10826 freeAsmop (right, NULL, ic, FALSE);
10828 some alternative code for processors without auto-toggle
10829 no time to test now, so later well put in...kpb
10830 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10831 emitcode("mov", "dps,#1"); /* Select DPTR2. */
10832 emitcode ("mov", "dptr,#%s", rSym->rname);
10833 /* DP2 = result, DP1 = right, DP1 is current. */
10837 emitcode("movx", "a,@dptr");
10839 emitcode("inc", "dptr");
10840 emitcode("inc", "dps");
10841 emitcode("movx", "@dptr,a");
10843 emitcode("inc", "dptr");
10844 emitcode("inc", "dps");
10846 emitcode("mov", "dps,#0");
10847 freeAsmop (right, NULL, ic, FALSE);
10852 D (emitcode (";", "genFarFarAssign"););
10853 aopOp (result, ic, TRUE, TRUE);
10855 _startLazyDPSEvaluation ();
10859 aopPut (AOP (result),
10860 aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
10863 _endLazyDPSEvaluation ();
10864 freeAsmop (result, NULL, ic, FALSE);
10865 freeAsmop (right, NULL, ic, FALSE);
10869 /*-----------------------------------------------------------------*/
10870 /* genAssign - generate code for assignment */
10871 /*-----------------------------------------------------------------*/
10873 genAssign (iCode * ic)
10875 operand *result, *right;
10877 unsigned long lit = 0L;
10879 D (emitcode (";", "genAssign ");
10882 result = IC_RESULT (ic);
10883 right = IC_RIGHT (ic);
10885 /* if they are the same */
10886 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10889 aopOp (right, ic, FALSE, FALSE);
10891 emitcode (";", "genAssign: resultIsFar = %s",
10892 isOperandInFarSpace (result) ?
10895 /* special case both in far space */
10896 if ((AOP_TYPE (right) == AOP_DPTR ||
10897 AOP_TYPE (right) == AOP_DPTR2) &&
10898 /* IS_TRUE_SYMOP(result) && */
10899 isOperandInFarSpace (result))
10901 genFarFarAssign (result, right, ic);
10905 aopOp (result, ic, TRUE, FALSE);
10907 /* if they are the same registers */
10908 if (sameRegs (AOP (right), AOP (result)))
10911 /* if the result is a bit */
10912 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10914 /* if the right size is a literal then
10915 we know what the value is */
10916 if (AOP_TYPE (right) == AOP_LIT)
10918 if (((int) operandLitValue (right)))
10919 aopPut (AOP (result), one, 0);
10921 aopPut (AOP (result), zero, 0);
10925 /* the right is also a bit variable */
10926 if (AOP_TYPE (right) == AOP_CRY)
10928 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10929 aopPut (AOP (result), "c", 0);
10933 /* we need to or */
10935 aopPut (AOP (result), "a", 0);
10939 /* bit variables done */
10941 size = AOP_SIZE (result);
10943 if (AOP_TYPE (right) == AOP_LIT)
10944 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10947 (AOP_TYPE (result) != AOP_REG) &&
10948 (AOP_TYPE (right) == AOP_LIT) &&
10949 !IS_FLOAT (operandType (right)))
10951 _startLazyDPSEvaluation ();
10952 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10954 aopPut (AOP (result),
10955 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10960 /* And now fill the rest with zeros. */
10963 emitcode ("clr", "a");
10967 aopPut (AOP (result), "a", offset++);
10969 _endLazyDPSEvaluation ();
10973 _startLazyDPSEvaluation ();
10976 aopPut (AOP (result),
10977 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10981 _endLazyDPSEvaluation ();
10985 freeAsmop (right, NULL, ic, FALSE);
10986 freeAsmop (result, NULL, ic, TRUE);
10989 /*-----------------------------------------------------------------*/
10990 /* genJumpTab - generates code for jump table */
10991 /*-----------------------------------------------------------------*/
10993 genJumpTab (iCode * ic)
10998 D (emitcode (";", "genJumpTab ");
11001 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
11002 /* get the condition into accumulator */
11003 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
11005 /* multiply by four! */
11006 emitcode ("add", "a,acc");
11007 emitcode ("add", "a,acc");
11008 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11010 jtab = newiTempLabel (NULL);
11011 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
11012 emitcode ("jmp", "@a+dptr");
11013 emitcode ("", "!tlabeldef", jtab->key + 100);
11014 /* now generate the jump labels */
11015 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11016 jtab = setNextItem (IC_JTLABELS (ic)))
11017 emitcode ("ljmp", "!tlabel", jtab->key + 100);
11021 /*-----------------------------------------------------------------*/
11022 /* genCast - gen code for casting */
11023 /*-----------------------------------------------------------------*/
11025 genCast (iCode * ic)
11027 operand *result = IC_RESULT (ic);
11028 sym_link *ctype = operandType (IC_LEFT (ic));
11029 sym_link *rtype = operandType (IC_RIGHT (ic));
11030 operand *right = IC_RIGHT (ic);
11033 D (emitcode (";", "genCast "););
11035 /* if they are equivalent then do nothing */
11036 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11039 aopOp (right, ic, FALSE, FALSE);
11040 aopOp (result, ic, FALSE, AOP_USESDPTR(right));
11042 /* if the result is a bit */
11043 if (IS_BITVAR (OP_SYMBOL (result)->type)
11044 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
11046 /* if the right size is a literal then
11047 we know what the value is */
11048 if (AOP_TYPE (right) == AOP_LIT)
11050 if (((int) operandLitValue (right)))
11051 aopPut (AOP (result), one, 0);
11053 aopPut (AOP (result), zero, 0);
11058 /* the right is also a bit variable */
11059 if (AOP_TYPE (right) == AOP_CRY)
11061 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11062 aopPut (AOP (result), "c", 0);
11066 /* we need to or */
11068 aopPut (AOP (result), "a", 0);
11072 /* if they are the same size : or less */
11073 if (AOP_SIZE (result) <= AOP_SIZE (right))
11076 /* if they are in the same place */
11077 if (sameRegs (AOP (right), AOP (result)))
11080 /* if they in different places then copy */
11081 size = AOP_SIZE (result);
11083 _startLazyDPSEvaluation ();
11086 aopPut (AOP (result),
11087 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11091 _endLazyDPSEvaluation ();
11096 /* if the result is of type pointer */
11097 if (IS_PTR (ctype))
11101 sym_link *type = operandType (right);
11103 /* pointer to generic pointer */
11104 if (IS_GENPTR (ctype))
11108 p_type = DCL_TYPE (type);
11112 #if OLD_CAST_BEHAVIOR
11113 /* KV: we are converting a non-pointer type to
11114 * a generic pointer. This (ifdef'd out) code
11115 * says that the resulting generic pointer
11116 * should have the same class as the storage
11117 * location of the non-pointer variable.
11119 * For example, converting an int (which happens
11120 * to be stored in DATA space) to a pointer results
11121 * in a DATA generic pointer; if the original int
11122 * in XDATA space, so will be the resulting pointer.
11124 * I don't like that behavior, and thus this change:
11125 * all such conversions will be forced to XDATA and
11126 * throw a warning. If you want some non-XDATA
11127 * type, or you want to suppress the warning, you
11128 * must go through an intermediate cast, like so:
11130 * char _generic *gp = (char _xdata *)(intVar);
11132 sym_link *etype = getSpec (type);
11134 /* we have to go by the storage class */
11135 if (SPEC_OCLS (etype) != generic)
11137 p_type = PTR_TYPE (SPEC_OCLS (etype));
11142 /* Converting unknown class (i.e. register variable)
11143 * to generic pointer. This is not good, but
11144 * we'll make a guess (and throw a warning).
11147 werror (W_INT_TO_GEN_PTR_CAST);
11151 /* the first two bytes are known */
11152 size = GPTRSIZE - 1;
11154 _startLazyDPSEvaluation ();
11157 aopPut (AOP (result),
11158 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11162 _endLazyDPSEvaluation ();
11164 /* the last byte depending on type */
11166 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11171 // pointerTypeToGPByte will have bitched.
11175 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11176 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11181 /* just copy the pointers */
11182 size = AOP_SIZE (result);
11184 _startLazyDPSEvaluation ();
11187 aopPut (AOP (result),
11188 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11192 _endLazyDPSEvaluation ();
11196 /* so we now know that the size of destination is greater
11197 than the size of the source */
11198 /* we move to result for the size of source */
11199 size = AOP_SIZE (right);
11201 _startLazyDPSEvaluation ();
11204 aopPut (AOP (result),
11205 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11209 _endLazyDPSEvaluation ();
11211 /* now depending on the sign of the source && destination */
11212 size = AOP_SIZE (result) - AOP_SIZE (right);
11213 /* if unsigned or not an integral type */
11214 /* also, if the source is a bit, we don't need to sign extend, because
11215 * it can't possibly have set the sign bit.
11217 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
11221 aopPut (AOP (result), zero, offset++);
11226 /* we need to extend the sign :{ */
11227 MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11228 FALSE, FALSE, NULL));
11229 emitcode ("rlc", "a");
11230 emitcode ("subb", "a,acc");
11232 aopPut (AOP (result), "a", offset++);
11235 /* we are done hurray !!!! */
11238 freeAsmop (right, NULL, ic, TRUE);
11239 freeAsmop (result, NULL, ic, TRUE);
11243 /*-----------------------------------------------------------------*/
11244 /* genDjnz - generate decrement & jump if not zero instrucion */
11245 /*-----------------------------------------------------------------*/
11247 genDjnz (iCode * ic, iCode * ifx)
11249 symbol *lbl, *lbl1;
11253 /* if the if condition has a false label
11254 then we cannot save */
11255 if (IC_FALSE (ifx))
11258 /* if the minus is not of the form
11260 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11261 !IS_OP_LITERAL (IC_RIGHT (ic)))
11264 if (operandLitValue (IC_RIGHT (ic)) != 1)
11267 /* if the size of this greater than one then no
11269 if (getSize (operandType (IC_RESULT (ic))) > 1)
11272 /* otherwise we can save BIG */
11273 D(emitcode(";", "genDjnz"););
11275 lbl = newiTempLabel (NULL);
11276 lbl1 = newiTempLabel (NULL);
11278 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11280 if (AOP_NEEDSACC(IC_RESULT(ic)))
11282 /* If the result is accessed indirectly via
11283 * the accumulator, we must explicitly write
11284 * it back after the decrement.
11286 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11288 if (strcmp(rByte, "a"))
11290 /* Something is hopelessly wrong */
11291 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11292 __FILE__, __LINE__);
11293 /* We can just give up; the generated code will be inefficient,
11294 * but what the hey.
11296 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11299 emitcode ("dec", "%s", rByte);
11300 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11301 emitcode ("jnz", "!tlabel", lbl->key + 100);
11303 else if (IS_AOP_PREG (IC_RESULT (ic)))
11305 emitcode ("dec", "%s",
11306 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11307 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11308 emitcode ("jnz", "!tlabel", lbl->key + 100);
11312 emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11315 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11316 emitcode ("", "!tlabeldef", lbl->key + 100);
11317 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11318 emitcode ("", "!tlabeldef", lbl1->key + 100);
11320 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11321 ifx->generated = 1;
11325 /*-----------------------------------------------------------------*/
11326 /* genReceive - generate code for a receive iCode */
11327 /*-----------------------------------------------------------------*/
11329 genReceive (iCode * ic)
11331 int size = getSize (operandType (IC_RESULT (ic)));
11335 D (emitcode (";", "genReceive "););
11337 if (ic->argreg == 1)
11339 /* first parameter */
11340 if (AOP_IS_STR(IC_RESULT(ic)))
11342 /* Nothing to do: it's already in the proper place. */
11349 useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11350 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11351 IS_TRUE_SYMOP (IC_RESULT (ic)));
11354 aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11357 /* Sanity checking... */
11358 if (AOP_USESDPTR(IC_RESULT(ic)))
11360 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11361 "genReceive got unexpected DPTR.");
11363 assignResultValue (IC_RESULT (ic));
11368 /* second receive onwards */
11369 /* this gets a little tricky since unused recevies will be
11370 eliminated, we have saved the reg in the type field . and
11371 we use that to figure out which register to use */
11372 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11373 rb1off = ic->argreg;
11376 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11379 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11382 /*-----------------------------------------------------------------*/
11383 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
11384 /*-----------------------------------------------------------------*/
11385 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11387 operand *from , *to , *count;
11392 /* we know it has to be 3 parameters */
11393 assert (nparms == 3);
11395 rsave = newBitVect(16);
11396 /* save DPTR if it needs to be saved */
11397 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11398 if (bitVectBitValue(ic->rMask,i))
11399 rsave = bitVectSetBit(rsave,i);
11401 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11402 ds390_rUmaskForOp (IC_RESULT(ic))));
11409 aopOp (from, ic->next, FALSE, FALSE);
11411 /* get from into DPTR1 */
11412 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11413 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11414 if (options.model == MODEL_FLAT24) {
11415 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11418 freeAsmop (from, NULL, ic, FALSE);
11419 aopOp (to, ic, FALSE, FALSE);
11420 /* get "to" into DPTR */
11421 /* if the operand is already in dptr
11422 then we do nothing else we move the value to dptr */
11423 if (AOP_TYPE (to) != AOP_STR) {
11424 /* if already in DPTR then we need to push */
11425 if (AOP_TYPE(to) == AOP_DPTR) {
11426 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11427 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11428 if (options.model == MODEL_FLAT24)
11429 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11430 emitcode ("pop", "dph");
11431 emitcode ("pop", "dpl");
11433 _startLazyDPSEvaluation ();
11434 /* if this is remateriazable */
11435 if (AOP_TYPE (to) == AOP_IMMD) {
11436 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11437 } else { /* we need to get it byte by byte */
11438 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11439 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11440 if (options.model == MODEL_FLAT24) {
11441 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11444 _endLazyDPSEvaluation ();
11447 freeAsmop (to, NULL, ic, FALSE);
11448 _G.dptrInUse = _G.dptr1InUse = 1;
11449 aopOp (count, ic->next->next, FALSE,FALSE);
11450 lbl =newiTempLabel(NULL);
11452 /* now for the actual copy */
11453 if (AOP_TYPE(count) == AOP_LIT &&
11454 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11455 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11457 emitcode ("lcall","__bi_memcpyc2x_s");
11459 emitcode ("lcall","__bi_memcpyx2x_s");
11461 freeAsmop (count, NULL, ic, FALSE);
11463 symbol *lbl1 = newiTempLabel(NULL);
11465 emitcode (";"," Auto increment but no djnz");
11466 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11467 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11468 freeAsmop (count, NULL, ic, FALSE);
11469 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11470 emitcode ("","!tlabeldef",lbl->key+100);
11472 emitcode ("clr","a");
11473 emitcode ("movc", "a,@a+dptr");
11475 emitcode ("movx", "a,@dptr");
11476 emitcode ("movx", "@dptr,a");
11477 emitcode ("inc", "dptr");
11478 emitcode ("inc", "dptr");
11479 emitcode ("mov","a,b");
11480 emitcode ("orl","a,_ap");
11481 emitcode ("jz","!tlabel",lbl1->key+100);
11482 emitcode ("mov","a,_ap");
11483 emitcode ("add","a,#!constbyte",0xFF);
11484 emitcode ("mov","_ap,a");
11485 emitcode ("mov","a,b");
11486 emitcode ("addc","a,#!constbyte",0xFF);
11487 emitcode ("mov","b,a");
11488 emitcode ("sjmp","!tlabel",lbl->key+100);
11489 emitcode ("","!tlabeldef",lbl1->key+100);
11491 emitcode ("mov", "dps,#0");
11492 _G.dptrInUse = _G.dptr1InUse = 0;
11493 unsavermask(rsave);
11497 /*-----------------------------------------------------------------*/
11498 /* genMemcmpX2X - gen code for memcmp xdata to xdata */
11499 /*-----------------------------------------------------------------*/
11500 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11502 operand *from , *to , *count;
11507 /* we know it has to be 3 parameters */
11508 assert (nparms == 3);
11510 rsave = newBitVect(16);
11511 /* save DPTR if it needs to be saved */
11512 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11513 if (bitVectBitValue(ic->rMask,i))
11514 rsave = bitVectSetBit(rsave,i);
11516 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11517 ds390_rUmaskForOp (IC_RESULT(ic))));
11524 aopOp (from, ic->next, FALSE, FALSE);
11526 /* get from into DPTR1 */
11527 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11528 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11529 if (options.model == MODEL_FLAT24) {
11530 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11533 freeAsmop (from, NULL, ic, FALSE);
11534 aopOp (to, ic, FALSE, FALSE);
11535 /* get "to" into DPTR */
11536 /* if the operand is already in dptr
11537 then we do nothing else we move the value to dptr */
11538 if (AOP_TYPE (to) != AOP_STR) {
11539 /* if already in DPTR then we need to push */
11540 if (AOP_TYPE(to) == AOP_DPTR) {
11541 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11542 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11543 if (options.model == MODEL_FLAT24)
11544 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11545 emitcode ("pop", "dph");
11546 emitcode ("pop", "dpl");
11548 _startLazyDPSEvaluation ();
11549 /* if this is remateriazable */
11550 if (AOP_TYPE (to) == AOP_IMMD) {
11551 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11552 } else { /* we need to get it byte by byte */
11553 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11554 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11555 if (options.model == MODEL_FLAT24) {
11556 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11559 _endLazyDPSEvaluation ();
11562 freeAsmop (to, NULL, ic, FALSE);
11563 _G.dptrInUse = _G.dptr1InUse = 1;
11564 aopOp (count, ic->next->next, FALSE,FALSE);
11565 lbl =newiTempLabel(NULL);
11566 lbl2 =newiTempLabel(NULL);
11568 /* now for the actual compare */
11569 if (AOP_TYPE(count) == AOP_LIT &&
11570 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11571 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11573 emitcode("lcall","__bi_memcmpc2x_s");
11575 emitcode("lcall","__bi_memcmpx2x_s");
11576 freeAsmop (count, NULL, ic, FALSE);
11577 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11578 aopPut(AOP(IC_RESULT(ic)),"a",0);
11579 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11581 symbol *lbl1 = newiTempLabel(NULL);
11583 emitcode("push","ar0");
11584 emitcode (";"," Auto increment but no djnz");
11585 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11586 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11587 freeAsmop (count, NULL, ic, FALSE);
11588 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11589 emitcode ("","!tlabeldef",lbl->key+100);
11591 emitcode ("clr","a");
11592 emitcode ("movc", "a,@a+dptr");
11594 emitcode ("movx", "a,@dptr");
11595 emitcode ("mov","r0,a");
11596 emitcode ("movx", "a,@dptr");
11597 emitcode ("clr","c");
11598 emitcode ("subb","a,r0");
11599 emitcode ("jnz","!tlabel",lbl2->key+100);
11600 emitcode ("inc", "dptr");
11601 emitcode ("inc", "dptr");
11602 emitcode ("mov","a,b");
11603 emitcode ("orl","a,_ap");
11604 emitcode ("jz","!tlabel",lbl1->key+100);
11605 emitcode ("mov","a,_ap");
11606 emitcode ("add","a,#!constbyte",0xFF);
11607 emitcode ("mov","_ap,a");
11608 emitcode ("mov","a,b");
11609 emitcode ("addc","a,#!constbyte",0xFF);
11610 emitcode ("mov","b,a");
11611 emitcode ("sjmp","!tlabel",lbl->key+100);
11612 emitcode ("","!tlabeldef",lbl1->key+100);
11613 emitcode ("clr","a");
11614 emitcode ("","!tlabeldef",lbl2->key+100);
11615 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11616 aopPut(AOP(IC_RESULT(ic)),"a",0);
11617 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11618 emitcode("pop","ar0");
11619 emitcode ("mov", "dps,#0");
11621 _G.dptrInUse = _G.dptr1InUse = 0;
11622 unsavermask(rsave);
11626 /*-----------------------------------------------------------------*/
11627 /* genInp - gen code for __builtin_inp read data from a mem mapped */
11628 /* port, first parameter output area second parameter pointer to */
11629 /* port third parameter count */
11630 /*-----------------------------------------------------------------*/
11631 static void genInp( iCode *ic, int nparms, operand **parms)
11633 operand *from , *to , *count;
11638 /* we know it has to be 3 parameters */
11639 assert (nparms == 3);
11641 rsave = newBitVect(16);
11642 /* save DPTR if it needs to be saved */
11643 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11644 if (bitVectBitValue(ic->rMask,i))
11645 rsave = bitVectSetBit(rsave,i);
11647 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11648 ds390_rUmaskForOp (IC_RESULT(ic))));
11655 aopOp (from, ic->next, FALSE, FALSE);
11657 /* get from into DPTR1 */
11658 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11659 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11660 if (options.model == MODEL_FLAT24) {
11661 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11664 freeAsmop (from, NULL, ic, FALSE);
11665 aopOp (to, ic, FALSE, FALSE);
11666 /* get "to" into DPTR */
11667 /* if the operand is already in dptr
11668 then we do nothing else we move the value to dptr */
11669 if (AOP_TYPE (to) != AOP_STR) {
11670 /* if already in DPTR then we need to push */
11671 if (AOP_TYPE(to) == AOP_DPTR) {
11672 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11673 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11674 if (options.model == MODEL_FLAT24)
11675 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11676 emitcode ("pop", "dph");
11677 emitcode ("pop", "dpl");
11679 _startLazyDPSEvaluation ();
11680 /* if this is remateriazable */
11681 if (AOP_TYPE (to) == AOP_IMMD) {
11682 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11683 } else { /* we need to get it byte by byte */
11684 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11685 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11686 if (options.model == MODEL_FLAT24) {
11687 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11690 _endLazyDPSEvaluation ();
11693 freeAsmop (to, NULL, ic, FALSE);
11695 _G.dptrInUse = _G.dptr1InUse = 1;
11696 aopOp (count, ic->next->next, FALSE,FALSE);
11697 lbl =newiTempLabel(NULL);
11699 /* now for the actual copy */
11700 if (AOP_TYPE(count) == AOP_LIT &&
11701 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11702 emitcode (";","OH JOY auto increment with djnz (very fast)");
11703 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11704 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11705 freeAsmop (count, NULL, ic, FALSE);
11706 emitcode ("","!tlabeldef",lbl->key+100);
11707 emitcode ("movx", "a,@dptr"); /* read data from port */
11708 emitcode ("dec","dps"); /* switch to DPTR */
11709 emitcode ("movx", "@dptr,a"); /* save into location */
11710 emitcode ("inc", "dptr"); /* point to next area */
11711 emitcode ("inc","dps"); /* switch to DPTR2 */
11712 emitcode ("djnz","b,!tlabel",lbl->key+100);
11714 symbol *lbl1 = newiTempLabel(NULL);
11716 emitcode (";"," Auto increment but no djnz");
11717 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11718 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11719 freeAsmop (count, NULL, ic, FALSE);
11720 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11721 emitcode ("","!tlabeldef",lbl->key+100);
11722 emitcode ("movx", "a,@dptr");
11723 emitcode ("dec","dps"); /* switch to DPTR */
11724 emitcode ("movx", "@dptr,a");
11725 emitcode ("inc", "dptr");
11726 emitcode ("inc","dps"); /* switch to DPTR2 */
11727 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
11728 /* emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
11729 emitcode ("mov","a,b");
11730 emitcode ("orl","a,_ap");
11731 emitcode ("jz","!tlabel",lbl1->key+100);
11732 emitcode ("mov","a,_ap");
11733 emitcode ("add","a,#!constbyte",0xFF);
11734 emitcode ("mov","_ap,a");
11735 emitcode ("mov","a,b");
11736 emitcode ("addc","a,#!constbyte",0xFF);
11737 emitcode ("mov","b,a");
11738 emitcode ("sjmp","!tlabel",lbl->key+100);
11739 emitcode ("","!tlabeldef",lbl1->key+100);
11741 emitcode ("mov", "dps,#0");
11742 _G.dptrInUse = _G.dptr1InUse = 0;
11743 unsavermask(rsave);
11747 /*-----------------------------------------------------------------*/
11748 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
11749 /* port, first parameter output area second parameter pointer to */
11750 /* port third parameter count */
11751 /*-----------------------------------------------------------------*/
11752 static void genOutp( iCode *ic, int nparms, operand **parms)
11754 operand *from , *to , *count;
11759 /* we know it has to be 3 parameters */
11760 assert (nparms == 3);
11762 rsave = newBitVect(16);
11763 /* save DPTR if it needs to be saved */
11764 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11765 if (bitVectBitValue(ic->rMask,i))
11766 rsave = bitVectSetBit(rsave,i);
11768 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11769 ds390_rUmaskForOp (IC_RESULT(ic))));
11776 aopOp (from, ic->next, FALSE, FALSE);
11778 /* get from into DPTR1 */
11779 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11780 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11781 if (options.model == MODEL_FLAT24) {
11782 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11785 freeAsmop (from, NULL, ic, FALSE);
11786 aopOp (to, ic, FALSE, FALSE);
11787 /* get "to" into DPTR */
11788 /* if the operand is already in dptr
11789 then we do nothing else we move the value to dptr */
11790 if (AOP_TYPE (to) != AOP_STR) {
11791 /* if already in DPTR then we need to push */
11792 if (AOP_TYPE(to) == AOP_DPTR) {
11793 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11794 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11795 if (options.model == MODEL_FLAT24)
11796 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11797 emitcode ("pop", "dph");
11798 emitcode ("pop", "dpl");
11800 _startLazyDPSEvaluation ();
11801 /* if this is remateriazable */
11802 if (AOP_TYPE (to) == AOP_IMMD) {
11803 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11804 } else { /* we need to get it byte by byte */
11805 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11806 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11807 if (options.model == MODEL_FLAT24) {
11808 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11811 _endLazyDPSEvaluation ();
11814 freeAsmop (to, NULL, ic, FALSE);
11816 _G.dptrInUse = _G.dptr1InUse = 1;
11817 aopOp (count, ic->next->next, FALSE,FALSE);
11818 lbl =newiTempLabel(NULL);
11820 /* now for the actual copy */
11821 if (AOP_TYPE(count) == AOP_LIT &&
11822 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11823 emitcode (";","OH JOY auto increment with djnz (very fast)");
11824 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
11825 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11826 emitcode ("","!tlabeldef",lbl->key+100);
11827 emitcode ("movx", "a,@dptr"); /* read data from port */
11828 emitcode ("inc","dps"); /* switch to DPTR2 */
11829 emitcode ("movx", "@dptr,a"); /* save into location */
11830 emitcode ("inc", "dptr"); /* point to next area */
11831 emitcode ("dec","dps"); /* switch to DPTR */
11832 emitcode ("djnz","b,!tlabel",lbl->key+100);
11833 freeAsmop (count, NULL, ic, FALSE);
11835 symbol *lbl1 = newiTempLabel(NULL);
11837 emitcode (";"," Auto increment but no djnz");
11838 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11839 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11840 freeAsmop (count, NULL, ic, FALSE);
11841 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
11842 emitcode ("","!tlabeldef",lbl->key+100);
11843 emitcode ("movx", "a,@dptr");
11844 emitcode ("inc", "dptr");
11845 emitcode ("inc","dps"); /* switch to DPTR2 */
11846 emitcode ("movx", "@dptr,a");
11847 emitcode ("dec","dps"); /* switch to DPTR */
11848 emitcode ("mov","a,b");
11849 emitcode ("orl","a,_ap");
11850 emitcode ("jz","!tlabel",lbl1->key+100);
11851 emitcode ("mov","a,_ap");
11852 emitcode ("add","a,#!constbyte",0xFF);
11853 emitcode ("mov","_ap,a");
11854 emitcode ("mov","a,b");
11855 emitcode ("addc","a,#!constbyte",0xFF);
11856 emitcode ("mov","b,a");
11857 emitcode ("sjmp","!tlabel",lbl->key+100);
11858 emitcode ("","!tlabeldef",lbl1->key+100);
11860 emitcode ("mov", "dps,#0");
11861 _G.dptrInUse = _G.dptr1InUse = 0;
11862 unsavermask(rsave);
11866 /*-----------------------------------------------------------------*/
11867 /* genSwapW - swap lower & high order bytes */
11868 /*-----------------------------------------------------------------*/
11869 static void genSwapW(iCode *ic, int nparms, operand **parms)
11873 assert (nparms==1);
11876 dest=IC_RESULT(ic);
11878 assert(getSize(operandType(src))==2);
11880 aopOp (src, ic, FALSE, FALSE);
11881 emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
11883 MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
11885 freeAsmop (src, NULL, ic, FALSE);
11887 aopOp (dest,ic, FALSE, FALSE);
11888 aopPut(AOP(dest),"b",0);
11889 aopPut(AOP(dest),"a",1);
11890 freeAsmop (dest, NULL, ic, FALSE);
11893 /*-----------------------------------------------------------------*/
11894 /* genMemsetX - gencode for memSetX data */
11895 /*-----------------------------------------------------------------*/
11896 static void genMemsetX(iCode *ic, int nparms, operand **parms)
11898 operand *to , *val , *count;
11904 /* we know it has to be 3 parameters */
11905 assert (nparms == 3);
11911 /* save DPTR if it needs to be saved */
11912 rsave = newBitVect(16);
11913 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11914 if (bitVectBitValue(ic->rMask,i))
11915 rsave = bitVectSetBit(rsave,i);
11917 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11918 ds390_rUmaskForOp (IC_RESULT(ic))));
11921 aopOp (to, ic, FALSE, FALSE);
11922 /* get "to" into DPTR */
11923 /* if the operand is already in dptr
11924 then we do nothing else we move the value to dptr */
11925 if (AOP_TYPE (to) != AOP_STR) {
11926 /* if already in DPTR then we need to push */
11927 if (AOP_TYPE(to) == AOP_DPTR) {
11928 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11929 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11930 if (options.model == MODEL_FLAT24)
11931 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11932 emitcode ("pop", "dph");
11933 emitcode ("pop", "dpl");
11935 _startLazyDPSEvaluation ();
11936 /* if this is remateriazable */
11937 if (AOP_TYPE (to) == AOP_IMMD) {
11938 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11939 } else { /* we need to get it byte by byte */
11940 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11941 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11942 if (options.model == MODEL_FLAT24) {
11943 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11946 _endLazyDPSEvaluation ();
11949 freeAsmop (to, NULL, ic, FALSE);
11951 aopOp (val, ic->next->next, FALSE,FALSE);
11952 aopOp (count, ic->next->next, FALSE,FALSE);
11953 lbl =newiTempLabel(NULL);
11954 /* now for the actual copy */
11955 if (AOP_TYPE(count) == AOP_LIT &&
11956 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11957 l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
11958 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11960 emitcode ("","!tlabeldef",lbl->key+100);
11961 emitcode ("movx", "@dptr,a");
11962 emitcode ("inc", "dptr");
11963 emitcode ("djnz","b,!tlabel",lbl->key+100);
11965 symbol *lbl1 = newiTempLabel(NULL);
11967 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11968 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11969 emitcode ("","!tlabeldef",lbl->key+100);
11970 MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
11971 emitcode ("movx", "@dptr,a");
11972 emitcode ("inc", "dptr");
11973 emitcode ("mov","a,b");
11974 emitcode ("orl","a,_ap");
11975 emitcode ("jz","!tlabel",lbl1->key+100);
11976 emitcode ("mov","a,_ap");
11977 emitcode ("add","a,#!constbyte",0xFF);
11978 emitcode ("mov","_ap,a");
11979 emitcode ("mov","a,b");
11980 emitcode ("addc","a,#!constbyte",0xFF);
11981 emitcode ("mov","b,a");
11982 emitcode ("sjmp","!tlabel",lbl->key+100);
11983 emitcode ("","!tlabeldef",lbl1->key+100);
11985 freeAsmop (count, NULL, ic, FALSE);
11986 unsavermask(rsave);
11989 /*-----------------------------------------------------------------*/
11990 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
11991 /*-----------------------------------------------------------------*/
11992 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
11995 operand *pnum, *result;
11998 assert (nparms==1);
11999 /* save registers that need to be saved */
12000 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12001 ds390_rUmaskForOp (IC_RESULT(ic))));
12004 aopOp (pnum, ic, FALSE, FALSE);
12005 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12006 freeAsmop (pnum, NULL, ic, FALSE);
12007 emitcode ("lcall","NatLib_LoadPrimitive");
12008 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12009 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
12010 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
12011 for (i = (size-1) ; i >= 0 ; i-- ) {
12012 emitcode ("push","a%s",javaRet[i]);
12014 for (i=0; i < size ; i++ ) {
12015 emitcode ("pop","a%s",
12016 aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
12019 for (i = 0 ; i < size ; i++ ) {
12020 aopPut(AOP(result),javaRet[i],i);
12023 freeAsmop (result, NULL, ic, FALSE);
12024 unsavermask(rsave);
12027 /*-----------------------------------------------------------------*/
12028 /* genNatLibLoadPointer - calls TINI api function to load pointer */
12029 /*-----------------------------------------------------------------*/
12030 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
12033 operand *pnum, *result;
12037 assert (nparms==1);
12038 /* save registers that need to be saved */
12039 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12040 ds390_rUmaskForOp (IC_RESULT(ic))));
12043 aopOp (pnum, ic, FALSE, FALSE);
12044 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12045 freeAsmop (pnum, NULL, ic, FALSE);
12046 emitcode ("lcall","NatLib_LoadPointer");
12047 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12048 if (AOP_TYPE(result)!=AOP_STR) {
12049 for (i = 0 ; i < size ; i++ ) {
12050 aopPut(AOP(result),fReturn[i],i);
12053 freeAsmop (result, NULL, ic, FALSE);
12054 unsavermask(rsave);
12057 /*-----------------------------------------------------------------*/
12058 /* genNatLibInstallStateBlock - */
12059 /*-----------------------------------------------------------------*/
12060 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
12061 operand **parms, const char *name)
12064 operand *psb, *handle;
12065 assert (nparms==2);
12067 /* save registers that need to be saved */
12068 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12069 ds390_rUmaskForOp (IC_RESULT(ic))));
12073 /* put pointer to state block into DPTR1 */
12074 aopOp (psb, ic, FALSE, FALSE);
12075 if (AOP_TYPE (psb) == AOP_IMMD) {
12076 emitcode ("mov","dps,#1");
12077 emitcode ("mov", "dptr,%s",
12078 aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12079 emitcode ("mov","dps,#0");
12081 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12082 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12083 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12085 freeAsmop (psb, NULL, ic, FALSE);
12087 /* put libraryID into DPTR */
12088 emitcode ("mov","dptr,#LibraryID");
12090 /* put handle into r3:r2 */
12091 aopOp (handle, ic, FALSE, FALSE);
12092 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12093 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12094 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12095 emitcode ("pop","ar3");
12096 emitcode ("pop","ar2");
12098 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12099 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12101 freeAsmop (psb, NULL, ic, FALSE);
12103 /* make the call */
12104 emitcode ("lcall","NatLib_Install%sStateBlock",name);
12106 /* put return value into place*/
12108 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12110 aopPut(AOP(IC_RESULT(ic)),"a",0);
12111 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12112 unsavermask(rsave);
12115 /*-----------------------------------------------------------------*/
12116 /* genNatLibRemoveStateBlock - */
12117 /*-----------------------------------------------------------------*/
12118 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12124 /* save registers that need to be saved */
12125 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12126 ds390_rUmaskForOp (IC_RESULT(ic))));
12128 /* put libraryID into DPTR */
12129 emitcode ("mov","dptr,#LibraryID");
12130 /* make the call */
12131 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12132 unsavermask(rsave);
12135 /*-----------------------------------------------------------------*/
12136 /* genNatLibGetStateBlock - */
12137 /*-----------------------------------------------------------------*/
12138 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12139 operand **parms,const char *name)
12142 symbol *lbl = newiTempLabel(NULL);
12145 /* save registers that need to be saved */
12146 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12147 ds390_rUmaskForOp (IC_RESULT(ic))));
12149 /* put libraryID into DPTR */
12150 emitcode ("mov","dptr,#LibraryID");
12151 /* make the call */
12152 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12153 emitcode ("jnz","!tlabel",lbl->key+100);
12155 /* put return value into place */
12156 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12157 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12158 emitcode ("push","ar3");
12159 emitcode ("push","ar2");
12160 emitcode ("pop","%s",
12161 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12162 emitcode ("pop","%s",
12163 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12165 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12166 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12168 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12169 emitcode ("","!tlabeldef",lbl->key+100);
12170 unsavermask(rsave);
12173 /*-----------------------------------------------------------------*/
12174 /* genMMMalloc - */
12175 /*-----------------------------------------------------------------*/
12176 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12177 int size, const char *name)
12182 symbol *lbl = newiTempLabel(NULL);
12184 assert (nparms == 1);
12185 /* save registers that need to be saved */
12186 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12187 ds390_rUmaskForOp (IC_RESULT(ic))));
12190 aopOp (bsize,ic,FALSE,FALSE);
12192 /* put the size in R4-R2 */
12193 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12194 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12195 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12197 emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12198 emitcode("pop","ar4");
12200 emitcode("pop","ar3");
12201 emitcode("pop","ar2");
12203 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12204 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12206 emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12209 freeAsmop (bsize, NULL, ic, FALSE);
12211 /* make the call */
12212 emitcode ("lcall","MM_%s",name);
12213 emitcode ("jz","!tlabel",lbl->key+100);
12214 emitcode ("mov","r2,#!constbyte",0xff);
12215 emitcode ("mov","r3,#!constbyte",0xff);
12216 emitcode ("","!tlabeldef",lbl->key+100);
12217 /* we don't care about the pointer : we just save the handle */
12218 rsym = OP_SYMBOL(IC_RESULT(ic));
12219 if (rsym->liveFrom != rsym->liveTo) {
12220 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12221 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12222 emitcode ("push","ar3");
12223 emitcode ("push","ar2");
12224 emitcode ("pop","%s",
12225 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12226 emitcode ("pop","%s",
12227 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12229 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12230 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12232 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12234 unsavermask(rsave);
12237 /*-----------------------------------------------------------------*/
12239 /*-----------------------------------------------------------------*/
12240 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12245 assert (nparms == 1);
12246 /* save registers that need to be saved */
12247 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12248 ds390_rUmaskForOp (IC_RESULT(ic))));
12251 aopOp (handle,ic,FALSE,FALSE);
12253 /* put the size in R4-R2 */
12254 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12255 emitcode("push","%s",
12256 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12257 emitcode("push","%s",
12258 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12259 emitcode("pop","ar3");
12260 emitcode("pop","ar2");
12262 emitcode ("mov","r2,%s",
12263 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12264 emitcode ("mov","r3,%s",
12265 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12267 freeAsmop (handle, NULL, ic, FALSE);
12269 /* make the call */
12270 emitcode ("lcall","MM_Deref");
12273 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12274 if (rsym->liveFrom != rsym->liveTo) {
12275 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12276 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12277 _startLazyDPSEvaluation ();
12279 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12280 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12281 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12283 _endLazyDPSEvaluation ();
12288 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12289 unsavermask(rsave);
12292 /*-----------------------------------------------------------------*/
12293 /* genMMUnrestrictedPersist - */
12294 /*-----------------------------------------------------------------*/
12295 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12300 assert (nparms == 1);
12301 /* save registers that need to be saved */
12302 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12303 ds390_rUmaskForOp (IC_RESULT(ic))));
12306 aopOp (handle,ic,FALSE,FALSE);
12308 /* put the size in R3-R2 */
12309 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12310 emitcode("push","%s",
12311 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12312 emitcode("push","%s",
12313 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12314 emitcode("pop","ar3");
12315 emitcode("pop","ar2");
12317 emitcode ("mov","r2,%s",
12318 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12319 emitcode ("mov","r3,%s",
12320 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12322 freeAsmop (handle, NULL, ic, FALSE);
12324 /* make the call */
12325 emitcode ("lcall","MM_UnrestrictedPersist");
12328 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12329 if (rsym->liveFrom != rsym->liveTo) {
12330 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12331 aopPut(AOP(IC_RESULT(ic)),"a",0);
12332 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12335 unsavermask(rsave);
12338 /*-----------------------------------------------------------------*/
12339 /* genSystemExecJavaProcess - */
12340 /*-----------------------------------------------------------------*/
12341 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12344 operand *handle, *pp;
12346 assert (nparms==2);
12347 /* save registers that need to be saved */
12348 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12349 ds390_rUmaskForOp (IC_RESULT(ic))));
12354 /* put the handle in R3-R2 */
12355 aopOp (handle,ic,FALSE,FALSE);
12356 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12357 emitcode("push","%s",
12358 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12359 emitcode("push","%s",
12360 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12361 emitcode("pop","ar3");
12362 emitcode("pop","ar2");
12364 emitcode ("mov","r2,%s",
12365 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12366 emitcode ("mov","r3,%s",
12367 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12369 freeAsmop (handle, NULL, ic, FALSE);
12371 /* put pointer in DPTR */
12372 aopOp (pp,ic,FALSE,FALSE);
12373 if (AOP_TYPE(pp) == AOP_IMMD) {
12374 emitcode ("mov", "dptr,%s",
12375 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12376 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12377 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12378 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12379 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12381 freeAsmop (handle, NULL, ic, FALSE);
12383 /* make the call */
12384 emitcode ("lcall","System_ExecJavaProcess");
12386 /* put result in place */
12388 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12389 if (rsym->liveFrom != rsym->liveTo) {
12390 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12391 aopPut(AOP(IC_RESULT(ic)),"a",0);
12392 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12396 unsavermask(rsave);
12399 /*-----------------------------------------------------------------*/
12400 /* genSystemRTCRegisters - */
12401 /*-----------------------------------------------------------------*/
12402 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12408 assert (nparms==1);
12409 /* save registers that need to be saved */
12410 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12411 ds390_rUmaskForOp (IC_RESULT(ic))));
12414 /* put pointer in DPTR */
12415 aopOp (pp,ic,FALSE,FALSE);
12416 if (AOP_TYPE (pp) == AOP_IMMD) {
12417 emitcode ("mov","dps,#1");
12418 emitcode ("mov", "dptr,%s",
12419 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12420 emitcode ("mov","dps,#0");
12422 emitcode ("mov","dpl1,%s",
12423 aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12424 emitcode ("mov","dph1,%s",
12425 aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12426 emitcode ("mov","dpx1,%s",
12427 aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12429 freeAsmop (pp, NULL, ic, FALSE);
12431 /* make the call */
12432 emitcode ("lcall","System_%sRTCRegisters",name);
12434 unsavermask(rsave);
12437 /*-----------------------------------------------------------------*/
12438 /* genSystemThreadSleep - */
12439 /*-----------------------------------------------------------------*/
12440 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12445 assert (nparms==1);
12446 /* save registers that need to be saved */
12447 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12448 ds390_rUmaskForOp (IC_RESULT(ic))));
12451 aopOp(to,ic,FALSE,FALSE);
12452 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12453 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12454 emitcode ("push","%s",
12455 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12456 emitcode ("push","%s",
12457 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12458 emitcode ("push","%s",
12459 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12460 emitcode ("push","%s",
12461 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12462 emitcode ("pop","ar3");
12463 emitcode ("pop","ar2");
12464 emitcode ("pop","ar1");
12465 emitcode ("pop","ar0");
12467 emitcode ("mov","r0,%s",
12468 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12469 emitcode ("mov","r1,%s",
12470 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12471 emitcode ("mov","r2,%s",
12472 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12473 emitcode ("mov","r3,%s",
12474 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12476 freeAsmop (to, NULL, ic, FALSE);
12478 /* suspend in acc */
12480 aopOp(s,ic,FALSE,FALSE);
12481 emitcode ("mov","a,%s",
12482 aopGet(AOP(s),0,FALSE,TRUE,NULL));
12483 freeAsmop (s, NULL, ic, FALSE);
12485 /* make the call */
12486 emitcode ("lcall","System_%s",name);
12488 unsavermask(rsave);
12491 /*-----------------------------------------------------------------*/
12492 /* genSystemThreadResume - */
12493 /*-----------------------------------------------------------------*/
12494 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12499 assert (nparms==2);
12500 /* save registers that need to be saved */
12501 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12502 ds390_rUmaskForOp (IC_RESULT(ic))));
12508 aopOp(pid,ic,FALSE,FALSE);
12509 emitcode ("mov","r0,%s",
12510 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12511 freeAsmop (pid, NULL, ic, FALSE);
12514 aopOp(tid,ic,FALSE,FALSE);
12515 emitcode ("mov","a,%s",
12516 aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
12517 freeAsmop (tid, NULL, ic, FALSE);
12519 emitcode ("lcall","System_ThreadResume");
12521 /* put result into place */
12523 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12524 if (rsym->liveFrom != rsym->liveTo) {
12525 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12526 aopPut(AOP(IC_RESULT(ic)),"a",0);
12527 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12530 unsavermask(rsave);
12533 /*-----------------------------------------------------------------*/
12534 /* genSystemProcessResume - */
12535 /*-----------------------------------------------------------------*/
12536 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
12541 assert (nparms==1);
12542 /* save registers that need to be saved */
12543 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12544 ds390_rUmaskForOp (IC_RESULT(ic))));
12549 aopOp(pid,ic,FALSE,FALSE);
12550 emitcode ("mov","a,%s",
12551 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12552 freeAsmop (pid, NULL, ic, FALSE);
12554 emitcode ("lcall","System_ProcessResume");
12556 unsavermask(rsave);
12559 /*-----------------------------------------------------------------*/
12561 /*-----------------------------------------------------------------*/
12562 static void genSystem (iCode *ic,int nparms,char *name)
12564 assert(nparms == 0);
12566 emitcode ("lcall","System_%s",name);
12569 /*-----------------------------------------------------------------*/
12570 /* genSystemPoll - */
12571 /*-----------------------------------------------------------------*/
12572 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
12577 assert (nparms==1);
12578 /* save registers that need to be saved */
12579 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12580 ds390_rUmaskForOp (IC_RESULT(ic))));
12583 aopOp (fp,ic,FALSE,FALSE);
12584 if (AOP_TYPE (fp) == AOP_IMMD) {
12585 emitcode ("mov", "dptr,%s",
12586 aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
12587 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
12588 emitcode ("mov","dpl,%s",
12589 aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
12590 emitcode ("mov","dph,%s",
12591 aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
12592 emitcode ("mov","dpx,%s",
12593 aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
12595 freeAsmop (fp, NULL, ic, FALSE);
12597 emitcode ("lcall","System_%sPoll",name);
12599 /* put result into place */
12601 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12602 if (rsym->liveFrom != rsym->liveTo) {
12603 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12604 aopPut(AOP(IC_RESULT(ic)),"a",0);
12605 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12608 unsavermask(rsave);
12611 /*-----------------------------------------------------------------*/
12612 /* genSystemGetCurrentID - */
12613 /*-----------------------------------------------------------------*/
12614 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
12616 assert (nparms==0);
12618 emitcode ("lcall","System_GetCurrent%sId",name);
12619 /* put result into place */
12621 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12622 if (rsym->liveFrom != rsym->liveTo) {
12623 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12624 aopPut(AOP(IC_RESULT(ic)),"a",0);
12625 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12630 /*-----------------------------------------------------------------*/
12631 /* genDummyRead - generate code for dummy read of volatiles */
12632 /*-----------------------------------------------------------------*/
12634 genDummyRead (iCode * ic)
12639 D(emitcode("; genDummyRead",""));
12641 right = IC_RIGHT (ic);
12643 aopOp (right, ic, FALSE, FALSE);
12645 /* if the result is a bit */
12646 if (AOP_TYPE (right) == AOP_CRY)
12648 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
12652 /* bit variables done */
12654 size = AOP_SIZE (right);
12658 emitcode ("mov", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
12663 freeAsmop (right, NULL, ic, TRUE);
12666 /*-----------------------------------------------------------------*/
12667 /* genBuiltIn - calls the appropriate function to generating code */
12668 /* for a built in function */
12669 /*-----------------------------------------------------------------*/
12670 static void genBuiltIn (iCode *ic)
12672 operand *bi_parms[MAX_BUILTIN_ARGS];
12677 /* get all the arguments for a built in function */
12678 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
12680 /* which function is it */
12681 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
12682 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
12683 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
12684 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
12685 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
12686 } else if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
12687 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
12688 } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
12689 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
12690 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
12691 genMemsetX(bi_iCode,nbi_parms,bi_parms);
12692 } else if (strcmp(bif->name,"__builtin_inp")==0) {
12693 genInp(bi_iCode,nbi_parms,bi_parms);
12694 } else if (strcmp(bif->name,"__builtin_outp")==0) {
12695 genOutp(bi_iCode,nbi_parms,bi_parms);
12696 } else if (strcmp(bif->name,"__builtin_swapw")==0) {
12697 genSwapW(bi_iCode,nbi_parms,bi_parms);
12698 /* JavaNative builtIns */
12699 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
12700 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
12701 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
12702 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
12703 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
12704 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
12705 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
12706 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
12707 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
12708 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12709 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
12710 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12711 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
12712 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
12713 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
12714 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
12715 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
12716 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12717 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
12718 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12719 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
12720 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
12721 } else if (strcmp(bif->name,"MM_Malloc")==0) {
12722 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
12723 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
12724 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
12725 } else if (strcmp(bif->name,"MM_Free")==0) {
12726 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
12727 } else if (strcmp(bif->name,"MM_Deref")==0) {
12728 genMMDeref(bi_iCode,nbi_parms,bi_parms);
12729 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
12730 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
12731 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
12732 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
12733 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
12734 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
12735 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
12736 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
12737 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
12738 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
12739 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
12740 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
12741 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
12742 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
12743 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
12744 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
12745 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12746 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12747 } else if (strcmp(bif->name,"System_SaveThread")==0) {
12748 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12749 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12750 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12751 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
12752 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
12753 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
12754 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
12755 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
12756 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
12757 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
12758 genSystem(bi_iCode,nbi_parms,"ProcessYield");
12759 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
12760 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
12761 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
12762 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
12763 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
12764 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
12765 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
12766 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
12767 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
12768 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
12770 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
12776 /*-----------------------------------------------------------------*/
12777 /* gen390Code - generate code for Dallas 390 based controllers */
12778 /*-----------------------------------------------------------------*/
12780 gen390Code (iCode * lic)
12785 lineHead = lineCurr = NULL;
12786 dptrn[1][0] = "dpl1";
12787 dptrn[1][1] = "dph1";
12788 dptrn[1][2] = "dpx1";
12790 if (options.model == MODEL_FLAT24) {
12791 fReturnSizeDS390 = 5;
12792 fReturn = fReturn24;
12794 fReturnSizeDS390 = 4;
12795 fReturn = fReturn16;
12796 options.stack10bit=0;
12799 /* print the allocation information */
12800 if (allocInfo && currFunc)
12801 printAllocInfo (currFunc, codeOutFile);
12803 /* if debug information required */
12804 if (options.debug && currFunc)
12806 debugFile->writeFunction(currFunc);
12808 if (IS_STATIC (currFunc->etype))
12809 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
12811 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
12814 /* stack pointer name */
12815 if (options.useXstack)
12821 for (ic = lic; ic; ic = ic->next)
12824 if (ic->lineno && cln != ic->lineno)
12829 emitcode ("", "C$%s$%d$%d$%d ==.",
12830 FileBaseName (ic->filename), ic->lineno,
12831 ic->level, ic->block);
12834 if (!options.noCcodeInAsm) {
12835 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
12836 printCLine(ic->filename, ic->lineno));
12840 if (options.iCodeInAsm) {
12841 emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
12843 /* if the result is marked as
12844 spilt and rematerializable or code for
12845 this has already been generated then
12847 if (resultRemat (ic) || ic->generated)
12850 /* depending on the operation */
12870 /* IPOP happens only when trying to restore a
12871 spilt live range, if there is an ifx statement
12872 following this pop then the if statement might
12873 be using some of the registers being popped which
12874 would destory the contents of the register so
12875 we need to check for this condition and handle it */
12877 ic->next->op == IFX &&
12878 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
12879 genIfx (ic->next, ic);
12897 genEndFunction (ic);
12917 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
12934 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
12938 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
12945 /* note these two are xlated by algebraic equivalence
12946 during parsing SDCC.y */
12947 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12948 "got '>=' or '<=' shouldn't have come here");
12952 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
12964 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
12968 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
12972 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
12996 genRightShift (ic);
12999 case GET_VALUE_AT_ADDRESS:
13000 genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
13004 if (POINTER_SET (ic))
13005 genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
13031 if (ic->builtinSEND) genBuiltIn(ic);
13032 else addSet (&_G.sendSet, ic);
13035 case DUMMY_READ_VOLATILE:
13039 #if 0 // obsolete, and buggy for != xdata
13051 /* now we are ready to call the
13052 peep hole optimizer */
13053 if (!options.nopeep)
13054 peepHole (&lineHead);
13056 /* now do the actual printing */
13057 printLine (lineHead, codeOutFile);