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");
2901 /* here we need to generate the equates for the
2902 register bank if required */
2903 if (FUNC_REGBANK (ftype) != rbank)
2907 rbank = FUNC_REGBANK (ftype);
2908 for (i = 0; i < ds390_nRegs; i++)
2910 if (regs390[i].print) {
2911 if (strcmp (regs390[i].base, "0") == 0)
2912 emitcode ("", "%s !equ !constbyte",
2914 8 * rbank + regs390[i].offset);
2916 emitcode ("", "%s !equ %s + !constbyte",
2919 8 * rbank + regs390[i].offset);
2924 /* if this is an interrupt service routine then
2925 save acc, b, dpl, dph */
2926 if (IFFUNC_ISISR (sym->type))
2928 if (!inExcludeList ("acc"))
2929 emitcode ("push", "acc");
2930 if (!inExcludeList ("b"))
2931 emitcode ("push", "b");
2932 if (!inExcludeList ("dpl"))
2933 emitcode ("push", "dpl");
2934 if (!inExcludeList ("dph"))
2935 emitcode ("push", "dph");
2936 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2938 emitcode ("push", "dpx");
2939 /* Make sure we're using standard DPTR */
2940 emitcode ("push", "dps");
2941 emitcode ("mov", "dps,#0");
2942 if (options.stack10bit)
2944 /* This ISR could conceivably use DPTR2. Better save it. */
2945 emitcode ("push", "dpl1");
2946 emitcode ("push", "dph1");
2947 emitcode ("push", "dpx1");
2948 emitcode ("push", DP2_RESULT_REG);
2951 /* if this isr has no bank i.e. is going to
2952 run with bank 0 , then we need to save more
2954 if (!FUNC_REGBANK (sym->type))
2958 /* if this function does not call any other
2959 function then we can be economical and
2960 save only those registers that are used */
2961 if (!IFFUNC_HASFCALL(sym->type))
2964 /* if any registers used */
2967 /* save the registers used */
2968 for (i = 0; i < sym->regsUsed->size; i++)
2970 if (bitVectBitValue (sym->regsUsed, i) ||
2971 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2972 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2979 /* this function has a function call cannot
2980 determines register usage so we will have to push the
2982 saveRBank (0, ic, FALSE);
2983 if (options.parms_in_bank1) {
2984 for (i=0; i < 8 ; i++ ) {
2985 emitcode ("push","%s",rb1regs[i]);
2992 /* This ISR uses a non-zero bank.
2994 * We assume that the bank is available for our
2997 * However, if this ISR calls a function which uses some
2998 * other bank, we must save that bank entirely.
3000 unsigned long banksToSave = 0;
3002 if (IFFUNC_HASFCALL(sym->type))
3005 #define MAX_REGISTER_BANKS 4
3010 for (i = ic; i; i = i->next)
3012 if (i->op == ENDFUNCTION)
3014 /* we got to the end OK. */
3022 dtype = operandType (IC_LEFT(i));
3024 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3026 /* Mark this bank for saving. */
3027 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3029 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3033 banksToSave |= (1 << FUNC_REGBANK(dtype));
3036 /* And note that we don't need to do it in
3044 /* This is a mess; we have no idea what
3045 * register bank the called function might
3048 * The only thing I can think of to do is
3049 * throw a warning and hope.
3051 werror(W_FUNCPTR_IN_USING_ISR);
3055 if (banksToSave && options.useXstack)
3057 /* Since we aren't passing it an ic,
3058 * saveRBank will assume r0 is available to abuse.
3060 * So switch to our (trashable) bank now, so
3061 * the caller's R0 isn't trashed.
3063 emitcode ("push", "psw");
3064 emitcode ("mov", "psw,#!constbyte",
3065 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3069 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3071 if (banksToSave & (1 << ix))
3073 saveRBank(ix, NULL, FALSE);
3077 // TODO: this needs a closer look
3078 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3083 /* if callee-save to be used for this function
3084 then save the registers being used in this function */
3085 if (IFFUNC_CALLEESAVES(sym->type))
3089 /* if any registers used */
3092 /* save the registers used */
3093 for (i = 0; i < sym->regsUsed->size; i++)
3095 if (bitVectBitValue (sym->regsUsed, i) ||
3096 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3098 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3106 /* set the register bank to the desired value */
3107 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3110 emitcode ("push", "psw");
3111 emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3114 if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3115 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3116 if (options.stack10bit) {
3117 emitcode ("push","_bpx");
3118 emitcode ("push","_bpx+1");
3119 emitcode ("mov","_bpx,%s",spname);
3120 emitcode ("mov","_bpx+1,esp");
3121 adjustEsp("_bpx+1");
3123 if (options.useXstack) {
3124 emitcode ("mov", "r0,%s", spname);
3125 emitcode ("mov", "a,_bp");
3126 emitcode ("movx", "@r0,a");
3127 emitcode ("inc", "%s", spname);
3129 /* set up the stack */
3130 emitcode ("push", "_bp"); /* save the callers stack */
3132 emitcode ("mov", "_bp,%s", spname);
3136 /* adjust the stack for the function */
3139 if (options.stack10bit) {
3140 if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
3141 assert (sym->recvSize <= 4);
3142 if (sym->stack <= 8) {
3143 while (i--) emitcode ("push","acc");
3146 emitcode ("mov","a,sp");
3147 emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3148 emitcode ("mov","sp,a");
3149 emitcode ("mov","a,esp");
3151 emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3152 emitcode ("mov","esp,a");
3157 werror (W_STACK_OVERFLOW, sym->name);
3159 if (i > 3 && sym->recvSize < 4) {
3161 emitcode ("mov", "a,sp");
3162 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3163 emitcode ("mov", "sp,a");
3167 emitcode ("inc", "sp");
3174 emitcode ("mov", "a,_spx");
3175 emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3176 emitcode ("mov", "_spx,a");
3179 /* if critical function then turn interrupts off */
3180 if (IFFUNC_ISCRITICAL (ftype))
3182 emitcode ("mov", "c,ea");
3183 emitcode ("push", "psw"); /* save old ea via c in psw */
3184 emitcode ("clr", "ea");
3189 /*-----------------------------------------------------------------*/
3190 /* genEndFunction - generates epilogue for functions */
3191 /*-----------------------------------------------------------------*/
3193 genEndFunction (iCode * ic)
3195 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3197 D (emitcode (";", "genEndFunction "););
3199 if (IFFUNC_ISNAKED(sym->type))
3201 emitcode(";", "naked function: no epilogue.");
3205 if (IFFUNC_ISCRITICAL (sym->type))
3207 emitcode ("pop", "psw"); /* restore ea via c in psw */
3208 emitcode ("mov", "ea,c");
3211 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3212 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3214 if (options.stack10bit) {
3216 emitcode ("mov", "sp,_bpx", spname);
3217 emitcode ("mov", "esp,_bpx+1", spname);
3220 emitcode ("mov", "%s,_bp", spname);
3224 /* if use external stack but some variables were
3225 added to the local stack then decrement the
3227 if (options.useXstack && sym->stack) {
3228 emitcode ("mov", "a,sp");
3229 emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3230 emitcode ("mov", "sp,a");
3234 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3235 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3237 if (options.useXstack) {
3238 emitcode ("mov", "r0,%s", spname);
3239 emitcode ("movx", "a,@r0");
3240 emitcode ("mov", "_bp,a");
3241 emitcode ("dec", "%s", spname);
3243 if (options.stack10bit) {
3244 emitcode ("pop", "_bpx+1");
3245 emitcode ("pop", "_bpx");
3247 emitcode ("pop", "_bp");
3252 /* restore the register bank */
3253 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3255 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3256 || !options.useXstack)
3258 /* Special case of ISR using non-zero bank with useXstack
3261 emitcode ("pop", "psw");
3265 if (IFFUNC_ISISR (sym->type))
3268 /* now we need to restore the registers */
3269 /* if this isr has no bank i.e. is going to
3270 run with bank 0 , then we need to save more
3272 if (!FUNC_REGBANK (sym->type))
3275 /* if this function does not call any other
3276 function then we can be economical and
3277 save only those registers that are used */
3278 if (!IFFUNC_HASFCALL(sym->type))
3281 /* if any registers used */
3284 /* save the registers used */
3285 for (i = sym->regsUsed->size; i >= 0; i--)
3287 if (bitVectBitValue (sym->regsUsed, i) ||
3288 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3289 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3296 /* this function has a function call cannot
3297 determines register usage so we will have to pop the
3299 if (options.parms_in_bank1) {
3300 for (i = 7 ; i >= 0 ; i-- ) {
3301 emitcode ("pop","%s",rb1regs[i]);
3304 unsaveRBank (0, ic, FALSE);
3309 /* This ISR uses a non-zero bank.
3311 * Restore any register banks saved by genFunction
3314 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3317 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3319 if (savedBanks & (1 << ix))
3321 unsaveRBank(ix, NULL, FALSE);
3325 if (options.useXstack)
3327 /* Restore bank AFTER calling unsaveRBank,
3328 * since it can trash r0.
3330 emitcode ("pop", "psw");
3334 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3336 if (options.stack10bit)
3338 emitcode ("pop", DP2_RESULT_REG);
3339 emitcode ("pop", "dpx1");
3340 emitcode ("pop", "dph1");
3341 emitcode ("pop", "dpl1");
3343 emitcode ("pop", "dps");
3344 emitcode ("pop", "dpx");
3346 if (!inExcludeList ("dph"))
3347 emitcode ("pop", "dph");
3348 if (!inExcludeList ("dpl"))
3349 emitcode ("pop", "dpl");
3350 if (!inExcludeList ("b"))
3351 emitcode ("pop", "b");
3352 if (!inExcludeList ("acc"))
3353 emitcode ("pop", "acc");
3355 /* if debug then send end of function */
3356 if (options.debug && currFunc) {
3358 emitcode ("", "C$%s$%d$%d$%d ==.",
3359 FileBaseName (ic->filename), currFunc->lastLine,
3360 ic->level, ic->block);
3361 if (IS_STATIC (currFunc->etype))
3362 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3364 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3368 emitcode ("reti", "");
3372 if (IFFUNC_CALLEESAVES(sym->type))
3376 /* if any registers used */
3379 /* save the registers used */
3380 for (i = sym->regsUsed->size; i >= 0; i--)
3382 if (bitVectBitValue (sym->regsUsed, i) ||
3383 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3384 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3390 /* if debug then send end of function */
3391 if (options.debug && currFunc)
3394 emitcode ("", "C$%s$%d$%d$%d ==.",
3395 FileBaseName (ic->filename), currFunc->lastLine,
3396 ic->level, ic->block);
3397 if (IS_STATIC (currFunc->etype))
3398 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3400 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3404 emitcode ("ret", "");
3409 /*-----------------------------------------------------------------*/
3410 /* genJavaNativeRet - generate code for return JavaNative */
3411 /*-----------------------------------------------------------------*/
3412 static void genJavaNativeRet(iCode *ic)
3416 aopOp (IC_LEFT (ic), ic, FALSE,
3417 AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
3418 size = AOP_SIZE (IC_LEFT (ic));
3422 /* it is assigned to GPR0-R3 then push them */
3423 if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3424 aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3425 for (i = 0 ; i < size ; i++ ) {
3426 emitcode ("push","%s",
3427 aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3429 for (i = (size-1) ; i >= 0 ; i--) {
3430 emitcode ("pop","a%s",javaRet[i]);
3433 for (i = 0 ; i < size ; i++)
3434 emitcode ("mov","%s,%s",javaRet[i],
3435 aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3437 for (i = size ; i < 4 ; i++ )
3438 emitcode ("mov","%s,#0",javaRet[i]);
3442 /*-----------------------------------------------------------------*/
3443 /* genRet - generate code for return statement */
3444 /*-----------------------------------------------------------------*/
3448 int size, offset = 0, pushed = 0;
3450 D (emitcode (";", "genRet "););
3452 /* if we have no return value then
3453 just generate the "ret" */
3457 /* if this is a JavaNative function then return
3458 value in different register */
3459 if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3460 genJavaNativeRet(ic);
3463 /* we have something to return then
3464 move the return value into place */
3465 aopOp (IC_LEFT (ic), ic, FALSE,
3466 (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
3467 size = AOP_SIZE (IC_LEFT (ic));
3469 _startLazyDPSEvaluation ();
3473 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3475 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3477 emitcode ("push", "%s", l);
3482 /* Since A is the last element of fReturn,
3483 * is is OK to clobber it in the aopGet.
3485 l = aopGet (AOP (IC_LEFT (ic)), offset,
3486 FALSE, FALSE, NULL);
3487 if (strcmp (fReturn[offset], l))
3488 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3491 _endLazyDPSEvaluation ();
3498 if (strcmp (fReturn[pushed], "a"))
3499 emitcode ("pop", fReturn[pushed]);
3501 emitcode ("pop", "acc");
3504 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3507 /* generate a jump to the return label
3508 if the next is not the return statement */
3509 if (!(ic->next && ic->next->op == LABEL &&
3510 IC_LABEL (ic->next) == returnLabel))
3512 emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3516 /*-----------------------------------------------------------------*/
3517 /* genLabel - generates a label */
3518 /*-----------------------------------------------------------------*/
3520 genLabel (iCode * ic)
3522 /* special case never generate */
3523 if (IC_LABEL (ic) == entryLabel)
3526 D (emitcode (";", "genLabel ");
3529 emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3532 /*-----------------------------------------------------------------*/
3533 /* genGoto - generates a ljmp */
3534 /*-----------------------------------------------------------------*/
3536 genGoto (iCode * ic)
3538 D (emitcode (";", "genGoto ");
3540 emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3543 /*-----------------------------------------------------------------*/
3544 /* findLabelBackwards: walks back through the iCode chain looking */
3545 /* for the given label. Returns number of iCode instructions */
3546 /* between that label and given ic. */
3547 /* Returns zero if label not found. */
3548 /*-----------------------------------------------------------------*/
3550 findLabelBackwards (iCode * ic, int key)
3559 /* If we have any pushes or pops, we cannot predict the distance.
3560 I don't like this at all, this should be dealt with in the
3562 if (ic->op == IPUSH || ic->op == IPOP) {
3566 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3568 /* printf("findLabelBackwards = %d\n", count); */
3576 /*-----------------------------------------------------------------*/
3577 /* genPlusIncr :- does addition with increment if possible */
3578 /*-----------------------------------------------------------------*/
3580 genPlusIncr (iCode * ic)
3582 unsigned int icount;
3583 unsigned int size = getDataSize (IC_RESULT (ic));
3585 /* will try to generate an increment */
3586 /* if the right side is not a literal
3588 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3591 /* if the literal value of the right hand side
3592 is greater than 4 then it is not worth it */
3593 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3596 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3597 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3599 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
3603 /* if increment 16 bits in register */
3605 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3606 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3607 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3616 /* If the next instruction is a goto and the goto target
3617 * is <= 5 instructions previous to this, we can generate
3618 * jumps straight to that target.
3620 if (ic->next && ic->next->op == GOTO
3621 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3624 D(emitcode (";", "tail increment optimized (range %d)", labelRange););
3625 tlbl = IC_LABEL (ic->next);
3630 tlbl = newiTempLabel (NULL);
3634 l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
3635 emitcode ("inc", "%s", l);
3637 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3638 IS_AOP_PREG (IC_RESULT (ic)))
3640 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3644 emitcode ("clr", "a");
3645 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3648 l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
3649 emitcode ("inc", "%s", l);
3652 if (!strcmp(l, "acc"))
3654 emitcode("jnz", "!tlabel", tlbl->key + 100);
3656 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3657 IS_AOP_PREG (IC_RESULT (ic)))
3659 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3663 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3666 l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
3667 emitcode ("inc", "%s", l);
3671 if (!strcmp(l, "acc"))
3673 emitcode("jnz", "!tlabel", tlbl->key + 100);
3675 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3676 IS_AOP_PREG (IC_RESULT (ic)))
3678 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3682 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3685 l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
3686 emitcode ("inc", "%s", l); }
3690 emitcode ("", "!tlabeldef", tlbl->key + 100);
3695 if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3696 !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 &&
3697 options.model == MODEL_FLAT24 ) {
3701 emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, NULL));
3703 emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, NULL));
3705 emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3708 while (icount--) emitcode ("inc","dptr");
3712 if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3713 AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3715 emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3716 while (icount--) emitcode ("inc","dptr");
3717 emitcode ("mov","dps,#0");
3721 /* if the sizes are greater than 1 then we cannot */
3722 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3723 AOP_SIZE (IC_LEFT (ic)) > 1)
3726 /* we can if the aops of the left & result match or
3727 if they are in registers and the registers are the
3730 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3731 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3732 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3737 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3738 emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3739 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3744 _startLazyDPSEvaluation ();
3747 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3749 _endLazyDPSEvaluation ();
3758 /*-----------------------------------------------------------------*/
3759 /* outBitAcc - output a bit in acc */
3760 /*-----------------------------------------------------------------*/
3762 outBitAcc (operand * result)
3764 symbol *tlbl = newiTempLabel (NULL);
3765 /* if the result is a bit */
3766 if (AOP_TYPE (result) == AOP_CRY)
3768 aopPut (AOP (result), "a", 0);
3772 emitcode ("jz", "!tlabel", tlbl->key + 100);
3773 emitcode ("mov", "a,%s", one);
3774 emitcode ("", "!tlabeldef", tlbl->key + 100);
3779 /*-----------------------------------------------------------------*/
3780 /* genPlusBits - generates code for addition of two bits */
3781 /*-----------------------------------------------------------------*/
3783 genPlusBits (iCode * ic)
3785 D (emitcode (";", "genPlusBits "););
3787 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3789 symbol *lbl = newiTempLabel (NULL);
3790 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3791 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3792 emitcode ("cpl", "c");
3793 emitcode ("", "!tlabeldef", (lbl->key + 100));
3794 outBitC (IC_RESULT (ic));
3798 emitcode ("clr", "a");
3799 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3800 emitcode ("rlc", "a");
3801 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3802 emitcode ("addc", "a,#0");
3803 outAcc (IC_RESULT (ic));
3808 adjustArithmeticResult (iCode * ic)
3810 if (opIsGptr (IC_RESULT (ic)) &&
3811 opIsGptr (IC_LEFT (ic)) &&
3812 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3814 aopPut (AOP (IC_RESULT (ic)),
3815 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3819 if (opIsGptr (IC_RESULT (ic)) &&
3820 opIsGptr (IC_RIGHT (ic)) &&
3821 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3823 aopPut (AOP (IC_RESULT (ic)),
3824 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3828 if (opIsGptr (IC_RESULT (ic)) &&
3829 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3830 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3831 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3832 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3835 SNPRINTF (buff, sizeof(buff),
3836 "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3837 aopPut (AOP (IC_RESULT (ic)), buff, GPTRSIZE - 1);
3841 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
3842 // generates the result if possible. If result is generated, returns TRUE; otherwise
3843 // returns false and caller must deal with fact that result isn't aopOp'd.
3844 bool aopOp3(iCode * ic)
3846 bool dp1InUse, dp2InUse;
3849 // First, generate the right opcode. DPTR may be used if neither left nor result are
3852 // D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
3853 // AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
3854 // AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
3855 // AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
3857 // D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
3858 // AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
3859 // AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
3860 // AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
3863 // Right uses DPTR unless left or result is an AOP_STR; however,
3864 // if right is an AOP_STR, it must use DPTR regardless.
3865 if ((AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)))
3866 && !AOP_IS_STR(IC_RIGHT(ic)))
3875 aopOp (IC_RIGHT(ic),ic,FALSE, useDp2);
3877 // if the right used DPTR, left MUST use DPTR2.
3878 // if the right used DPTR2, left MUST use DPTR.
3879 // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
3880 // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
3881 // enabling us to assign DPTR to result.
3883 if (AOP_USESDPTR(IC_RIGHT(ic)))
3887 else if (AOP_USESDPTR2(IC_RIGHT(ic)))
3893 if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
3903 aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
3905 // We've op'd the left & right. So, if left or right are the same operand as result,
3906 // we know aopOp will succeed, and we can just do it & bail.
3907 if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)) ||
3908 isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
3910 // D(emitcode(";", "aopOp3: (left | right) & result equal"););
3911 aopOp(IC_RESULT(ic),ic,TRUE, FALSE);
3915 // Note which dptrs are currently in use.
3916 dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
3917 dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
3919 // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot
3921 if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
3926 // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
3927 if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
3932 // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck
3933 if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
3938 aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
3940 // Some sanity checking...
3941 if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
3944 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
3945 __FILE__, __LINE__, ic->filename, ic->lineno);
3946 emitcode(";", ">>> unexpected DPTR here.");
3949 if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
3952 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
3953 __FILE__, __LINE__, ic->filename, ic->lineno);
3954 emitcode(";", ">>> unexpected DPTR2 here.");
3960 // Macro to aopOp all three operands of an ic. If this cannot be done,
3961 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3962 // will be set TRUE. The caller must then handle the case specially, noting
3963 // that the IC_RESULT operand is not aopOp'd.
3965 #define AOP_OP_3_NOFATAL(ic, rc) \
3966 do { rc = !aopOp3(ic); } while (0)
3968 // aopOp the left & right operands of an ic.
3969 #define AOP_OP_2(ic) \
3970 aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
3971 aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
3973 // convienience macro.
3974 #define AOP_SET_LOCALS(ic) \
3975 left = IC_LEFT(ic); \
3976 right = IC_RIGHT(ic); \
3977 result = IC_RESULT(ic);
3980 // Given an integer value of pushedSize bytes on the stack,
3981 // adjust it to be resultSize bytes, either by discarding
3982 // the most significant bytes or by zero-padding.
3984 // On exit from this macro, pushedSize will have been adjusted to
3985 // equal resultSize, and ACC may be trashed.
3986 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3987 /* If the pushed data is bigger than the result, \
3988 * simply discard unused bytes. Icky, but works. \
3990 while (pushedSize > resultSize) \
3992 D (emitcode (";", "discarding unused result byte."););\
3993 emitcode ("pop", "acc"); \
3996 if (pushedSize < resultSize) \
3998 emitcode ("clr", "a"); \
3999 /* Conversly, we haven't pushed enough here. \
4000 * just zero-pad, and all is well. \
4002 while (pushedSize < resultSize) \
4004 emitcode("push", "acc"); \
4008 assert(pushedSize == resultSize);
4010 /*-----------------------------------------------------------------*/
4011 /* genPlus - generates code for addition */
4012 /*-----------------------------------------------------------------*/
4014 genPlus (iCode * ic)
4016 int size, offset = 0;
4020 D (emitcode (";", "genPlus "););
4022 /* special cases :- */
4023 if ( AOP_IS_STR(IC_LEFT(ic)) &&
4024 isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
4025 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
4026 size = (int)floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
4028 while (size--) emitcode ("inc","dptr");
4030 emitcode ("mov","a,dpl");
4031 emitcode ("add","a,#!constbyte",size & 0xff);
4032 emitcode ("mov","dpl,a");
4033 emitcode ("mov","a,dph");
4034 emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
4035 emitcode ("mov","dph,a");
4036 emitcode ("mov","a,dpx");
4037 emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
4038 emitcode ("mov","dpx,a");
4040 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
4043 if ( IS_SYMOP(IC_LEFT(ic)) &&
4044 OP_SYMBOL(IC_LEFT(ic))->remat &&
4045 isOperandInFarSpace(IC_RIGHT(ic))) {
4046 operand *op = IC_RIGHT(ic);
4047 IC_RIGHT(ic) = IC_LEFT(ic);
4051 AOP_OP_3_NOFATAL (ic, pushResult);
4055 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
4060 /* if literal, literal on the right or
4061 if left requires ACC or right is already
4063 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4064 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
4065 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4067 operand *t = IC_RIGHT (ic);
4068 IC_RIGHT (ic) = IC_LEFT (ic);
4070 emitcode (";", "Swapped plus args.");
4073 /* if both left & right are in bit
4075 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4076 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4082 /* if left in bit space & right literal */
4083 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4084 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4086 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4087 /* if result in bit space */
4088 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4090 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4091 emitcode ("cpl", "c");
4092 outBitC (IC_RESULT (ic));
4096 size = getDataSize (IC_RESULT (ic));
4097 _startLazyDPSEvaluation ();
4100 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4101 emitcode ("addc", "a,#0");
4102 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4104 _endLazyDPSEvaluation ();
4109 /* if I can do an increment instead
4110 of add then GOOD for ME */
4111 if (genPlusIncr (ic) == TRUE)
4113 emitcode (";", "did genPlusIncr");
4118 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4120 _startLazyDPSEvaluation ();
4123 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4125 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4127 emitcode ("add", "a,%s",
4128 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4130 emitcode ("addc", "a,%s",
4131 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4135 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4137 /* right is going to use ACC or we would have taken the
4140 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4142 D(emitcode(";", "+ AOP_ACC special case."););
4143 emitcode("xch", "a, %s", DP2_RESULT_REG);
4145 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4148 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4151 emitcode("add", "a, %s", DP2_RESULT_REG);
4155 emitcode ("add", "a,%s",
4156 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE,
4162 emitcode ("addc", "a,%s",
4163 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE,
4169 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4173 emitcode ("push", "acc");
4177 _endLazyDPSEvaluation ();
4181 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4183 size = getDataSize (IC_LEFT (ic));
4184 rSize = getDataSize (IC_RESULT (ic));
4186 ADJUST_PUSHED_RESULT(size, rSize);
4188 _startLazyDPSEvaluation ();
4191 emitcode ("pop", "acc");
4192 aopPut (AOP (IC_RESULT (ic)), "a", size);
4194 _endLazyDPSEvaluation ();
4197 adjustArithmeticResult (ic);
4200 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4201 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4202 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4205 /*-----------------------------------------------------------------*/
4206 /* genMinusDec :- does subtraction with deccrement if possible */
4207 /*-----------------------------------------------------------------*/
4209 genMinusDec (iCode * ic)
4211 unsigned int icount;
4212 unsigned int size = getDataSize (IC_RESULT (ic));
4214 /* will try to generate an increment */
4215 /* if the right side is not a literal
4217 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4220 /* if the literal value of the right hand side
4221 is greater than 4 then it is not worth it */
4222 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4225 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4226 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4228 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
4232 /* if decrement 16 bits in register */
4233 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4234 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4235 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4244 /* If the next instruction is a goto and the goto target
4245 * is <= 5 instructions previous to this, we can generate
4246 * jumps straight to that target.
4248 if (ic->next && ic->next->op == GOTO
4249 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4252 emitcode (";", "tail decrement optimized (range %d)", labelRange);
4253 tlbl = IC_LABEL (ic->next);
4258 tlbl = newiTempLabel (NULL);
4262 l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
4263 emitcode ("dec", "%s", l);
4265 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4266 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4267 IS_AOP_PREG (IC_RESULT (ic)))
4269 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4273 emitcode ("mov", "a,#!constbyte",0xff);
4274 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4276 l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
4277 emitcode ("dec", "%s", l);
4280 if (!strcmp(l, "acc"))
4282 emitcode("jnz", "!tlabel", tlbl->key + 100);
4284 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4285 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4286 IS_AOP_PREG (IC_RESULT (ic)))
4288 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4292 emitcode ("mov", "a,#!constbyte",0xff);
4293 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4295 l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
4296 emitcode ("dec", "%s", l);
4300 if (!strcmp(l, "acc"))
4302 emitcode("jnz", "!tlabel", tlbl->key + 100);
4304 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4305 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4306 IS_AOP_PREG (IC_RESULT (ic)))
4308 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4312 emitcode ("mov", "a,#!constbyte",0xff);
4313 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4315 l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
4316 emitcode ("dec", "%s", l);
4320 emitcode ("", "!tlabeldef", tlbl->key + 100);
4325 /* if the sizes are greater than 1 then we cannot */
4326 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4327 AOP_SIZE (IC_LEFT (ic)) > 1)
4330 /* we can if the aops of the left & result match or
4331 if they are in registers and the registers are the
4334 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4335 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4336 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4339 _startLazyDPSEvaluation ();
4342 emitcode ("dec", "%s",
4343 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
4345 _endLazyDPSEvaluation ();
4353 /*-----------------------------------------------------------------*/
4354 /* addSign - complete with sign */
4355 /*-----------------------------------------------------------------*/
4357 addSign (operand * result, int offset, int sign)
4359 int size = (getDataSize (result) - offset);
4362 _startLazyDPSEvaluation();
4365 emitcode ("rlc", "a");
4366 emitcode ("subb", "a,acc");
4369 aopPut (AOP (result), "a", offset++);
4376 aopPut (AOP (result), zero, offset++);
4379 _endLazyDPSEvaluation();
4383 /*-----------------------------------------------------------------*/
4384 /* genMinusBits - generates code for subtraction of two bits */
4385 /*-----------------------------------------------------------------*/
4387 genMinusBits (iCode * ic)
4389 symbol *lbl = newiTempLabel (NULL);
4391 D (emitcode (";", "genMinusBits "););
4393 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4395 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4396 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4397 emitcode ("cpl", "c");
4398 emitcode ("", "!tlabeldef", (lbl->key + 100));
4399 outBitC (IC_RESULT (ic));
4403 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4404 emitcode ("subb", "a,acc");
4405 emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4406 emitcode ("inc", "a");
4407 emitcode ("", "!tlabeldef", (lbl->key + 100));
4408 aopPut (AOP (IC_RESULT (ic)), "a", 0);
4409 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4413 /*-----------------------------------------------------------------*/
4414 /* genMinus - generates code for subtraction */
4415 /*-----------------------------------------------------------------*/
4417 genMinus (iCode * ic)
4419 int size, offset = 0;
4424 D (emitcode (";", "genMinus "););
4426 AOP_OP_3_NOFATAL(ic, pushResult);
4430 /* special cases :- */
4431 /* if both left & right are in bit space */
4432 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4433 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4439 /* if I can do an decrement instead
4440 of subtract then GOOD for ME */
4441 if (genMinusDec (ic) == TRUE)
4446 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4448 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4454 lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4459 /* if literal, add a,#-lit, else normal subb */
4460 _startLazyDPSEvaluation ();
4462 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4463 if (AOP_USESDPTR(IC_RIGHT(ic))) {
4464 emitcode ("mov","b,%s",
4465 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4466 MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4467 emitcode ("subb","a,b");
4469 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4470 emitcode ("subb", "a,%s",
4471 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE,
4475 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4476 /* first add without previous c */
4478 if (!size && lit==-1) {
4479 emitcode ("dec", "a");
4481 emitcode ("add", "a,#!constbyte",
4482 (unsigned int) (lit & 0x0FFL));
4485 emitcode ("addc", "a,#!constbyte",
4486 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4491 emitcode ("push", "acc");
4493 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4497 _endLazyDPSEvaluation ();
4501 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4503 size = getDataSize (IC_LEFT (ic));
4504 rSize = getDataSize (IC_RESULT (ic));
4506 ADJUST_PUSHED_RESULT(size, rSize);
4508 _startLazyDPSEvaluation ();
4511 emitcode ("pop", "acc");
4512 aopPut (AOP (IC_RESULT (ic)), "a", size);
4514 _endLazyDPSEvaluation ();
4517 adjustArithmeticResult (ic);
4520 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4521 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4522 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4526 /*-----------------------------------------------------------------*/
4527 /* genMultbits :- multiplication of bits */
4528 /*-----------------------------------------------------------------*/
4530 genMultbits (operand * left,
4535 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4536 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4537 aopOp(result, ic, TRUE, FALSE);
4542 /*-----------------------------------------------------------------*/
4543 /* genMultOneByte : 8*8=8/16 bit multiplication */
4544 /*-----------------------------------------------------------------*/
4546 genMultOneByte (operand * left,
4551 sym_link *opetype = operandType (result);
4555 /* (if two literals: the value is computed before) */
4556 /* if one literal, literal on the right */
4557 if (AOP_TYPE (left) == AOP_LIT)
4562 emitcode (";", "swapped left and right");
4565 if (SPEC_USIGN(opetype)
4566 // ignore the sign of left and right, what else can we do?
4567 || (SPEC_USIGN(operandType(left)) &&
4568 SPEC_USIGN(operandType(right)))) {
4569 // just an unsigned 8*8=8/16 multiply
4570 //emitcode (";","unsigned");
4571 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4572 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4573 emitcode ("mul", "ab");
4575 _G.accInUse++; _G.bInUse++;
4576 aopOp(result, ic, TRUE, FALSE);
4578 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4580 // this should never happen
4581 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4582 AOP_SIZE(result), __FILE__, lineno);
4586 aopPut (AOP (result), "a", 0);
4587 _G.accInUse--; _G.bInUse--;
4588 if (AOP_SIZE(result)==2)
4590 aopPut (AOP (result), "b", 1);
4595 // we have to do a signed multiply
4597 emitcode (";", "signed");
4598 emitcode ("clr", "F0"); // reset sign flag
4599 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4601 lbl=newiTempLabel(NULL);
4602 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4603 // left side is negative, 8-bit two's complement, this fails for -128
4604 emitcode ("setb", "F0"); // set sign flag
4605 emitcode ("cpl", "a");
4606 emitcode ("inc", "a");
4608 emitcode ("", "!tlabeldef", lbl->key+100);
4611 if (AOP_TYPE(right)==AOP_LIT) {
4612 signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
4613 /* AND literal negative */
4614 if ((int) val < 0) {
4615 emitcode ("cpl", "F0"); // complement sign flag
4616 emitcode ("mov", "b,#!constbyte", -val);
4618 emitcode ("mov", "b,#!constbyte", val);
4621 lbl=newiTempLabel(NULL);
4622 emitcode ("mov", "b,a");
4623 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4624 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4625 // right side is negative, 8-bit two's complement
4626 emitcode ("cpl", "F0"); // complement sign flag
4627 emitcode ("cpl", "a");
4628 emitcode ("inc", "a");
4629 emitcode ("", "!tlabeldef", lbl->key+100);
4631 emitcode ("mul", "ab");
4633 _G.accInUse++;_G.bInUse++;
4634 aopOp(result, ic, TRUE, FALSE);
4636 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4638 // this should never happen
4639 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4640 AOP_SIZE(result), __FILE__, lineno);
4644 lbl=newiTempLabel(NULL);
4645 emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4646 // only ONE op was negative, we have to do a 8/16-bit two's complement
4647 emitcode ("cpl", "a"); // lsb
4648 if (AOP_SIZE(result)==1) {
4649 emitcode ("inc", "a");
4651 emitcode ("add", "a,#1");
4652 emitcode ("xch", "a,b");
4653 emitcode ("cpl", "a"); // msb
4654 emitcode ("addc", "a,#0");
4655 emitcode ("xch", "a,b");
4658 emitcode ("", "!tlabeldef", lbl->key+100);
4659 aopPut (AOP (result), "a", 0);
4660 _G.accInUse--;_G.bInUse--;
4661 if (AOP_SIZE(result)==2) {
4662 aopPut (AOP (result), "b", 1);
4666 /*-----------------------------------------------------------------*/
4667 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
4668 /*-----------------------------------------------------------------*/
4669 static void genMultTwoByte (operand *left, operand *right,
4670 operand *result, iCode *ic)
4672 sym_link *retype = getSpec(operandType(right));
4673 sym_link *letype = getSpec(operandType(left));
4674 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4677 if (AOP_TYPE (left) == AOP_LIT) {
4682 /* save EA bit in F1 */
4683 lbl = newiTempLabel(NULL);
4684 emitcode ("setb","F1");
4685 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4686 emitcode ("clr","F1");
4687 emitcode("","!tlabeldef",lbl->key+100);
4689 /* load up MB with right */
4691 emitcode("clr","F0");
4692 if (AOP_TYPE(right) == AOP_LIT) {
4693 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
4695 emitcode("setb","F0");
4698 emitcode ("mov","mb,#!constbyte",val & 0xff);
4699 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4701 lbl = newiTempLabel(NULL);
4702 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4703 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4704 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4705 emitcode ("xch", "a,b");
4706 emitcode ("cpl","a");
4707 emitcode ("add", "a,#1");
4708 emitcode ("xch", "a,b");
4709 emitcode ("cpl", "a"); // msb
4710 emitcode ("addc", "a,#0");
4711 emitcode ("setb","F0");
4712 emitcode ("","!tlabeldef",lbl->key+100);
4713 emitcode ("mov","mb,b");
4714 emitcode ("mov","mb,a");
4717 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4718 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4720 /* load up MA with left */
4722 lbl = newiTempLabel(NULL);
4723 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4724 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4725 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4726 emitcode ("xch", "a,b");
4727 emitcode ("cpl","a");
4728 emitcode ("add", "a,#1");
4729 emitcode ("xch", "a,b");
4730 emitcode ("cpl", "a"); // msb
4731 emitcode ("addc","a,#0");
4732 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4733 emitcode ("setb","F0");
4734 emitcode ("","!tlabeldef",lbl->key+100);
4735 emitcode ("mov","ma,b");
4736 emitcode ("mov","ma,a");
4738 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4739 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4741 /* wait for multiplication to finish */
4742 lbl = newiTempLabel(NULL);
4743 emitcode("","!tlabeldef", lbl->key+100);
4744 emitcode("mov","a,mcnt1");
4745 emitcode("anl","a,#!constbyte",0x80);
4746 emitcode("jnz","!tlabel",lbl->key+100);
4748 freeAsmop (left, NULL, ic, TRUE);
4749 freeAsmop (right, NULL, ic,TRUE);
4750 aopOp(result, ic, TRUE, FALSE);
4752 /* if unsigned then simple */
4754 emitcode ("mov","a,ma");
4755 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4756 emitcode ("mov","a,ma");
4757 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4758 aopPut(AOP(result),"ma",1);
4759 aopPut(AOP(result),"ma",0);
4761 emitcode("push","ma");
4762 emitcode("push","ma");
4763 emitcode("push","ma");
4765 /* negate result if needed */
4766 lbl = newiTempLabel(NULL);
4767 emitcode("jnb","F0,!tlabel",lbl->key+100);
4768 emitcode("cpl","a");
4769 emitcode("add","a,#1");
4770 emitcode("","!tlabeldef", lbl->key+100);
4771 if (AOP_TYPE(result) == AOP_ACC)
4773 D(emitcode(";", "ACC special case."););
4774 /* We know result is the only live aop, and
4775 * it's obviously not a DPTR2, so AP is available.
4777 emitcode("mov", "%s,acc", DP2_RESULT_REG);
4781 aopPut(AOP(result),"a",0);
4784 emitcode("pop","acc");
4785 lbl = newiTempLabel(NULL);
4786 emitcode("jnb","F0,!tlabel",lbl->key+100);
4787 emitcode("cpl","a");
4788 emitcode("addc","a,#0");
4789 emitcode("","!tlabeldef", lbl->key+100);
4790 aopPut(AOP(result),"a",1);
4791 emitcode("pop","acc");
4792 if (AOP_SIZE(result) >= 3) {
4793 lbl = newiTempLabel(NULL);
4794 emitcode("jnb","F0,!tlabel",lbl->key+100);
4795 emitcode("cpl","a");
4796 emitcode("addc","a,#0");
4797 emitcode("","!tlabeldef", lbl->key+100);
4798 aopPut(AOP(result),"a",2);
4800 emitcode("pop","acc");
4801 if (AOP_SIZE(result) >= 4) {
4802 lbl = newiTempLabel(NULL);
4803 emitcode("jnb","F0,!tlabel",lbl->key+100);
4804 emitcode("cpl","a");
4805 emitcode("addc","a,#0");
4806 emitcode("","!tlabeldef", lbl->key+100);
4807 aopPut(AOP(result),"a",3);
4809 if (AOP_TYPE(result) == AOP_ACC)
4811 /* We stashed the result away above. */
4812 emitcode("mov", "acc,%s", DP2_RESULT_REG);
4816 freeAsmop (result, NULL, ic, TRUE);
4818 /* restore EA bit in F1 */
4819 lbl = newiTempLabel(NULL);
4820 emitcode ("jnb","F1,!tlabel",lbl->key+100);
4821 emitcode ("setb","EA");
4822 emitcode("","!tlabeldef",lbl->key+100);
4826 /*-----------------------------------------------------------------*/
4827 /* genMult - generates code for multiplication */
4828 /*-----------------------------------------------------------------*/
4830 genMult (iCode * ic)
4832 operand *left = IC_LEFT (ic);
4833 operand *right = IC_RIGHT (ic);
4834 operand *result = IC_RESULT (ic);
4836 D (emitcode (";", "genMult "););
4838 /* assign the amsops */
4841 /* special cases first */
4843 if (AOP_TYPE (left) == AOP_CRY &&
4844 AOP_TYPE (right) == AOP_CRY)
4846 genMultbits (left, right, result, ic);
4850 /* if both are of size == 1 */
4851 if (AOP_SIZE (left) == 1 &&
4852 AOP_SIZE (right) == 1)
4854 genMultOneByte (left, right, result, ic);
4858 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4859 /* use the ds390 ARITHMETIC accel UNIT */
4860 genMultTwoByte (left, right, result, ic);
4863 /* should have been converted to function call */
4867 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4868 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4869 freeAsmop (result, NULL, ic, TRUE);
4872 /*-----------------------------------------------------------------*/
4873 /* genDivbits :- division of bits */
4874 /*-----------------------------------------------------------------*/
4876 genDivbits (operand * left,
4884 /* the result must be bit */
4885 LOAD_AB_FOR_DIV (left, right, l);
4886 emitcode ("div", "ab");
4887 emitcode ("rrc", "a");
4888 aopOp(result, ic, TRUE, FALSE);
4890 aopPut (AOP (result), "c", 0);
4893 /*-----------------------------------------------------------------*/
4894 /* genDivOneByte : 8 bit division */
4895 /*-----------------------------------------------------------------*/
4897 genDivOneByte (operand * left,
4902 sym_link *opetype = operandType (result);
4908 /* signed or unsigned */
4909 if (SPEC_USIGN (opetype))
4911 /* unsigned is easy */
4912 LOAD_AB_FOR_DIV (left, right, l);
4913 emitcode ("div", "ab");
4916 aopOp(result, ic, TRUE, FALSE);
4917 aopPut (AOP (result), "a", 0);
4920 size = AOP_SIZE (result) - 1;
4924 aopPut (AOP (result), zero, offset++);
4929 /* signed is a little bit more difficult */
4931 /* save the signs of the operands */
4932 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4933 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4934 emitcode ("push", "acc"); /* save it on the stack */
4936 /* now sign adjust for both left & right */
4937 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4938 lbl = newiTempLabel (NULL);
4939 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4940 emitcode ("cpl", "a");
4941 emitcode ("inc", "a");
4942 emitcode ("", "!tlabeldef", (lbl->key + 100));
4943 emitcode ("mov", "b,a");
4945 /* sign adjust left side */
4946 MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4948 lbl = newiTempLabel (NULL);
4949 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4950 emitcode ("cpl", "a");
4951 emitcode ("inc", "a");
4952 emitcode ("", "!tlabeldef", (lbl->key + 100));
4954 /* now the division */
4955 emitcode ("nop", "; workaround for DS80C390 div bug.");
4956 emitcode ("div", "ab");
4957 /* we are interested in the lower order
4959 emitcode ("mov", "b,a");
4960 lbl = newiTempLabel (NULL);
4961 emitcode ("pop", "acc");
4962 /* if there was an over flow we don't
4963 adjust the sign of the result */
4964 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4965 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4967 emitcode ("clr", "a");
4968 emitcode ("subb", "a,b");
4969 emitcode ("mov", "b,a");
4970 emitcode ("", "!tlabeldef", (lbl->key + 100));
4972 /* now we are done */
4973 _G.accInUse++; _G.bInUse++;
4974 aopOp(result, ic, TRUE, FALSE);
4976 aopPut (AOP (result), "b", 0);
4978 size = AOP_SIZE (result) - 1;
4982 emitcode ("mov", "c,b.7");
4983 emitcode ("subb", "a,acc");
4987 aopPut (AOP (result), "a", offset++);
4989 _G.accInUse--; _G.bInUse--;
4993 /*-----------------------------------------------------------------*/
4994 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
4995 /*-----------------------------------------------------------------*/
4996 static void genDivTwoByte (operand *left, operand *right,
4997 operand *result, iCode *ic)
4999 sym_link *retype = getSpec(operandType(right));
5000 sym_link *letype = getSpec(operandType(left));
5001 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5004 /* save EA bit in F1 */
5005 lbl = newiTempLabel(NULL);
5006 emitcode ("setb","F1");
5007 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5008 emitcode ("clr","F1");
5009 emitcode("","!tlabeldef",lbl->key+100);
5011 /* load up MA with left */
5013 emitcode("clr","F0");
5014 lbl = newiTempLabel(NULL);
5015 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5016 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5017 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5018 emitcode ("xch", "a,b");
5019 emitcode ("cpl","a");
5020 emitcode ("add", "a,#1");
5021 emitcode ("xch", "a,b");
5022 emitcode ("cpl", "a"); // msb
5023 emitcode ("addc","a,#0");
5024 emitcode ("setb","F0");
5025 emitcode ("","!tlabeldef",lbl->key+100);
5026 emitcode ("mov","ma,b");
5027 emitcode ("mov","ma,a");
5029 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5030 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5033 /* load up MB with right */
5035 if (AOP_TYPE(right) == AOP_LIT) {
5036 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5038 lbl = newiTempLabel(NULL);
5039 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5040 emitcode("setb","F0");
5041 emitcode ("","!tlabeldef",lbl->key+100);
5044 emitcode ("mov","mb,#!constbyte",val & 0xff);
5045 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5047 lbl = newiTempLabel(NULL);
5048 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5049 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5050 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5051 emitcode ("xch", "a,b");
5052 emitcode ("cpl","a");
5053 emitcode ("add", "a,#1");
5054 emitcode ("xch", "a,b");
5055 emitcode ("cpl", "a"); // msb
5056 emitcode ("addc", "a,#0");
5057 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5058 emitcode ("setb","F0");
5059 emitcode ("","!tlabeldef",lbl->key+100);
5060 emitcode ("mov","mb,b");
5061 emitcode ("mov","mb,a");
5064 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5065 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5068 /* wait for multiplication to finish */
5069 lbl = newiTempLabel(NULL);
5070 emitcode("","!tlabeldef", lbl->key+100);
5071 emitcode("mov","a,mcnt1");
5072 emitcode("anl","a,#!constbyte",0x80);
5073 emitcode("jnz","!tlabel",lbl->key+100);
5075 freeAsmop (left, NULL, ic, TRUE);
5076 freeAsmop (right, NULL, ic,TRUE);
5077 aopOp(result, ic, TRUE, FALSE);
5079 /* if unsigned then simple */
5081 aopPut(AOP(result),"ma",1);
5082 aopPut(AOP(result),"ma",0);
5084 emitcode("push","ma");
5086 /* negate result if needed */
5087 lbl = newiTempLabel(NULL);
5088 emitcode("jnb","F0,!tlabel",lbl->key+100);
5089 emitcode("cpl","a");
5090 emitcode("add","a,#1");
5091 emitcode("","!tlabeldef", lbl->key+100);
5092 aopPut(AOP(result),"a",0);
5093 emitcode("pop","acc");
5094 lbl = newiTempLabel(NULL);
5095 emitcode("jnb","F0,!tlabel",lbl->key+100);
5096 emitcode("cpl","a");
5097 emitcode("addc","a,#0");
5098 emitcode("","!tlabeldef", lbl->key+100);
5099 aopPut(AOP(result),"a",1);
5101 freeAsmop (result, NULL, ic, TRUE);
5102 /* restore EA bit in F1 */
5103 lbl = newiTempLabel(NULL);
5104 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5105 emitcode ("setb","EA");
5106 emitcode("","!tlabeldef",lbl->key+100);
5110 /*-----------------------------------------------------------------*/
5111 /* genDiv - generates code for division */
5112 /*-----------------------------------------------------------------*/
5116 operand *left = IC_LEFT (ic);
5117 operand *right = IC_RIGHT (ic);
5118 operand *result = IC_RESULT (ic);
5120 D (emitcode (";", "genDiv "););
5122 /* assign the amsops */
5125 /* special cases first */
5127 if (AOP_TYPE (left) == AOP_CRY &&
5128 AOP_TYPE (right) == AOP_CRY)
5130 genDivbits (left, right, result, ic);
5134 /* if both are of size == 1 */
5135 if (AOP_SIZE (left) == 1 &&
5136 AOP_SIZE (right) == 1)
5138 genDivOneByte (left, right, result, ic);
5142 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5143 /* use the ds390 ARITHMETIC accel UNIT */
5144 genDivTwoByte (left, right, result, ic);
5147 /* should have been converted to function call */
5150 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5151 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5152 freeAsmop (result, NULL, ic, TRUE);
5155 /*-----------------------------------------------------------------*/
5156 /* genModbits :- modulus of bits */
5157 /*-----------------------------------------------------------------*/
5159 genModbits (operand * left,
5167 /* the result must be bit */
5168 LOAD_AB_FOR_DIV (left, right, l);
5169 emitcode ("div", "ab");
5170 emitcode ("mov", "a,b");
5171 emitcode ("rrc", "a");
5172 aopOp(result, ic, TRUE, FALSE);
5173 aopPut (AOP (result), "c", 0);
5176 /*-----------------------------------------------------------------*/
5177 /* genModOneByte : 8 bit modulus */
5178 /*-----------------------------------------------------------------*/
5180 genModOneByte (operand * left,
5185 sym_link *opetype = operandType (result);
5189 /* signed or unsigned */
5190 if (SPEC_USIGN (opetype))
5192 /* unsigned is easy */
5193 LOAD_AB_FOR_DIV (left, right, l);
5194 emitcode ("div", "ab");
5195 aopOp(result, ic, TRUE, FALSE);
5196 aopPut (AOP (result), "b", 0);
5200 /* signed is a little bit more difficult */
5202 /* save the signs of the operands */
5203 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5205 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
5206 emitcode ("push", "acc"); /* save it on the stack */
5208 /* now sign adjust for both left & right */
5209 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5211 lbl = newiTempLabel (NULL);
5212 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5213 emitcode ("cpl", "a");
5214 emitcode ("inc", "a");
5215 emitcode ("", "!tlabeldef", (lbl->key + 100));
5216 emitcode ("mov", "b,a");
5218 /* sign adjust left side */
5219 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5221 lbl = newiTempLabel (NULL);
5222 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5223 emitcode ("cpl", "a");
5224 emitcode ("inc", "a");
5225 emitcode ("", "!tlabeldef", (lbl->key + 100));
5227 /* now the multiplication */
5228 emitcode ("nop", "; workaround for DS80C390 div bug.");
5229 emitcode ("div", "ab");
5230 /* we are interested in the lower order
5232 lbl = newiTempLabel (NULL);
5233 emitcode ("pop", "acc");
5234 /* if there was an over flow we don't
5235 adjust the sign of the result */
5236 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
5237 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5239 emitcode ("clr", "a");
5240 emitcode ("subb", "a,b");
5241 emitcode ("mov", "b,a");
5242 emitcode ("", "!tlabeldef", (lbl->key + 100));
5245 /* now we are done */
5246 aopOp(result, ic, TRUE, FALSE);
5247 aopPut (AOP (result), "b", 0);
5252 /*-----------------------------------------------------------------*/
5253 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
5254 /*-----------------------------------------------------------------*/
5255 static void genModTwoByte (operand *left, operand *right,
5256 operand *result, iCode *ic)
5258 sym_link *retype = getSpec(operandType(right));
5259 sym_link *letype = getSpec(operandType(left));
5260 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5263 /* load up MA with left */
5264 /* save EA bit in F1 */
5265 lbl = newiTempLabel(NULL);
5266 emitcode ("setb","F1");
5267 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5268 emitcode ("clr","F1");
5269 emitcode("","!tlabeldef",lbl->key+100);
5272 lbl = newiTempLabel(NULL);
5273 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5274 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5275 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5276 emitcode ("xch", "a,b");
5277 emitcode ("cpl","a");
5278 emitcode ("add", "a,#1");
5279 emitcode ("xch", "a,b");
5280 emitcode ("cpl", "a"); // msb
5281 emitcode ("addc","a,#0");
5282 emitcode ("","!tlabeldef",lbl->key+100);
5283 emitcode ("mov","ma,b");
5284 emitcode ("mov","ma,a");
5286 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5287 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5290 /* load up MB with right */
5292 if (AOP_TYPE(right) == AOP_LIT) {
5293 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5297 emitcode ("mov","mb,#!constbyte",val & 0xff);
5298 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5300 lbl = newiTempLabel(NULL);
5301 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5302 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5303 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5304 emitcode ("xch", "a,b");
5305 emitcode ("cpl","a");
5306 emitcode ("add", "a,#1");
5307 emitcode ("xch", "a,b");
5308 emitcode ("cpl", "a"); // msb
5309 emitcode ("addc", "a,#0");
5310 emitcode ("","!tlabeldef",lbl->key+100);
5311 emitcode ("mov","mb,b");
5312 emitcode ("mov","mb,a");
5315 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5316 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5319 /* wait for multiplication to finish */
5320 lbl = newiTempLabel(NULL);
5321 emitcode("","!tlabeldef", lbl->key+100);
5322 emitcode("mov","a,mcnt1");
5323 emitcode("anl","a,#!constbyte",0x80);
5324 emitcode("jnz","!tlabel",lbl->key+100);
5326 freeAsmop (left, NULL, ic, TRUE);
5327 freeAsmop (right, NULL, ic,TRUE);
5328 aopOp(result, ic, TRUE, FALSE);
5330 aopPut(AOP(result),"mb",1);
5331 aopPut(AOP(result),"mb",0);
5332 freeAsmop (result, NULL, ic, TRUE);
5334 /* restore EA bit in F1 */
5335 lbl = newiTempLabel(NULL);
5336 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5337 emitcode ("setb","EA");
5338 emitcode("","!tlabeldef",lbl->key+100);
5342 /*-----------------------------------------------------------------*/
5343 /* genMod - generates code for division */
5344 /*-----------------------------------------------------------------*/
5348 operand *left = IC_LEFT (ic);
5349 operand *right = IC_RIGHT (ic);
5350 operand *result = IC_RESULT (ic);
5352 D (emitcode (";", "genMod "); );
5354 /* assign the amsops */
5357 /* special cases first */
5359 if (AOP_TYPE (left) == AOP_CRY &&
5360 AOP_TYPE (right) == AOP_CRY)
5362 genModbits (left, right, result, ic);
5366 /* if both are of size == 1 */
5367 if (AOP_SIZE (left) == 1 &&
5368 AOP_SIZE (right) == 1)
5370 genModOneByte (left, right, result, ic);
5374 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5375 /* use the ds390 ARITHMETIC accel UNIT */
5376 genModTwoByte (left, right, result, ic);
5380 /* should have been converted to function call */
5384 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5385 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5386 freeAsmop (result, NULL, ic, TRUE);
5389 /*-----------------------------------------------------------------*/
5390 /* genIfxJump :- will create a jump depending on the ifx */
5391 /*-----------------------------------------------------------------*/
5393 genIfxJump (iCode * ic, char *jval)
5396 symbol *tlbl = newiTempLabel (NULL);
5399 D (emitcode (";", "genIfxJump"););
5401 /* if true label then we jump if condition
5405 jlbl = IC_TRUE (ic);
5406 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5407 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5411 /* false label is present */
5412 jlbl = IC_FALSE (ic);
5413 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5414 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5416 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5417 emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5419 emitcode (inst, "!tlabel", tlbl->key + 100);
5420 emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5421 emitcode ("", "!tlabeldef", tlbl->key + 100);
5423 /* mark the icode as generated */
5427 /*-----------------------------------------------------------------*/
5428 /* genCmp :- greater or less than comparison */
5429 /*-----------------------------------------------------------------*/
5431 genCmp (operand * left, operand * right,
5432 iCode * ic, iCode * ifx, int sign)
5434 int size, offset = 0;
5435 unsigned long lit = 0L;
5438 D (emitcode (";", "genCmp"););
5440 result = IC_RESULT (ic);
5442 /* if left & right are bit variables */
5443 if (AOP_TYPE (left) == AOP_CRY &&
5444 AOP_TYPE (right) == AOP_CRY)
5446 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5447 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5451 /* subtract right from left if at the
5452 end the carry flag is set then we know that
5453 left is greater than right */
5454 size = max (AOP_SIZE (left), AOP_SIZE (right));
5456 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5457 if ((size == 1) && !sign
5458 && (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5460 symbol *lbl = newiTempLabel (NULL);
5461 emitcode ("cjne", "%s,%s,!tlabel",
5462 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
5463 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5465 emitcode ("", "!tlabeldef", lbl->key + 100);
5469 if (AOP_TYPE (right) == AOP_LIT)
5471 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5472 /* optimize if(x < 0) or if(x >= 0) */
5481 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
5483 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5484 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5486 aopOp (result, ic, FALSE, FALSE);
5488 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5490 freeAsmop (result, NULL, ic, TRUE);
5491 genIfxJump (ifx, "acc.7");
5496 emitcode ("rlc", "a");
5498 goto release_freedLR;
5506 // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5507 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5508 // emitcode (";", "genCmp #2");
5509 if (sign && (size == 0))
5511 // emitcode (";", "genCmp #3");
5512 emitcode ("xrl", "a,#!constbyte",0x80);
5513 if (AOP_TYPE (right) == AOP_LIT)
5515 unsigned long lit = (unsigned long)
5516 floatFromVal (AOP (right)->aopu.aop_lit);
5517 // emitcode (";", "genCmp #3.1");
5518 emitcode ("subb", "a,#!constbyte",
5519 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5523 // emitcode (";", "genCmp #3.2");
5525 MOVB(aopGet (AOP (right), offset++, FALSE, FALSE, "b"));
5526 saveAccWarn = DEFAULT_ACC_WARNING;
5527 emitcode ("xrl", "b,#!constbyte",0x80);
5528 emitcode ("subb", "a,b");
5535 // emitcode (";", "genCmp #4");
5537 s = aopGet (AOP (right), offset++, FALSE, FALSE, "b");
5538 saveAccWarn = DEFAULT_ACC_WARNING;
5540 emitcode ("subb", "a,%s", s);
5547 /* Don't need the left & right operands any more; do need the result. */
5548 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5549 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5551 aopOp (result, ic, FALSE, FALSE);
5555 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5561 /* if the result is used in the next
5562 ifx conditional branch then generate
5563 code a little differently */
5566 genIfxJump (ifx, "c");
5572 /* leave the result in acc */
5574 freeAsmop (result, NULL, ic, TRUE);
5577 /*-----------------------------------------------------------------*/
5578 /* genCmpGt :- greater than comparison */
5579 /*-----------------------------------------------------------------*/
5581 genCmpGt (iCode * ic, iCode * ifx)
5583 operand *left, *right;
5584 sym_link *letype, *retype;
5587 D (emitcode (";", "genCmpGt ");
5590 left = IC_LEFT (ic);
5591 right = IC_RIGHT (ic);
5593 letype = getSpec (operandType (left));
5594 retype = getSpec (operandType (right));
5595 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5597 /* assign the left & right amsops */
5600 genCmp (right, left, ic, ifx, sign);
5603 /*-----------------------------------------------------------------*/
5604 /* genCmpLt - less than comparisons */
5605 /*-----------------------------------------------------------------*/
5607 genCmpLt (iCode * ic, iCode * ifx)
5609 operand *left, *right;
5610 sym_link *letype, *retype;
5613 D (emitcode (";", "genCmpLt "););
5615 left = IC_LEFT (ic);
5616 right = IC_RIGHT (ic);
5618 letype = getSpec (operandType (left));
5619 retype = getSpec (operandType (right));
5620 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5622 /* assign the left & right amsops */
5625 genCmp (left, right, ic, ifx, sign);
5628 /*-----------------------------------------------------------------*/
5629 /* gencjneshort - compare and jump if not equal */
5630 /*-----------------------------------------------------------------*/
5632 gencjneshort (operand * left, operand * right, symbol * lbl)
5634 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5636 unsigned long lit = 0L;
5638 D (emitcode (";", "gencjneshort");
5641 /* if the left side is a literal or
5642 if the right is in a pointer register and left
5644 if ((AOP_TYPE (left) == AOP_LIT) ||
5645 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5652 if (AOP_TYPE (right) == AOP_LIT)
5653 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5655 if (opIsGptr (left) || opIsGptr (right))
5657 /* We are comparing a generic pointer to something.
5658 * Exclude the generic type byte from the comparison.
5661 D (emitcode (";", "cjneshort: generic ptr special case."););
5665 /* if the right side is a literal then anything goes */
5666 if (AOP_TYPE (right) == AOP_LIT &&
5667 AOP_TYPE (left) != AOP_DIR)
5671 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5672 emitcode ("cjne", "a,%s,!tlabel",
5673 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5679 /* if the right side is in a register or in direct space or
5680 if the left is a pointer register & right is not */
5681 else if (AOP_TYPE (right) == AOP_REG ||
5682 AOP_TYPE (right) == AOP_DIR ||
5683 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5684 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5688 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5689 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5690 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5691 emitcode ("jnz", "!tlabel", lbl->key + 100);
5693 emitcode ("cjne", "a,%s,!tlabel",
5694 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
5701 /* right is a pointer reg need both a & b */
5704 MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5705 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
5706 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5712 /*-----------------------------------------------------------------*/
5713 /* gencjne - compare and jump if not equal */
5714 /*-----------------------------------------------------------------*/
5716 gencjne (operand * left, operand * right, symbol * lbl)
5718 symbol *tlbl = newiTempLabel (NULL);
5720 D (emitcode (";", "gencjne");
5723 gencjneshort (left, right, lbl);
5725 emitcode ("mov", "a,%s", one);
5726 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5727 emitcode ("", "!tlabeldef", lbl->key + 100);
5728 emitcode ("clr", "a");
5729 emitcode ("", "!tlabeldef", tlbl->key + 100);
5732 /*-----------------------------------------------------------------*/
5733 /* genCmpEq - generates code for equal to */
5734 /*-----------------------------------------------------------------*/
5736 genCmpEq (iCode * ic, iCode * ifx)
5738 operand *left, *right, *result;
5740 D (emitcode (";", "genCmpEq ");
5744 AOP_SET_LOCALS (ic);
5746 /* if literal, literal on the right or
5747 if the right is in a pointer register and left
5749 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5750 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5752 operand *t = IC_RIGHT (ic);
5753 IC_RIGHT (ic) = IC_LEFT (ic);
5757 if (ifx && /* !AOP_SIZE(result) */
5758 OP_SYMBOL (result) &&
5759 OP_SYMBOL (result)->regType == REG_CND)
5762 /* if they are both bit variables */
5763 if (AOP_TYPE (left) == AOP_CRY &&
5764 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5766 if (AOP_TYPE (right) == AOP_LIT)
5768 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5771 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5772 emitcode ("cpl", "c");
5776 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5780 emitcode ("clr", "c");
5782 /* AOP_TYPE(right) == AOP_CRY */
5786 symbol *lbl = newiTempLabel (NULL);
5787 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5788 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5789 emitcode ("cpl", "c");
5790 emitcode ("", "!tlabeldef", (lbl->key + 100));
5792 /* if true label then we jump if condition
5794 tlbl = newiTempLabel (NULL);
5797 emitcode ("jnc", "!tlabel", tlbl->key + 100);
5798 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5802 emitcode ("jc", "!tlabel", tlbl->key + 100);
5803 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5805 emitcode ("", "!tlabeldef", tlbl->key + 100);
5809 tlbl = newiTempLabel (NULL);
5810 gencjneshort (left, right, tlbl);
5813 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5814 emitcode ("", "!tlabeldef", tlbl->key + 100);
5818 symbol *lbl = newiTempLabel (NULL);
5819 emitcode ("sjmp", "!tlabel", lbl->key + 100);
5820 emitcode ("", "!tlabeldef", tlbl->key + 100);
5821 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5822 emitcode ("", "!tlabeldef", lbl->key + 100);
5825 /* mark the icode as generated */
5828 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5829 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5833 /* if they are both bit variables */
5834 if (AOP_TYPE (left) == AOP_CRY &&
5835 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5837 if (AOP_TYPE (right) == AOP_LIT)
5839 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5842 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5843 emitcode ("cpl", "c");
5847 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5851 emitcode ("clr", "c");
5853 /* AOP_TYPE(right) == AOP_CRY */
5857 symbol *lbl = newiTempLabel (NULL);
5858 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5859 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5860 emitcode ("cpl", "c");
5861 emitcode ("", "!tlabeldef", (lbl->key + 100));
5864 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5865 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5867 aopOp (result, ic, TRUE, FALSE);
5870 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5877 genIfxJump (ifx, "c");
5880 /* if the result is used in an arithmetic operation
5881 then put the result in place */
5886 gencjne (left, right, newiTempLabel (NULL));
5888 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5889 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5891 aopOp (result, ic, TRUE, FALSE);
5893 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5895 aopPut (AOP (result), "a", 0);
5900 genIfxJump (ifx, "a");
5903 /* if the result is used in an arithmetic operation
5904 then put the result in place */
5905 if (AOP_TYPE (result) != AOP_CRY)
5907 /* leave the result in acc */
5911 freeAsmop (result, NULL, ic, TRUE);
5914 /*-----------------------------------------------------------------*/
5915 /* ifxForOp - returns the icode containing the ifx for operand */
5916 /*-----------------------------------------------------------------*/
5918 ifxForOp (operand * op, iCode * ic)
5920 /* if true symbol then needs to be assigned */
5921 if (IS_TRUE_SYMOP (op))
5924 /* if this has register type condition and
5925 the next instruction is ifx with the same operand
5926 and live to of the operand is upto the ifx only then */
5928 ic->next->op == IFX &&
5929 IC_COND (ic->next)->key == op->key &&
5930 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5935 /*-----------------------------------------------------------------*/
5936 /* hasInc - operand is incremented before any other use */
5937 /*-----------------------------------------------------------------*/
5939 hasInc (operand *op, iCode *ic, int osize)
5941 sym_link *type = operandType(op);
5942 sym_link *retype = getSpec (type);
5943 iCode *lic = ic->next;
5946 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5947 if (!IS_SYMOP(op)) return NULL;
5949 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5950 if (IS_AGGREGATE(type->next)) return NULL;
5951 if (osize != (isize = getSize(type->next))) return NULL;
5954 /* if operand of the form op = op + <sizeof *op> */
5955 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5956 isOperandEqual(IC_RESULT(lic),op) &&
5957 isOperandLiteral(IC_RIGHT(lic)) &&
5958 operandLitValue(IC_RIGHT(lic)) == isize) {
5961 /* if the operand used or deffed */
5962 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5965 /* if GOTO or IFX */
5966 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5972 /*-----------------------------------------------------------------*/
5973 /* genAndOp - for && operation */
5974 /*-----------------------------------------------------------------*/
5976 genAndOp (iCode * ic)
5978 operand *left, *right, *result;
5981 D (emitcode (";", "genAndOp "););
5983 /* note here that && operations that are in an
5984 if statement are taken away by backPatchLabels
5985 only those used in arthmetic operations remain */
5987 AOP_SET_LOCALS (ic);
5989 /* if both are bit variables */
5990 if (AOP_TYPE (left) == AOP_CRY &&
5991 AOP_TYPE (right) == AOP_CRY)
5993 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5994 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5995 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5996 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5998 aopOp (result,ic,FALSE, FALSE);
6003 tlbl = newiTempLabel (NULL);
6005 emitcode ("jz", "!tlabel", tlbl->key + 100);
6007 emitcode ("", "!tlabeldef", tlbl->key + 100);
6008 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6009 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6011 aopOp (result,ic,FALSE, FALSE);
6014 freeAsmop (result, NULL, ic, TRUE);
6018 /*-----------------------------------------------------------------*/
6019 /* genOrOp - for || operation */
6020 /*-----------------------------------------------------------------*/
6022 genOrOp (iCode * ic)
6024 operand *left, *right, *result;
6027 D (emitcode (";", "genOrOp "););
6029 /* note here that || operations that are in an
6030 if statement are taken away by backPatchLabels
6031 only those used in arthmetic operations remain */
6033 AOP_SET_LOCALS (ic);
6035 /* if both are bit variables */
6036 if (AOP_TYPE (left) == AOP_CRY &&
6037 AOP_TYPE (right) == AOP_CRY)
6039 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6040 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6041 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6042 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6044 aopOp (result,ic,FALSE, FALSE);
6050 tlbl = newiTempLabel (NULL);
6052 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6054 emitcode ("", "!tlabeldef", tlbl->key + 100);
6055 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6056 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6058 aopOp (result,ic,FALSE, FALSE);
6063 freeAsmop (result, NULL, ic, TRUE);
6066 /*-----------------------------------------------------------------*/
6067 /* isLiteralBit - test if lit == 2^n */
6068 /*-----------------------------------------------------------------*/
6070 isLiteralBit (unsigned long lit)
6072 unsigned long pw[32] =
6073 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6074 0x100L, 0x200L, 0x400L, 0x800L,
6075 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6076 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6077 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6078 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6079 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6082 for (idx = 0; idx < 32; idx++)
6088 /*-----------------------------------------------------------------*/
6089 /* continueIfTrue - */
6090 /*-----------------------------------------------------------------*/
6092 continueIfTrue (iCode * ic)
6095 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6099 /*-----------------------------------------------------------------*/
6101 /*-----------------------------------------------------------------*/
6103 jumpIfTrue (iCode * ic)
6106 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6110 /*-----------------------------------------------------------------*/
6111 /* jmpTrueOrFalse - */
6112 /*-----------------------------------------------------------------*/
6114 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6116 // ugly but optimized by peephole
6119 symbol *nlbl = newiTempLabel (NULL);
6120 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6121 emitcode ("", "!tlabeldef", tlbl->key + 100);
6122 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6123 emitcode ("", "!tlabeldef", nlbl->key + 100);
6127 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6128 emitcode ("", "!tlabeldef", tlbl->key + 100);
6133 // Generate code to perform a bit-wise logic operation
6134 // on two operands in far space (assumed to already have been
6135 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6136 // in far space. This requires pushing the result on the stack
6137 // then popping it into the result.
6139 genFarFarLogicOp(iCode *ic, char *logicOp)
6141 int size, resultSize, compSize;
6145 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6146 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
6147 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6149 _startLazyDPSEvaluation();
6150 for (size = compSize; (size--); offset++)
6152 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6153 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6154 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6156 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6157 emitcode ("push", "acc");
6159 _endLazyDPSEvaluation();
6161 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6162 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6163 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6165 resultSize = AOP_SIZE(IC_RESULT(ic));
6167 ADJUST_PUSHED_RESULT(compSize, resultSize);
6169 _startLazyDPSEvaluation();
6172 emitcode ("pop", "acc");
6173 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6175 _endLazyDPSEvaluation();
6176 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6180 /*-----------------------------------------------------------------*/
6181 /* genAnd - code for and */
6182 /*-----------------------------------------------------------------*/
6184 genAnd (iCode * ic, iCode * ifx)
6186 operand *left, *right, *result;
6187 int size, offset = 0;
6188 unsigned long lit = 0L;
6193 D (emitcode (";", "genAnd "););
6195 AOP_OP_3_NOFATAL (ic, pushResult);
6196 AOP_SET_LOCALS (ic);
6200 genFarFarLogicOp(ic, "anl");
6205 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6207 AOP_TYPE (left), AOP_TYPE (right));
6208 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6210 AOP_SIZE (left), AOP_SIZE (right));
6213 /* if left is a literal & right is not then exchange them */
6214 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6215 #ifdef LOGIC_OPS_BROKEN
6216 || AOP_NEEDSACC (left)
6220 operand *tmp = right;
6225 /* if result = right then exchange them */
6226 if (sameRegs (AOP (result), AOP (right)))
6228 operand *tmp = right;
6233 /* if right is bit then exchange them */
6234 if (AOP_TYPE (right) == AOP_CRY &&
6235 AOP_TYPE (left) != AOP_CRY)
6237 operand *tmp = right;
6241 if (AOP_TYPE (right) == AOP_LIT)
6242 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6244 size = AOP_SIZE (result);
6247 // result = bit & yy;
6248 if (AOP_TYPE (left) == AOP_CRY)
6250 // c = bit & literal;
6251 if (AOP_TYPE (right) == AOP_LIT)
6255 if (size && sameRegs (AOP (result), AOP (left)))
6258 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6263 if (size && (AOP_TYPE (result) == AOP_CRY))
6265 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6268 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6273 emitcode ("clr", "c");
6278 if (AOP_TYPE (right) == AOP_CRY)
6281 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6282 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6287 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6289 emitcode ("rrc", "a");
6290 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6298 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6299 genIfxJump (ifx, "c");
6303 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6304 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6305 if ((AOP_TYPE (right) == AOP_LIT) &&
6306 (AOP_TYPE (result) == AOP_CRY) &&
6307 (AOP_TYPE (left) != AOP_CRY))
6309 int posbit = isLiteralBit (lit);
6314 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6317 emitcode ("mov", "c,acc.%d", posbit & 0x07);
6323 SNPRINTF (buff, sizeof(buff),
6324 "acc.%d", posbit & 0x07);
6325 genIfxJump (ifx, buff);
6329 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6336 symbol *tlbl = newiTempLabel (NULL);
6337 int sizel = AOP_SIZE (left);
6339 emitcode ("setb", "c");
6342 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6344 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6346 if ((posbit = isLiteralBit (bytelit)) != 0)
6347 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6350 if (bytelit != 0x0FFL)
6351 emitcode ("anl", "a,%s",
6352 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6353 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6358 // bit = left & literal
6361 emitcode ("clr", "c");
6362 emitcode ("", "!tlabeldef", tlbl->key + 100);
6364 // if(left & literal)
6368 jmpTrueOrFalse (ifx, tlbl);
6376 /* if left is same as result */
6377 if (sameRegs (AOP (result), AOP (left)))
6379 for (; size--; offset++)
6381 if (AOP_TYPE (right) == AOP_LIT)
6383 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6385 else if (bytelit == 0)
6386 aopPut (AOP (result), zero, offset);
6387 else if (IS_AOP_PREG (result))
6389 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6390 emitcode ("anl", "a,%s",
6391 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6392 aopPut (AOP (result), "a", offset);
6395 emitcode ("anl", "%s,%s",
6396 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6397 aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6401 if (AOP_TYPE (left) == AOP_ACC)
6402 emitcode ("anl", "a,%s",
6403 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6406 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6407 if (IS_AOP_PREG (result))
6409 emitcode ("anl", "a,%s",
6410 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6411 aopPut (AOP (result), "a", offset);
6414 emitcode ("anl", "%s,a",
6415 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6422 // left & result in different registers
6423 if (AOP_TYPE (result) == AOP_CRY)
6426 // if(size), result in bit
6427 // if(!size && ifx), conditional oper: if(left & right)
6428 symbol *tlbl = newiTempLabel (NULL);
6429 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6431 emitcode ("setb", "c");
6434 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6435 emitcode ("anl", "a,%s",
6436 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6438 if (AOP_TYPE(left)==AOP_ACC) {
6439 emitcode("mov", "b,a");
6440 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6441 emitcode("anl", "a,b");
6443 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6444 emitcode ("anl", "a,%s",
6445 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6448 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6454 emitcode ("", "!tlabeldef", tlbl->key + 100);
6458 jmpTrueOrFalse (ifx, tlbl);
6462 for (; (size--); offset++)
6465 // result = left & right
6466 if (AOP_TYPE (right) == AOP_LIT)
6468 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6470 aopPut (AOP (result),
6471 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6475 else if (bytelit == 0)
6477 aopPut (AOP (result), zero, offset);
6480 D (emitcode (";", "better literal AND."););
6481 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6482 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6483 FALSE, FALSE, DP2_RESULT_REG));
6488 // faster than result <- left, anl result,right
6489 // and better if result is SFR
6490 if (AOP_TYPE (left) == AOP_ACC)
6492 emitcode ("anl", "a,%s",
6493 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6497 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6498 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6500 emitcode("mov", "b,a");
6504 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6505 emitcode ("anl", "a,%s", rOp);
6508 aopPut (AOP (result), "a", offset);
6514 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6515 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6516 freeAsmop (result, NULL, ic, TRUE);
6520 /*-----------------------------------------------------------------*/
6521 /* genOr - code for or */
6522 /*-----------------------------------------------------------------*/
6524 genOr (iCode * ic, iCode * ifx)
6526 operand *left, *right, *result;
6527 int size, offset = 0;
6528 unsigned long lit = 0L;
6531 D (emitcode (";", "genOr "););
6533 AOP_OP_3_NOFATAL (ic, pushResult);
6534 AOP_SET_LOCALS (ic);
6538 genFarFarLogicOp(ic, "orl");
6544 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6546 AOP_TYPE (left), AOP_TYPE (right));
6547 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6549 AOP_SIZE (left), AOP_SIZE (right));
6552 /* if left is a literal & right is not then exchange them */
6553 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6554 #ifdef LOGIC_OPS_BROKEN
6555 || AOP_NEEDSACC (left) // I think this is a net loss now.
6559 operand *tmp = right;
6564 /* if result = right then exchange them */
6565 if (sameRegs (AOP (result), AOP (right)))
6567 operand *tmp = right;
6572 /* if right is bit then exchange them */
6573 if (AOP_TYPE (right) == AOP_CRY &&
6574 AOP_TYPE (left) != AOP_CRY)
6576 operand *tmp = right;
6580 if (AOP_TYPE (right) == AOP_LIT)
6581 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6583 size = AOP_SIZE (result);
6587 if (AOP_TYPE (left) == AOP_CRY)
6589 if (AOP_TYPE (right) == AOP_LIT)
6591 // c = bit & literal;
6594 // lit != 0 => result = 1
6595 if (AOP_TYPE (result) == AOP_CRY)
6598 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6600 continueIfTrue (ifx);
6603 emitcode ("setb", "c");
6607 // lit == 0 => result = left
6608 if (size && sameRegs (AOP (result), AOP (left)))
6610 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6615 if (AOP_TYPE (right) == AOP_CRY)
6618 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6619 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6624 symbol *tlbl = newiTempLabel (NULL);
6625 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6626 emitcode ("setb", "c");
6627 emitcode ("jb", "%s,!tlabel",
6628 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6630 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6631 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6633 jmpTrueOrFalse (ifx, tlbl);
6639 emitcode ("", "!tlabeldef", tlbl->key + 100);
6648 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6649 genIfxJump (ifx, "c");
6653 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6654 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6655 if ((AOP_TYPE (right) == AOP_LIT) &&
6656 (AOP_TYPE (result) == AOP_CRY) &&
6657 (AOP_TYPE (left) != AOP_CRY))
6663 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6665 continueIfTrue (ifx);
6670 // lit = 0, result = boolean(left)
6672 emitcode ("setb", "c");
6676 symbol *tlbl = newiTempLabel (NULL);
6677 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6679 emitcode ("", "!tlabeldef", tlbl->key + 100);
6683 genIfxJump (ifx, "a");
6691 /* if left is same as result */
6692 if (sameRegs (AOP (result), AOP (left)))
6694 for (; size--; offset++)
6696 if (AOP_TYPE (right) == AOP_LIT)
6698 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6704 if (IS_AOP_PREG (left))
6706 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6707 emitcode ("orl", "a,%s",
6708 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6709 aopPut (AOP (result), "a", offset);
6713 emitcode ("orl", "%s,%s",
6714 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6715 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6721 if (AOP_TYPE (left) == AOP_ACC)
6723 emitcode ("orl", "a,%s",
6724 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6728 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6729 if (IS_AOP_PREG (left))
6731 emitcode ("orl", "a,%s",
6732 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6733 aopPut (AOP (result), "a", offset);
6737 emitcode ("orl", "%s,a",
6738 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6746 // left & result in different registers
6747 if (AOP_TYPE (result) == AOP_CRY)
6750 // if(size), result in bit
6751 // if(!size && ifx), conditional oper: if(left | right)
6752 symbol *tlbl = newiTempLabel (NULL);
6753 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6755 emitcode ("setb", "c");
6758 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6759 emitcode ("orl", "a,%s",
6760 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6762 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6763 emitcode ("orl", "a,%s",
6764 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6766 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6772 emitcode ("", "!tlabeldef", tlbl->key + 100);
6776 jmpTrueOrFalse (ifx, tlbl);
6780 _startLazyDPSEvaluation();
6781 for (; (size--); offset++)
6784 // result = left & right
6785 if (AOP_TYPE (right) == AOP_LIT)
6787 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6789 aopPut (AOP (result),
6790 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6794 D (emitcode (";", "better literal OR."););
6795 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6796 emitcode ("orl", "a, %s",
6797 aopGet (AOP (right), offset,
6798 FALSE, FALSE, DP2_RESULT_REG));
6803 // faster than result <- left, anl result,right
6804 // and better if result is SFR
6805 if (AOP_TYPE (left) == AOP_ACC)
6807 emitcode ("orl", "a,%s",
6808 aopGet (AOP (right), offset,
6809 FALSE, FALSE, DP2_RESULT_REG));
6813 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6815 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6817 emitcode("mov", "b,a");
6821 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6822 emitcode ("orl", "a,%s", rOp);
6825 aopPut (AOP (result), "a", offset);
6827 _endLazyDPSEvaluation();
6832 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6833 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6834 freeAsmop (result, NULL, ic, TRUE);
6837 /*-----------------------------------------------------------------*/
6838 /* genXor - code for xclusive or */
6839 /*-----------------------------------------------------------------*/
6841 genXor (iCode * ic, iCode * ifx)
6843 operand *left, *right, *result;
6844 int size, offset = 0;
6845 unsigned long lit = 0L;
6848 D (emitcode (";", "genXor "););
6850 AOP_OP_3_NOFATAL (ic, pushResult);
6851 AOP_SET_LOCALS (ic);
6855 genFarFarLogicOp(ic, "xrl");
6860 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6862 AOP_TYPE (left), AOP_TYPE (right));
6863 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6865 AOP_SIZE (left), AOP_SIZE (right));
6868 /* if left is a literal & right is not ||
6869 if left needs acc & right does not */
6870 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6871 #ifdef LOGIC_OPS_BROKEN
6872 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6876 operand *tmp = right;
6881 /* if result = right then exchange them */
6882 if (sameRegs (AOP (result), AOP (right)))
6884 operand *tmp = right;
6889 /* if right is bit then exchange them */
6890 if (AOP_TYPE (right) == AOP_CRY &&
6891 AOP_TYPE (left) != AOP_CRY)
6893 operand *tmp = right;
6897 if (AOP_TYPE (right) == AOP_LIT)
6898 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6900 size = AOP_SIZE (result);
6904 if (AOP_TYPE (left) == AOP_CRY)
6906 if (AOP_TYPE (right) == AOP_LIT)
6908 // c = bit & literal;
6911 // lit>>1 != 0 => result = 1
6912 if (AOP_TYPE (result) == AOP_CRY)
6915 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6917 continueIfTrue (ifx);
6920 emitcode ("setb", "c");
6927 // lit == 0, result = left
6928 if (size && sameRegs (AOP (result), AOP (left)))
6930 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6934 // lit == 1, result = not(left)
6935 if (size && sameRegs (AOP (result), AOP (left)))
6937 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6942 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6943 emitcode ("cpl", "c");
6952 symbol *tlbl = newiTempLabel (NULL);
6953 if (AOP_TYPE (right) == AOP_CRY)
6956 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6960 int sizer = AOP_SIZE (right);
6962 // if val>>1 != 0, result = 1
6963 emitcode ("setb", "c");
6966 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
6968 // test the msb of the lsb
6969 emitcode ("anl", "a,#!constbyte",0xfe);
6970 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6974 emitcode ("rrc", "a");
6976 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6977 emitcode ("cpl", "c");
6978 emitcode ("", "!tlabeldef", (tlbl->key + 100));
6985 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6986 genIfxJump (ifx, "c");
6990 if (sameRegs (AOP (result), AOP (left)))
6992 /* if left is same as result */
6993 for (; size--; offset++)
6995 if (AOP_TYPE (right) == AOP_LIT)
6997 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6999 else if (IS_AOP_PREG (left))
7001 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7002 emitcode ("xrl", "a,%s",
7003 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7004 aopPut (AOP (result), "a", offset);
7007 emitcode ("xrl", "%s,%s",
7008 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
7009 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7013 if (AOP_TYPE (left) == AOP_ACC)
7014 emitcode ("xrl", "a,%s",
7015 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7018 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7019 if (IS_AOP_PREG (left))
7021 emitcode ("xrl", "a,%s",
7022 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7023 aopPut (AOP (result), "a", offset);
7026 emitcode ("xrl", "%s,a",
7027 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7034 // left & result in different registers
7035 if (AOP_TYPE (result) == AOP_CRY)
7038 // if(size), result in bit
7039 // if(!size && ifx), conditional oper: if(left ^ right)
7040 symbol *tlbl = newiTempLabel (NULL);
7041 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7044 emitcode ("setb", "c");
7047 if ((AOP_TYPE (right) == AOP_LIT) &&
7048 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7050 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7054 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7055 emitcode ("xrl", "a,%s",
7056 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7058 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7059 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7061 emitcode("mov", "b,a");
7065 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7066 emitcode ("xrl", "a,%s", rOp);
7069 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7075 emitcode ("", "!tlabeldef", tlbl->key + 100);
7079 jmpTrueOrFalse (ifx, tlbl);
7083 for (; (size--); offset++)
7086 // result = left & right
7087 if (AOP_TYPE (right) == AOP_LIT)
7089 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7091 aopPut (AOP (result),
7092 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7096 D (emitcode (";", "better literal XOR."););
7097 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7098 emitcode ("xrl", "a, %s",
7099 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7103 // faster than result <- left, anl result,right
7104 // and better if result is SFR
7105 if (AOP_TYPE (left) == AOP_ACC)
7107 emitcode ("xrl", "a,%s",
7108 aopGet (AOP (right), offset,
7109 FALSE, FALSE, DP2_RESULT_REG));
7113 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7114 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7116 emitcode("mov", "b,a");
7120 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7121 emitcode ("xrl", "a,%s", rOp);
7124 aopPut (AOP (result), "a", offset);
7131 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7132 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7133 freeAsmop (result, NULL, ic, TRUE);
7136 /*-----------------------------------------------------------------*/
7137 /* genInline - write the inline code out */
7138 /*-----------------------------------------------------------------*/
7140 genInline (iCode * ic)
7142 char *buffer, *bp, *bp1;
7144 D (emitcode (";", "genInline "); );
7146 _G.inLine += (!options.asmpeep);
7148 buffer = Safe_strdup(IC_INLINE(ic));
7152 /* emit each line as a code */
7177 /* emitcode("",buffer); */
7178 _G.inLine -= (!options.asmpeep);
7181 /*-----------------------------------------------------------------*/
7182 /* genRRC - rotate right with carry */
7183 /*-----------------------------------------------------------------*/
7187 operand *left, *result;
7190 D (emitcode (";", "genRRC "););
7192 /* rotate right with carry */
7193 left = IC_LEFT (ic);
7194 result = IC_RESULT (ic);
7195 aopOp (left, ic, FALSE, FALSE);
7196 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7198 /* move it to the result */
7199 size = AOP_SIZE (result);
7203 _startLazyDPSEvaluation ();
7206 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7207 emitcode ("rrc", "a");
7208 if (AOP_SIZE (result) > 1)
7209 aopPut (AOP (result), "a", offset--);
7211 _endLazyDPSEvaluation ();
7213 /* now we need to put the carry into the
7214 highest order byte of the result */
7215 if (AOP_SIZE (result) > 1)
7217 MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7219 emitcode ("mov", "acc.7,c");
7220 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7221 freeAsmop (left, NULL, ic, TRUE);
7222 freeAsmop (result, NULL, ic, TRUE);
7225 /*-----------------------------------------------------------------*/
7226 /* genRLC - generate code for rotate left with carry */
7227 /*-----------------------------------------------------------------*/
7231 operand *left, *result;
7235 D (emitcode (";", "genRLC "););
7237 /* rotate right with carry */
7238 left = IC_LEFT (ic);
7239 result = IC_RESULT (ic);
7240 aopOp (left, ic, FALSE, FALSE);
7241 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7243 /* move it to the result */
7244 size = AOP_SIZE (result);
7248 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7250 emitcode ("add", "a,acc");
7251 if (AOP_SIZE (result) > 1)
7253 aopPut (AOP (result), "a", offset++);
7256 _startLazyDPSEvaluation ();
7259 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7261 emitcode ("rlc", "a");
7262 if (AOP_SIZE (result) > 1)
7263 aopPut (AOP (result), "a", offset++);
7265 _endLazyDPSEvaluation ();
7267 /* now we need to put the carry into the
7268 highest order byte of the result */
7269 if (AOP_SIZE (result) > 1)
7271 l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7274 emitcode ("mov", "acc.0,c");
7275 aopPut (AOP (result), "a", 0);
7276 freeAsmop (left, NULL, ic, TRUE);
7277 freeAsmop (result, NULL, ic, TRUE);
7280 /*-----------------------------------------------------------------*/
7281 /* genGetHbit - generates code get highest order bit */
7282 /*-----------------------------------------------------------------*/
7284 genGetHbit (iCode * ic)
7286 operand *left, *result;
7287 left = IC_LEFT (ic);
7288 result = IC_RESULT (ic);
7289 aopOp (left, ic, FALSE, FALSE);
7290 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7292 D (emitcode (";", "genGetHbit "););
7294 /* get the highest order byte into a */
7295 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7296 if (AOP_TYPE (result) == AOP_CRY)
7298 emitcode ("rlc", "a");
7303 emitcode ("rl", "a");
7304 emitcode ("anl", "a,#1");
7309 freeAsmop (left, NULL, ic, TRUE);
7310 freeAsmop (result, NULL, ic, TRUE);
7313 /*-----------------------------------------------------------------*/
7314 /* AccRol - rotate left accumulator by known count */
7315 /*-----------------------------------------------------------------*/
7317 AccRol (int shCount)
7319 shCount &= 0x0007; // shCount : 0..7
7326 emitcode ("rl", "a");
7329 emitcode ("rl", "a");
7330 emitcode ("rl", "a");
7333 emitcode ("swap", "a");
7334 emitcode ("rr", "a");
7337 emitcode ("swap", "a");
7340 emitcode ("swap", "a");
7341 emitcode ("rl", "a");
7344 emitcode ("rr", "a");
7345 emitcode ("rr", "a");
7348 emitcode ("rr", "a");
7353 /*-----------------------------------------------------------------*/
7354 /* AccLsh - left shift accumulator by known count */
7355 /*-----------------------------------------------------------------*/
7357 AccLsh (int shCount)
7362 emitcode ("add", "a,acc");
7363 else if (shCount == 2)
7365 emitcode ("add", "a,acc");
7366 emitcode ("add", "a,acc");
7370 /* rotate left accumulator */
7372 /* and kill the lower order bits */
7373 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7378 /*-----------------------------------------------------------------*/
7379 /* AccRsh - right shift accumulator by known count */
7380 /*-----------------------------------------------------------------*/
7382 AccRsh (int shCount)
7389 emitcode ("rrc", "a");
7393 /* rotate right accumulator */
7394 AccRol (8 - shCount);
7395 /* and kill the higher order bits */
7396 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7401 #ifdef BETTER_LITERAL_SHIFT
7402 /*-----------------------------------------------------------------*/
7403 /* AccSRsh - signed right shift accumulator by known count */
7404 /*-----------------------------------------------------------------*/
7406 AccSRsh (int shCount)
7413 emitcode ("mov", "c,acc.7");
7414 emitcode ("rrc", "a");
7416 else if (shCount == 2)
7418 emitcode ("mov", "c,acc.7");
7419 emitcode ("rrc", "a");
7420 emitcode ("mov", "c,acc.7");
7421 emitcode ("rrc", "a");
7425 tlbl = newiTempLabel (NULL);
7426 /* rotate right accumulator */
7427 AccRol (8 - shCount);
7428 /* and kill the higher order bits */
7429 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7430 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7431 emitcode ("orl", "a,#!constbyte",
7432 (unsigned char) ~SRMask[shCount]);
7433 emitcode ("", "!tlabeldef", tlbl->key + 100);
7439 #ifdef BETTER_LITERAL_SHIFT
7440 /*-----------------------------------------------------------------*/
7441 /* shiftR1Left2Result - shift right one byte from left to result */
7442 /*-----------------------------------------------------------------*/
7444 shiftR1Left2Result (operand * left, int offl,
7445 operand * result, int offr,
7446 int shCount, int sign)
7448 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7449 /* shift right accumulator */
7454 aopPut (AOP (result), "a", offr);
7458 #ifdef BETTER_LITERAL_SHIFT
7459 /*-----------------------------------------------------------------*/
7460 /* shiftL1Left2Result - shift left one byte from left to result */
7461 /*-----------------------------------------------------------------*/
7463 shiftL1Left2Result (operand * left, int offl,
7464 operand * result, int offr, int shCount)
7466 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7467 /* shift left accumulator */
7469 aopPut (AOP (result), "a", offr);
7473 #ifdef BETTER_LITERAL_SHIFT
7474 /*-----------------------------------------------------------------*/
7475 /* movLeft2Result - move byte from left to result */
7476 /*-----------------------------------------------------------------*/
7478 movLeft2Result (operand * left, int offl,
7479 operand * result, int offr, int sign)
7482 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7484 l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
7486 if (*l == '@' && (IS_AOP_PREG (result)))
7488 emitcode ("mov", "a,%s", l);
7489 aopPut (AOP (result), "a", offr);
7495 aopPut (AOP (result), l, offr);
7499 /* MSB sign in acc.7 ! */
7500 if (getDataSize (left) == offl + 1)
7502 emitcode ("mov", "a,%s", l);
7503 aopPut (AOP (result), "a", offr);
7511 #ifdef BETTER_LITERAL_SHIFT
7512 /*-----------------------------------------------------------------*/
7513 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7514 /*-----------------------------------------------------------------*/
7518 emitcode ("rrc", "a");
7519 emitcode ("xch", "a,%s", x);
7520 emitcode ("rrc", "a");
7521 emitcode ("xch", "a,%s", x);
7525 #ifdef BETTER_LITERAL_SHIFT
7527 /*-----------------------------------------------------------------*/
7528 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7529 /*-----------------------------------------------------------------*/
7533 emitcode ("xch", "a,%s", x);
7534 emitcode ("rlc", "a");
7535 emitcode ("xch", "a,%s", x);
7536 emitcode ("rlc", "a");
7540 #ifdef BETTER_LITERAL_SHIFT
7541 /*-----------------------------------------------------------------*/
7542 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7543 /*-----------------------------------------------------------------*/
7547 emitcode ("xch", "a,%s", x);
7548 emitcode ("add", "a,acc");
7549 emitcode ("xch", "a,%s", x);
7550 emitcode ("rlc", "a");
7554 #ifdef BETTER_LITERAL_SHIFT
7555 /*-----------------------------------------------------------------*/
7556 /* AccAXLsh - left shift a:x by known count (0..7) */
7557 /*-----------------------------------------------------------------*/
7559 AccAXLsh (char *x, int shCount)
7574 case 5: // AAAAABBB:CCCCCDDD
7576 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7578 emitcode ("anl", "a,#!constbyte",
7579 SLMask[shCount]); // BBB00000:CCCCCDDD
7581 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7583 AccRol (shCount); // DDDCCCCC:BBB00000
7585 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7587 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7589 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7591 emitcode ("anl", "a,#!constbyte",
7592 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7594 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7596 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7599 case 6: // AAAAAABB:CCCCCCDD
7600 emitcode ("anl", "a,#!constbyte",
7601 SRMask[shCount]); // 000000BB:CCCCCCDD
7602 emitcode ("mov", "c,acc.0"); // c = B
7603 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7605 AccAXRrl1 (x); // BCCCCCCD:D000000B
7606 AccAXRrl1 (x); // BBCCCCCC:DD000000
7608 emitcode("rrc","a");
7609 emitcode("xch","a,%s", x);
7610 emitcode("rrc","a");
7611 emitcode("mov","c,acc.0"); //<< get correct bit
7612 emitcode("xch","a,%s", x);
7614 emitcode("rrc","a");
7615 emitcode("xch","a,%s", x);
7616 emitcode("rrc","a");
7617 emitcode("xch","a,%s", x);
7620 case 7: // a:x <<= 7
7622 emitcode ("anl", "a,#!constbyte",
7623 SRMask[shCount]); // 0000000B:CCCCCCCD
7625 emitcode ("mov", "c,acc.0"); // c = B
7627 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7629 AccAXRrl1 (x); // BCCCCCCC:D0000000
7638 #ifdef BETTER_LITERAL_SHIFT
7640 /*-----------------------------------------------------------------*/
7641 /* AccAXRsh - right shift a:x known count (0..7) */
7642 /*-----------------------------------------------------------------*/
7644 AccAXRsh (char *x, int shCount)
7652 AccAXRrl1 (x); // 0->a:x
7657 AccAXRrl1 (x); // 0->a:x
7660 AccAXRrl1 (x); // 0->a:x
7665 case 5: // AAAAABBB:CCCCCDDD = a:x
7667 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7669 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7671 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7673 emitcode ("anl", "a,#!constbyte",
7674 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7676 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7678 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7680 emitcode ("anl", "a,#!constbyte",
7681 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7683 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7685 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7687 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7690 case 6: // AABBBBBB:CCDDDDDD
7692 emitcode ("mov", "c,acc.7");
7693 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7695 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7697 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7699 emitcode ("anl", "a,#!constbyte",
7700 SRMask[shCount]); // 000000AA:BBBBBBCC
7703 case 7: // ABBBBBBB:CDDDDDDD
7705 emitcode ("mov", "c,acc.7"); // c = A
7707 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7709 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7711 emitcode ("anl", "a,#!constbyte",
7712 SRMask[shCount]); // 0000000A:BBBBBBBC
7721 #ifdef BETTER_LITERAL_SHIFT
7722 /*-----------------------------------------------------------------*/
7723 /* AccAXRshS - right shift signed a:x known count (0..7) */
7724 /*-----------------------------------------------------------------*/
7726 AccAXRshS (char *x, int shCount)
7734 emitcode ("mov", "c,acc.7");
7735 AccAXRrl1 (x); // s->a:x
7739 emitcode ("mov", "c,acc.7");
7740 AccAXRrl1 (x); // s->a:x
7742 emitcode ("mov", "c,acc.7");
7743 AccAXRrl1 (x); // s->a:x
7748 case 5: // AAAAABBB:CCCCCDDD = a:x
7750 tlbl = newiTempLabel (NULL);
7751 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7753 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7755 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7757 emitcode ("anl", "a,#!constbyte",
7758 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7760 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7762 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7764 emitcode ("anl", "a,#!constbyte",
7765 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7767 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7769 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7771 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7773 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7774 emitcode ("orl", "a,#!constbyte",
7775 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7777 emitcode ("", "!tlabeldef", tlbl->key + 100);
7778 break; // SSSSAAAA:BBBCCCCC
7780 case 6: // AABBBBBB:CCDDDDDD
7782 tlbl = newiTempLabel (NULL);
7783 emitcode ("mov", "c,acc.7");
7784 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7786 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7788 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7790 emitcode ("anl", "a,#!constbyte",
7791 SRMask[shCount]); // 000000AA:BBBBBBCC
7793 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7794 emitcode ("orl", "a,#!constbyte",
7795 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7797 emitcode ("", "!tlabeldef", tlbl->key + 100);
7799 case 7: // ABBBBBBB:CDDDDDDD
7801 tlbl = newiTempLabel (NULL);
7802 emitcode ("mov", "c,acc.7"); // c = A
7804 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7806 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7808 emitcode ("anl", "a,#!constbyte",
7809 SRMask[shCount]); // 0000000A:BBBBBBBC
7811 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7812 emitcode ("orl", "a,#!constbyte",
7813 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7815 emitcode ("", "!tlabeldef", tlbl->key + 100);
7823 #ifdef BETTER_LITERAL_SHIFT
7825 _loadLeftIntoAx(char **lsb,
7831 // Get the initial value from left into a pair of registers.
7832 // MSB must be in A, LSB can be any register.
7834 // If the result is held in registers, it is an optimization
7835 // if the LSB can be held in the register which will hold the,
7836 // result LSB since this saves us from having to copy it into
7837 // the result following AccAXLsh.
7839 // If the result is addressed indirectly, this is not a gain.
7840 if (AOP_NEEDSACC(result))
7844 _startLazyDPSEvaluation();
7845 if (AOP_TYPE(left) == AOP_DPTR2)
7848 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
7849 // get LSB in DP2_RESULT_REG.
7850 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
7851 assert(!strcmp(leftByte, DP2_RESULT_REG));
7855 // get LSB into DP2_RESULT_REG
7856 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
7857 if (strcmp(leftByte, DP2_RESULT_REG))
7860 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7863 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
7864 assert(strcmp(leftByte, DP2_RESULT_REG));
7867 _endLazyDPSEvaluation();
7868 *lsb = DP2_RESULT_REG;
7872 if (sameRegs (AOP (result), AOP (left)) &&
7873 ((offl + MSB16) == offr))
7875 /* don't crash result[offr] */
7876 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
7877 emitcode ("xch", "a,%s",
7878 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
7882 movLeft2Result (left, offl, result, offr, 0);
7883 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
7885 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
7886 assert(strcmp(*lsb,"a"));
7891 _storeAxResults(char *lsb,
7895 _startLazyDPSEvaluation();
7896 if (AOP_NEEDSACC(result))
7898 /* We have to explicitly update the result LSB.
7900 emitcode("xch","a,%s", lsb);
7901 aopPut(AOP(result), "a", offr);
7902 emitcode("mov","a,%s", lsb);
7904 if (getDataSize (result) > 1)
7906 aopPut (AOP (result), "a", offr + MSB16);
7908 _endLazyDPSEvaluation();
7911 /*-----------------------------------------------------------------*/
7912 /* shiftL2Left2Result - shift left two bytes from left to result */
7913 /*-----------------------------------------------------------------*/
7915 shiftL2Left2Result (operand * left, int offl,
7916 operand * result, int offr, int shCount)
7920 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7922 AccAXLsh (lsb, shCount);
7924 _storeAxResults(lsb, result, offr);
7928 #ifdef BETTER_LITERAL_SHIFT
7929 /*-----------------------------------------------------------------*/
7930 /* shiftR2Left2Result - shift right two bytes from left to result */
7931 /*-----------------------------------------------------------------*/
7933 shiftR2Left2Result (operand * left, int offl,
7934 operand * result, int offr,
7935 int shCount, int sign)
7939 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7941 /* a:x >> shCount (x = lsb(result)) */
7944 AccAXRshS(lsb, shCount);
7948 AccAXRsh(lsb, shCount);
7951 _storeAxResults(lsb, result, offr);
7955 /*-----------------------------------------------------------------*/
7956 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7957 /*-----------------------------------------------------------------*/
7959 shiftLLeftOrResult (operand * left, int offl,
7960 operand * result, int offr, int shCount)
7962 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7963 /* shift left accumulator */
7965 /* or with result */
7966 emitcode ("orl", "a,%s",
7967 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7968 /* back to result */
7969 aopPut (AOP (result), "a", offr);
7974 /*-----------------------------------------------------------------*/
7975 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7976 /*-----------------------------------------------------------------*/
7978 shiftRLeftOrResult (operand * left, int offl,
7979 operand * result, int offr, int shCount)
7981 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7982 /* shift right accumulator */
7984 /* or with result */
7985 emitcode ("orl", "a,%s",
7986 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7987 /* back to result */
7988 aopPut (AOP (result), "a", offr);
7992 #ifdef BETTER_LITERAL_SHIFT
7993 /*-----------------------------------------------------------------*/
7994 /* genlshOne - left shift a one byte quantity by known count */
7995 /*-----------------------------------------------------------------*/
7997 genlshOne (operand * result, operand * left, int shCount)
7999 D (emitcode (";", "genlshOne "););
8000 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8004 #ifdef BETTER_LITERAL_SHIFT
8005 /*-----------------------------------------------------------------*/
8006 /* genlshTwo - left shift two bytes by known amount != 0 */
8007 /*-----------------------------------------------------------------*/
8009 genlshTwo (operand * result, operand * left, int shCount)
8013 D (emitcode (";", "genlshTwo "););
8015 size = getDataSize (result);
8017 /* if shCount >= 8 */
8022 _startLazyDPSEvaluation();
8028 _endLazyDPSEvaluation();
8029 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8030 aopPut (AOP (result), zero, LSB);
8034 movLeft2Result (left, LSB, result, MSB16, 0);
8035 aopPut (AOP (result), zero, LSB);
8036 _endLazyDPSEvaluation();
8041 aopPut (AOP (result), zero, LSB);
8042 _endLazyDPSEvaluation();
8046 /* 1 <= shCount <= 7 */
8051 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8055 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8063 /*-----------------------------------------------------------------*/
8064 /* shiftLLong - shift left one long from left to result */
8065 /* offl = LSB or MSB16 */
8066 /*-----------------------------------------------------------------*/
8068 shiftLLong (operand * left, operand * result, int offr)
8071 int size = AOP_SIZE (result);
8073 if (size >= LSB + offr)
8075 l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8077 emitcode ("add", "a,acc");
8078 if (sameRegs (AOP (left), AOP (result)) &&
8079 size >= MSB16 + offr && offr != LSB)
8080 emitcode ("xch", "a,%s",
8081 aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8083 aopPut (AOP (result), "a", LSB + offr);
8086 if (size >= MSB16 + offr)
8088 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8090 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8092 emitcode ("rlc", "a");
8093 if (sameRegs (AOP (left), AOP (result)) &&
8094 size >= MSB24 + offr && offr != LSB)
8095 emitcode ("xch", "a,%s",
8096 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8098 aopPut (AOP (result), "a", MSB16 + offr);
8101 if (size >= MSB24 + offr)
8103 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8105 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8107 emitcode ("rlc", "a");
8108 if (sameRegs (AOP (left), AOP (result)) &&
8109 size >= MSB32 + offr && offr != LSB)
8110 emitcode ("xch", "a,%s",
8111 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8113 aopPut (AOP (result), "a", MSB24 + offr);
8116 if (size > MSB32 + offr)
8118 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8120 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8122 emitcode ("rlc", "a");
8123 aopPut (AOP (result), "a", MSB32 + offr);
8126 aopPut (AOP (result), zero, LSB);
8132 /*-----------------------------------------------------------------*/
8133 /* genlshFour - shift four byte by a known amount != 0 */
8134 /*-----------------------------------------------------------------*/
8136 genlshFour (operand * result, operand * left, int shCount)
8140 D (emitcode (";", "genlshFour ");
8143 size = AOP_SIZE (result);
8145 /* if shifting more that 3 bytes */
8150 /* lowest order of left goes to the highest
8151 order of the destination */
8152 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8154 movLeft2Result (left, LSB, result, MSB32, 0);
8155 aopPut (AOP (result), zero, LSB);
8156 aopPut (AOP (result), zero, MSB16);
8157 aopPut (AOP (result), zero, MSB24);
8161 /* more than two bytes */
8162 else if (shCount >= 16)
8164 /* lower order two bytes goes to higher order two bytes */
8166 /* if some more remaining */
8168 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8171 movLeft2Result (left, MSB16, result, MSB32, 0);
8172 movLeft2Result (left, LSB, result, MSB24, 0);
8174 aopPut (AOP (result), zero, MSB16);
8175 aopPut (AOP (result), zero, LSB);
8179 /* if more than 1 byte */
8180 else if (shCount >= 8)
8182 /* lower order three bytes goes to higher order three bytes */
8187 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8189 movLeft2Result (left, LSB, result, MSB16, 0);
8195 movLeft2Result (left, MSB24, result, MSB32, 0);
8196 movLeft2Result (left, MSB16, result, MSB24, 0);
8197 movLeft2Result (left, LSB, result, MSB16, 0);
8198 aopPut (AOP (result), zero, LSB);
8200 else if (shCount == 1)
8201 shiftLLong (left, result, MSB16);
8204 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8205 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8206 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8207 aopPut (AOP (result), zero, LSB);
8212 /* 1 <= shCount <= 7 */
8213 else if (shCount <= 2)
8215 shiftLLong (left, result, LSB);
8217 shiftLLong (result, result, LSB);
8219 /* 3 <= shCount <= 7, optimize */
8222 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8223 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8224 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8229 #ifdef BETTER_LITERAL_SHIFT
8230 /*-----------------------------------------------------------------*/
8231 /* genLeftShiftLiteral - left shifting by known count */
8232 /*-----------------------------------------------------------------*/
8234 genLeftShiftLiteral (operand * left,
8239 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8242 size = getSize (operandType (result));
8244 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8246 /* We only handle certain easy cases so far. */
8248 && (shCount < (size * 8))
8252 D(emitcode (";", "genLeftShiftLiteral wimping out"););
8256 freeAsmop (right, NULL, ic, TRUE);
8258 aopOp(left, ic, FALSE, FALSE);
8259 aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8262 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8264 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8265 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8267 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8270 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8272 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8273 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8275 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8281 emitcode ("; shift left ", "result %d, left %d", size,
8285 /* I suppose that the left size >= result size */
8288 _startLazyDPSEvaluation();
8291 movLeft2Result (left, size, result, size, 0);
8293 _endLazyDPSEvaluation();
8295 else if (shCount >= (size * 8))
8297 _startLazyDPSEvaluation();
8300 aopPut (AOP (result), zero, size);
8302 _endLazyDPSEvaluation();
8309 genlshOne (result, left, shCount);
8313 genlshTwo (result, left, shCount);
8317 genlshFour (result, left, shCount);
8321 fprintf(stderr, "*** ack! mystery literal shift!\n");
8325 freeAsmop (left, NULL, ic, TRUE);
8326 freeAsmop (result, NULL, ic, TRUE);
8331 /*-----------------------------------------------------------------*/
8332 /* genLeftShift - generates code for left shifting */
8333 /*-----------------------------------------------------------------*/
8335 genLeftShift (iCode * ic)
8337 operand *left, *right, *result;
8340 symbol *tlbl, *tlbl1;
8342 D (emitcode (";", "genLeftShift "););
8344 right = IC_RIGHT (ic);
8345 left = IC_LEFT (ic);
8346 result = IC_RESULT (ic);
8348 aopOp (right, ic, FALSE, FALSE);
8351 #ifdef BETTER_LITERAL_SHIFT
8352 /* if the shift count is known then do it
8353 as efficiently as possible */
8354 if (AOP_TYPE (right) == AOP_LIT)
8356 if (genLeftShiftLiteral (left, right, result, ic))
8363 /* shift count is unknown then we have to form
8364 a loop get the loop count in B : Note: we take
8365 only the lower order byte since shifting
8366 more that 32 bits make no sense anyway, ( the
8367 largest size of an object can be only 32 bits ) */
8369 if (AOP_TYPE (right) == AOP_LIT)
8371 /* Really should be handled by genLeftShiftLiteral,
8372 * but since I'm too lazy to fix that today, at least we can make
8373 * some small improvement.
8375 emitcode("mov", "b,#!constbyte",
8376 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8380 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8381 emitcode ("inc", "b");
8383 freeAsmop (right, NULL, ic, TRUE);
8384 aopOp (left, ic, FALSE, FALSE);
8385 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8387 /* now move the left to the result if they are not the
8389 if (!sameRegs (AOP (left), AOP (result)) &&
8390 AOP_SIZE (result) > 1)
8393 size = AOP_SIZE (result);
8395 _startLazyDPSEvaluation ();
8398 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8399 if (*l == '@' && (IS_AOP_PREG (result)))
8402 emitcode ("mov", "a,%s", l);
8403 aopPut (AOP (result), "a", offset);
8406 aopPut (AOP (result), l, offset);
8409 _endLazyDPSEvaluation ();
8412 tlbl = newiTempLabel (NULL);
8413 size = AOP_SIZE (result);
8415 tlbl1 = newiTempLabel (NULL);
8417 /* if it is only one byte then */
8420 symbol *tlbl1 = newiTempLabel (NULL);
8422 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8423 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8424 emitcode ("", "!tlabeldef", tlbl->key + 100);
8425 emitcode ("add", "a,acc");
8426 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8427 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8428 aopPut (AOP (result), "a", 0);
8432 reAdjustPreg (AOP (result));
8434 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8435 emitcode ("", "!tlabeldef", tlbl->key + 100);
8436 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8437 emitcode ("add", "a,acc");
8438 aopPut (AOP (result), "a", offset++);
8439 _startLazyDPSEvaluation ();
8442 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8443 emitcode ("rlc", "a");
8444 aopPut (AOP (result), "a", offset++);
8446 _endLazyDPSEvaluation ();
8447 reAdjustPreg (AOP (result));
8449 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8450 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8452 freeAsmop (left, NULL, ic, TRUE);
8453 freeAsmop (result, NULL, ic, TRUE);
8456 #ifdef BETTER_LITERAL_SHIFT
8457 /*-----------------------------------------------------------------*/
8458 /* genrshOne - right shift a one byte quantity by known count */
8459 /*-----------------------------------------------------------------*/
8461 genrshOne (operand * result, operand * left,
8462 int shCount, int sign)
8464 D (emitcode (";", "genrshOne"););
8465 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8469 #ifdef BETTER_LITERAL_SHIFT
8470 /*-----------------------------------------------------------------*/
8471 /* genrshTwo - right shift two bytes by known amount != 0 */
8472 /*-----------------------------------------------------------------*/
8474 genrshTwo (operand * result, operand * left,
8475 int shCount, int sign)
8477 D (emitcode (";", "genrshTwo"););
8479 /* if shCount >= 8 */
8483 _startLazyDPSEvaluation();
8486 shiftR1Left2Result (left, MSB16, result, LSB,
8491 movLeft2Result (left, MSB16, result, LSB, sign);
8493 addSign (result, MSB16, sign);
8494 _endLazyDPSEvaluation();
8497 /* 1 <= shCount <= 7 */
8500 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8505 /*-----------------------------------------------------------------*/
8506 /* shiftRLong - shift right one long from left to result */
8507 /* offl = LSB or MSB16 */
8508 /*-----------------------------------------------------------------*/
8510 shiftRLong (operand * left, int offl,
8511 operand * result, int sign)
8513 int isSameRegs=sameRegs(AOP(left),AOP(result));
8515 if (isSameRegs && offl>1) {
8516 // we are in big trouble, but this shouldn't happen
8517 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8520 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8525 emitcode ("rlc", "a");
8526 emitcode ("subb", "a,acc");
8527 emitcode ("xch", "a,%s",
8528 aopGet(AOP(left), MSB32, FALSE, FALSE, DP2_RESULT_REG));
8530 aopPut (AOP(result), zero, MSB32);
8535 emitcode ("clr", "c");
8537 emitcode ("mov", "c,acc.7");
8540 emitcode ("rrc", "a");
8542 if (isSameRegs && offl==MSB16) {
8544 "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE, DP2_RESULT_REG));
8546 aopPut (AOP (result), "a", MSB32);
8547 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8550 emitcode ("rrc", "a");
8551 if (isSameRegs && offl==1) {
8552 emitcode ("xch", "a,%s",
8553 aopGet (AOP (left), MSB16, FALSE, FALSE, DP2_RESULT_REG));
8555 aopPut (AOP (result), "a", MSB24);
8556 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, NULL));
8558 emitcode ("rrc", "a");
8559 aopPut (AOP (result), "a", MSB16 - offl);
8563 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, NULL));
8564 emitcode ("rrc", "a");
8565 aopPut (AOP (result), "a", LSB);
8569 /*-----------------------------------------------------------------*/
8570 /* genrshFour - shift four byte by a known amount != 0 */
8571 /*-----------------------------------------------------------------*/
8573 genrshFour (operand * result, operand * left,
8574 int shCount, int sign)
8576 D (emitcode (";", "genrshFour"););
8578 /* if shifting more that 3 bytes */
8582 _startLazyDPSEvaluation();
8584 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8586 movLeft2Result (left, MSB32, result, LSB, sign);
8587 addSign (result, MSB16, sign);
8588 _endLazyDPSEvaluation();
8590 else if (shCount >= 16)
8593 _startLazyDPSEvaluation();
8595 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8598 movLeft2Result (left, MSB24, result, LSB, 0);
8599 movLeft2Result (left, MSB32, result, MSB16, sign);
8601 addSign (result, MSB24, sign);
8602 _endLazyDPSEvaluation();
8604 else if (shCount >= 8)
8607 _startLazyDPSEvaluation();
8610 shiftRLong (left, MSB16, result, sign);
8612 else if (shCount == 0)
8614 movLeft2Result (left, MSB16, result, LSB, 0);
8615 movLeft2Result (left, MSB24, result, MSB16, 0);
8616 movLeft2Result (left, MSB32, result, MSB24, sign);
8617 addSign (result, MSB32, sign);
8621 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8622 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8623 /* the last shift is signed */
8624 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8625 addSign (result, MSB32, sign);
8627 _endLazyDPSEvaluation();
8631 /* 1 <= shCount <= 7 */
8634 shiftRLong (left, LSB, result, sign);
8636 shiftRLong (result, LSB, result, sign);
8640 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8641 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8642 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8647 #ifdef BETTER_LITERAL_SHIFT
8648 /*-----------------------------------------------------------------*/
8649 /* genRightShiftLiteral - right shifting by known count */
8650 /*-----------------------------------------------------------------*/
8652 genRightShiftLiteral (operand * left,
8658 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8661 size = getSize (operandType (result));
8663 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8665 /* We only handle certain easy cases so far. */
8667 && (shCount < (size * 8))
8672 D(emitcode (";", "genRightShiftLiteral wimping out"););
8676 freeAsmop (right, NULL, ic, TRUE);
8678 aopOp (left, ic, FALSE, FALSE);
8679 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8682 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8686 /* test the LEFT size !!! */
8688 /* I suppose that the left size >= result size */
8691 size = getDataSize (result);
8692 _startLazyDPSEvaluation();
8695 movLeft2Result (left, size, result, size, 0);
8697 _endLazyDPSEvaluation();
8699 else if (shCount >= (size * 8))
8703 /* get sign in acc.7 */
8704 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
8706 addSign (result, LSB, sign);
8713 genrshOne (result, left, shCount, sign);
8717 genrshTwo (result, left, shCount, sign);
8721 genrshFour (result, left, shCount, sign);
8728 freeAsmop (left, NULL, ic, TRUE);
8729 freeAsmop (result, NULL, ic, TRUE);
8735 /*-----------------------------------------------------------------*/
8736 /* genSignedRightShift - right shift of signed number */
8737 /*-----------------------------------------------------------------*/
8739 genSignedRightShift (iCode * ic)
8741 operand *right, *left, *result;
8744 symbol *tlbl, *tlbl1;
8746 D (emitcode (";", "genSignedRightShift "););
8748 /* we do it the hard way put the shift count in b
8749 and loop thru preserving the sign */
8751 right = IC_RIGHT (ic);
8752 left = IC_LEFT (ic);
8753 result = IC_RESULT (ic);
8755 aopOp (right, ic, FALSE, FALSE);
8757 #ifdef BETTER_LITERAL_SHIFT
8758 if (AOP_TYPE (right) == AOP_LIT)
8760 if (genRightShiftLiteral (left, right, result, ic, 1))
8766 /* shift count is unknown then we have to form
8767 a loop get the loop count in B : Note: we take
8768 only the lower order byte since shifting
8769 more that 32 bits make no sense anyway, ( the
8770 largest size of an object can be only 32 bits ) */
8772 if (AOP_TYPE (right) == AOP_LIT)
8774 /* Really should be handled by genRightShiftLiteral,
8775 * but since I'm too lazy to fix that today, at least we can make
8776 * some small improvement.
8778 emitcode("mov", "b,#!constbyte",
8779 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8783 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8784 emitcode ("inc", "b");
8786 freeAsmop (right, NULL, ic, TRUE);
8787 aopOp (left, ic, FALSE, FALSE);
8788 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8790 /* now move the left to the result if they are not the
8792 if (!sameRegs (AOP (left), AOP (result)) &&
8793 AOP_SIZE (result) > 1)
8796 size = AOP_SIZE (result);
8798 _startLazyDPSEvaluation ();
8801 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8802 if (*l == '@' && IS_AOP_PREG (result))
8805 emitcode ("mov", "a,%s", l);
8806 aopPut (AOP (result), "a", offset);
8809 aopPut (AOP (result), l, offset);
8812 _endLazyDPSEvaluation ();
8815 /* mov the highest order bit to OVR */
8816 tlbl = newiTempLabel (NULL);
8817 tlbl1 = newiTempLabel (NULL);
8819 size = AOP_SIZE (result);
8821 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
8822 emitcode ("rlc", "a");
8823 emitcode ("mov", "ov,c");
8824 /* if it is only one byte then */
8827 MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8828 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8829 emitcode ("", "!tlabeldef", tlbl->key + 100);
8830 emitcode ("mov", "c,ov");
8831 emitcode ("rrc", "a");
8832 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8833 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8834 aopPut (AOP (result), "a", 0);
8838 reAdjustPreg (AOP (result));
8839 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8840 emitcode ("", "!tlabeldef", tlbl->key + 100);
8841 emitcode ("mov", "c,ov");
8842 _startLazyDPSEvaluation ();
8845 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8846 emitcode ("rrc", "a");
8847 aopPut (AOP (result), "a", offset--);
8849 _endLazyDPSEvaluation ();
8850 reAdjustPreg (AOP (result));
8851 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8852 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8855 freeAsmop (left, NULL, ic, TRUE);
8856 freeAsmop (result, NULL, ic, TRUE);
8859 /*-----------------------------------------------------------------*/
8860 /* genRightShift - generate code for right shifting */
8861 /*-----------------------------------------------------------------*/
8863 genRightShift (iCode * ic)
8865 operand *right, *left, *result;
8869 symbol *tlbl, *tlbl1;
8871 D (emitcode (";", "genRightShift "););
8873 /* if signed then we do it the hard way preserve the
8874 sign bit moving it inwards */
8875 retype = getSpec (operandType (IC_RESULT (ic)));
8877 if (!SPEC_USIGN (retype))
8879 genSignedRightShift (ic);
8883 /* signed & unsigned types are treated the same : i.e. the
8884 signed is NOT propagated inwards : quoting from the
8885 ANSI - standard : "for E1 >> E2, is equivalent to division
8886 by 2**E2 if unsigned or if it has a non-negative value,
8887 otherwise the result is implementation defined ", MY definition
8888 is that the sign does not get propagated */
8890 right = IC_RIGHT (ic);
8891 left = IC_LEFT (ic);
8892 result = IC_RESULT (ic);
8894 aopOp (right, ic, FALSE, FALSE);
8896 #ifdef BETTER_LITERAL_SHIFT
8897 /* if the shift count is known then do it
8898 as efficiently as possible */
8899 if (AOP_TYPE (right) == AOP_LIT)
8901 if (genRightShiftLiteral (left, right, result, ic, 0))
8908 /* shift count is unknown then we have to form
8909 a loop get the loop count in B : Note: we take
8910 only the lower order byte since shifting
8911 more that 32 bits make no sense anyway, ( the
8912 largest size of an object can be only 32 bits ) */
8914 if (AOP_TYPE (right) == AOP_LIT)
8916 /* Really should be handled by genRightShiftLiteral,
8917 * but since I'm too lazy to fix that today, at least we can make
8918 * some small improvement.
8920 emitcode("mov", "b,#!constbyte",
8921 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8925 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8926 emitcode ("inc", "b");
8928 freeAsmop (right, NULL, ic, TRUE);
8929 aopOp (left, ic, FALSE, FALSE);
8930 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8932 /* now move the left to the result if they are not the
8934 if (!sameRegs (AOP (left), AOP (result)) &&
8935 AOP_SIZE (result) > 1)
8938 size = AOP_SIZE (result);
8940 _startLazyDPSEvaluation ();
8943 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8944 if (*l == '@' && IS_AOP_PREG (result))
8947 emitcode ("mov", "a,%s", l);
8948 aopPut (AOP (result), "a", offset);
8951 aopPut (AOP (result), l, offset);
8954 _endLazyDPSEvaluation ();
8957 tlbl = newiTempLabel (NULL);
8958 tlbl1 = newiTempLabel (NULL);
8959 size = AOP_SIZE (result);
8962 /* if it is only one byte then */
8965 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8966 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8967 emitcode ("", "!tlabeldef", tlbl->key + 100);
8969 emitcode ("rrc", "a");
8970 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8971 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8972 aopPut (AOP (result), "a", 0);
8976 reAdjustPreg (AOP (result));
8977 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8978 emitcode ("", "!tlabeldef", tlbl->key + 100);
8980 _startLazyDPSEvaluation ();
8983 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8984 emitcode ("rrc", "a");
8985 aopPut (AOP (result), "a", offset--);
8987 _endLazyDPSEvaluation ();
8988 reAdjustPreg (AOP (result));
8990 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8991 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8994 freeAsmop (left, NULL, ic, TRUE);
8995 freeAsmop (result, NULL, ic, TRUE);
8999 /*-----------------------------------------------------------------*/
9000 /* emitPtrByteGet - emits code to get a byte into A through a */
9001 /* pointer register (R0, R1, or DPTR). The */
9002 /* original value of A can be preserved in B. */
9003 /*-----------------------------------------------------------------*/
9005 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9012 emitcode ("mov", "b,a");
9013 emitcode ("mov", "a,@%s", rname);
9018 emitcode ("mov", "b,a");
9019 emitcode ("movx", "a,@%s", rname);
9024 emitcode ("mov", "b,a");
9025 emitcode ("movx", "a,@dptr");
9030 emitcode ("mov", "b,a");
9031 emitcode ("clr", "a");
9032 emitcode ("movc", "a,@a+dptr");
9038 emitcode ("push", "b");
9039 emitcode ("push", "acc");
9041 emitcode ("lcall", "__gptrget");
9043 emitcode ("pop", "b");
9048 /*-----------------------------------------------------------------*/
9049 /* emitPtrByteSet - emits code to set a byte from src through a */
9050 /* pointer register (R0, R1, or DPTR). */
9051 /*-----------------------------------------------------------------*/
9053 emitPtrByteSet (char *rname, int p_type, char *src)
9062 emitcode ("mov", "@%s,a", rname);
9065 emitcode ("mov", "@%s,%s", rname, src);
9070 emitcode ("movx", "@%s,a", rname);
9075 emitcode ("movx", "@dptr,a");
9080 emitcode ("lcall", "__gptrput");
9085 /*-----------------------------------------------------------------*/
9086 /* genUnpackBits - generates code for unpacking bits */
9087 /*-----------------------------------------------------------------*/
9089 genUnpackBits (operand * result, char *rname, int ptype)
9091 int offset = 0; /* result byte offset */
9092 int rsize; /* result size */
9093 int rlen = 0; /* remaining bitfield length */
9094 sym_link *etype; /* bitfield type information */
9095 int blen; /* bitfield length */
9096 int bstr; /* bitfield starting bit within byte */
9098 D(emitcode ("; genUnpackBits",""));
9100 etype = getSpec (operandType (result));
9101 rsize = getSize (operandType (result));
9102 blen = SPEC_BLEN (etype);
9103 bstr = SPEC_BSTR (etype);
9105 /* If the bitfield length is less than a byte */
9108 emitPtrByteGet (rname, ptype, FALSE);
9110 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
9111 aopPut (AOP (result), "a", offset++);
9115 /* Bit field did not fit in a byte. Copy all
9116 but the partial byte at the end. */
9117 for (rlen=blen;rlen>=8;rlen-=8)
9119 emitPtrByteGet (rname, ptype, FALSE);
9120 aopPut (AOP (result), "a", offset++);
9122 emitcode ("inc", "%s", rname);
9125 /* Handle the partial byte at the end */
9128 emitPtrByteGet (rname, ptype, FALSE);
9129 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
9130 aopPut (AOP (result), "a", offset++);
9138 aopPut (AOP (result), zero, offset++);
9143 /*-----------------------------------------------------------------*/
9144 /* genDataPointerGet - generates code when ptr offset is known */
9145 /*-----------------------------------------------------------------*/
9147 genDataPointerGet (operand * left,
9153 int size, offset = 0;
9154 aopOp (result, ic, TRUE, FALSE);
9156 /* get the string representation of the name */
9157 l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9158 size = AOP_SIZE (result);
9159 _startLazyDPSEvaluation ();
9164 SNPRINTF (buff, sizeof(buff),
9165 "(%s + %d)", l + 1, offset);
9169 SNPRINTF (buff, sizeof(buff),
9172 aopPut (AOP (result), buff, offset++);
9174 _endLazyDPSEvaluation ();
9176 freeAsmop (left, NULL, ic, TRUE);
9177 freeAsmop (result, NULL, ic, TRUE);
9180 /*-----------------------------------------------------------------*/
9181 /* genNearPointerGet - emitcode for near pointer fetch */
9182 /*-----------------------------------------------------------------*/
9184 genNearPointerGet (operand * left,
9192 sym_link *rtype, *retype, *letype;
9193 sym_link *ltype = operandType (left);
9196 rtype = operandType (result);
9197 retype = getSpec (rtype);
9198 letype = getSpec (ltype);
9200 aopOp (left, ic, FALSE, FALSE);
9202 /* if left is rematerialisable and
9203 result is not bit variable type and
9204 the left is pointer to data space i.e
9205 lower 128 bytes of space */
9206 if (AOP_TYPE (left) == AOP_IMMD &&
9207 !IS_BITVAR (retype) &&
9208 !IS_BITVAR (letype) &&
9209 DCL_TYPE (ltype) == POINTER)
9211 genDataPointerGet (left, result, ic);
9215 /* if the value is already in a pointer register
9216 then don't need anything more */
9217 if (!AOP_INPREG (AOP (left)))
9219 /* otherwise get a free pointer register */
9221 preg = getFreePtr (ic, &aop, FALSE);
9222 emitcode ("mov", "%s,%s",
9224 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9228 rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9230 freeAsmop (left, NULL, ic, TRUE);
9231 aopOp (result, ic, FALSE, FALSE);
9233 /* if bitfield then unpack the bits */
9234 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9235 genUnpackBits (result, rname, POINTER);
9238 /* we have can just get the values */
9239 int size = AOP_SIZE (result);
9244 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9247 emitcode ("mov", "a,@%s", rname);
9248 aopPut (AOP (result), "a", offset);
9252 SNPRINTF (buff, sizeof(buff), "@%s", rname);
9253 aopPut (AOP (result), buff, offset);
9258 emitcode ("inc", "%s", rname);
9263 /* now some housekeeping stuff */
9266 /* we had to allocate for this iCode */
9267 if (pi) { /* post increment present */
9268 aopPut(AOP ( left ),rname,0);
9270 freeAsmop (NULL, aop, ic, TRUE);
9274 /* we did not allocate which means left
9275 already in a pointer register, then
9276 if size > 0 && this could be used again
9277 we have to point it back to where it
9279 if (AOP_SIZE (result) > 1 &&
9280 !OP_SYMBOL (left)->remat &&
9281 (OP_SYMBOL (left)->liveTo > ic->seq ||
9285 int size = AOP_SIZE (result) - 1;
9287 emitcode ("dec", "%s", rname);
9292 freeAsmop (result, NULL, ic, TRUE);
9293 if (pi) pi->generated = 1;
9296 /*-----------------------------------------------------------------*/
9297 /* genPagedPointerGet - emitcode for paged pointer fetch */
9298 /*-----------------------------------------------------------------*/
9300 genPagedPointerGet (operand * left,
9308 sym_link *rtype, *retype, *letype;
9310 rtype = operandType (result);
9311 retype = getSpec (rtype);
9312 letype = getSpec (operandType (left));
9313 aopOp (left, ic, FALSE, FALSE);
9315 /* if the value is already in a pointer register
9316 then don't need anything more */
9317 if (!AOP_INPREG (AOP (left)))
9319 /* otherwise get a free pointer register */
9321 preg = getFreePtr (ic, &aop, FALSE);
9322 emitcode ("mov", "%s,%s",
9324 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9328 rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9330 freeAsmop (left, NULL, ic, TRUE);
9331 aopOp (result, ic, FALSE, FALSE);
9333 /* if bitfield then unpack the bits */
9334 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9335 genUnpackBits (result, rname, PPOINTER);
9338 /* we have can just get the values */
9339 int size = AOP_SIZE (result);
9345 emitcode ("movx", "a,@%s", rname);
9346 aopPut (AOP (result), "a", offset);
9351 emitcode ("inc", "%s", rname);
9355 /* now some housekeeping stuff */
9358 /* we had to allocate for this iCode */
9359 if (pi) aopPut ( AOP (left), rname, 0);
9360 freeAsmop (NULL, aop, ic, TRUE);
9364 /* we did not allocate which means left
9365 already in a pointer register, then
9366 if size > 0 && this could be used again
9367 we have to point it back to where it
9369 if (AOP_SIZE (result) > 1 &&
9370 !OP_SYMBOL (left)->remat &&
9371 (OP_SYMBOL (left)->liveTo > ic->seq ||
9375 int size = AOP_SIZE (result) - 1;
9377 emitcode ("dec", "%s", rname);
9382 freeAsmop (result, NULL, ic, TRUE);
9383 if (pi) pi->generated = 1;
9386 /*-----------------------------------------------------------------*/
9387 /* genFarPointerGet - gget value from far space */
9388 /*-----------------------------------------------------------------*/
9390 genFarPointerGet (operand * left,
9391 operand * result, iCode * ic, iCode *pi)
9393 int size, offset, dopi=1;
9394 sym_link *retype = getSpec (operandType (result));
9395 sym_link *letype = getSpec (operandType (left));
9396 D (emitcode (";", "genFarPointerGet"););
9398 aopOp (left, ic, FALSE, FALSE);
9400 /* if the operand is already in dptr
9401 then we do nothing else we move the value to dptr */
9402 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9404 /* if this is remateriazable */
9405 if (AOP_TYPE (left) == AOP_IMMD)
9407 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9411 /* we need to get it byte by byte */
9412 _startLazyDPSEvaluation ();
9413 if (AOP_TYPE (left) != AOP_DPTR)
9415 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9416 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9417 if (options.model == MODEL_FLAT24)
9418 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9422 /* We need to generate a load to DPTR indirect through DPTR. */
9423 D (emitcode (";", "genFarPointerGet -- indirection special case."););
9424 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9425 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9426 if (options.model == MODEL_FLAT24)
9427 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9428 emitcode ("pop", "dph");
9429 emitcode ("pop", "dpl");
9432 _endLazyDPSEvaluation ();
9435 /* so dptr know contains the address */
9436 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9438 /* if bit then unpack */
9439 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9440 if (AOP_INDPTRn(left)) {
9441 genSetDPTR(AOP(left)->aopu.dptr);
9443 genUnpackBits (result, "dptr", FPOINTER);
9444 if (AOP_INDPTRn(left)) {
9449 size = AOP_SIZE (result);
9452 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9454 genSetDPTR(AOP(left)->aopu.dptr);
9455 emitcode ("movx", "a,@dptr");
9456 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9457 emitcode ("inc", "dptr");
9459 aopPut (AOP (result), "a", offset++);
9462 _startLazyDPSEvaluation ();
9464 if (AOP_INDPTRn(left)) {
9465 genSetDPTR(AOP(left)->aopu.dptr);
9471 emitcode ("movx", "a,@dptr");
9472 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9473 emitcode ("inc", "dptr");
9475 aopPut (AOP (result), "a", offset++);
9477 _endLazyDPSEvaluation ();
9480 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9481 if (!AOP_INDPTRn(left)) {
9482 _startLazyDPSEvaluation ();
9483 aopPut ( AOP (left), "dpl", 0);
9484 aopPut ( AOP (left), "dph", 1);
9485 if (options.model == MODEL_FLAT24)
9486 aopPut ( AOP (left), "dpx", 2);
9487 _endLazyDPSEvaluation ();
9490 } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) &&
9491 AOP_SIZE(result) > 1 &&
9493 (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
9495 size = AOP_SIZE (result) - 1;
9496 if (AOP_INDPTRn(left)) {
9497 genSetDPTR(AOP(left)->aopu.dptr);
9499 while (size--) emitcode ("lcall","__decdptr");
9500 if (AOP_INDPTRn(left)) {
9505 freeAsmop (left, NULL, ic, TRUE);
9506 freeAsmop (result, NULL, ic, TRUE);
9509 /*-----------------------------------------------------------------*/
9510 /* genCodePointerGet - get value from code space */
9511 /*-----------------------------------------------------------------*/
9513 genCodePointerGet (operand * left,
9514 operand * result, iCode * ic, iCode *pi)
9516 int size, offset, dopi=1;
9517 sym_link *retype = getSpec (operandType (result));
9519 aopOp (left, ic, FALSE, FALSE);
9521 /* if the operand is already in dptr
9522 then we do nothing else we move the value to dptr */
9523 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
9525 /* if this is remateriazable */
9526 if (AOP_TYPE (left) == AOP_IMMD)
9528 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9531 { /* we need to get it byte by byte */
9532 _startLazyDPSEvaluation ();
9533 if (AOP_TYPE (left) != AOP_DPTR)
9535 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9536 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9537 if (options.model == MODEL_FLAT24)
9538 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9542 /* We need to generate a load to DPTR indirect through DPTR. */
9543 D (emitcode (";", "gencodePointerGet -- indirection special case."););
9544 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9545 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9546 if (options.model == MODEL_FLAT24)
9547 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9548 emitcode ("pop", "dph");
9549 emitcode ("pop", "dpl");
9552 _endLazyDPSEvaluation ();
9555 /* so dptr know contains the address */
9556 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9558 /* if bit then unpack */
9559 if (IS_BITVAR (retype)) {
9560 if (AOP_INDPTRn(left)) {
9561 genSetDPTR(AOP(left)->aopu.dptr);
9563 genUnpackBits (result, "dptr", CPOINTER);
9564 if (AOP_INDPTRn(left)) {
9569 size = AOP_SIZE (result);
9571 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9573 genSetDPTR(AOP(left)->aopu.dptr);
9574 emitcode ("clr", "a");
9575 emitcode ("movc", "a,@a+dptr");
9576 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9577 emitcode ("inc", "dptr");
9579 aopPut (AOP (result), "a", offset++);
9582 _startLazyDPSEvaluation ();
9585 if (AOP_INDPTRn(left)) {
9586 genSetDPTR(AOP(left)->aopu.dptr);
9592 emitcode ("clr", "a");
9593 emitcode ("movc", "a,@a+dptr");
9594 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9595 emitcode ("inc", "dptr");
9596 aopPut (AOP (result), "a", offset++);
9598 _endLazyDPSEvaluation ();
9601 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9602 if (!AOP_INDPTRn(left)) {
9603 _startLazyDPSEvaluation ();
9605 aopPut ( AOP (left), "dpl", 0);
9606 aopPut ( AOP (left), "dph", 1);
9607 if (options.model == MODEL_FLAT24)
9608 aopPut ( AOP (left), "dpx", 2);
9610 _endLazyDPSEvaluation ();
9613 } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
9614 AOP_SIZE(result) > 1 &&
9615 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9617 size = AOP_SIZE (result) - 1;
9618 if (AOP_INDPTRn(left)) {
9619 genSetDPTR(AOP(left)->aopu.dptr);
9621 while (size--) emitcode ("lcall","__decdptr");
9622 if (AOP_INDPTRn(left)) {
9627 freeAsmop (left, NULL, ic, TRUE);
9628 freeAsmop (result, NULL, ic, TRUE);
9631 /*-----------------------------------------------------------------*/
9632 /* genGenPointerGet - gget value from generic pointer space */
9633 /*-----------------------------------------------------------------*/
9635 genGenPointerGet (operand * left,
9636 operand * result, iCode * ic, iCode * pi)
9639 sym_link *retype = getSpec (operandType (result));
9640 sym_link *letype = getSpec (operandType (left));
9642 D (emitcode (";", "genGenPointerGet "); );
9644 aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
9646 /* if the operand is already in dptr
9647 then we do nothing else we move the value to dptr */
9648 if (AOP_TYPE (left) != AOP_STR)
9650 /* if this is remateriazable */
9651 if (AOP_TYPE (left) == AOP_IMMD)
9653 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9654 if (AOP(left)->aopu.aop_immd.from_cast_remat)
9656 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
9660 emitcode ("mov", "b,#%d", pointerCode (retype));
9664 { /* we need to get it byte by byte */
9665 _startLazyDPSEvaluation ();
9666 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
9667 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
9668 if (options.model == MODEL_FLAT24) {
9669 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9670 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
9672 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9674 _endLazyDPSEvaluation ();
9678 /* so dptr-b now contains the address */
9680 aopOp (result, ic, FALSE, TRUE);
9683 /* if bit then unpack */
9684 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9686 genUnpackBits (result, "dptr", GPOINTER);
9690 size = AOP_SIZE (result);
9697 // Get two bytes at a time, results in _AP & A.
9698 // dptr will be incremented ONCE by __gptrgetWord.
9700 // Note: any change here must be coordinated
9701 // with the implementation of __gptrgetWord
9702 // in device/lib/_gptrget.c
9703 emitcode ("lcall", "__gptrgetWord");
9704 aopPut (AOP (result), DP2_RESULT_REG, offset++);
9705 aopPut (AOP (result), "a", offset++);
9710 // Only one byte to get.
9711 emitcode ("lcall", "__gptrget");
9712 aopPut (AOP (result), "a", offset++);
9715 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9717 emitcode ("inc", "dptr");
9722 if (pi && AOP_TYPE (left) != AOP_IMMD) {
9723 _startLazyDPSEvaluation ();
9725 aopPut ( AOP (left), "dpl", 0);
9726 aopPut ( AOP (left), "dph", 1);
9727 if (options.model == MODEL_FLAT24) {
9728 aopPut ( AOP (left), "dpx", 2);
9729 aopPut ( AOP (left), "b", 3);
9730 } else aopPut ( AOP (left), "b", 2);
9732 _endLazyDPSEvaluation ();
9735 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9736 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9738 size = AOP_SIZE (result) - 1;
9739 while (size--) emitcode ("lcall","__decdptr");
9742 freeAsmop (left, NULL, ic, TRUE);
9743 freeAsmop (result, NULL, ic, TRUE);
9746 /*-----------------------------------------------------------------*/
9747 /* genPointerGet - generate code for pointer get */
9748 /*-----------------------------------------------------------------*/
9750 genPointerGet (iCode * ic, iCode *pi)
9752 operand *left, *result;
9753 sym_link *type, *etype;
9756 D (emitcode (";", "genPointerGet ");
9759 left = IC_LEFT (ic);
9760 result = IC_RESULT (ic);
9762 /* depending on the type of pointer we need to
9763 move it to the correct pointer register */
9764 type = operandType (left);
9765 etype = getSpec (type);
9766 /* if left is of type of pointer then it is simple */
9767 if (IS_PTR (type) && !IS_FUNC (type->next))
9768 p_type = DCL_TYPE (type);
9771 /* we have to go by the storage class */
9772 p_type = PTR_TYPE (SPEC_OCLS (etype));
9774 /* special case when cast remat */
9775 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9776 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9777 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9778 type = operandType (left);
9779 p_type = DCL_TYPE (type);
9781 /* now that we have the pointer type we assign
9782 the pointer values */
9788 genNearPointerGet (left, result, ic, pi);
9792 genPagedPointerGet (left, result, ic, pi);
9796 genFarPointerGet (left, result, ic, pi);
9800 genCodePointerGet (left, result, ic, pi);
9804 genGenPointerGet (left, result, ic, pi);
9810 /*-----------------------------------------------------------------*/
9811 /* genPackBits - generates code for packed bit storage */
9812 /*-----------------------------------------------------------------*/
9814 genPackBits (sym_link * etype,
9816 char *rname, int p_type)
9818 int offset = 0; /* source byte offset */
9819 int rlen = 0; /* remaining bitfield length */
9820 int blen; /* bitfield length */
9821 int bstr; /* bitfield starting bit within byte */
9822 int litval; /* source literal value (if AOP_LIT) */
9823 unsigned char mask; /* bitmask within current byte */
9825 D(emitcode ("; genPackBits",""));
9827 blen = SPEC_BLEN (etype);
9828 bstr = SPEC_BSTR (etype);
9830 /* If the bitfield length is less than a byte */
9833 mask = ((unsigned char) (0xFF << (blen + bstr)) |
9834 (unsigned char) (0xFF >> (8 - bstr)));
9836 if (AOP_TYPE (right) == AOP_LIT)
9838 /* Case with a bitfield length <8 and literal source
9840 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9842 litval &= (~mask) & 0xff;
9843 emitPtrByteGet (rname, p_type, FALSE);
9844 if ((mask|litval)!=0xff)
9845 emitcode ("anl","a,#!constbyte", mask);
9847 emitcode ("orl","a,#!constbyte", litval);
9851 if ((blen==1) && (p_type!=GPOINTER))
9853 /* Case with a bitfield length == 1 and no generic pointer
9855 if (AOP_TYPE (right) == AOP_CRY)
9856 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9859 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
9860 emitcode ("rrc","a");
9862 emitPtrByteGet (rname, p_type, FALSE);
9863 emitcode ("mov","acc.%d,c",bstr);
9867 /* Case with a bitfield length < 8 and arbitrary source
9869 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
9870 /* shift and mask source value */
9872 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
9874 /* transfer A to B and get next byte */
9875 emitPtrByteGet (rname, p_type, TRUE);
9877 emitcode ("anl", "a,#!constbyte", mask);
9878 emitcode ("orl", "a,b");
9879 if (p_type == GPOINTER)
9880 emitcode ("pop", "b");
9884 emitPtrByteSet (rname, p_type, "a");
9888 /* Bit length is greater than 7 bits. In this case, copy */
9889 /* all except the partial byte at the end */
9890 for (rlen=blen;rlen>=8;rlen-=8)
9892 emitPtrByteSet (rname, p_type,
9893 aopGet (AOP (right), offset++, FALSE, TRUE, NULL) );
9895 emitcode ("inc", "%s", rname);
9898 /* If there was a partial byte at the end */
9901 mask = (((unsigned char) -1 << rlen) & 0xff);
9903 if (AOP_TYPE (right) == AOP_LIT)
9905 /* Case with partial byte and literal source
9907 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9908 litval >>= (blen-rlen);
9909 litval &= (~mask) & 0xff;
9910 emitPtrByteGet (rname, p_type, FALSE);
9911 if ((mask|litval)!=0xff)
9912 emitcode ("anl","a,#!constbyte", mask);
9914 emitcode ("orl","a,#!constbyte", litval);
9918 /* Case with partial byte and arbitrary source
9920 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9921 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
9923 /* transfer A to B and get next byte */
9924 emitPtrByteGet (rname, p_type, TRUE);
9926 emitcode ("anl", "a,#!constbyte", mask);
9927 emitcode ("orl", "a,b");
9928 if (p_type == GPOINTER)
9929 emitcode ("pop", "b");
9931 emitPtrByteSet (rname, p_type, "a");
9937 /*-----------------------------------------------------------------*/
9938 /* genDataPointerSet - remat pointer to data space */
9939 /*-----------------------------------------------------------------*/
9941 genDataPointerSet (operand * right,
9945 int size, offset = 0;
9948 aopOp (right, ic, FALSE, FALSE);
9950 l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
9951 size = AOP_SIZE (right);
9956 SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
9960 SNPRINTF (buff, sizeof(buff), "%s", l + 1);
9963 emitcode ("mov", "%s,%s", buff,
9964 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9967 freeAsmop (right, NULL, ic, TRUE);
9968 freeAsmop (result, NULL, ic, TRUE);
9971 /*-----------------------------------------------------------------*/
9972 /* genNearPointerSet - emitcode for near pointer put */
9973 /*-----------------------------------------------------------------*/
9975 genNearPointerSet (operand * right,
9982 sym_link *retype, *letype;
9983 sym_link *ptype = operandType (result);
9985 retype = getSpec (operandType (right));
9986 letype = getSpec (ptype);
9988 aopOp (result, ic, FALSE, FALSE);
9990 /* if the result is rematerializable &
9991 in data space & not a bit variable */
9992 if (AOP_TYPE (result) == AOP_IMMD &&
9993 DCL_TYPE (ptype) == POINTER &&
9994 !IS_BITVAR (retype) &&
9995 !IS_BITVAR (letype))
9997 genDataPointerSet (right, result, ic);
10001 /* if the value is already in a pointer register
10002 then don't need anything more */
10003 if (!AOP_INPREG (AOP (result)))
10005 /* otherwise get a free pointer register */
10008 aop = newAsmop (0);
10009 preg = getFreePtr (ic, &aop, FALSE);
10010 emitcode ("mov", "%s,%s",
10012 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10013 rname = preg->name;
10016 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10018 aopOp (right, ic, FALSE, FALSE);
10020 /* if bitfield then unpack the bits */
10021 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10022 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
10025 /* we have can just get the values */
10026 int size = AOP_SIZE (right);
10031 l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
10035 emitcode ("mov", "@%s,a", rname);
10038 emitcode ("mov", "@%s,%s", rname, l);
10040 emitcode ("inc", "%s", rname);
10045 /* now some housekeeping stuff */
10048 /* we had to allocate for this iCode */
10049 if (pi) aopPut (AOP (result),rname,0);
10050 freeAsmop (NULL, aop, ic, TRUE);
10054 /* we did not allocate which means left
10055 already in a pointer register, then
10056 if size > 0 && this could be used again
10057 we have to point it back to where it
10059 if (AOP_SIZE (right) > 1 &&
10060 !OP_SYMBOL (result)->remat &&
10061 (OP_SYMBOL (result)->liveTo > ic->seq ||
10065 int size = AOP_SIZE (right) - 1;
10067 emitcode ("dec", "%s", rname);
10072 if (pi) pi->generated = 1;
10073 freeAsmop (result, NULL, ic, TRUE);
10074 freeAsmop (right, NULL, ic, TRUE);
10079 /*-----------------------------------------------------------------*/
10080 /* genPagedPointerSet - emitcode for Paged pointer put */
10081 /*-----------------------------------------------------------------*/
10083 genPagedPointerSet (operand * right,
10090 sym_link *retype, *letype;
10092 retype = getSpec (operandType (right));
10093 letype = getSpec (operandType (result));
10095 aopOp (result, ic, FALSE, FALSE);
10097 /* if the value is already in a pointer register
10098 then don't need anything more */
10099 if (!AOP_INPREG (AOP (result)))
10101 /* otherwise get a free pointer register */
10104 aop = newAsmop (0);
10105 preg = getFreePtr (ic, &aop, FALSE);
10106 emitcode ("mov", "%s,%s",
10108 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10109 rname = preg->name;
10112 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10114 aopOp (right, ic, FALSE, FALSE);
10116 /* if bitfield then unpack the bits */
10117 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10118 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
10121 /* we have can just get the values */
10122 int size = AOP_SIZE (right);
10127 MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10129 emitcode ("movx", "@%s,a", rname);
10132 emitcode ("inc", "%s", rname);
10138 /* now some housekeeping stuff */
10141 if (pi) aopPut (AOP (result),rname,0);
10142 /* we had to allocate for this iCode */
10143 freeAsmop (NULL, aop, ic, TRUE);
10147 /* we did not allocate which means left
10148 already in a pointer register, then
10149 if size > 0 && this could be used again
10150 we have to point it back to where it
10152 if (AOP_SIZE (right) > 1 &&
10153 !OP_SYMBOL (result)->remat &&
10154 (OP_SYMBOL (result)->liveTo > ic->seq ||
10158 int size = AOP_SIZE (right) - 1;
10160 emitcode ("dec", "%s", rname);
10165 if (pi) pi->generated = 1;
10166 freeAsmop (result, NULL, ic, TRUE);
10167 freeAsmop (right, NULL, ic, TRUE);
10172 /*-----------------------------------------------------------------*/
10173 /* genFarPointerSet - set value from far space */
10174 /*-----------------------------------------------------------------*/
10176 genFarPointerSet (operand * right,
10177 operand * result, iCode * ic, iCode *pi)
10179 int size, offset, dopi=1;
10180 sym_link *retype = getSpec (operandType (right));
10181 sym_link *letype = getSpec (operandType (result));
10183 aopOp (result, ic, FALSE, FALSE);
10185 /* if the operand is already in dptr
10186 then we do nothing else we move the value to dptr */
10187 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10189 /* if this is remateriazable */
10190 if (AOP_TYPE (result) == AOP_IMMD)
10191 emitcode ("mov", "dptr,%s",
10192 aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10195 /* we need to get it byte by byte */
10196 _startLazyDPSEvaluation ();
10197 if (AOP_TYPE (result) != AOP_DPTR)
10199 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10200 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10201 if (options.model == MODEL_FLAT24)
10202 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10206 /* We need to generate a load to DPTR indirect through DPTR. */
10207 D (emitcode (";", "genFarPointerSet -- indirection special case."););
10209 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10210 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10211 if (options.model == MODEL_FLAT24)
10212 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10213 emitcode ("pop", "dph");
10214 emitcode ("pop", "dpl");
10217 _endLazyDPSEvaluation ();
10220 /* so dptr know contains the address */
10221 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10223 /* if bit then unpack */
10224 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
10225 if (AOP_INDPTRn(result)) {
10226 genSetDPTR(AOP(result)->aopu.dptr);
10228 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
10229 if (AOP_INDPTRn(result)) {
10233 size = AOP_SIZE (right);
10235 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10237 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10239 genSetDPTR(AOP(result)->aopu.dptr);
10240 emitcode ("movx", "@dptr,a");
10241 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10242 emitcode ("inc", "dptr");
10246 _startLazyDPSEvaluation ();
10248 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10250 if (AOP_INDPTRn(result)) {
10251 genSetDPTR(AOP(result)->aopu.dptr);
10257 emitcode ("movx", "@dptr,a");
10258 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10259 emitcode ("inc", "dptr");
10261 _endLazyDPSEvaluation ();
10265 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10266 if (!AOP_INDPTRn(result)) {
10267 _startLazyDPSEvaluation ();
10269 aopPut (AOP(result),"dpl",0);
10270 aopPut (AOP(result),"dph",1);
10271 if (options.model == MODEL_FLAT24)
10272 aopPut (AOP(result),"dpx",2);
10274 _endLazyDPSEvaluation ();
10277 } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
10278 AOP_SIZE(right) > 1 &&
10279 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10281 size = AOP_SIZE (right) - 1;
10282 if (AOP_INDPTRn(result)) {
10283 genSetDPTR(AOP(result)->aopu.dptr);
10285 while (size--) emitcode ("lcall","__decdptr");
10286 if (AOP_INDPTRn(result)) {
10290 freeAsmop (result, NULL, ic, TRUE);
10291 freeAsmop (right, NULL, ic, TRUE);
10294 /*-----------------------------------------------------------------*/
10295 /* genGenPointerSet - set value from generic pointer space */
10296 /*-----------------------------------------------------------------*/
10298 genGenPointerSet (operand * right,
10299 operand * result, iCode * ic, iCode *pi)
10302 sym_link *retype = getSpec (operandType (right));
10303 sym_link *letype = getSpec (operandType (result));
10305 aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10307 /* if the operand is already in dptr
10308 then we do nothing else we move the value to dptr */
10309 if (AOP_TYPE (result) != AOP_STR)
10311 _startLazyDPSEvaluation ();
10312 /* if this is remateriazable */
10313 if (AOP_TYPE (result) == AOP_IMMD)
10315 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10316 if (AOP(result)->aopu.aop_immd.from_cast_remat)
10318 MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10323 "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10327 { /* we need to get it byte by byte */
10328 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10329 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10330 if (options.model == MODEL_FLAT24) {
10331 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10332 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10334 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10337 _endLazyDPSEvaluation ();
10339 /* so dptr + b now contains the address */
10341 aopOp (right, ic, FALSE, TRUE);
10345 /* if bit then unpack */
10346 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10348 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
10352 size = AOP_SIZE (right);
10355 _startLazyDPSEvaluation ();
10360 // Set two bytes at a time, passed in _AP & A.
10361 // dptr will be incremented ONCE by __gptrputWord.
10363 // Note: any change here must be coordinated
10364 // with the implementation of __gptrputWord
10365 // in device/lib/_gptrput.c
10366 emitcode("mov", "_ap, %s",
10367 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10368 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10372 emitcode ("lcall", "__gptrputWord");
10377 // Only one byte to put.
10378 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10382 emitcode ("lcall", "__gptrput");
10385 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10387 emitcode ("inc", "dptr");
10390 _endLazyDPSEvaluation ();
10393 if (pi && AOP_TYPE (result) != AOP_IMMD) {
10394 _startLazyDPSEvaluation ();
10396 aopPut (AOP(result),"dpl",0);
10397 aopPut (AOP(result),"dph",1);
10398 if (options.model == MODEL_FLAT24) {
10399 aopPut (AOP(result),"dpx",2);
10400 aopPut (AOP(result),"b",3);
10402 aopPut (AOP(result),"b",2);
10404 _endLazyDPSEvaluation ();
10407 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10408 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10410 size = AOP_SIZE (right) - 1;
10411 while (size--) emitcode ("lcall","__decdptr");
10413 freeAsmop (result, NULL, ic, TRUE);
10414 freeAsmop (right, NULL, ic, TRUE);
10417 /*-----------------------------------------------------------------*/
10418 /* genPointerSet - stores the value into a pointer location */
10419 /*-----------------------------------------------------------------*/
10421 genPointerSet (iCode * ic, iCode *pi)
10423 operand *right, *result;
10424 sym_link *type, *etype;
10427 D (emitcode (";", "genPointerSet "););
10429 right = IC_RIGHT (ic);
10430 result = IC_RESULT (ic);
10432 /* depending on the type of pointer we need to
10433 move it to the correct pointer register */
10434 type = operandType (result);
10435 etype = getSpec (type);
10436 /* if left is of type of pointer then it is simple */
10437 if (IS_PTR (type) && !IS_FUNC (type->next))
10439 p_type = DCL_TYPE (type);
10443 /* we have to go by the storage class */
10444 p_type = PTR_TYPE (SPEC_OCLS (etype));
10446 /* special case when cast remat */
10447 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10448 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10449 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10450 type = operandType (result);
10451 p_type = DCL_TYPE (type);
10454 /* now that we have the pointer type we assign
10455 the pointer values */
10461 genNearPointerSet (right, result, ic, pi);
10465 genPagedPointerSet (right, result, ic, pi);
10469 genFarPointerSet (right, result, ic, pi);
10473 genGenPointerSet (right, result, ic, pi);
10477 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10478 "genPointerSet: illegal pointer type");
10483 /*-----------------------------------------------------------------*/
10484 /* genIfx - generate code for Ifx statement */
10485 /*-----------------------------------------------------------------*/
10487 genIfx (iCode * ic, iCode * popIc)
10489 operand *cond = IC_COND (ic);
10492 D (emitcode (";", "genIfx "););
10494 aopOp (cond, ic, FALSE, FALSE);
10496 /* get the value into acc */
10497 if (AOP_TYPE (cond) != AOP_CRY)
10506 /* the result is now in the accumulator */
10507 freeAsmop (cond, NULL, ic, TRUE);
10509 /* if there was something to be popped then do it */
10513 /* if the condition is a bit variable */
10514 if (isbit && IS_ITEMP (cond) &&
10517 genIfxJump (ic, SPIL_LOC (cond)->rname);
10519 else if (isbit && !IS_ITEMP (cond))
10521 genIfxJump (ic, OP_SYMBOL (cond)->rname);
10525 genIfxJump (ic, "a");
10531 /*-----------------------------------------------------------------*/
10532 /* genAddrOf - generates code for address of */
10533 /*-----------------------------------------------------------------*/
10535 genAddrOf (iCode * ic)
10537 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10540 D (emitcode (";", "genAddrOf ");
10543 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10545 /* if the operand is on the stack then we
10546 need to get the stack offset of this
10548 if (sym->onStack) {
10550 /* if 10 bit stack */
10551 if (options.stack10bit) {
10555 tsprintf(buff, sizeof(buff),
10556 "#!constbyte",(options.stack_loc >> 16) & 0xff);
10557 /* if it has an offset then we need to compute it */
10558 /* emitcode ("subb", "a,#!constbyte", */
10559 /* -((sym->stack < 0) ? */
10560 /* ((short) (sym->stack - _G.nRegsSaved)) : */
10561 /* ((short) sym->stack)) & 0xff); */
10562 /* emitcode ("mov","b,a"); */
10563 /* emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
10564 /* ((short) (sym->stack - _G.nRegsSaved)) : */
10565 /* ((short) sym->stack)) >> 8) & 0xff); */
10567 emitcode ("mov", "a,_bpx");
10568 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
10569 ((char) (sym->stack - _G.nRegsSaved)) :
10570 ((char) sym->stack )) & 0xff);
10571 emitcode ("mov", "b,a");
10572 emitcode ("mov", "a,_bpx+1");
10574 offset = (((sym->stack < 0) ?
10575 ((short) (sym->stack - _G.nRegsSaved)) :
10576 ((short) sym->stack )) >> 8) & 0xff;
10578 emitcode ("addc","a,#!constbyte", offset);
10580 aopPut (AOP (IC_RESULT (ic)), "b", 0);
10581 aopPut (AOP (IC_RESULT (ic)), "a", 1);
10582 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10584 /* we can just move _bp */
10585 aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10586 aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10587 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10590 /* if it has an offset then we need to compute it */
10592 emitcode ("mov", "a,_bp");
10593 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10594 aopPut (AOP (IC_RESULT (ic)), "a", 0);
10596 /* we can just move _bp */
10597 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10599 /* fill the result with zero */
10600 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10603 if (options.stack10bit && size < (FPTRSIZE - 1)) {
10605 "*** warning: pointer to stack var truncated.\n");
10610 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10616 /* object not on stack then we need the name */
10617 size = AOP_SIZE (IC_RESULT (ic));
10622 char s[SDCC_NAME_MAX];
10626 tsprintf(s, sizeof(s), "#!his",sym->rname);
10629 tsprintf(s, sizeof(s), "#!hihis",sym->rname);
10632 tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
10634 default: /* should not need this (just in case) */
10635 SNPRINTF (s, sizeof(s), "#(%s >> %d)",
10642 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10645 aopPut (AOP (IC_RESULT (ic)), s, offset++);
10649 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10653 #if 0 // obsolete, and buggy for != xdata
10654 /*-----------------------------------------------------------------*/
10655 /* genArrayInit - generates code for address of */
10656 /*-----------------------------------------------------------------*/
10658 genArrayInit (iCode * ic)
10660 literalList *iLoop;
10662 int elementSize = 0, eIndex;
10663 unsigned val, lastVal;
10665 operand *left=IC_LEFT(ic);
10667 D (emitcode (";", "genArrayInit "););
10669 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10671 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10673 // Load immediate value into DPTR.
10674 emitcode("mov", "dptr, %s",
10675 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
10677 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10680 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10681 "Unexpected operand to genArrayInit.\n");
10684 // a regression because of SDCCcse.c:1.52
10685 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10686 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10687 if (options.model == MODEL_FLAT24)
10688 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10692 type = operandType(IC_LEFT(ic));
10694 if (type && type->next)
10696 elementSize = getSize(type->next);
10700 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10701 "can't determine element size in genArrayInit.\n");
10705 iLoop = IC_ARRAYILIST(ic);
10710 bool firstpass = TRUE;
10712 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
10713 iLoop->count, (int)iLoop->literalValue, elementSize);
10719 symbol *tlbl = NULL;
10721 count = ix > 256 ? 256 : ix;
10725 tlbl = newiTempLabel (NULL);
10726 if (firstpass || (count & 0xff))
10728 emitcode("mov", "b, #!constbyte", count & 0xff);
10731 emitcode ("", "!tlabeldef", tlbl->key + 100);
10736 for (eIndex = 0; eIndex < elementSize; eIndex++)
10738 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10739 if (val != lastVal)
10741 emitcode("mov", "a, #!constbyte", val);
10745 emitcode("movx", "@dptr, a");
10746 emitcode("inc", "dptr");
10751 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10757 iLoop = iLoop->next;
10760 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10764 /*-----------------------------------------------------------------*/
10765 /* genFarFarAssign - assignment when both are in far space */
10766 /*-----------------------------------------------------------------*/
10768 genFarFarAssign (operand * result, operand * right, iCode * ic)
10770 int size = AOP_SIZE (right);
10772 symbol *rSym = NULL;
10776 /* quick & easy case. */
10777 D(emitcode(";","genFarFarAssign (1 byte case)"););
10778 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
10779 freeAsmop (right, NULL, ic, FALSE);
10780 /* now assign DPTR to result */
10782 aopOp(result, ic, FALSE, FALSE);
10784 aopPut(AOP(result), "a", 0);
10785 freeAsmop(result, NULL, ic, FALSE);
10789 /* See if we've got an underlying symbol to abuse. */
10790 if (IS_SYMOP(result) && OP_SYMBOL(result))
10792 if (IS_TRUE_SYMOP(result))
10794 rSym = OP_SYMBOL(result);
10796 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10798 rSym = OP_SYMBOL(result)->usl.spillLoc;
10802 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10804 /* We can use the '390 auto-toggle feature to good effect here. */
10806 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10807 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
10808 emitcode ("mov", "dptr,#%s", rSym->rname);
10809 /* DP2 = result, DP1 = right, DP1 is current. */
10812 emitcode("movx", "a,@dptr");
10813 emitcode("movx", "@dptr,a");
10816 emitcode("inc", "dptr");
10817 emitcode("inc", "dptr");
10820 emitcode("mov", "dps,#0");
10821 freeAsmop (right, NULL, ic, FALSE);
10823 some alternative code for processors without auto-toggle
10824 no time to test now, so later well put in...kpb
10825 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10826 emitcode("mov", "dps,#1"); /* Select DPTR2. */
10827 emitcode ("mov", "dptr,#%s", rSym->rname);
10828 /* DP2 = result, DP1 = right, DP1 is current. */
10832 emitcode("movx", "a,@dptr");
10834 emitcode("inc", "dptr");
10835 emitcode("inc", "dps");
10836 emitcode("movx", "@dptr,a");
10838 emitcode("inc", "dptr");
10839 emitcode("inc", "dps");
10841 emitcode("mov", "dps,#0");
10842 freeAsmop (right, NULL, ic, FALSE);
10847 D (emitcode (";", "genFarFarAssign"););
10848 aopOp (result, ic, TRUE, TRUE);
10850 _startLazyDPSEvaluation ();
10854 aopPut (AOP (result),
10855 aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
10858 _endLazyDPSEvaluation ();
10859 freeAsmop (result, NULL, ic, FALSE);
10860 freeAsmop (right, NULL, ic, FALSE);
10864 /*-----------------------------------------------------------------*/
10865 /* genAssign - generate code for assignment */
10866 /*-----------------------------------------------------------------*/
10868 genAssign (iCode * ic)
10870 operand *result, *right;
10872 unsigned long lit = 0L;
10874 D (emitcode (";", "genAssign ");
10877 result = IC_RESULT (ic);
10878 right = IC_RIGHT (ic);
10880 /* if they are the same */
10881 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10884 aopOp (right, ic, FALSE, FALSE);
10886 emitcode (";", "genAssign: resultIsFar = %s",
10887 isOperandInFarSpace (result) ?
10890 /* special case both in far space */
10891 if ((AOP_TYPE (right) == AOP_DPTR ||
10892 AOP_TYPE (right) == AOP_DPTR2) &&
10893 /* IS_TRUE_SYMOP(result) && */
10894 isOperandInFarSpace (result))
10896 genFarFarAssign (result, right, ic);
10900 aopOp (result, ic, TRUE, FALSE);
10902 /* if they are the same registers */
10903 if (sameRegs (AOP (right), AOP (result)))
10906 /* if the result is a bit */
10907 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10909 /* if the right size is a literal then
10910 we know what the value is */
10911 if (AOP_TYPE (right) == AOP_LIT)
10913 if (((int) operandLitValue (right)))
10914 aopPut (AOP (result), one, 0);
10916 aopPut (AOP (result), zero, 0);
10920 /* the right is also a bit variable */
10921 if (AOP_TYPE (right) == AOP_CRY)
10923 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10924 aopPut (AOP (result), "c", 0);
10928 /* we need to or */
10930 aopPut (AOP (result), "a", 0);
10934 /* bit variables done */
10936 size = AOP_SIZE (result);
10938 if (AOP_TYPE (right) == AOP_LIT)
10939 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10942 (AOP_TYPE (result) != AOP_REG) &&
10943 (AOP_TYPE (right) == AOP_LIT) &&
10944 !IS_FLOAT (operandType (right)))
10946 _startLazyDPSEvaluation ();
10947 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10949 aopPut (AOP (result),
10950 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10955 /* And now fill the rest with zeros. */
10958 emitcode ("clr", "a");
10962 aopPut (AOP (result), "a", offset++);
10964 _endLazyDPSEvaluation ();
10968 _startLazyDPSEvaluation ();
10971 aopPut (AOP (result),
10972 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10976 _endLazyDPSEvaluation ();
10980 freeAsmop (right, NULL, ic, FALSE);
10981 freeAsmop (result, NULL, ic, TRUE);
10984 /*-----------------------------------------------------------------*/
10985 /* genJumpTab - generates code for jump table */
10986 /*-----------------------------------------------------------------*/
10988 genJumpTab (iCode * ic)
10993 D (emitcode (";", "genJumpTab ");
10996 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10997 /* get the condition into accumulator */
10998 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
11000 /* multiply by four! */
11001 emitcode ("add", "a,acc");
11002 emitcode ("add", "a,acc");
11003 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11005 jtab = newiTempLabel (NULL);
11006 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
11007 emitcode ("jmp", "@a+dptr");
11008 emitcode ("", "!tlabeldef", jtab->key + 100);
11009 /* now generate the jump labels */
11010 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11011 jtab = setNextItem (IC_JTLABELS (ic)))
11012 emitcode ("ljmp", "!tlabel", jtab->key + 100);
11016 /*-----------------------------------------------------------------*/
11017 /* genCast - gen code for casting */
11018 /*-----------------------------------------------------------------*/
11020 genCast (iCode * ic)
11022 operand *result = IC_RESULT (ic);
11023 sym_link *ctype = operandType (IC_LEFT (ic));
11024 sym_link *rtype = operandType (IC_RIGHT (ic));
11025 operand *right = IC_RIGHT (ic);
11028 D (emitcode (";", "genCast "););
11030 /* if they are equivalent then do nothing */
11031 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11034 aopOp (right, ic, FALSE, FALSE);
11035 aopOp (result, ic, FALSE, AOP_USESDPTR(right));
11037 /* if the result is a bit */
11038 if (IS_BITVAR (OP_SYMBOL (result)->type)
11039 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
11041 /* if the right size is a literal then
11042 we know what the value is */
11043 if (AOP_TYPE (right) == AOP_LIT)
11045 if (((int) operandLitValue (right)))
11046 aopPut (AOP (result), one, 0);
11048 aopPut (AOP (result), zero, 0);
11053 /* the right is also a bit variable */
11054 if (AOP_TYPE (right) == AOP_CRY)
11056 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11057 aopPut (AOP (result), "c", 0);
11061 /* we need to or */
11063 aopPut (AOP (result), "a", 0);
11067 /* if they are the same size : or less */
11068 if (AOP_SIZE (result) <= AOP_SIZE (right))
11071 /* if they are in the same place */
11072 if (sameRegs (AOP (right), AOP (result)))
11075 /* if they in different places then copy */
11076 size = AOP_SIZE (result);
11078 _startLazyDPSEvaluation ();
11081 aopPut (AOP (result),
11082 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11086 _endLazyDPSEvaluation ();
11091 /* if the result is of type pointer */
11092 if (IS_PTR (ctype))
11096 sym_link *type = operandType (right);
11098 /* pointer to generic pointer */
11099 if (IS_GENPTR (ctype))
11103 p_type = DCL_TYPE (type);
11107 #if OLD_CAST_BEHAVIOR
11108 /* KV: we are converting a non-pointer type to
11109 * a generic pointer. This (ifdef'd out) code
11110 * says that the resulting generic pointer
11111 * should have the same class as the storage
11112 * location of the non-pointer variable.
11114 * For example, converting an int (which happens
11115 * to be stored in DATA space) to a pointer results
11116 * in a DATA generic pointer; if the original int
11117 * in XDATA space, so will be the resulting pointer.
11119 * I don't like that behavior, and thus this change:
11120 * all such conversions will be forced to XDATA and
11121 * throw a warning. If you want some non-XDATA
11122 * type, or you want to suppress the warning, you
11123 * must go through an intermediate cast, like so:
11125 * char _generic *gp = (char _xdata *)(intVar);
11127 sym_link *etype = getSpec (type);
11129 /* we have to go by the storage class */
11130 if (SPEC_OCLS (etype) != generic)
11132 p_type = PTR_TYPE (SPEC_OCLS (etype));
11137 /* Converting unknown class (i.e. register variable)
11138 * to generic pointer. This is not good, but
11139 * we'll make a guess (and throw a warning).
11142 werror (W_INT_TO_GEN_PTR_CAST);
11146 /* the first two bytes are known */
11147 size = GPTRSIZE - 1;
11149 _startLazyDPSEvaluation ();
11152 aopPut (AOP (result),
11153 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11157 _endLazyDPSEvaluation ();
11159 /* the last byte depending on type */
11161 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11166 // pointerTypeToGPByte will have bitched.
11170 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11171 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11176 /* just copy the pointers */
11177 size = AOP_SIZE (result);
11179 _startLazyDPSEvaluation ();
11182 aopPut (AOP (result),
11183 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11187 _endLazyDPSEvaluation ();
11191 /* so we now know that the size of destination is greater
11192 than the size of the source */
11193 /* we move to result for the size of source */
11194 size = AOP_SIZE (right);
11196 _startLazyDPSEvaluation ();
11199 aopPut (AOP (result),
11200 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11204 _endLazyDPSEvaluation ();
11206 /* now depending on the sign of the source && destination */
11207 size = AOP_SIZE (result) - AOP_SIZE (right);
11208 /* if unsigned or not an integral type */
11209 /* also, if the source is a bit, we don't need to sign extend, because
11210 * it can't possibly have set the sign bit.
11212 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
11216 aopPut (AOP (result), zero, offset++);
11221 /* we need to extend the sign :{ */
11222 MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11223 FALSE, FALSE, NULL));
11224 emitcode ("rlc", "a");
11225 emitcode ("subb", "a,acc");
11227 aopPut (AOP (result), "a", offset++);
11230 /* we are done hurray !!!! */
11233 freeAsmop (right, NULL, ic, TRUE);
11234 freeAsmop (result, NULL, ic, TRUE);
11238 /*-----------------------------------------------------------------*/
11239 /* genDjnz - generate decrement & jump if not zero instrucion */
11240 /*-----------------------------------------------------------------*/
11242 genDjnz (iCode * ic, iCode * ifx)
11244 symbol *lbl, *lbl1;
11248 /* if the if condition has a false label
11249 then we cannot save */
11250 if (IC_FALSE (ifx))
11253 /* if the minus is not of the form
11255 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11256 !IS_OP_LITERAL (IC_RIGHT (ic)))
11259 if (operandLitValue (IC_RIGHT (ic)) != 1)
11262 /* if the size of this greater than one then no
11264 if (getSize (operandType (IC_RESULT (ic))) > 1)
11267 /* otherwise we can save BIG */
11268 D(emitcode(";", "genDjnz"););
11270 lbl = newiTempLabel (NULL);
11271 lbl1 = newiTempLabel (NULL);
11273 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11275 if (AOP_NEEDSACC(IC_RESULT(ic)))
11277 /* If the result is accessed indirectly via
11278 * the accumulator, we must explicitly write
11279 * it back after the decrement.
11281 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11283 if (strcmp(rByte, "a"))
11285 /* Something is hopelessly wrong */
11286 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11287 __FILE__, __LINE__);
11288 /* We can just give up; the generated code will be inefficient,
11289 * but what the hey.
11291 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11294 emitcode ("dec", "%s", rByte);
11295 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11296 emitcode ("jnz", "!tlabel", lbl->key + 100);
11298 else if (IS_AOP_PREG (IC_RESULT (ic)))
11300 emitcode ("dec", "%s",
11301 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11302 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11303 emitcode ("jnz", "!tlabel", lbl->key + 100);
11307 emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11310 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11311 emitcode ("", "!tlabeldef", lbl->key + 100);
11312 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11313 emitcode ("", "!tlabeldef", lbl1->key + 100);
11315 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11316 ifx->generated = 1;
11320 /*-----------------------------------------------------------------*/
11321 /* genReceive - generate code for a receive iCode */
11322 /*-----------------------------------------------------------------*/
11324 genReceive (iCode * ic)
11326 int size = getSize (operandType (IC_RESULT (ic)));
11330 D (emitcode (";", "genReceive "););
11332 if (ic->argreg == 1)
11334 /* first parameter */
11335 if (AOP_IS_STR(IC_RESULT(ic)))
11337 /* Nothing to do: it's already in the proper place. */
11344 useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11345 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11346 IS_TRUE_SYMOP (IC_RESULT (ic)));
11349 aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11352 /* Sanity checking... */
11353 if (AOP_USESDPTR(IC_RESULT(ic)))
11355 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11356 "genReceive got unexpected DPTR.");
11358 assignResultValue (IC_RESULT (ic));
11363 /* second receive onwards */
11364 /* this gets a little tricky since unused recevies will be
11365 eliminated, we have saved the reg in the type field . and
11366 we use that to figure out which register to use */
11367 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11368 rb1off = ic->argreg;
11371 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11374 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11377 /*-----------------------------------------------------------------*/
11378 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
11379 /*-----------------------------------------------------------------*/
11380 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11382 operand *from , *to , *count;
11387 /* we know it has to be 3 parameters */
11388 assert (nparms == 3);
11390 rsave = newBitVect(16);
11391 /* save DPTR if it needs to be saved */
11392 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11393 if (bitVectBitValue(ic->rMask,i))
11394 rsave = bitVectSetBit(rsave,i);
11396 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11397 ds390_rUmaskForOp (IC_RESULT(ic))));
11404 aopOp (from, ic->next, FALSE, FALSE);
11406 /* get from into DPTR1 */
11407 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11408 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11409 if (options.model == MODEL_FLAT24) {
11410 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11413 freeAsmop (from, NULL, ic, FALSE);
11414 aopOp (to, ic, FALSE, FALSE);
11415 /* get "to" into DPTR */
11416 /* if the operand is already in dptr
11417 then we do nothing else we move the value to dptr */
11418 if (AOP_TYPE (to) != AOP_STR) {
11419 /* if already in DPTR then we need to push */
11420 if (AOP_TYPE(to) == AOP_DPTR) {
11421 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11422 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11423 if (options.model == MODEL_FLAT24)
11424 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11425 emitcode ("pop", "dph");
11426 emitcode ("pop", "dpl");
11428 _startLazyDPSEvaluation ();
11429 /* if this is remateriazable */
11430 if (AOP_TYPE (to) == AOP_IMMD) {
11431 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11432 } else { /* we need to get it byte by byte */
11433 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11434 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11435 if (options.model == MODEL_FLAT24) {
11436 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11439 _endLazyDPSEvaluation ();
11442 freeAsmop (to, NULL, ic, FALSE);
11443 _G.dptrInUse = _G.dptr1InUse = 1;
11444 aopOp (count, ic->next->next, FALSE,FALSE);
11445 lbl =newiTempLabel(NULL);
11447 /* now for the actual copy */
11448 if (AOP_TYPE(count) == AOP_LIT &&
11449 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11450 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11452 emitcode ("lcall","__bi_memcpyc2x_s");
11454 emitcode ("lcall","__bi_memcpyx2x_s");
11456 freeAsmop (count, NULL, ic, FALSE);
11458 symbol *lbl1 = newiTempLabel(NULL);
11460 emitcode (";"," Auto increment but no djnz");
11461 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11462 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11463 freeAsmop (count, NULL, ic, FALSE);
11464 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11465 emitcode ("","!tlabeldef",lbl->key+100);
11467 emitcode ("clr","a");
11468 emitcode ("movc", "a,@a+dptr");
11470 emitcode ("movx", "a,@dptr");
11471 emitcode ("movx", "@dptr,a");
11472 emitcode ("inc", "dptr");
11473 emitcode ("inc", "dptr");
11474 emitcode ("mov","a,b");
11475 emitcode ("orl","a,_ap");
11476 emitcode ("jz","!tlabel",lbl1->key+100);
11477 emitcode ("mov","a,_ap");
11478 emitcode ("add","a,#!constbyte",0xFF);
11479 emitcode ("mov","_ap,a");
11480 emitcode ("mov","a,b");
11481 emitcode ("addc","a,#!constbyte",0xFF);
11482 emitcode ("mov","b,a");
11483 emitcode ("sjmp","!tlabel",lbl->key+100);
11484 emitcode ("","!tlabeldef",lbl1->key+100);
11486 emitcode ("mov", "dps,#0");
11487 _G.dptrInUse = _G.dptr1InUse = 0;
11488 unsavermask(rsave);
11492 /*-----------------------------------------------------------------*/
11493 /* genMemcmpX2X - gen code for memcmp xdata to xdata */
11494 /*-----------------------------------------------------------------*/
11495 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11497 operand *from , *to , *count;
11502 /* we know it has to be 3 parameters */
11503 assert (nparms == 3);
11505 rsave = newBitVect(16);
11506 /* save DPTR if it needs to be saved */
11507 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11508 if (bitVectBitValue(ic->rMask,i))
11509 rsave = bitVectSetBit(rsave,i);
11511 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11512 ds390_rUmaskForOp (IC_RESULT(ic))));
11519 aopOp (from, ic->next, FALSE, FALSE);
11521 /* get from into DPTR1 */
11522 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11523 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11524 if (options.model == MODEL_FLAT24) {
11525 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11528 freeAsmop (from, NULL, ic, FALSE);
11529 aopOp (to, ic, FALSE, FALSE);
11530 /* get "to" into DPTR */
11531 /* if the operand is already in dptr
11532 then we do nothing else we move the value to dptr */
11533 if (AOP_TYPE (to) != AOP_STR) {
11534 /* if already in DPTR then we need to push */
11535 if (AOP_TYPE(to) == AOP_DPTR) {
11536 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11537 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11538 if (options.model == MODEL_FLAT24)
11539 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11540 emitcode ("pop", "dph");
11541 emitcode ("pop", "dpl");
11543 _startLazyDPSEvaluation ();
11544 /* if this is remateriazable */
11545 if (AOP_TYPE (to) == AOP_IMMD) {
11546 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11547 } else { /* we need to get it byte by byte */
11548 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11549 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11550 if (options.model == MODEL_FLAT24) {
11551 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11554 _endLazyDPSEvaluation ();
11557 freeAsmop (to, NULL, ic, FALSE);
11558 _G.dptrInUse = _G.dptr1InUse = 1;
11559 aopOp (count, ic->next->next, FALSE,FALSE);
11560 lbl =newiTempLabel(NULL);
11561 lbl2 =newiTempLabel(NULL);
11563 /* now for the actual compare */
11564 if (AOP_TYPE(count) == AOP_LIT &&
11565 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11566 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11568 emitcode("lcall","__bi_memcmpc2x_s");
11570 emitcode("lcall","__bi_memcmpx2x_s");
11571 freeAsmop (count, NULL, ic, FALSE);
11572 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11573 aopPut(AOP(IC_RESULT(ic)),"a",0);
11574 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11576 symbol *lbl1 = newiTempLabel(NULL);
11578 emitcode("push","ar0");
11579 emitcode (";"," Auto increment but no djnz");
11580 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11581 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11582 freeAsmop (count, NULL, ic, FALSE);
11583 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11584 emitcode ("","!tlabeldef",lbl->key+100);
11586 emitcode ("clr","a");
11587 emitcode ("movc", "a,@a+dptr");
11589 emitcode ("movx", "a,@dptr");
11590 emitcode ("mov","r0,a");
11591 emitcode ("movx", "a,@dptr");
11592 emitcode ("clr","c");
11593 emitcode ("subb","a,r0");
11594 emitcode ("jnz","!tlabel",lbl2->key+100);
11595 emitcode ("inc", "dptr");
11596 emitcode ("inc", "dptr");
11597 emitcode ("mov","a,b");
11598 emitcode ("orl","a,_ap");
11599 emitcode ("jz","!tlabel",lbl1->key+100);
11600 emitcode ("mov","a,_ap");
11601 emitcode ("add","a,#!constbyte",0xFF);
11602 emitcode ("mov","_ap,a");
11603 emitcode ("mov","a,b");
11604 emitcode ("addc","a,#!constbyte",0xFF);
11605 emitcode ("mov","b,a");
11606 emitcode ("sjmp","!tlabel",lbl->key+100);
11607 emitcode ("","!tlabeldef",lbl1->key+100);
11608 emitcode ("clr","a");
11609 emitcode ("","!tlabeldef",lbl2->key+100);
11610 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11611 aopPut(AOP(IC_RESULT(ic)),"a",0);
11612 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11613 emitcode("pop","ar0");
11614 emitcode ("mov", "dps,#0");
11616 _G.dptrInUse = _G.dptr1InUse = 0;
11617 unsavermask(rsave);
11621 /*-----------------------------------------------------------------*/
11622 /* genInp - gen code for __builtin_inp read data from a mem mapped */
11623 /* port, first parameter output area second parameter pointer to */
11624 /* port third parameter count */
11625 /*-----------------------------------------------------------------*/
11626 static void genInp( iCode *ic, int nparms, operand **parms)
11628 operand *from , *to , *count;
11633 /* we know it has to be 3 parameters */
11634 assert (nparms == 3);
11636 rsave = newBitVect(16);
11637 /* save DPTR if it needs to be saved */
11638 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11639 if (bitVectBitValue(ic->rMask,i))
11640 rsave = bitVectSetBit(rsave,i);
11642 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11643 ds390_rUmaskForOp (IC_RESULT(ic))));
11650 aopOp (from, ic->next, FALSE, FALSE);
11652 /* get from into DPTR1 */
11653 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11654 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11655 if (options.model == MODEL_FLAT24) {
11656 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11659 freeAsmop (from, NULL, ic, FALSE);
11660 aopOp (to, ic, FALSE, FALSE);
11661 /* get "to" into DPTR */
11662 /* if the operand is already in dptr
11663 then we do nothing else we move the value to dptr */
11664 if (AOP_TYPE (to) != AOP_STR) {
11665 /* if already in DPTR then we need to push */
11666 if (AOP_TYPE(to) == AOP_DPTR) {
11667 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11668 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11669 if (options.model == MODEL_FLAT24)
11670 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11671 emitcode ("pop", "dph");
11672 emitcode ("pop", "dpl");
11674 _startLazyDPSEvaluation ();
11675 /* if this is remateriazable */
11676 if (AOP_TYPE (to) == AOP_IMMD) {
11677 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11678 } else { /* we need to get it byte by byte */
11679 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11680 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11681 if (options.model == MODEL_FLAT24) {
11682 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11685 _endLazyDPSEvaluation ();
11688 freeAsmop (to, NULL, ic, FALSE);
11690 _G.dptrInUse = _G.dptr1InUse = 1;
11691 aopOp (count, ic->next->next, FALSE,FALSE);
11692 lbl =newiTempLabel(NULL);
11694 /* now for the actual copy */
11695 if (AOP_TYPE(count) == AOP_LIT &&
11696 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11697 emitcode (";","OH JOY auto increment with djnz (very fast)");
11698 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11699 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11700 freeAsmop (count, NULL, ic, FALSE);
11701 emitcode ("","!tlabeldef",lbl->key+100);
11702 emitcode ("movx", "a,@dptr"); /* read data from port */
11703 emitcode ("dec","dps"); /* switch to DPTR */
11704 emitcode ("movx", "@dptr,a"); /* save into location */
11705 emitcode ("inc", "dptr"); /* point to next area */
11706 emitcode ("inc","dps"); /* switch to DPTR2 */
11707 emitcode ("djnz","b,!tlabel",lbl->key+100);
11709 symbol *lbl1 = newiTempLabel(NULL);
11711 emitcode (";"," Auto increment but no djnz");
11712 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11713 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11714 freeAsmop (count, NULL, ic, FALSE);
11715 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11716 emitcode ("","!tlabeldef",lbl->key+100);
11717 emitcode ("movx", "a,@dptr");
11718 emitcode ("dec","dps"); /* switch to DPTR */
11719 emitcode ("movx", "@dptr,a");
11720 emitcode ("inc", "dptr");
11721 emitcode ("inc","dps"); /* switch to DPTR2 */
11722 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
11723 /* emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
11724 emitcode ("mov","a,b");
11725 emitcode ("orl","a,_ap");
11726 emitcode ("jz","!tlabel",lbl1->key+100);
11727 emitcode ("mov","a,_ap");
11728 emitcode ("add","a,#!constbyte",0xFF);
11729 emitcode ("mov","_ap,a");
11730 emitcode ("mov","a,b");
11731 emitcode ("addc","a,#!constbyte",0xFF);
11732 emitcode ("mov","b,a");
11733 emitcode ("sjmp","!tlabel",lbl->key+100);
11734 emitcode ("","!tlabeldef",lbl1->key+100);
11736 emitcode ("mov", "dps,#0");
11737 _G.dptrInUse = _G.dptr1InUse = 0;
11738 unsavermask(rsave);
11742 /*-----------------------------------------------------------------*/
11743 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
11744 /* port, first parameter output area second parameter pointer to */
11745 /* port third parameter count */
11746 /*-----------------------------------------------------------------*/
11747 static void genOutp( iCode *ic, int nparms, operand **parms)
11749 operand *from , *to , *count;
11754 /* we know it has to be 3 parameters */
11755 assert (nparms == 3);
11757 rsave = newBitVect(16);
11758 /* save DPTR if it needs to be saved */
11759 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11760 if (bitVectBitValue(ic->rMask,i))
11761 rsave = bitVectSetBit(rsave,i);
11763 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11764 ds390_rUmaskForOp (IC_RESULT(ic))));
11771 aopOp (from, ic->next, FALSE, FALSE);
11773 /* get from into DPTR1 */
11774 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11775 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11776 if (options.model == MODEL_FLAT24) {
11777 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11780 freeAsmop (from, NULL, ic, FALSE);
11781 aopOp (to, ic, FALSE, FALSE);
11782 /* get "to" into DPTR */
11783 /* if the operand is already in dptr
11784 then we do nothing else we move the value to dptr */
11785 if (AOP_TYPE (to) != AOP_STR) {
11786 /* if already in DPTR then we need to push */
11787 if (AOP_TYPE(to) == AOP_DPTR) {
11788 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11789 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11790 if (options.model == MODEL_FLAT24)
11791 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11792 emitcode ("pop", "dph");
11793 emitcode ("pop", "dpl");
11795 _startLazyDPSEvaluation ();
11796 /* if this is remateriazable */
11797 if (AOP_TYPE (to) == AOP_IMMD) {
11798 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11799 } else { /* we need to get it byte by byte */
11800 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11801 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11802 if (options.model == MODEL_FLAT24) {
11803 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11806 _endLazyDPSEvaluation ();
11809 freeAsmop (to, NULL, ic, FALSE);
11811 _G.dptrInUse = _G.dptr1InUse = 1;
11812 aopOp (count, ic->next->next, FALSE,FALSE);
11813 lbl =newiTempLabel(NULL);
11815 /* now for the actual copy */
11816 if (AOP_TYPE(count) == AOP_LIT &&
11817 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11818 emitcode (";","OH JOY auto increment with djnz (very fast)");
11819 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
11820 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11821 emitcode ("","!tlabeldef",lbl->key+100);
11822 emitcode ("movx", "a,@dptr"); /* read data from port */
11823 emitcode ("inc","dps"); /* switch to DPTR2 */
11824 emitcode ("movx", "@dptr,a"); /* save into location */
11825 emitcode ("inc", "dptr"); /* point to next area */
11826 emitcode ("dec","dps"); /* switch to DPTR */
11827 emitcode ("djnz","b,!tlabel",lbl->key+100);
11828 freeAsmop (count, NULL, ic, FALSE);
11830 symbol *lbl1 = newiTempLabel(NULL);
11832 emitcode (";"," Auto increment but no djnz");
11833 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11834 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11835 freeAsmop (count, NULL, ic, FALSE);
11836 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
11837 emitcode ("","!tlabeldef",lbl->key+100);
11838 emitcode ("movx", "a,@dptr");
11839 emitcode ("inc", "dptr");
11840 emitcode ("inc","dps"); /* switch to DPTR2 */
11841 emitcode ("movx", "@dptr,a");
11842 emitcode ("dec","dps"); /* switch to DPTR */
11843 emitcode ("mov","a,b");
11844 emitcode ("orl","a,_ap");
11845 emitcode ("jz","!tlabel",lbl1->key+100);
11846 emitcode ("mov","a,_ap");
11847 emitcode ("add","a,#!constbyte",0xFF);
11848 emitcode ("mov","_ap,a");
11849 emitcode ("mov","a,b");
11850 emitcode ("addc","a,#!constbyte",0xFF);
11851 emitcode ("mov","b,a");
11852 emitcode ("sjmp","!tlabel",lbl->key+100);
11853 emitcode ("","!tlabeldef",lbl1->key+100);
11855 emitcode ("mov", "dps,#0");
11856 _G.dptrInUse = _G.dptr1InUse = 0;
11857 unsavermask(rsave);
11861 /*-----------------------------------------------------------------*/
11862 /* genSwapW - swap lower & high order bytes */
11863 /*-----------------------------------------------------------------*/
11864 static void genSwapW(iCode *ic, int nparms, operand **parms)
11868 assert (nparms==1);
11871 dest=IC_RESULT(ic);
11873 assert(getSize(operandType(src))==2);
11875 aopOp (src, ic, FALSE, FALSE);
11876 emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
11878 MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
11880 freeAsmop (src, NULL, ic, FALSE);
11882 aopOp (dest,ic, FALSE, FALSE);
11883 aopPut(AOP(dest),"b",0);
11884 aopPut(AOP(dest),"a",1);
11885 freeAsmop (dest, NULL, ic, FALSE);
11888 /*-----------------------------------------------------------------*/
11889 /* genMemsetX - gencode for memSetX data */
11890 /*-----------------------------------------------------------------*/
11891 static void genMemsetX(iCode *ic, int nparms, operand **parms)
11893 operand *to , *val , *count;
11899 /* we know it has to be 3 parameters */
11900 assert (nparms == 3);
11906 /* save DPTR if it needs to be saved */
11907 rsave = newBitVect(16);
11908 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11909 if (bitVectBitValue(ic->rMask,i))
11910 rsave = bitVectSetBit(rsave,i);
11912 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11913 ds390_rUmaskForOp (IC_RESULT(ic))));
11916 aopOp (to, ic, FALSE, FALSE);
11917 /* get "to" into DPTR */
11918 /* if the operand is already in dptr
11919 then we do nothing else we move the value to dptr */
11920 if (AOP_TYPE (to) != AOP_STR) {
11921 /* if already in DPTR then we need to push */
11922 if (AOP_TYPE(to) == AOP_DPTR) {
11923 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11924 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11925 if (options.model == MODEL_FLAT24)
11926 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11927 emitcode ("pop", "dph");
11928 emitcode ("pop", "dpl");
11930 _startLazyDPSEvaluation ();
11931 /* if this is remateriazable */
11932 if (AOP_TYPE (to) == AOP_IMMD) {
11933 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11934 } else { /* we need to get it byte by byte */
11935 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11936 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11937 if (options.model == MODEL_FLAT24) {
11938 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11941 _endLazyDPSEvaluation ();
11944 freeAsmop (to, NULL, ic, FALSE);
11946 aopOp (val, ic->next->next, FALSE,FALSE);
11947 aopOp (count, ic->next->next, FALSE,FALSE);
11948 lbl =newiTempLabel(NULL);
11949 /* now for the actual copy */
11950 if (AOP_TYPE(count) == AOP_LIT &&
11951 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11952 l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
11953 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11955 emitcode ("","!tlabeldef",lbl->key+100);
11956 emitcode ("movx", "@dptr,a");
11957 emitcode ("inc", "dptr");
11958 emitcode ("djnz","b,!tlabel",lbl->key+100);
11960 symbol *lbl1 = newiTempLabel(NULL);
11962 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11963 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11964 emitcode ("","!tlabeldef",lbl->key+100);
11965 MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
11966 emitcode ("movx", "@dptr,a");
11967 emitcode ("inc", "dptr");
11968 emitcode ("mov","a,b");
11969 emitcode ("orl","a,_ap");
11970 emitcode ("jz","!tlabel",lbl1->key+100);
11971 emitcode ("mov","a,_ap");
11972 emitcode ("add","a,#!constbyte",0xFF);
11973 emitcode ("mov","_ap,a");
11974 emitcode ("mov","a,b");
11975 emitcode ("addc","a,#!constbyte",0xFF);
11976 emitcode ("mov","b,a");
11977 emitcode ("sjmp","!tlabel",lbl->key+100);
11978 emitcode ("","!tlabeldef",lbl1->key+100);
11980 freeAsmop (count, NULL, ic, FALSE);
11981 unsavermask(rsave);
11984 /*-----------------------------------------------------------------*/
11985 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
11986 /*-----------------------------------------------------------------*/
11987 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
11990 operand *pnum, *result;
11993 assert (nparms==1);
11994 /* save registers that need to be saved */
11995 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11996 ds390_rUmaskForOp (IC_RESULT(ic))));
11999 aopOp (pnum, ic, FALSE, FALSE);
12000 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12001 freeAsmop (pnum, NULL, ic, FALSE);
12002 emitcode ("lcall","NatLib_LoadPrimitive");
12003 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12004 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
12005 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
12006 for (i = (size-1) ; i >= 0 ; i-- ) {
12007 emitcode ("push","a%s",javaRet[i]);
12009 for (i=0; i < size ; i++ ) {
12010 emitcode ("pop","a%s",
12011 aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
12014 for (i = 0 ; i < size ; i++ ) {
12015 aopPut(AOP(result),javaRet[i],i);
12018 freeAsmop (result, NULL, ic, FALSE);
12019 unsavermask(rsave);
12022 /*-----------------------------------------------------------------*/
12023 /* genNatLibLoadPointer - calls TINI api function to load pointer */
12024 /*-----------------------------------------------------------------*/
12025 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
12028 operand *pnum, *result;
12032 assert (nparms==1);
12033 /* save registers that need to be saved */
12034 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12035 ds390_rUmaskForOp (IC_RESULT(ic))));
12038 aopOp (pnum, ic, FALSE, FALSE);
12039 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12040 freeAsmop (pnum, NULL, ic, FALSE);
12041 emitcode ("lcall","NatLib_LoadPointer");
12042 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12043 if (AOP_TYPE(result)!=AOP_STR) {
12044 for (i = 0 ; i < size ; i++ ) {
12045 aopPut(AOP(result),fReturn[i],i);
12048 freeAsmop (result, NULL, ic, FALSE);
12049 unsavermask(rsave);
12052 /*-----------------------------------------------------------------*/
12053 /* genNatLibInstallStateBlock - */
12054 /*-----------------------------------------------------------------*/
12055 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
12056 operand **parms, const char *name)
12059 operand *psb, *handle;
12060 assert (nparms==2);
12062 /* save registers that need to be saved */
12063 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12064 ds390_rUmaskForOp (IC_RESULT(ic))));
12068 /* put pointer to state block into DPTR1 */
12069 aopOp (psb, ic, FALSE, FALSE);
12070 if (AOP_TYPE (psb) == AOP_IMMD) {
12071 emitcode ("mov","dps,#1");
12072 emitcode ("mov", "dptr,%s",
12073 aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12074 emitcode ("mov","dps,#0");
12076 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12077 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12078 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12080 freeAsmop (psb, NULL, ic, FALSE);
12082 /* put libraryID into DPTR */
12083 emitcode ("mov","dptr,#LibraryID");
12085 /* put handle into r3:r2 */
12086 aopOp (handle, ic, FALSE, FALSE);
12087 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12088 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12089 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12090 emitcode ("pop","ar3");
12091 emitcode ("pop","ar2");
12093 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12094 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12096 freeAsmop (psb, NULL, ic, FALSE);
12098 /* make the call */
12099 emitcode ("lcall","NatLib_Install%sStateBlock",name);
12101 /* put return value into place*/
12103 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12105 aopPut(AOP(IC_RESULT(ic)),"a",0);
12106 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12107 unsavermask(rsave);
12110 /*-----------------------------------------------------------------*/
12111 /* genNatLibRemoveStateBlock - */
12112 /*-----------------------------------------------------------------*/
12113 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12119 /* save registers that need to be saved */
12120 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12121 ds390_rUmaskForOp (IC_RESULT(ic))));
12123 /* put libraryID into DPTR */
12124 emitcode ("mov","dptr,#LibraryID");
12125 /* make the call */
12126 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12127 unsavermask(rsave);
12130 /*-----------------------------------------------------------------*/
12131 /* genNatLibGetStateBlock - */
12132 /*-----------------------------------------------------------------*/
12133 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12134 operand **parms,const char *name)
12137 symbol *lbl = newiTempLabel(NULL);
12140 /* save registers that need to be saved */
12141 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12142 ds390_rUmaskForOp (IC_RESULT(ic))));
12144 /* put libraryID into DPTR */
12145 emitcode ("mov","dptr,#LibraryID");
12146 /* make the call */
12147 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12148 emitcode ("jnz","!tlabel",lbl->key+100);
12150 /* put return value into place */
12151 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12152 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12153 emitcode ("push","ar3");
12154 emitcode ("push","ar2");
12155 emitcode ("pop","%s",
12156 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12157 emitcode ("pop","%s",
12158 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12160 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12161 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12163 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12164 emitcode ("","!tlabeldef",lbl->key+100);
12165 unsavermask(rsave);
12168 /*-----------------------------------------------------------------*/
12169 /* genMMMalloc - */
12170 /*-----------------------------------------------------------------*/
12171 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12172 int size, const char *name)
12177 symbol *lbl = newiTempLabel(NULL);
12179 assert (nparms == 1);
12180 /* save registers that need to be saved */
12181 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12182 ds390_rUmaskForOp (IC_RESULT(ic))));
12185 aopOp (bsize,ic,FALSE,FALSE);
12187 /* put the size in R4-R2 */
12188 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12189 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12190 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12192 emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12193 emitcode("pop","ar4");
12195 emitcode("pop","ar3");
12196 emitcode("pop","ar2");
12198 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12199 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12201 emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12204 freeAsmop (bsize, NULL, ic, FALSE);
12206 /* make the call */
12207 emitcode ("lcall","MM_%s",name);
12208 emitcode ("jz","!tlabel",lbl->key+100);
12209 emitcode ("mov","r2,#!constbyte",0xff);
12210 emitcode ("mov","r3,#!constbyte",0xff);
12211 emitcode ("","!tlabeldef",lbl->key+100);
12212 /* we don't care about the pointer : we just save the handle */
12213 rsym = OP_SYMBOL(IC_RESULT(ic));
12214 if (rsym->liveFrom != rsym->liveTo) {
12215 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12216 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12217 emitcode ("push","ar3");
12218 emitcode ("push","ar2");
12219 emitcode ("pop","%s",
12220 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12221 emitcode ("pop","%s",
12222 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12224 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12225 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12227 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12229 unsavermask(rsave);
12232 /*-----------------------------------------------------------------*/
12234 /*-----------------------------------------------------------------*/
12235 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12240 assert (nparms == 1);
12241 /* save registers that need to be saved */
12242 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12243 ds390_rUmaskForOp (IC_RESULT(ic))));
12246 aopOp (handle,ic,FALSE,FALSE);
12248 /* put the size in R4-R2 */
12249 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12250 emitcode("push","%s",
12251 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12252 emitcode("push","%s",
12253 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12254 emitcode("pop","ar3");
12255 emitcode("pop","ar2");
12257 emitcode ("mov","r2,%s",
12258 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12259 emitcode ("mov","r3,%s",
12260 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12262 freeAsmop (handle, NULL, ic, FALSE);
12264 /* make the call */
12265 emitcode ("lcall","MM_Deref");
12268 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12269 if (rsym->liveFrom != rsym->liveTo) {
12270 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12271 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12272 _startLazyDPSEvaluation ();
12274 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12275 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12276 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12278 _endLazyDPSEvaluation ();
12283 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12284 unsavermask(rsave);
12287 /*-----------------------------------------------------------------*/
12288 /* genMMUnrestrictedPersist - */
12289 /*-----------------------------------------------------------------*/
12290 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12295 assert (nparms == 1);
12296 /* save registers that need to be saved */
12297 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12298 ds390_rUmaskForOp (IC_RESULT(ic))));
12301 aopOp (handle,ic,FALSE,FALSE);
12303 /* put the size in R3-R2 */
12304 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12305 emitcode("push","%s",
12306 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12307 emitcode("push","%s",
12308 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12309 emitcode("pop","ar3");
12310 emitcode("pop","ar2");
12312 emitcode ("mov","r2,%s",
12313 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12314 emitcode ("mov","r3,%s",
12315 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12317 freeAsmop (handle, NULL, ic, FALSE);
12319 /* make the call */
12320 emitcode ("lcall","MM_UnrestrictedPersist");
12323 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12324 if (rsym->liveFrom != rsym->liveTo) {
12325 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12326 aopPut(AOP(IC_RESULT(ic)),"a",0);
12327 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12330 unsavermask(rsave);
12333 /*-----------------------------------------------------------------*/
12334 /* genSystemExecJavaProcess - */
12335 /*-----------------------------------------------------------------*/
12336 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12339 operand *handle, *pp;
12341 assert (nparms==2);
12342 /* save registers that need to be saved */
12343 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12344 ds390_rUmaskForOp (IC_RESULT(ic))));
12349 /* put the handle in R3-R2 */
12350 aopOp (handle,ic,FALSE,FALSE);
12351 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12352 emitcode("push","%s",
12353 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12354 emitcode("push","%s",
12355 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12356 emitcode("pop","ar3");
12357 emitcode("pop","ar2");
12359 emitcode ("mov","r2,%s",
12360 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12361 emitcode ("mov","r3,%s",
12362 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12364 freeAsmop (handle, NULL, ic, FALSE);
12366 /* put pointer in DPTR */
12367 aopOp (pp,ic,FALSE,FALSE);
12368 if (AOP_TYPE(pp) == AOP_IMMD) {
12369 emitcode ("mov", "dptr,%s",
12370 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12371 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12372 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12373 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12374 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12376 freeAsmop (handle, NULL, ic, FALSE);
12378 /* make the call */
12379 emitcode ("lcall","System_ExecJavaProcess");
12381 /* put result in place */
12383 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12384 if (rsym->liveFrom != rsym->liveTo) {
12385 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12386 aopPut(AOP(IC_RESULT(ic)),"a",0);
12387 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12391 unsavermask(rsave);
12394 /*-----------------------------------------------------------------*/
12395 /* genSystemRTCRegisters - */
12396 /*-----------------------------------------------------------------*/
12397 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12403 assert (nparms==1);
12404 /* save registers that need to be saved */
12405 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12406 ds390_rUmaskForOp (IC_RESULT(ic))));
12409 /* put pointer in DPTR */
12410 aopOp (pp,ic,FALSE,FALSE);
12411 if (AOP_TYPE (pp) == AOP_IMMD) {
12412 emitcode ("mov","dps,#1");
12413 emitcode ("mov", "dptr,%s",
12414 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12415 emitcode ("mov","dps,#0");
12417 emitcode ("mov","dpl1,%s",
12418 aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12419 emitcode ("mov","dph1,%s",
12420 aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12421 emitcode ("mov","dpx1,%s",
12422 aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12424 freeAsmop (pp, NULL, ic, FALSE);
12426 /* make the call */
12427 emitcode ("lcall","System_%sRTCRegisters",name);
12429 unsavermask(rsave);
12432 /*-----------------------------------------------------------------*/
12433 /* genSystemThreadSleep - */
12434 /*-----------------------------------------------------------------*/
12435 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12440 assert (nparms==1);
12441 /* save registers that need to be saved */
12442 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12443 ds390_rUmaskForOp (IC_RESULT(ic))));
12446 aopOp(to,ic,FALSE,FALSE);
12447 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12448 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12449 emitcode ("push","%s",
12450 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12451 emitcode ("push","%s",
12452 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12453 emitcode ("push","%s",
12454 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12455 emitcode ("push","%s",
12456 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12457 emitcode ("pop","ar3");
12458 emitcode ("pop","ar2");
12459 emitcode ("pop","ar1");
12460 emitcode ("pop","ar0");
12462 emitcode ("mov","r0,%s",
12463 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12464 emitcode ("mov","r1,%s",
12465 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12466 emitcode ("mov","r2,%s",
12467 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12468 emitcode ("mov","r3,%s",
12469 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12471 freeAsmop (to, NULL, ic, FALSE);
12473 /* suspend in acc */
12475 aopOp(s,ic,FALSE,FALSE);
12476 emitcode ("mov","a,%s",
12477 aopGet(AOP(s),0,FALSE,TRUE,NULL));
12478 freeAsmop (s, NULL, ic, FALSE);
12480 /* make the call */
12481 emitcode ("lcall","System_%s",name);
12483 unsavermask(rsave);
12486 /*-----------------------------------------------------------------*/
12487 /* genSystemThreadResume - */
12488 /*-----------------------------------------------------------------*/
12489 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12494 assert (nparms==2);
12495 /* save registers that need to be saved */
12496 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12497 ds390_rUmaskForOp (IC_RESULT(ic))));
12503 aopOp(pid,ic,FALSE,FALSE);
12504 emitcode ("mov","r0,%s",
12505 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12506 freeAsmop (pid, NULL, ic, FALSE);
12509 aopOp(tid,ic,FALSE,FALSE);
12510 emitcode ("mov","a,%s",
12511 aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
12512 freeAsmop (tid, NULL, ic, FALSE);
12514 emitcode ("lcall","System_ThreadResume");
12516 /* put result into place */
12518 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12519 if (rsym->liveFrom != rsym->liveTo) {
12520 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12521 aopPut(AOP(IC_RESULT(ic)),"a",0);
12522 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12525 unsavermask(rsave);
12528 /*-----------------------------------------------------------------*/
12529 /* genSystemProcessResume - */
12530 /*-----------------------------------------------------------------*/
12531 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
12536 assert (nparms==1);
12537 /* save registers that need to be saved */
12538 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12539 ds390_rUmaskForOp (IC_RESULT(ic))));
12544 aopOp(pid,ic,FALSE,FALSE);
12545 emitcode ("mov","a,%s",
12546 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12547 freeAsmop (pid, NULL, ic, FALSE);
12549 emitcode ("lcall","System_ProcessResume");
12551 unsavermask(rsave);
12554 /*-----------------------------------------------------------------*/
12556 /*-----------------------------------------------------------------*/
12557 static void genSystem (iCode *ic,int nparms,char *name)
12559 assert(nparms == 0);
12561 emitcode ("lcall","System_%s",name);
12564 /*-----------------------------------------------------------------*/
12565 /* genSystemPoll - */
12566 /*-----------------------------------------------------------------*/
12567 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
12572 assert (nparms==1);
12573 /* save registers that need to be saved */
12574 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12575 ds390_rUmaskForOp (IC_RESULT(ic))));
12578 aopOp (fp,ic,FALSE,FALSE);
12579 if (AOP_TYPE (fp) == AOP_IMMD) {
12580 emitcode ("mov", "dptr,%s",
12581 aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
12582 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
12583 emitcode ("mov","dpl,%s",
12584 aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
12585 emitcode ("mov","dph,%s",
12586 aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
12587 emitcode ("mov","dpx,%s",
12588 aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
12590 freeAsmop (fp, NULL, ic, FALSE);
12592 emitcode ("lcall","System_%sPoll",name);
12594 /* put result into place */
12596 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12597 if (rsym->liveFrom != rsym->liveTo) {
12598 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12599 aopPut(AOP(IC_RESULT(ic)),"a",0);
12600 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12603 unsavermask(rsave);
12606 /*-----------------------------------------------------------------*/
12607 /* genSystemGetCurrentID - */
12608 /*-----------------------------------------------------------------*/
12609 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
12611 assert (nparms==0);
12613 emitcode ("lcall","System_GetCurrent%sId",name);
12614 /* put result into place */
12616 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12617 if (rsym->liveFrom != rsym->liveTo) {
12618 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12619 aopPut(AOP(IC_RESULT(ic)),"a",0);
12620 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12625 /*-----------------------------------------------------------------*/
12626 /* genDummyRead - generate code for dummy read of volatiles */
12627 /*-----------------------------------------------------------------*/
12629 genDummyRead (iCode * ic)
12634 D(emitcode("; genDummyRead",""));
12636 right = IC_RIGHT (ic);
12638 aopOp (right, ic, FALSE, FALSE);
12640 /* if the result is a bit */
12641 if (AOP_TYPE (right) == AOP_CRY)
12643 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
12647 /* bit variables done */
12649 size = AOP_SIZE (right);
12653 emitcode ("mov", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
12658 freeAsmop (right, NULL, ic, TRUE);
12661 /*-----------------------------------------------------------------*/
12662 /* genBuiltIn - calls the appropriate function to generating code */
12663 /* for a built in function */
12664 /*-----------------------------------------------------------------*/
12665 static void genBuiltIn (iCode *ic)
12667 operand *bi_parms[MAX_BUILTIN_ARGS];
12672 /* get all the arguments for a built in function */
12673 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
12675 /* which function is it */
12676 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
12677 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
12678 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
12679 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
12680 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
12681 } else if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
12682 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
12683 } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
12684 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
12685 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
12686 genMemsetX(bi_iCode,nbi_parms,bi_parms);
12687 } else if (strcmp(bif->name,"__builtin_inp")==0) {
12688 genInp(bi_iCode,nbi_parms,bi_parms);
12689 } else if (strcmp(bif->name,"__builtin_outp")==0) {
12690 genOutp(bi_iCode,nbi_parms,bi_parms);
12691 } else if (strcmp(bif->name,"__builtin_swapw")==0) {
12692 genSwapW(bi_iCode,nbi_parms,bi_parms);
12693 /* JavaNative builtIns */
12694 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
12695 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
12696 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
12697 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
12698 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
12699 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
12700 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
12701 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
12702 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
12703 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12704 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
12705 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12706 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
12707 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
12708 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
12709 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
12710 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
12711 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12712 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
12713 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12714 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
12715 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
12716 } else if (strcmp(bif->name,"MM_Malloc")==0) {
12717 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
12718 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
12719 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
12720 } else if (strcmp(bif->name,"MM_Free")==0) {
12721 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
12722 } else if (strcmp(bif->name,"MM_Deref")==0) {
12723 genMMDeref(bi_iCode,nbi_parms,bi_parms);
12724 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
12725 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
12726 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
12727 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
12728 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
12729 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
12730 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
12731 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
12732 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
12733 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
12734 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
12735 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
12736 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
12737 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
12738 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
12739 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
12740 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12741 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12742 } else if (strcmp(bif->name,"System_SaveThread")==0) {
12743 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12744 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12745 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12746 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
12747 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
12748 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
12749 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
12750 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
12751 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
12752 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
12753 genSystem(bi_iCode,nbi_parms,"ProcessYield");
12754 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
12755 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
12756 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
12757 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
12758 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
12759 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
12760 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
12761 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
12762 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
12763 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
12765 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
12771 /*-----------------------------------------------------------------*/
12772 /* gen390Code - generate code for Dallas 390 based controllers */
12773 /*-----------------------------------------------------------------*/
12775 gen390Code (iCode * lic)
12780 lineHead = lineCurr = NULL;
12781 dptrn[1][0] = "dpl1";
12782 dptrn[1][1] = "dph1";
12783 dptrn[1][2] = "dpx1";
12785 if (options.model == MODEL_FLAT24) {
12786 fReturnSizeDS390 = 5;
12787 fReturn = fReturn24;
12789 fReturnSizeDS390 = 4;
12790 fReturn = fReturn16;
12791 options.stack10bit=0;
12794 /* print the allocation information */
12795 if (allocInfo && currFunc)
12796 printAllocInfo (currFunc, codeOutFile);
12798 /* if debug information required */
12799 if (options.debug && currFunc)
12801 debugFile->writeFunction(currFunc);
12803 if (IS_STATIC (currFunc->etype))
12804 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
12806 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
12809 /* stack pointer name */
12810 if (options.useXstack)
12816 for (ic = lic; ic; ic = ic->next)
12819 if (ic->lineno && cln != ic->lineno)
12824 emitcode ("", "C$%s$%d$%d$%d ==.",
12825 FileBaseName (ic->filename), ic->lineno,
12826 ic->level, ic->block);
12829 if (!options.noCcodeInAsm) {
12830 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
12831 printCLine(ic->filename, ic->lineno));
12835 if (options.iCodeInAsm) {
12836 emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
12838 /* if the result is marked as
12839 spilt and rematerializable or code for
12840 this has already been generated then
12842 if (resultRemat (ic) || ic->generated)
12845 /* depending on the operation */
12865 /* IPOP happens only when trying to restore a
12866 spilt live range, if there is an ifx statement
12867 following this pop then the if statement might
12868 be using some of the registers being popped which
12869 would destory the contents of the register so
12870 we need to check for this condition and handle it */
12872 ic->next->op == IFX &&
12873 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
12874 genIfx (ic->next, ic);
12892 genEndFunction (ic);
12912 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
12929 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
12933 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
12940 /* note these two are xlated by algebraic equivalence
12941 during parsing SDCC.y */
12942 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12943 "got '>=' or '<=' shouldn't have come here");
12947 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
12959 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
12963 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
12967 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
12991 genRightShift (ic);
12994 case GET_VALUE_AT_ADDRESS:
12995 genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
12999 if (POINTER_SET (ic))
13000 genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
13026 if (ic->builtinSEND) genBuiltIn(ic);
13027 else addSet (&_G.sendSet, ic);
13030 case DUMMY_READ_VOLATILE:
13034 #if 0 // obsolete, and buggy for != xdata
13046 /* now we are ready to call the
13047 peep hole optimizer */
13048 if (!options.nopeep)
13049 peepHole (&lineHead);
13051 /* now do the actual printing */
13052 printLine (lineHead, codeOutFile);