1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for DS80C390
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7 DS390 adaptation by Kevin Vigor <kevin@vigor.nu>
9 This program is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 2, or (at your option) any
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 In other words, you are welcome to use, share and improve this program.
24 You are forbidden to forbid anyone else to use, share and improve
25 what you give them. Help stamp out software-hoarding!
26 -------------------------------------------------------------------------*/
36 #include "SDCCglobl.h"
39 #define BETTER_LITERAL_SHIFT
41 char *aopLiteral (value * val, int offset);
44 /* this is the down and dirty file with all kinds of
45 kludgy & hacky stuff. This is what it is all about
46 CODE GENERATION for a specific MCU . some of the
47 routines may be reusable, will have to see */
49 static char *zero = "#0";
50 static char *one = "#1";
55 #define TR_DPTR(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_DPTR1 %s ", s); }
56 #define TR_AP(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_AP %s ", s); }
58 unsigned fReturnSizeDS390 = 5; /* shared with ralloc.c */
59 static char *fReturn24[] =
60 {"dpl", "dph", "dpx", "b", "a"};
61 static char *fReturn16[] =
62 {"dpl", "dph", "b", "a"};
63 static char **fReturn = fReturn24;
64 static char *accUse[] =
66 static char *dptrn[2][3];
67 static char *javaRet[] = { "r0","r1","r2","r3"};
68 static short rbank = -1;
85 static char *rb1regs[] = {
86 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
89 static void saveRBank (int, iCode *, bool);
91 #define RESULTONSTACK(x) \
92 (IC_RESULT(x) && IC_RESULT(x)->aop && \
93 IC_RESULT(x)->aop->type == AOP_STK )
95 #define MOVA(x) _movA(x)
96 #define MOVB(x) _movB(x)
98 #define CLRC emitcode("clr","c")
99 #define SETC emitcode("setb","c")
101 // A scratch register which will be used to hold
102 // result bytes from operands in far space via DPTR2.
103 #define DP2_RESULT_REG "_ap"
105 static lineNode *lineHead = NULL;
106 static lineNode *lineCurr = NULL;
108 static unsigned char SLMask[] =
109 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
110 0xE0, 0xC0, 0x80, 0x00};
111 static unsigned char SRMask[] =
112 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
113 0x07, 0x03, 0x01, 0x00};
119 #define PROTECT_SP {if (options.protect_sp_update) { \
120 symbol *lbl = newiTempLabel(NULL); \
121 emitcode ("setb","F1"); \
122 emitcode ("jbc","EA,!tlabel",lbl->key+100); \
123 emitcode ("clr","F1"); \
124 emitcode ("","!tlabeldef",lbl->key+100); \
126 #define UNPROTECT_SP { if (options.protect_sp_update) { \
127 symbol *lbl = newiTempLabel(NULL); \
128 emitcode ("jnb","F1,!tlabel",lbl->key+100); \
129 emitcode ("setb","EA"); \
130 emitcode ("","!tlabeldef",lbl->key+100); \
134 /*-----------------------------------------------------------------*/
135 /* emitcode - writes the code into a file : for now it is simple */
136 /*-----------------------------------------------------------------*/
138 emitcode (char *inst, char *fmt,...)
141 char lb[INITIAL_INLINEASM];
150 SNPRINTF (lb, sizeof(lb), "%s\t", inst);
154 SNPRINTF (lb, sizeof(lb), "%s", inst);
157 tvsprintf (lb + strlen(lb), sizeof(lb) - strlen(lb),
162 tvsprintf (lb, sizeof(lb), fmt, ap);
166 while (isspace (*lbp))
173 lineCurr = (lineCurr ?
174 connectLine (lineCurr, newLineNode (lb)) :
175 (lineHead = newLineNode (lb)));
178 lineCurr->isInline = _G.inLine;
179 lineCurr->isDebug = _G.debugLine;
184 // Move the passed value into A unless it is already there.
189 if (strcmp(s,"a") && strcmp(s,"acc"))
191 emitcode("mov","a,%s",s);
196 // Move the passed value into B unless it is already there.
203 emitcode("mov","b,%s",s);
207 /*-----------------------------------------------------------------*/
208 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
209 /*-----------------------------------------------------------------*/
211 getFreePtr (iCode * ic, asmop ** aopp, bool result)
216 /* the logic: if r0 & r1 used in the instruction
217 then we are in trouble otherwise */
219 /* first check if r0 & r1 are used by this
220 instruction, in which case we are in trouble */
221 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
222 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
227 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
228 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
230 /* if no usage of r0 then return it */
233 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
234 (*aopp)->type = AOP_R0;
236 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
239 /* if no usage of r1 then return it */
242 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
243 (*aopp)->type = AOP_R1;
245 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
248 /* now we know they both have usage */
249 /* if r0 not used in this instruction */
252 /* push it if not already pushed */
255 emitcode ("push", "%s",
256 ds390_regWithIdx (R0_IDX)->dname);
260 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
261 (*aopp)->type = AOP_R0;
263 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
266 /* if r1 not used then */
270 /* push it if not already pushed */
273 emitcode ("push", "%s",
274 ds390_regWithIdx (R1_IDX)->dname);
278 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
279 (*aopp)->type = AOP_R1;
280 return ds390_regWithIdx (R1_IDX);
284 /* I said end of world but not quite end of world yet */
285 /* if this is a result then we can push it on the stack */
288 (*aopp)->type = AOP_STK;
292 /* other wise this is true end of the world */
293 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
294 "getFreePtr should never reach here");
297 return NULL; // notreached, but makes compiler happy.
300 /*-----------------------------------------------------------------*/
301 /* newAsmop - creates a new asmOp */
302 /*-----------------------------------------------------------------*/
304 newAsmop (short type)
308 aop = Safe_calloc (1, sizeof (asmop));
313 static int _currentDPS; /* Current processor DPS. */
314 static int _desiredDPS; /* DPS value compiler thinks we should be using. */
315 static int _lazyDPS = 0; /* if non-zero, we are doing lazy evaluation of DPS changes. */
317 /*-----------------------------------------------------------------*/
318 /* genSetDPTR: generate code to select which DPTR is in use (zero */
319 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390 */
320 /* alternate DPTR (DPL1/DPH1/DPX1). */
321 /*-----------------------------------------------------------------*/
326 /* If we are doing lazy evaluation, simply note the desired
327 * change, but don't emit any code yet.
337 emitcode ("mov", "dps,#0");
342 emitcode ("mov", "dps,#1");
346 /*-----------------------------------------------------------------*/
347 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
349 /* Any code that operates on DPTR (NB: not on the individual */
350 /* components, like DPH) *must* call _flushLazyDPS() before using */
351 /* DPTR within a lazy DPS evaluation block. */
353 /* Note that aopPut and aopGet already contain the proper calls to */
354 /* _flushLazyDPS, so it is safe to use these calls within a lazy */
355 /* DPS evaluation block. */
357 /* Also, _flushLazyDPS must be called before any flow control */
358 /* operations that could potentially branch out of the block. */
360 /* Lazy DPS evaluation is simply an optimization (though an */
361 /* important one), so if in doubt, leave it out. */
362 /*-----------------------------------------------------------------*/
364 _startLazyDPSEvaluation (void)
368 #ifdef BETTER_LITERAL_SHIFT
375 /*-----------------------------------------------------------------*/
376 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
377 /* desired one. Call before using DPTR within a lazy DPS evaluation */
379 /*-----------------------------------------------------------------*/
389 if (_desiredDPS != _currentDPS)
393 emitcode ("inc", "dps");
397 emitcode ("dec", "dps");
399 _currentDPS = _desiredDPS;
403 /*-----------------------------------------------------------------*/
404 /* _endLazyDPSEvaluation: end lazy DPS evaluation block. */
406 /* Forces us back to the safe state (standard DPTR selected). */
407 /*-----------------------------------------------------------------*/
409 _endLazyDPSEvaluation (void)
411 #ifdef BETTER_LITERAL_SHIFT
430 /*-----------------------------------------------------------------*/
431 /* pointerCode - returns the code for a pointer type */
432 /*-----------------------------------------------------------------*/
434 pointerCode (sym_link * etype)
437 return PTR_TYPE (SPEC_OCLS (etype));
441 /*-----------------------------------------------------------------*/
442 /* leftRightUseAcc - returns size of accumulator use by operands */
443 /*-----------------------------------------------------------------*/
445 leftRightUseAcc(iCode *ic)
454 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
455 "null iCode pointer");
462 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
465 size = getSize (OP_SYMBOL (op)->type);
470 else if (ic->op == JUMPTABLE)
473 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
476 size = getSize (OP_SYMBOL (op)->type);
484 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
487 size = getSize (OP_SYMBOL (op)->type);
492 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
495 size = getSize (OP_SYMBOL (op)->type);
507 /*-----------------------------------------------------------------*/
508 /* aopForSym - for a true symbol */
509 /*-----------------------------------------------------------------*/
511 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
514 memmap *space = SPEC_OCLS (sym->etype);
515 int accuse = leftRightUseAcc (ic);
517 /* if already has one */
521 /* assign depending on the storage class */
522 /* if it is on the stack or indirectly addressable */
523 /* space we need to assign either r0 or r1 to it */
524 if ((sym->onStack && !options.stack10bit) || sym->iaccess)
526 sym->aop = aop = newAsmop (0);
527 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
528 aop->size = getSize (sym->type);
530 /* now assign the address of the variable to
531 the pointer register */
532 if (aop->type != AOP_STK)
537 if (_G.accInUse || accuse)
538 emitcode ("push", "acc");
540 if (_G.bInUse || (accuse>1))
541 emitcode ("push", "b");
543 emitcode ("mov", "a,_bp");
544 emitcode ("add", "a,#!constbyte",
546 ((char) (sym->stack - _G.nRegsSaved)) :
547 ((char) sym->stack)) & 0xff);
548 emitcode ("mov", "%s,a",
549 aop->aopu.aop_ptr->name);
551 if (_G.bInUse || (accuse>1))
552 emitcode ("pop", "b");
554 if (_G.accInUse || accuse)
555 emitcode ("pop", "acc");
558 emitcode ("mov", "%s,#%s",
559 aop->aopu.aop_ptr->name,
561 aop->paged = space->paged;
564 aop->aopu.aop_stk = sym->stack;
568 if (sym->onStack && options.stack10bit)
570 short stack_val = -((sym->stack < 0) ?
571 ((short) (sym->stack - _G.nRegsSaved)) :
572 ((short) sym->stack)) ;
573 if (useDP2 && _G.dptr1InUse) {
574 emitcode ("push","dpl1");
575 emitcode ("push","dph1");
576 emitcode ("push","dpx1");
577 } else if (_G.dptrInUse ) {
578 emitcode ("push","dpl");
579 emitcode ("push","dph");
580 emitcode ("push","dpx");
582 /* It's on the 10 bit stack, which is located in
585 if (stack_val < 0 && stack_val > -5) { /* between -5 & -1 */
587 if (options.model == MODEL_FLAT24)
589 emitcode ("mov", "dpx1,#!constbyte",
590 (options.stack_loc >> 16) & 0xff);
592 emitcode ("mov", "dph1,_bpx+1");
594 emitcode ("mov", "dpl1,_bpx");
595 emitcode ("mov","dps,#1");
597 if (options.model == MODEL_FLAT24)
599 emitcode ("mov", "dpx,#!constbyte",
600 (options.stack_loc >> 16) & 0xff);
602 emitcode ("mov", "dph,_bpx+1");
603 emitcode ("mov", "dpl,_bpx");
605 stack_val = -stack_val;
606 while (stack_val--) {
607 emitcode ("inc","dptr");
610 emitcode("mov","dps,#0");
613 if (_G.accInUse || accuse)
614 emitcode ("push", "acc");
616 if (_G.bInUse || (accuse>1))
617 emitcode ("push", "b");
619 emitcode ("mov", "a,_bpx");
620 emitcode ("clr","c");
621 emitcode ("subb", "a,#!constbyte", stack_val & 0xff);
622 emitcode ("mov","b,a");
623 emitcode ("mov","a,_bpx+1");
624 emitcode ("subb","a,#!constbyte",(stack_val >> 8) & 0xff);
626 if (options.model == MODEL_FLAT24)
628 emitcode ("mov", "dpx1,#!constbyte",
629 (options.stack_loc >> 16) & 0xff);
631 emitcode ("mov", "dph1,a");
632 emitcode ("mov", "dpl1,b");
634 if (options.model == MODEL_FLAT24)
636 emitcode ("mov", "dpx,#!constbyte",
637 (options.stack_loc >> 16) & 0xff);
639 emitcode ("mov", "dph,a");
640 emitcode ("mov", "dpl,b");
643 if (_G.bInUse || (accuse>1))
644 emitcode ("pop", "b");
646 if (_G.accInUse || accuse)
647 emitcode ("pop", "acc");
649 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
650 aop->size = getSize (sym->type);
654 /* if in bit space */
655 if (IN_BITSPACE (space))
657 sym->aop = aop = newAsmop (AOP_CRY);
658 aop->aopu.aop_dir = sym->rname;
659 aop->size = getSize (sym->type);
662 /* if it is in direct space */
663 if (IN_DIRSPACE (space))
665 sym->aop = aop = newAsmop (AOP_DIR);
666 aop->aopu.aop_dir = sym->rname;
667 aop->size = getSize (sym->type);
671 /* special case for a function */
672 if (IS_FUNC (sym->type) && !(sym->isitmp))
674 sym->aop = aop = newAsmop (AOP_IMMD);
675 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
676 aop->size = FPTRSIZE;
680 /* only remaining is far space */
681 /* in which case DPTR gets the address */
682 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
687 emitcode ("mov", "dptr,#%s", sym->rname);
692 emitcode ("mov", "dptr,#%s", sym->rname);
694 aop->size = getSize (sym->type);
696 /* if it is in code space */
697 if (IN_CODESPACE (space))
703 /*-----------------------------------------------------------------*/
704 /* aopForRemat - rematerialzes an object */
705 /*-----------------------------------------------------------------*/
707 aopForRemat (symbol * sym)
709 iCode *ic = sym->rematiCode;
710 asmop *aop = newAsmop (AOP_IMMD);
717 val += (int) operandLitValue (IC_RIGHT (ic));
718 else if (ic->op == '-')
719 val -= (int) operandLitValue (IC_RIGHT (ic));
720 else if (IS_CAST_ICODE(ic)) {
721 sym_link *from_type = operandType(IC_RIGHT(ic));
722 aop->aopu.aop_immd.from_cast_remat = 1;
723 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
724 ptr_type = DCL_TYPE(from_type);
725 if (ptr_type == IPOINTER) {
732 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
737 SNPRINTF (buffer, sizeof(buffer),
739 OP_SYMBOL (IC_LEFT (ic))->rname,
740 val >= 0 ? '+' : '-',
741 abs (val) & 0xffffff);
745 if (IS_ASSIGN_ICODE(ic) && isOperandLiteral(IC_RIGHT(ic)))
747 SNPRINTF(buffer, sizeof(buffer),
748 "0x%x",(int) operandLitValue (IC_RIGHT (ic)));
752 strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
756 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);
757 /* set immd2 field if required */
758 if (aop->aopu.aop_immd.from_cast_remat)
760 tsprintf(buffer, sizeof(buffer), "#!constbyte",ptr_type);
761 aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
767 /*-----------------------------------------------------------------*/
768 /* aopHasRegs - returns true if aop has regs between from-to */
769 /*-----------------------------------------------------------------*/
770 static int aopHasRegs(asmop *aop, int from, int to)
774 if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
776 for (; size < aop->size ; size++) {
778 for (reg = from ; reg <= to ; reg++)
779 if (aop->aopu.aop_reg[size] == ds390_regWithIdx(reg)) return 1;
784 /*-----------------------------------------------------------------*/
785 /* regsInCommon - two operands have some registers in common */
786 /*-----------------------------------------------------------------*/
788 regsInCommon (operand * op1, operand * op2)
793 /* if they have registers in common */
794 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
797 sym1 = OP_SYMBOL (op1);
798 sym2 = OP_SYMBOL (op2);
800 if (sym1->nRegs == 0 || sym2->nRegs == 0)
803 for (i = 0; i < sym1->nRegs; i++)
809 for (j = 0; j < sym2->nRegs; j++)
814 if (sym2->regs[j] == sym1->regs[i])
822 /*-----------------------------------------------------------------*/
823 /* operandsEqu - equivalent */
824 /*-----------------------------------------------------------------*/
826 operandsEqu (operand * op1, operand * op2)
830 /* if they not symbols */
831 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
834 sym1 = OP_SYMBOL (op1);
835 sym2 = OP_SYMBOL (op2);
837 /* if both are itemps & one is spilt
838 and the other is not then false */
839 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
840 sym1->isspilt != sym2->isspilt)
843 /* if they are the same */
847 if (strcmp (sym1->rname, sym2->rname) == 0)
851 /* if left is a tmp & right is not */
852 if (IS_ITEMP (op1) &&
855 (sym1->usl.spillLoc == sym2))
858 if (IS_ITEMP (op2) &&
862 (sym2->usl.spillLoc == sym1))
868 /*-----------------------------------------------------------------*/
869 /* sameRegs - two asmops have the same registers */
870 /*-----------------------------------------------------------------*/
872 sameRegs (asmop * aop1, asmop * aop2)
878 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
885 if (aop1->type != AOP_REG ||
886 aop2->type != AOP_REG)
889 if (aop1->size != aop2->size)
892 for (i = 0; i < aop1->size; i++)
893 if (aop1->aopu.aop_reg[i] !=
894 aop2->aopu.aop_reg[i])
900 /*-----------------------------------------------------------------*/
901 /* aopOp - allocates an asmop for an operand : */
902 /*-----------------------------------------------------------------*/
904 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
913 /* if this a literal */
914 if (IS_OP_LITERAL (op))
916 op->aop = aop = newAsmop (AOP_LIT);
917 aop->aopu.aop_lit = op->operand.valOperand;
918 aop->size = getSize (operandType (op));
922 /* if already has a asmop then continue */
926 /* if the underlying symbol has a aop */
927 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
929 op->aop = OP_SYMBOL (op)->aop;
933 /* if this is a true symbol */
934 if (IS_TRUE_SYMOP (op))
936 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
940 /* this is a temporary : this has
946 e) can be a return use only */
948 sym = OP_SYMBOL (op);
951 /* if the type is a conditional */
952 if (sym->regType == REG_CND)
954 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
959 /* if it is spilt then two situations
961 b) has a spill location */
962 if (sym->isspilt || sym->nRegs == 0)
965 /* rematerialize it NOW */
968 sym->aop = op->aop = aop =
970 aop->size = getSize (sym->type);
977 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
978 aop->size = getSize (sym->type);
979 for (i = 0; i < 2; i++)
980 aop->aopu.aop_str[i] = accUse[i];
990 /* a AOP_STR uses DPTR, but DPTR is already in use;
993 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"AOP_STR with DPTR in use!");
996 aop = op->aop = sym->aop = newAsmop (AOP_STR);
997 aop->size = getSize (sym->type);
998 for (i = 0; i < (int) fReturnSizeDS390; i++)
999 aop->aopu.aop_str[i] = fReturn[i];
1003 if (sym->dptr) { /* has been allocated to a DPTRn */
1004 aop = op->aop = sym->aop = newAsmop (AOP_DPTRn);
1005 aop->size = getSize (sym->type);
1006 aop->aopu.dptr = sym->dptr;
1010 if (sym->usl.spillLoc)
1012 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1014 /* force a new aop if sizes differ */
1015 sym->usl.spillLoc->aop = NULL;
1017 sym->aop = op->aop = aop =
1018 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
1019 aop->size = getSize (sym->type);
1023 /* else must be a dummy iTemp */
1024 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1025 aop->size = getSize (sym->type);
1029 /* must be in a register */
1030 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1031 aop->size = sym->nRegs;
1032 for (i = 0; i < sym->nRegs; i++)
1033 aop->aopu.aop_reg[i] = sym->regs[i];
1036 /*-----------------------------------------------------------------*/
1037 /* freeAsmop - free up the asmop given to an operand */
1038 /*----------------------------------------------------------------*/
1040 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1057 /* depending on the asmop type only three cases need work AOP_RO
1058 , AOP_R1 && AOP_STK */
1066 emitcode ("pop", "ar0");
1070 bitVectUnSetBit (ic->rUsed, R0_IDX);
1078 emitcode ("pop", "ar1");
1082 bitVectUnSetBit (ic->rUsed, R1_IDX);
1088 int stk = aop->aopu.aop_stk + aop->size;
1089 bitVectUnSetBit (ic->rUsed, R0_IDX);
1090 bitVectUnSetBit (ic->rUsed, R1_IDX);
1092 getFreePtr (ic, &aop, FALSE);
1094 if (options.stack10bit)
1096 /* I'm not sure what to do here yet... */
1099 "*** Warning: probably generating bad code for "
1100 "10 bit stack mode.\n");
1105 emitcode ("mov", "a,_bp");
1106 emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
1107 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1111 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1116 emitcode ("pop", "acc");
1117 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1120 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1123 freeAsmop (op, NULL, ic, TRUE);
1126 emitcode ("pop", "ar0");
1132 emitcode ("pop", "ar1");
1137 if (_G.dptr1InUse) {
1138 emitcode ("pop","dpx1");
1139 emitcode ("pop","dph1");
1140 emitcode ("pop","dpl1");
1145 emitcode ("pop","dpx");
1146 emitcode ("pop","dph");
1147 emitcode ("pop","dpl");
1152 /* all other cases just dealloc */
1158 OP_SYMBOL (op)->aop = NULL;
1159 /* if the symbol has a spill */
1161 SPIL_LOC (op)->aop = NULL;
1166 #define DEFAULT_ACC_WARNING 0
1167 static int saveAccWarn = DEFAULT_ACC_WARNING;
1169 /*-------------------------------------------------------------------*/
1170 /* aopGet - for fetching value of the aop */
1172 /* Set saveAcc to NULL if you are sure it is OK to clobber the value */
1173 /* in the accumulator. Set it to the name of a free register */
1174 /* if acc must be preserved; the register will be used to preserve */
1175 /* acc temporarily and to return the result byte. */
1176 /*-------------------------------------------------------------------*/
1185 /* offset is greater than
1187 if (offset > (aop->size - 1) &&
1188 aop->type != AOP_LIT)
1191 /* depending on type */
1199 /* if we need to increment it */
1200 while (offset > aop->coff)
1202 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1206 while (offset < aop->coff)
1208 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1215 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1216 return (dname ? "acc" : "a");
1218 SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1219 return Safe_strdup(buffer);
1222 assert(offset <= 3);
1223 return dptrn[aop->aopu.dptr][offset];
1228 if (aop->type == AOP_DPTR2)
1236 // if (aop->type != AOP_DPTR2)
1238 // if (saveAccWarn) { fprintf(stderr, "saveAcc for DPTR...\n"); }
1239 // emitcode(";", "spanky: saveAcc for DPTR");
1242 emitcode ("xch", "a, %s", saveAcc);
1247 while (offset > aop->coff)
1249 emitcode ("inc", "dptr");
1253 while (offset < aop->coff)
1255 emitcode ("lcall", "__decdptr");
1262 emitcode ("clr", "a");
1263 emitcode ("movc", "a,@a+dptr");
1267 emitcode ("movx", "a,@dptr");
1270 if (aop->type == AOP_DPTR2)
1278 emitcode ("xch", "a, %s", saveAcc);
1279 // if (strcmp(saveAcc, "_ap"))
1281 // emitcode(";", "spiffy: non _ap return from aopGet.");
1286 return (dname ? "acc" : "a");
1289 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1291 SNPRINTF(buffer, sizeof(buffer),
1292 "%s",aop->aopu.aop_immd.aop_immd2);
1296 SNPRINTF(buffer, sizeof(buffer),
1297 "#%s", aop->aopu.aop_immd.aop_immd1);
1303 tsprintf(buffer, sizeof(buffer),
1304 "#!his",aop->aopu.aop_immd.aop_immd1);
1307 tsprintf(buffer, sizeof(buffer),
1308 "#!hihis",aop->aopu.aop_immd.aop_immd1);
1311 tsprintf(buffer, sizeof(buffer),
1312 "#!hihihis",aop->aopu.aop_immd.aop_immd1);
1314 default: /* should not need this (just in case) */
1315 SNPRINTF (buffer, sizeof(buffer),
1317 aop->aopu.aop_immd.aop_immd1,
1323 SNPRINTF (buffer, sizeof(buffer),
1324 "#%s", aop->aopu.aop_immd.aop_immd1);
1326 return Safe_strdup(buffer);
1331 SNPRINTF (buffer, sizeof(buffer),
1338 SNPRINTF(buffer, sizeof(buffer),
1339 "%s", aop->aopu.aop_dir);
1342 return Safe_strdup(buffer);
1346 return aop->aopu.aop_reg[offset]->dname;
1348 return aop->aopu.aop_reg[offset]->name;
1351 emitcode ("clr", "a");
1352 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1353 emitcode ("rlc", "a");
1354 return (dname ? "acc" : "a");
1357 if (!offset && dname)
1359 return aop->aopu.aop_str[offset];
1362 return aopLiteral (aop->aopu.aop_lit, offset);
1366 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1370 return aop->aopu.aop_str[offset];
1374 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1375 "aopget got unsupported aop->type");
1378 return NULL; // not reached, but makes compiler happy.
1380 /*-----------------------------------------------------------------*/
1381 /* aopPut - puts a string for a aop */
1382 /*-----------------------------------------------------------------*/
1384 aopPut (asmop * aop, char *s, int offset)
1386 if (aop->size && offset > (aop->size - 1))
1388 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1389 "aopPut got offset > aop->size");
1393 /* will assign value to value */
1394 /* depending on where it is ofcourse */
1398 MOVA (s); /* read s in case it was volatile */
1404 SNPRINTF (buffer, sizeof(buffer),
1406 aop->aopu.aop_dir, offset);
1410 SNPRINTF (buffer, sizeof(buffer),
1411 "%s", aop->aopu.aop_dir);
1415 if (strcmp (buffer, s))
1417 emitcode ("mov", "%s,%s", buffer, s);
1422 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1423 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1426 strcmp (s, "r0") == 0 ||
1427 strcmp (s, "r1") == 0 ||
1428 strcmp (s, "r2") == 0 ||
1429 strcmp (s, "r3") == 0 ||
1430 strcmp (s, "r4") == 0 ||
1431 strcmp (s, "r5") == 0 ||
1432 strcmp (s, "r6") == 0 ||
1433 strcmp (s, "r7") == 0)
1435 emitcode ("mov", "%s,%s",
1436 aop->aopu.aop_reg[offset]->dname, s);
1440 emitcode ("mov", "%s,%s",
1441 aop->aopu.aop_reg[offset]->name, s);
1447 emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1453 if (aop->type == AOP_DPTR2)
1461 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1462 "aopPut writting to code space");
1466 while (offset > aop->coff)
1469 emitcode ("inc", "dptr");
1472 while (offset < aop->coff)
1475 emitcode ("lcall", "__decdptr");
1480 /* if not in accumulater */
1483 emitcode ("movx", "@dptr,a");
1485 if (aop->type == AOP_DPTR2)
1493 while (offset > aop->coff)
1496 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1498 while (offset < aop->coff)
1501 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1508 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1514 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1516 else if (strcmp (s, "r0") == 0 ||
1517 strcmp (s, "r1") == 0 ||
1518 strcmp (s, "r2") == 0 ||
1519 strcmp (s, "r3") == 0 ||
1520 strcmp (s, "r4") == 0 ||
1521 strcmp (s, "r5") == 0 ||
1522 strcmp (s, "r6") == 0 ||
1523 strcmp (s, "r7") == 0)
1526 SNPRINTF(buff, sizeof(buff),
1528 emitcode ("mov", "@%s,%s",
1529 aop->aopu.aop_ptr->name, buff);
1533 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1538 if (strcmp (s, "a") == 0)
1539 emitcode ("push", "acc");
1543 emitcode ("push", "acc");
1545 emitcode ("push", s);
1551 /* if bit variable */
1552 if (!aop->aopu.aop_dir)
1554 emitcode ("clr", "a");
1555 emitcode ("rlc", "a");
1560 emitcode ("clr", "%s", aop->aopu.aop_dir);
1562 emitcode ("setb", "%s", aop->aopu.aop_dir);
1563 else if (!strcmp (s, "c"))
1564 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1567 if (strcmp (s, "a"))
1572 /* set C, if a >= 1 */
1573 emitcode ("add", "a,#!constbyte",0xff);
1574 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1582 if (strcmp (aop->aopu.aop_str[offset], s))
1583 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1588 if (!offset && (strcmp (s, "acc") == 0))
1591 if (strcmp (aop->aopu.aop_str[offset], s))
1592 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1596 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1597 "aopPut got unsupported aop->type");
1604 /*--------------------------------------------------------------------*/
1605 /* reAdjustPreg - points a register back to where it should (coff==0) */
1606 /*--------------------------------------------------------------------*/
1608 reAdjustPreg (asmop * aop)
1610 if ((aop->coff==0) || (aop->size <= 1)) {
1619 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1623 if (aop->type == AOP_DPTR2)
1630 emitcode ("lcall", "__decdptr");
1633 if (aop->type == AOP_DPTR2)
1643 #define AOP(op) op->aop
1644 #define AOP_TYPE(op) AOP(op)->type
1645 #define AOP_SIZE(op) AOP(op)->size
1646 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1647 AOP_TYPE(x) == AOP_R0))
1649 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1650 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1653 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1654 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1655 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1656 #define AOP_INDPTRn(x) (AOP_TYPE(x) == AOP_DPTRn)
1657 #define AOP_USESDPTR(x) ((AOP_TYPE(x) == AOP_DPTR) || (AOP_TYPE(x) == AOP_STR))
1658 #define AOP_USESDPTR2(x) ((AOP_TYPE(x) == AOP_DPTR2) || (AOP_TYPE(x) == AOP_DPTRn))
1660 // The following two macros can be used even if the aop has not yet been aopOp'd.
1661 #define AOP_IS_STR(x) (IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
1662 #define AOP_IS_DPTRn(x) (IS_SYMOP(x) && OP_SYMBOL(x)->dptr)
1664 /* Workaround for DS80C390 bug: div ab may return bogus results
1665 * if A is accessed in instruction immediately before the div.
1667 * Will be fixed in B4 rev of processor, Dallas claims.
1670 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1671 if (!AOP_NEEDSACC(RIGHT)) \
1673 /* We can load A first, then B, since \
1674 * B (the RIGHT operand) won't clobber A, \
1675 * thus avoiding touching A right before the div. \
1677 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1678 L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL); \
1680 L = aopGet(AOP(RIGHT),0,FALSE,FALSE,"b"); \
1685 /* Just stuff in a nop after loading A. */ \
1686 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,NULL));\
1687 L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL); \
1689 emitcode("nop", "; workaround for DS80C390 div bug."); \
1693 /*-----------------------------------------------------------------*/
1694 /* opIsGptr: returns non-zero if the passed operand is */
1695 /* a generic pointer type. */
1696 /*-----------------------------------------------------------------*/
1698 opIsGptr (operand * op)
1700 sym_link *type = operandType (op);
1702 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1709 /*-----------------------------------------------------------------*/
1710 /* getDataSize - get the operand data size */
1711 /*-----------------------------------------------------------------*/
1713 getDataSize (operand * op)
1716 size = AOP_SIZE (op);
1717 if (size == GPTRSIZE)
1719 sym_link *type = operandType (op);
1720 if (IS_GENPTR (type))
1722 /* generic pointer; arithmetic operations
1723 * should ignore the high byte (pointer type).
1731 /*-----------------------------------------------------------------*/
1732 /* outAcc - output Acc */
1733 /*-----------------------------------------------------------------*/
1735 outAcc (operand * result)
1738 size = getDataSize (result);
1741 aopPut (AOP (result), "a", 0);
1744 /* unsigned or positive */
1747 aopPut (AOP (result), zero, offset++);
1752 /*-----------------------------------------------------------------*/
1753 /* outBitC - output a bit C */
1754 /*-----------------------------------------------------------------*/
1756 outBitC (operand * result)
1758 /* if the result is bit */
1759 if (AOP_TYPE (result) == AOP_CRY)
1761 aopPut (AOP (result), "c", 0);
1765 emitcode ("clr", "a");
1766 emitcode ("rlc", "a");
1771 /*-----------------------------------------------------------------*/
1772 /* toBoolean - emit code for orl a,operator(sizeop) */
1773 /*-----------------------------------------------------------------*/
1775 toBoolean (operand * oper)
1777 int size = AOP_SIZE (oper) - 1;
1781 /* The generic part of a generic pointer should
1782 * not participate in it's truth value.
1784 * i.e. 0x10000000 is zero.
1786 if (opIsGptr (oper))
1788 D (emitcode (";", "toBoolean: generic ptr special case."););
1792 _startLazyDPSEvaluation ();
1793 if (AOP_NEEDSACC (oper) && size)
1798 emitcode ("push", "b");
1800 MOVB (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1804 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1811 emitcode ("orl", "b,%s",
1812 aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1816 emitcode ("orl", "a,%s",
1817 aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1820 _endLazyDPSEvaluation ();
1824 emitcode ("mov", "a,b");
1827 emitcode ("pop", "b");
1834 /*-----------------------------------------------------------------*/
1835 /* genNot - generate code for ! operation */
1836 /*-----------------------------------------------------------------*/
1842 D (emitcode (";", "genNot "););
1844 /* assign asmOps to operand & result */
1845 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1846 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1848 /* if in bit space then a special case */
1849 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1851 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1852 emitcode ("cpl", "c");
1853 outBitC (IC_RESULT (ic));
1857 toBoolean (IC_LEFT (ic));
1859 tlbl = newiTempLabel (NULL);
1860 emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1861 emitcode ("", "!tlabeldef", tlbl->key + 100);
1862 outBitC (IC_RESULT (ic));
1865 /* release the aops */
1866 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1867 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1871 /*-----------------------------------------------------------------*/
1872 /* genCpl - generate code for complement */
1873 /*-----------------------------------------------------------------*/
1881 D (emitcode (";", "genCpl "););
1884 /* assign asmOps to operand & result */
1885 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1886 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1888 /* special case if in bit space */
1889 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1890 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1891 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1892 emitcode ("cpl", "c");
1893 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1896 tlbl=newiTempLabel(NULL);
1897 emitcode ("cjne", "%s,#0x01,%05d$",
1898 aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE,NULL), tlbl->key+100);
1899 emitcode ("", "%05d$:", tlbl->key+100);
1900 outBitC (IC_RESULT(ic));
1904 size = AOP_SIZE (IC_RESULT (ic));
1905 _startLazyDPSEvaluation ();
1908 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
1909 emitcode ("cpl", "a");
1910 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1912 _endLazyDPSEvaluation ();
1916 /* release the aops */
1917 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1918 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1921 /*-----------------------------------------------------------------*/
1922 /* genUminusFloat - unary minus for floating points */
1923 /*-----------------------------------------------------------------*/
1925 genUminusFloat (operand * op, operand * result)
1927 int size, offset = 0;
1929 D(emitcode (";", "genUminusFloat"););
1931 /* for this we just copy and then flip the bit */
1933 _startLazyDPSEvaluation ();
1934 size = AOP_SIZE (op) - 1;
1938 aopPut (AOP (result),
1939 aopGet (AOP (op), offset, FALSE, FALSE, NULL),
1944 MOVA(aopGet (AOP (op), offset, FALSE, FALSE, NULL));
1946 emitcode ("cpl", "acc.7");
1947 aopPut (AOP (result), "a", offset);
1948 _endLazyDPSEvaluation ();
1951 /*-----------------------------------------------------------------*/
1952 /* genUminus - unary minus code generation */
1953 /*-----------------------------------------------------------------*/
1955 genUminus (iCode * ic)
1960 D (emitcode (";", "genUminus "););
1963 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1964 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1966 /* if both in bit space then special
1968 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1969 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1972 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1973 emitcode ("cpl", "c");
1974 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1978 optype = operandType (IC_LEFT (ic));
1980 /* if float then do float stuff */
1981 if (IS_FLOAT (optype))
1983 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1987 /* otherwise subtract from zero */
1988 size = AOP_SIZE (IC_LEFT (ic));
1990 _startLazyDPSEvaluation ();
1993 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL);
1994 if (!strcmp (l, "a"))
1998 emitcode ("cpl", "a");
1999 emitcode ("addc", "a,#0");
2005 emitcode ("clr", "a");
2006 emitcode ("subb", "a,%s", l);
2008 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2010 _endLazyDPSEvaluation ();
2012 /* if any remaining bytes in the result */
2013 /* we just need to propagate the sign */
2014 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic)))) != 0)
2016 emitcode ("rlc", "a");
2017 emitcode ("subb", "a,acc");
2019 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2023 /* release the aops */
2024 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2025 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2028 /*-----------------------------------------------------------------*/
2029 /* savermask - saves registers in the mask */
2030 /*-----------------------------------------------------------------*/
2031 static void savermask(bitVect *rs_mask)
2034 if (options.useXstack) {
2035 if (bitVectBitValue (rs_mask, R0_IDX))
2036 emitcode ("mov", "b,r0");
2037 emitcode ("mov", "r0,%s", spname);
2038 for (i = 0; i < ds390_nRegs; i++) {
2039 if (bitVectBitValue (rs_mask, i)) {
2041 emitcode ("mov", "a,b");
2043 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
2044 emitcode ("movx", "@r0,a");
2045 emitcode ("inc", "r0");
2048 emitcode ("mov", "%s,r0", spname);
2049 if (bitVectBitValue (rs_mask, R0_IDX))
2050 emitcode ("mov", "r0,b");
2052 for (i = 0; i < ds390_nRegs; i++) {
2053 if (bitVectBitValue (rs_mask, i))
2054 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2059 /*-----------------------------------------------------------------*/
2060 /* saveRegisters - will look for a call and save the registers */
2061 /*-----------------------------------------------------------------*/
2063 saveRegisters (iCode * lic)
2069 for (ic = lic; ic; ic = ic->next)
2070 if (ic->op == CALL || ic->op == PCALL)
2075 fprintf (stderr, "found parameter push with no function call\n");
2079 /* if the registers have been saved already then
2082 || (IS_SYMOP(IC_LEFT(ic)) && IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))) && !TARGET_IS_DS400) )
2085 /* special case if DPTR alive across a function call then must save it
2086 even though callee saves */
2087 if (IS_SYMOP(IC_LEFT(ic)) &&
2088 IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2090 rsave = newBitVect(ic->rMask->size);
2091 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2092 if (bitVectBitValue(ic->rMask,i))
2093 rsave = bitVectSetBit(rsave,i);
2095 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2097 /* safe the registers in use at this time but skip the
2098 ones for the result */
2099 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2100 ds390_rUmaskForOp (IC_RESULT(ic)));
2106 /*-----------------------------------------------------------------*/
2107 /* usavermask - restore registers with mask */
2108 /*-----------------------------------------------------------------*/
2109 static void unsavermask(bitVect *rs_mask)
2112 if (options.useXstack) {
2113 emitcode ("mov", "r0,%s", spname);
2114 for (i = ds390_nRegs; i >= 0; i--) {
2115 if (bitVectBitValue (rs_mask, i)) {
2116 emitcode ("dec", "r0");
2117 emitcode ("movx", "a,@r0");
2119 emitcode ("mov", "b,a");
2121 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
2124 emitcode ("mov", "%s,r0", spname);
2125 if (bitVectBitValue (rs_mask, R0_IDX))
2126 emitcode ("mov", "r0,b");
2128 for (i = ds390_nRegs; i >= 0; i--) {
2129 if (bitVectBitValue (rs_mask, i))
2130 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2135 /*-----------------------------------------------------------------*/
2136 /* unsaveRegisters - pop the pushed registers */
2137 /*-----------------------------------------------------------------*/
2139 unsaveRegisters (iCode * ic)
2143 if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2145 rsave = newBitVect(ic->rMask->size);
2146 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2147 if (bitVectBitValue(ic->rMask,i))
2148 rsave = bitVectSetBit(rsave,i);
2150 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2152 /* restore the registers in use at this time but skip the
2153 ones for the result */
2154 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2155 ds390_rUmaskForOp (IC_RESULT(ic)));
2161 /*-----------------------------------------------------------------*/
2163 /*-----------------------------------------------------------------*/
2165 pushSide (operand * oper, int size)
2168 _startLazyDPSEvaluation ();
2171 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, NULL);
2172 if (AOP_TYPE (oper) != AOP_REG &&
2173 AOP_TYPE (oper) != AOP_DIR &&
2176 emitcode ("mov", "a,%s", l);
2177 emitcode ("push", "acc");
2180 emitcode ("push", "%s", l);
2182 _endLazyDPSEvaluation ();
2185 /*-----------------------------------------------------------------*/
2186 /* assignResultValue - */
2187 /*-----------------------------------------------------------------*/
2189 assignResultValue (operand * oper)
2192 int size = AOP_SIZE (oper);
2193 bool pushedAcc = FALSE;
2195 if (size == fReturnSizeDS390)
2197 /* I don't think this case can ever happen... */
2198 /* ACC is the last part of this. If writing the result
2199 * uses AC, we must preserve it.
2201 if (AOP_NEEDSACC(oper))
2203 emitcode(";", "assignResultValue special case for ACC.");
2204 emitcode("push", "acc");
2211 _startLazyDPSEvaluation ();
2214 aopPut (AOP (oper), fReturn[offset], offset);
2217 _endLazyDPSEvaluation ();
2221 emitcode("pop", "acc");
2222 aopPut(AOP(oper), "a", offset);
2227 /*-----------------------------------------------------------------*/
2228 /* genXpush - pushes onto the external stack */
2229 /*-----------------------------------------------------------------*/
2231 genXpush (iCode * ic)
2233 asmop *aop = newAsmop (0);
2235 int size, offset = 0;
2237 D (emitcode (";", "genXpush ");
2240 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2241 r = getFreePtr (ic, &aop, FALSE);
2244 emitcode ("mov", "%s,_spx", r->name);
2246 size = AOP_SIZE (IC_LEFT (ic));
2247 _startLazyDPSEvaluation ();
2251 MOVA (aopGet (AOP (IC_LEFT (ic)),
2252 offset++, FALSE, FALSE, NULL));
2253 emitcode ("movx", "@%s,a", r->name);
2254 emitcode ("inc", "%s", r->name);
2257 _endLazyDPSEvaluation ();
2260 emitcode ("mov", "_spx,%s", r->name);
2262 freeAsmop (NULL, aop, ic, TRUE);
2263 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2266 /*-----------------------------------------------------------------*/
2267 /* genIpush - generate code for pushing this gets a little complex */
2268 /*-----------------------------------------------------------------*/
2270 genIpush (iCode * ic)
2272 int size, offset = 0;
2275 D (emitcode (";", "genIpush ");
2278 /* if this is not a parm push : ie. it is spill push
2279 and spill push is always done on the local stack */
2283 /* and the item is spilt then do nothing */
2284 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2287 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2288 size = AOP_SIZE (IC_LEFT (ic));
2289 /* push it on the stack */
2290 _startLazyDPSEvaluation ();
2293 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2299 emitcode ("push", "%s", l);
2301 _endLazyDPSEvaluation ();
2305 /* this is a paramter push: in this case we call
2306 the routine to find the call and save those
2307 registers that need to be saved */
2310 /* if use external stack then call the external
2311 stack pushing routine */
2312 if (options.useXstack)
2318 /* then do the push */
2319 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2321 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2322 size = AOP_SIZE (IC_LEFT (ic));
2324 _startLazyDPSEvaluation ();
2327 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2328 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2329 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2332 emitcode ("mov", "a,%s", l);
2333 emitcode ("push", "acc");
2337 emitcode ("push", "%s", l);
2340 _endLazyDPSEvaluation ();
2342 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2345 /*-----------------------------------------------------------------*/
2346 /* genIpop - recover the registers: can happen only for spilling */
2347 /*-----------------------------------------------------------------*/
2349 genIpop (iCode * ic)
2353 D (emitcode (";", "genIpop ");
2357 /* if the temp was not pushed then */
2358 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2361 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2362 size = AOP_SIZE (IC_LEFT (ic));
2363 offset = (size - 1);
2364 _startLazyDPSEvaluation ();
2367 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2368 FALSE, TRUE, NULL));
2370 _endLazyDPSEvaluation ();
2372 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2375 /*-----------------------------------------------------------------*/
2376 /* unsaveRBank - restores the resgister bank from stack */
2377 /*-----------------------------------------------------------------*/
2379 unsaveRBank (int bank, iCode * ic, bool popPsw)
2385 if (options.useXstack)
2389 /* Assume r0 is available for use. */
2390 r = ds390_regWithIdx (R0_IDX);;
2395 r = getFreePtr (ic, &aop, FALSE);
2397 emitcode ("mov", "%s,_spx", r->name);
2402 if (options.useXstack)
2404 emitcode ("movx", "a,@%s", r->name);
2405 emitcode ("mov", "psw,a");
2406 emitcode ("dec", "%s", r->name);
2410 emitcode ("pop", "psw");
2414 for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2416 if (options.useXstack)
2418 emitcode ("movx", "a,@%s", r->name);
2419 emitcode ("mov", "(%s+%d),a",
2420 regs390[i].base, 8 * bank + regs390[i].offset);
2421 emitcode ("dec", "%s", r->name);
2425 emitcode ("pop", "(%s+%d)",
2426 regs390[i].base, 8 * bank + regs390[i].offset);
2429 if (options.useXstack)
2431 emitcode ("mov", "_spx,%s", r->name);
2436 freeAsmop (NULL, aop, ic, TRUE);
2440 /*-----------------------------------------------------------------*/
2441 /* saveRBank - saves an entire register bank on the stack */
2442 /*-----------------------------------------------------------------*/
2444 saveRBank (int bank, iCode * ic, bool pushPsw)
2450 if (options.useXstack)
2454 /* Assume r0 is available for use. */
2455 r = ds390_regWithIdx (R0_IDX);;
2460 r = getFreePtr (ic, &aop, FALSE);
2462 emitcode ("mov", "%s,_spx", r->name);
2465 for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2467 if (options.useXstack)
2469 emitcode ("inc", "%s", r->name);
2470 emitcode ("mov", "a,(%s+%d)",
2471 regs390[i].base, 8 * bank + regs390[i].offset);
2472 emitcode ("movx", "@%s,a", r->name);
2475 emitcode ("push", "(%s+%d)",
2476 regs390[i].base, 8 * bank + regs390[i].offset);
2481 if (options.useXstack)
2483 emitcode ("mov", "a,psw");
2484 emitcode ("movx", "@%s,a", r->name);
2485 emitcode ("inc", "%s", r->name);
2486 emitcode ("mov", "_spx,%s", r->name);
2490 emitcode ("push", "psw");
2493 emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2498 freeAsmop (NULL, aop, ic, TRUE);
2507 /*-----------------------------------------------------------------*/
2508 /* genSend - gen code for SEND */
2509 /*-----------------------------------------------------------------*/
2510 static void genSend(set *sendSet)
2514 static int rb1_count = 0;
2516 for (sic = setFirstItem (sendSet); sic;
2517 sic = setNextItem (sendSet)) {
2518 int size, offset = 0;
2520 size=getSize(operandType(IC_LEFT(sic)));
2521 D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2522 if (sendCount == 0) { /* first parameter */
2523 // we know that dpl(hxb) is the result, so
2525 _startLazyDPSEvaluation ();
2527 aopOp (IC_LEFT (sic), sic, FALSE,
2528 (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2530 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2533 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2534 FALSE, FALSE, NULL);
2535 if (strcmp (l, fReturn[offset])) {
2536 emitcode ("mov", "%s,%s",
2542 _endLazyDPSEvaluation ();
2543 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2545 } else { /* if more parameter in registers */
2546 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2548 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
2549 FALSE, FALSE, NULL));
2551 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2558 adjustEsp(const char *reg)
2560 emitcode ("anl","%s,#3", reg);
2561 if (TARGET_IS_DS400)
2563 emitcode ("orl","%s,#!constbyte",
2565 (options.stack_loc >> 8) & 0xff);
2569 /*-----------------------------------------------------------------*/
2570 /* genCall - generates a call statement */
2571 /*-----------------------------------------------------------------*/
2573 genCall (iCode * ic)
2576 bool restoreBank = FALSE;
2577 bool swapBanks = FALSE;
2579 D (emitcode (";", "genCall "););
2581 /* if we are calling a not _naked function that is not using
2582 the same register bank then we need to save the
2583 destination registers on the stack */
2584 dtype = operandType (IC_LEFT (ic));
2585 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2586 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2587 IFFUNC_ISISR (currFunc->type))
2591 /* This is unexpected; the bank should have been saved in
2594 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2600 /* if caller saves & we have not saved then */
2604 /* if send set is not empty the assign */
2605 /* We've saved all the registers we care about;
2606 * therefore, we may clobber any register not used
2607 * in the calling convention (i.e. anything not in
2612 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2613 genSend(reverseSet(_G.sendSet));
2615 genSend(_G.sendSet);
2622 emitcode ("mov", "psw,#!constbyte",
2623 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2627 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2628 OP_SYMBOL (IC_LEFT (ic))->rname :
2629 OP_SYMBOL (IC_LEFT (ic))->name));
2633 emitcode ("mov", "psw,#!constbyte",
2634 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2637 /* if we need assign a result value */
2638 if ((IS_ITEMP (IC_RESULT (ic)) &&
2639 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2640 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2641 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2642 IS_TRUE_SYMOP (IC_RESULT (ic)))
2644 if (isOperandInFarSpace (IC_RESULT (ic))
2645 && getSize (operandType (IC_RESULT (ic))) <= 2)
2647 int size = getSize (operandType (IC_RESULT (ic)));
2649 /* Special case for 1 or 2 byte return in far space. */
2653 emitcode ("mov", "b,%s", fReturn[1]);
2656 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2657 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2661 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2663 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2668 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2671 assignResultValue (IC_RESULT (ic));
2673 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2677 /* adjust the stack for parameters if
2679 if (ic->parmBytes) {
2681 if (options.stack10bit) {
2682 if (ic->parmBytes <= 10) {
2683 emitcode(";","stack adjustment for parms");
2684 for (i=0; i < ic->parmBytes ; i++) {
2685 emitcode("pop","acc");
2689 emitcode ("clr","c");
2690 emitcode ("mov","a,sp");
2691 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2692 emitcode ("mov","sp,a");
2693 emitcode ("mov","a,esp");
2695 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2696 emitcode ("mov","esp,a");
2700 if (ic->parmBytes > 3) {
2701 emitcode ("mov", "a,%s", spname);
2702 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2703 emitcode ("mov", "%s,a", spname);
2705 for (i = 0; i < ic->parmBytes; i++)
2706 emitcode ("dec", "%s", spname);
2710 /* if we hade saved some registers then unsave them */
2712 unsaveRegisters (ic);
2714 /* if register bank was saved then pop them */
2716 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2719 /*-----------------------------------------------------------------*/
2720 /* genPcall - generates a call by pointer statement */
2721 /*-----------------------------------------------------------------*/
2723 genPcall (iCode * ic)
2726 symbol *rlbl = newiTempLabel (NULL);
2727 bool restoreBank=FALSE;
2729 D (emitcode (";", "genPcall ");
2733 /* if caller saves & we have not saved then */
2737 /* if we are calling a function that is not using
2738 the same register bank then we need to save the
2739 destination registers on the stack */
2740 dtype = operandType (IC_LEFT (ic));
2741 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2742 IFFUNC_ISISR (currFunc->type) &&
2743 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2744 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2748 /* push the return address on to the stack */
2749 emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2750 emitcode ("push", "acc");
2751 emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2752 emitcode ("push", "acc");
2754 if (options.model == MODEL_FLAT24)
2756 emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2757 emitcode ("push", "acc");
2760 /* now push the calling address */
2761 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2763 pushSide (IC_LEFT (ic), FPTRSIZE);
2765 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2767 /* if send set is not empty the assign */
2770 genSend(reverseSet(_G.sendSet));
2774 emitcode ("ret", "");
2775 emitcode ("", "!tlabeldef", (rlbl->key + 100));
2778 /* if we need assign a result value */
2779 if ((IS_ITEMP (IC_RESULT (ic)) &&
2780 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2781 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2782 IS_TRUE_SYMOP (IC_RESULT (ic)))
2786 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2789 assignResultValue (IC_RESULT (ic));
2791 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2794 /* adjust the stack for parameters if
2799 if (options.stack10bit) {
2800 if (ic->parmBytes <= 10) {
2801 emitcode(";","stack adjustment for parms");
2802 for (i=0; i < ic->parmBytes ; i++) {
2803 emitcode("pop","acc");
2807 emitcode ("clr","c");
2808 emitcode ("mov","a,sp");
2809 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2810 emitcode ("mov","sp,a");
2811 emitcode ("mov","a,esp");
2813 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2814 emitcode ("mov","esp,a");
2818 if (ic->parmBytes > 3) {
2819 emitcode ("mov", "a,%s", spname);
2820 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2821 emitcode ("mov", "%s,a", spname);
2824 for (i = 0; i < ic->parmBytes; i++)
2825 emitcode ("dec", "%s", spname);
2829 /* if register bank was saved then unsave them */
2831 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2833 /* if we hade saved some registers then
2836 unsaveRegisters (ic);
2840 /*-----------------------------------------------------------------*/
2841 /* resultRemat - result is rematerializable */
2842 /*-----------------------------------------------------------------*/
2844 resultRemat (iCode * ic)
2846 if (SKIP_IC (ic) || ic->op == IFX)
2849 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2851 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2852 if (sym->remat && !POINTER_SET (ic))
2859 #if defined(__BORLANDC__) || defined(_MSC_VER)
2860 #define STRCASECMP stricmp
2862 #define STRCASECMP strcasecmp
2865 /*-----------------------------------------------------------------*/
2866 /* inExcludeList - return 1 if the string is in exclude Reg list */
2867 /*-----------------------------------------------------------------*/
2869 regsCmp(void *p1, void *p2)
2871 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2875 inExcludeList (char *s)
2877 const char *p = setFirstItem(options.excludeRegsSet);
2879 if (p == NULL || STRCASECMP(p, "none") == 0)
2883 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2886 /*-----------------------------------------------------------------*/
2887 /* genFunction - generated code for function entry */
2888 /*-----------------------------------------------------------------*/
2890 genFunction (iCode * ic)
2894 bool switchedPSW = FALSE;
2896 D (emitcode (";", "genFunction "););
2899 /* create the function header */
2900 emitcode (";", "-----------------------------------------");
2901 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2902 emitcode (";", "-----------------------------------------");
2904 emitcode ("", "%s:", sym->rname);
2905 ftype = operandType (IC_LEFT (ic));
2907 if (IFFUNC_ISNAKED(ftype))
2909 emitcode(";", "naked function: no prologue.");
2913 if (options.stack_probe)
2914 emitcode ("lcall","__stack_probe");
2916 /* here we need to generate the equates for the
2917 register bank if required */
2918 if (FUNC_REGBANK (ftype) != rbank)
2922 rbank = FUNC_REGBANK (ftype);
2923 for (i = 0; i < ds390_nRegs; i++)
2925 if (regs390[i].print) {
2926 if (strcmp (regs390[i].base, "0") == 0)
2927 emitcode ("", "%s !equ !constbyte",
2929 8 * rbank + regs390[i].offset);
2931 emitcode ("", "%s !equ %s + !constbyte",
2934 8 * rbank + regs390[i].offset);
2939 /* if this is an interrupt service routine then
2940 save acc, b, dpl, dph */
2941 if (IFFUNC_ISISR (sym->type))
2943 if (!inExcludeList ("acc"))
2944 emitcode ("push", "acc");
2945 if (!inExcludeList ("b"))
2946 emitcode ("push", "b");
2947 if (!inExcludeList ("dpl"))
2948 emitcode ("push", "dpl");
2949 if (!inExcludeList ("dph"))
2950 emitcode ("push", "dph");
2951 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2953 emitcode ("push", "dpx");
2954 /* Make sure we're using standard DPTR */
2955 emitcode ("push", "dps");
2956 emitcode ("mov", "dps,#0");
2957 if (options.stack10bit)
2959 /* This ISR could conceivably use DPTR2. Better save it. */
2960 emitcode ("push", "dpl1");
2961 emitcode ("push", "dph1");
2962 emitcode ("push", "dpx1");
2963 emitcode ("push", DP2_RESULT_REG);
2966 /* if this isr has no bank i.e. is going to
2967 run with bank 0 , then we need to save more
2969 if (!FUNC_REGBANK (sym->type))
2973 /* if this function does not call any other
2974 function then we can be economical and
2975 save only those registers that are used */
2976 if (!IFFUNC_HASFCALL(sym->type))
2979 /* if any registers used */
2982 /* save the registers used */
2983 for (i = 0; i < sym->regsUsed->size; i++)
2985 if (bitVectBitValue (sym->regsUsed, i) ||
2986 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2987 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2994 /* this function has a function call cannot
2995 determines register usage so we will have to push the
2997 saveRBank (0, ic, FALSE);
2998 if (options.parms_in_bank1) {
2999 for (i=0; i < 8 ; i++ ) {
3000 emitcode ("push","%s",rb1regs[i]);
3007 /* This ISR uses a non-zero bank.
3009 * We assume that the bank is available for our
3012 * However, if this ISR calls a function which uses some
3013 * other bank, we must save that bank entirely.
3015 unsigned long banksToSave = 0;
3017 if (IFFUNC_HASFCALL(sym->type))
3020 #define MAX_REGISTER_BANKS 4
3025 for (i = ic; i; i = i->next)
3027 if (i->op == ENDFUNCTION)
3029 /* we got to the end OK. */
3037 dtype = operandType (IC_LEFT(i));
3039 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3041 /* Mark this bank for saving. */
3042 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3044 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3048 banksToSave |= (1 << FUNC_REGBANK(dtype));
3051 /* And note that we don't need to do it in
3059 /* This is a mess; we have no idea what
3060 * register bank the called function might
3063 * The only thing I can think of to do is
3064 * throw a warning and hope.
3066 werror(W_FUNCPTR_IN_USING_ISR);
3070 if (banksToSave && options.useXstack)
3072 /* Since we aren't passing it an ic,
3073 * saveRBank will assume r0 is available to abuse.
3075 * So switch to our (trashable) bank now, so
3076 * the caller's R0 isn't trashed.
3078 emitcode ("push", "psw");
3079 emitcode ("mov", "psw,#!constbyte",
3080 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3084 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3086 if (banksToSave & (1 << ix))
3088 saveRBank(ix, NULL, FALSE);
3092 // TODO: this needs a closer look
3093 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3098 /* if callee-save to be used for this function
3099 then save the registers being used in this function */
3100 if (IFFUNC_CALLEESAVES(sym->type))
3104 /* if any registers used */
3107 /* save the registers used */
3108 for (i = 0; i < sym->regsUsed->size; i++)
3110 if (bitVectBitValue (sym->regsUsed, i) ||
3111 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3113 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3121 /* set the register bank to the desired value */
3122 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3125 emitcode ("push", "psw");
3126 emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3129 if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3130 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3131 if (options.stack10bit) {
3132 emitcode ("push","_bpx");
3133 emitcode ("push","_bpx+1");
3134 emitcode ("mov","_bpx,%s",spname);
3135 emitcode ("mov","_bpx+1,esp");
3136 adjustEsp("_bpx+1");
3138 if (options.useXstack) {
3139 emitcode ("mov", "r0,%s", spname);
3140 emitcode ("mov", "a,_bp");
3141 emitcode ("movx", "@r0,a");
3142 emitcode ("inc", "%s", spname);
3144 /* set up the stack */
3145 emitcode ("push", "_bp"); /* save the callers stack */
3147 emitcode ("mov", "_bp,%s", spname);
3151 /* adjust the stack for the function */
3154 if (options.stack10bit) {
3155 if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
3156 assert (sym->recvSize <= 4);
3157 if (sym->stack <= 8) {
3158 while (i--) emitcode ("push","acc");
3161 emitcode ("mov","a,sp");
3162 emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3163 emitcode ("mov","sp,a");
3164 emitcode ("mov","a,esp");
3166 emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3167 emitcode ("mov","esp,a");
3172 werror (W_STACK_OVERFLOW, sym->name);
3174 if (i > 3 && sym->recvSize < 4) {
3176 emitcode ("mov", "a,sp");
3177 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3178 emitcode ("mov", "sp,a");
3182 emitcode ("inc", "sp");
3189 emitcode ("mov", "a,_spx");
3190 emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3191 emitcode ("mov", "_spx,a");
3194 /* if critical function then turn interrupts off */
3195 if (IFFUNC_ISCRITICAL (ftype))
3197 symbol *tlbl = newiTempLabel (NULL);
3198 emitcode ("setb", "c");
3199 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3200 emitcode ("clr", "c");
3201 emitcode ("", "%05d$:", (tlbl->key + 100));
3202 emitcode ("push", "psw"); /* save old ea via c in psw */
3207 /*-----------------------------------------------------------------*/
3208 /* genEndFunction - generates epilogue for functions */
3209 /*-----------------------------------------------------------------*/
3211 genEndFunction (iCode * ic)
3213 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3215 D (emitcode (";", "genEndFunction "););
3217 if (IFFUNC_ISNAKED(sym->type))
3219 emitcode(";", "naked function: no epilogue.");
3223 if (IFFUNC_ISCRITICAL (sym->type))
3225 emitcode ("pop", "psw"); /* restore ea via c in psw */
3226 emitcode ("mov", "ea,c");
3229 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3230 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3232 if (options.stack10bit) {
3234 emitcode ("mov", "sp,_bpx", spname);
3235 emitcode ("mov", "esp,_bpx+1", spname);
3238 emitcode ("mov", "%s,_bp", spname);
3242 /* if use external stack but some variables were
3243 added to the local stack then decrement the
3245 if (options.useXstack && sym->stack) {
3246 emitcode ("mov", "a,sp");
3247 emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3248 emitcode ("mov", "sp,a");
3252 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3253 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3255 if (options.useXstack) {
3256 emitcode ("mov", "r0,%s", spname);
3257 emitcode ("movx", "a,@r0");
3258 emitcode ("mov", "_bp,a");
3259 emitcode ("dec", "%s", spname);
3261 if (options.stack10bit) {
3262 emitcode ("pop", "_bpx+1");
3263 emitcode ("pop", "_bpx");
3265 emitcode ("pop", "_bp");
3270 /* restore the register bank */
3271 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3273 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3274 || !options.useXstack)
3276 /* Special case of ISR using non-zero bank with useXstack
3279 emitcode ("pop", "psw");
3283 if (IFFUNC_ISISR (sym->type))
3286 /* now we need to restore the registers */
3287 /* if this isr has no bank i.e. is going to
3288 run with bank 0 , then we need to save more
3290 if (!FUNC_REGBANK (sym->type))
3293 /* if this function does not call any other
3294 function then we can be economical and
3295 save only those registers that are used */
3296 if (!IFFUNC_HASFCALL(sym->type))
3299 /* if any registers used */
3302 /* save the registers used */
3303 for (i = sym->regsUsed->size; i >= 0; i--)
3305 if (bitVectBitValue (sym->regsUsed, i) ||
3306 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3307 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3314 /* this function has a function call cannot
3315 determines register usage so we will have to pop the
3317 if (options.parms_in_bank1) {
3318 for (i = 7 ; i >= 0 ; i-- ) {
3319 emitcode ("pop","%s",rb1regs[i]);
3322 unsaveRBank (0, ic, FALSE);
3327 /* This ISR uses a non-zero bank.
3329 * Restore any register banks saved by genFunction
3332 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3335 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3337 if (savedBanks & (1 << ix))
3339 unsaveRBank(ix, NULL, FALSE);
3343 if (options.useXstack)
3345 /* Restore bank AFTER calling unsaveRBank,
3346 * since it can trash r0.
3348 emitcode ("pop", "psw");
3352 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3354 if (options.stack10bit)
3356 emitcode ("pop", DP2_RESULT_REG);
3357 emitcode ("pop", "dpx1");
3358 emitcode ("pop", "dph1");
3359 emitcode ("pop", "dpl1");
3361 emitcode ("pop", "dps");
3362 emitcode ("pop", "dpx");
3364 if (!inExcludeList ("dph"))
3365 emitcode ("pop", "dph");
3366 if (!inExcludeList ("dpl"))
3367 emitcode ("pop", "dpl");
3368 if (!inExcludeList ("b"))
3369 emitcode ("pop", "b");
3370 if (!inExcludeList ("acc"))
3371 emitcode ("pop", "acc");
3373 /* if debug then send end of function */
3374 if (options.debug && currFunc) {
3376 emitcode ("", "C$%s$%d$%d$%d ==.",
3377 FileBaseName (ic->filename), currFunc->lastLine,
3378 ic->level, ic->block);
3379 if (IS_STATIC (currFunc->etype))
3380 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3382 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3386 emitcode ("reti", "");
3390 if (IFFUNC_CALLEESAVES(sym->type))
3394 /* if any registers used */
3397 /* save the registers used */
3398 for (i = sym->regsUsed->size; i >= 0; i--)
3400 if (bitVectBitValue (sym->regsUsed, i) ||
3401 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3402 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3408 /* if debug then send end of function */
3409 if (options.debug && currFunc)
3412 emitcode ("", "C$%s$%d$%d$%d ==.",
3413 FileBaseName (ic->filename), currFunc->lastLine,
3414 ic->level, ic->block);
3415 if (IS_STATIC (currFunc->etype))
3416 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3418 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3422 emitcode ("ret", "");
3427 /*-----------------------------------------------------------------*/
3428 /* genJavaNativeRet - generate code for return JavaNative */
3429 /*-----------------------------------------------------------------*/
3430 static void genJavaNativeRet(iCode *ic)
3434 aopOp (IC_LEFT (ic), ic, FALSE,
3435 AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
3436 size = AOP_SIZE (IC_LEFT (ic));
3440 /* it is assigned to GPR0-R3 then push them */
3441 if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3442 aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3443 for (i = 0 ; i < size ; i++ ) {
3444 emitcode ("push","%s",
3445 aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3447 for (i = (size-1) ; i >= 0 ; i--) {
3448 emitcode ("pop","a%s",javaRet[i]);
3451 for (i = 0 ; i < size ; i++)
3452 emitcode ("mov","%s,%s",javaRet[i],
3453 aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3455 for (i = size ; i < 4 ; i++ )
3456 emitcode ("mov","%s,#0",javaRet[i]);
3460 /*-----------------------------------------------------------------*/
3461 /* genRet - generate code for return statement */
3462 /*-----------------------------------------------------------------*/
3466 int size, offset = 0, pushed = 0;
3468 D (emitcode (";", "genRet "););
3470 /* if we have no return value then
3471 just generate the "ret" */
3475 /* if this is a JavaNative function then return
3476 value in different register */
3477 if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3478 genJavaNativeRet(ic);
3481 /* we have something to return then
3482 move the return value into place */
3483 aopOp (IC_LEFT (ic), ic, FALSE,
3484 (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
3485 size = AOP_SIZE (IC_LEFT (ic));
3487 _startLazyDPSEvaluation ();
3491 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3493 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3495 emitcode ("push", "%s", l);
3500 /* Since A is the last element of fReturn,
3501 * is is OK to clobber it in the aopGet.
3503 l = aopGet (AOP (IC_LEFT (ic)), offset,
3504 FALSE, FALSE, NULL);
3505 if (strcmp (fReturn[offset], l))
3506 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3509 _endLazyDPSEvaluation ();
3516 if (strcmp (fReturn[pushed], "a"))
3517 emitcode ("pop", fReturn[pushed]);
3519 emitcode ("pop", "acc");
3522 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3525 /* generate a jump to the return label
3526 if the next is not the return statement */
3527 if (!(ic->next && ic->next->op == LABEL &&
3528 IC_LABEL (ic->next) == returnLabel))
3530 emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3534 /*-----------------------------------------------------------------*/
3535 /* genLabel - generates a label */
3536 /*-----------------------------------------------------------------*/
3538 genLabel (iCode * ic)
3540 /* special case never generate */
3541 if (IC_LABEL (ic) == entryLabel)
3544 D (emitcode (";", "genLabel ");
3547 emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3550 /*-----------------------------------------------------------------*/
3551 /* genGoto - generates a ljmp */
3552 /*-----------------------------------------------------------------*/
3554 genGoto (iCode * ic)
3556 D (emitcode (";", "genGoto ");
3558 emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3561 /*-----------------------------------------------------------------*/
3562 /* findLabelBackwards: walks back through the iCode chain looking */
3563 /* for the given label. Returns number of iCode instructions */
3564 /* between that label and given ic. */
3565 /* Returns zero if label not found. */
3566 /*-----------------------------------------------------------------*/
3568 findLabelBackwards (iCode * ic, int key)
3577 /* If we have any pushes or pops, we cannot predict the distance.
3578 I don't like this at all, this should be dealt with in the
3580 if (ic->op == IPUSH || ic->op == IPOP) {
3584 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3586 /* printf("findLabelBackwards = %d\n", count); */
3594 /*-----------------------------------------------------------------*/
3595 /* genPlusIncr :- does addition with increment if possible */
3596 /*-----------------------------------------------------------------*/
3598 genPlusIncr (iCode * ic)
3600 unsigned int icount;
3601 unsigned int size = getDataSize (IC_RESULT (ic));
3603 /* will try to generate an increment */
3604 /* if the right side is not a literal
3606 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3609 /* if the literal value of the right hand side
3610 is greater than 4 then it is not worth it */
3611 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3614 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3615 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3617 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
3621 /* if increment 16 bits in register */
3623 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3624 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3625 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3634 /* If the next instruction is a goto and the goto target
3635 * is <= 5 instructions previous to this, we can generate
3636 * jumps straight to that target.
3638 if (ic->next && ic->next->op == GOTO
3639 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3642 D(emitcode (";", "tail increment optimized (range %d)", labelRange););
3643 tlbl = IC_LABEL (ic->next);
3648 tlbl = newiTempLabel (NULL);
3652 l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
3653 emitcode ("inc", "%s", l);
3655 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3656 IS_AOP_PREG (IC_RESULT (ic)))
3658 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3662 emitcode ("clr", "a");
3663 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3666 l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
3667 emitcode ("inc", "%s", l);
3670 if (!strcmp(l, "acc"))
3672 emitcode("jnz", "!tlabel", tlbl->key + 100);
3674 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3675 IS_AOP_PREG (IC_RESULT (ic)))
3677 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3681 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3684 l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
3685 emitcode ("inc", "%s", l);
3689 if (!strcmp(l, "acc"))
3691 emitcode("jnz", "!tlabel", tlbl->key + 100);
3693 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3694 IS_AOP_PREG (IC_RESULT (ic)))
3696 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3700 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3703 l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
3704 emitcode ("inc", "%s", l); }
3708 emitcode ("", "!tlabeldef", tlbl->key + 100);
3713 if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3714 !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 &&
3715 options.model == MODEL_FLAT24 ) {
3719 emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, NULL));
3721 emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, NULL));
3723 emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3726 while (icount--) emitcode ("inc","dptr");
3730 if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3731 AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3733 emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3734 while (icount--) emitcode ("inc","dptr");
3735 emitcode ("mov","dps,#0");
3739 /* if the sizes are greater than 1 then we cannot */
3740 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3741 AOP_SIZE (IC_LEFT (ic)) > 1)
3744 /* we can if the aops of the left & result match or
3745 if they are in registers and the registers are the
3748 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3749 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3750 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3755 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3756 emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3757 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3762 _startLazyDPSEvaluation ();
3765 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3767 _endLazyDPSEvaluation ();
3776 /*-----------------------------------------------------------------*/
3777 /* outBitAcc - output a bit in acc */
3778 /*-----------------------------------------------------------------*/
3780 outBitAcc (operand * result)
3782 symbol *tlbl = newiTempLabel (NULL);
3783 /* if the result is a bit */
3784 if (AOP_TYPE (result) == AOP_CRY)
3786 aopPut (AOP (result), "a", 0);
3790 emitcode ("jz", "!tlabel", tlbl->key + 100);
3791 emitcode ("mov", "a,%s", one);
3792 emitcode ("", "!tlabeldef", tlbl->key + 100);
3797 /*-----------------------------------------------------------------*/
3798 /* genPlusBits - generates code for addition of two bits */
3799 /*-----------------------------------------------------------------*/
3801 genPlusBits (iCode * ic)
3803 D (emitcode (";", "genPlusBits "););
3805 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3807 symbol *lbl = newiTempLabel (NULL);
3808 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3809 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3810 emitcode ("cpl", "c");
3811 emitcode ("", "!tlabeldef", (lbl->key + 100));
3812 outBitC (IC_RESULT (ic));
3816 emitcode ("clr", "a");
3817 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3818 emitcode ("rlc", "a");
3819 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3820 emitcode ("addc", "a,#0");
3821 outAcc (IC_RESULT (ic));
3826 adjustArithmeticResult (iCode * ic)
3828 if (opIsGptr (IC_RESULT (ic)) &&
3829 opIsGptr (IC_LEFT (ic)) &&
3830 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3832 aopPut (AOP (IC_RESULT (ic)),
3833 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3837 if (opIsGptr (IC_RESULT (ic)) &&
3838 opIsGptr (IC_RIGHT (ic)) &&
3839 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3841 aopPut (AOP (IC_RESULT (ic)),
3842 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3846 if (opIsGptr (IC_RESULT (ic)) &&
3847 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3848 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3849 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3850 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3853 SNPRINTF (buff, sizeof(buff),
3854 "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3855 aopPut (AOP (IC_RESULT (ic)), buff, GPTRSIZE - 1);
3859 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
3860 // generates the result if possible. If result is generated, returns TRUE; otherwise
3861 // returns false and caller must deal with fact that result isn't aopOp'd.
3862 bool aopOp3(iCode * ic)
3864 bool dp1InUse, dp2InUse;
3867 // First, generate the right opcode. DPTR may be used if neither left nor result are
3870 // D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
3871 // AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
3872 // AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
3873 // AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
3875 // D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
3876 // AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
3877 // AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
3878 // AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
3881 // Right uses DPTR unless left or result is an AOP_STR; however,
3882 // if right is an AOP_STR, it must use DPTR regardless.
3883 if ((AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)))
3884 && !AOP_IS_STR(IC_RIGHT(ic)))
3893 aopOp (IC_RIGHT(ic),ic,FALSE, useDp2);
3895 // if the right used DPTR, left MUST use DPTR2.
3896 // if the right used DPTR2, left MUST use DPTR.
3897 // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
3898 // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
3899 // enabling us to assign DPTR to result.
3901 if (AOP_USESDPTR(IC_RIGHT(ic)))
3905 else if (AOP_USESDPTR2(IC_RIGHT(ic)))
3911 if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
3921 aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
3923 // We've op'd the left & right. So, if left or right are the same operand as result,
3924 // we know aopOp will succeed, and we can just do it & bail.
3925 if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)) ||
3926 isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
3928 // D(emitcode(";", "aopOp3: (left | right) & result equal"););
3929 aopOp(IC_RESULT(ic),ic,TRUE, FALSE);
3933 // Note which dptrs are currently in use.
3934 dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
3935 dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
3937 // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot
3939 if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
3944 // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
3945 if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
3950 // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck
3951 if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
3956 aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
3958 // Some sanity checking...
3959 if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
3962 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
3963 __FILE__, __LINE__, ic->filename, ic->lineno);
3964 emitcode(";", ">>> unexpected DPTR here.");
3967 if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
3970 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
3971 __FILE__, __LINE__, ic->filename, ic->lineno);
3972 emitcode(";", ">>> unexpected DPTR2 here.");
3978 // Macro to aopOp all three operands of an ic. If this cannot be done,
3979 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3980 // will be set TRUE. The caller must then handle the case specially, noting
3981 // that the IC_RESULT operand is not aopOp'd.
3983 #define AOP_OP_3_NOFATAL(ic, rc) \
3984 do { rc = !aopOp3(ic); } while (0)
3986 // aopOp the left & right operands of an ic.
3987 #define AOP_OP_2(ic) \
3988 aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
3989 aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
3991 // convienience macro.
3992 #define AOP_SET_LOCALS(ic) \
3993 left = IC_LEFT(ic); \
3994 right = IC_RIGHT(ic); \
3995 result = IC_RESULT(ic);
3998 // Given an integer value of pushedSize bytes on the stack,
3999 // adjust it to be resultSize bytes, either by discarding
4000 // the most significant bytes or by zero-padding.
4002 // On exit from this macro, pushedSize will have been adjusted to
4003 // equal resultSize, and ACC may be trashed.
4004 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
4005 /* If the pushed data is bigger than the result, \
4006 * simply discard unused bytes. Icky, but works. \
4008 while (pushedSize > resultSize) \
4010 D (emitcode (";", "discarding unused result byte."););\
4011 emitcode ("pop", "acc"); \
4014 if (pushedSize < resultSize) \
4016 emitcode ("clr", "a"); \
4017 /* Conversly, we haven't pushed enough here. \
4018 * just zero-pad, and all is well. \
4020 while (pushedSize < resultSize) \
4022 emitcode("push", "acc"); \
4026 assert(pushedSize == resultSize);
4028 /*-----------------------------------------------------------------*/
4029 /* genPlus - generates code for addition */
4030 /*-----------------------------------------------------------------*/
4032 genPlus (iCode * ic)
4034 int size, offset = 0;
4038 D (emitcode (";", "genPlus "););
4040 /* special cases :- */
4041 if ( AOP_IS_STR(IC_LEFT(ic)) &&
4042 isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
4043 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
4044 size = (int)floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
4046 while (size--) emitcode ("inc","dptr");
4048 emitcode ("mov","a,dpl");
4049 emitcode ("add","a,#!constbyte",size & 0xff);
4050 emitcode ("mov","dpl,a");
4051 emitcode ("mov","a,dph");
4052 emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
4053 emitcode ("mov","dph,a");
4054 emitcode ("mov","a,dpx");
4055 emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
4056 emitcode ("mov","dpx,a");
4058 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
4061 if ( IS_SYMOP(IC_LEFT(ic)) &&
4062 OP_SYMBOL(IC_LEFT(ic))->remat &&
4063 isOperandInFarSpace(IC_RIGHT(ic))) {
4064 operand *op = IC_RIGHT(ic);
4065 IC_RIGHT(ic) = IC_LEFT(ic);
4069 AOP_OP_3_NOFATAL (ic, pushResult);
4073 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
4078 /* if literal, literal on the right or
4079 if left requires ACC or right is already
4081 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4082 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
4083 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4085 operand *t = IC_RIGHT (ic);
4086 IC_RIGHT (ic) = IC_LEFT (ic);
4088 emitcode (";", "Swapped plus args.");
4091 /* if both left & right are in bit
4093 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4094 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4100 /* if left in bit space & right literal */
4101 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4102 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4104 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4105 /* if result in bit space */
4106 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4108 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4109 emitcode ("cpl", "c");
4110 outBitC (IC_RESULT (ic));
4114 size = getDataSize (IC_RESULT (ic));
4115 _startLazyDPSEvaluation ();
4118 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4119 emitcode ("addc", "a,#0");
4120 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4122 _endLazyDPSEvaluation ();
4127 /* if I can do an increment instead
4128 of add then GOOD for ME */
4129 if (genPlusIncr (ic) == TRUE)
4131 emitcode (";", "did genPlusIncr");
4136 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4138 _startLazyDPSEvaluation ();
4141 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4143 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4145 emitcode ("add", "a,%s",
4146 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4148 emitcode ("addc", "a,%s",
4149 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4153 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4155 /* right is going to use ACC or we would have taken the
4158 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4160 D(emitcode(";", "+ AOP_ACC special case."););
4161 emitcode("xch", "a, %s", DP2_RESULT_REG);
4163 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4166 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4169 emitcode("add", "a, %s", DP2_RESULT_REG);
4173 emitcode ("add", "a,%s",
4174 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE,
4180 emitcode ("addc", "a,%s",
4181 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE,
4187 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4191 emitcode ("push", "acc");
4195 _endLazyDPSEvaluation ();
4199 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4201 size = getDataSize (IC_LEFT (ic));
4202 rSize = getDataSize (IC_RESULT (ic));
4204 ADJUST_PUSHED_RESULT(size, rSize);
4206 _startLazyDPSEvaluation ();
4209 emitcode ("pop", "acc");
4210 aopPut (AOP (IC_RESULT (ic)), "a", size);
4212 _endLazyDPSEvaluation ();
4215 adjustArithmeticResult (ic);
4218 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4219 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4220 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4223 /*-----------------------------------------------------------------*/
4224 /* genMinusDec :- does subtraction with deccrement if possible */
4225 /*-----------------------------------------------------------------*/
4227 genMinusDec (iCode * ic)
4229 unsigned int icount;
4230 unsigned int size = getDataSize (IC_RESULT (ic));
4232 /* will try to generate an increment */
4233 /* if the right side is not a literal
4235 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4238 /* if the literal value of the right hand side
4239 is greater than 4 then it is not worth it */
4240 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4243 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4244 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4246 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
4250 /* if decrement 16 bits in register */
4251 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4252 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4253 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4262 /* If the next instruction is a goto and the goto target
4263 * is <= 5 instructions previous to this, we can generate
4264 * jumps straight to that target.
4266 if (ic->next && ic->next->op == GOTO
4267 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4270 emitcode (";", "tail decrement optimized (range %d)", labelRange);
4271 tlbl = IC_LABEL (ic->next);
4276 tlbl = newiTempLabel (NULL);
4280 l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
4281 emitcode ("dec", "%s", l);
4283 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4284 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4285 IS_AOP_PREG (IC_RESULT (ic)))
4287 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4291 emitcode ("mov", "a,#!constbyte",0xff);
4292 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4294 l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
4295 emitcode ("dec", "%s", l);
4298 if (!strcmp(l, "acc"))
4300 emitcode("jnz", "!tlabel", tlbl->key + 100);
4302 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4303 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4304 IS_AOP_PREG (IC_RESULT (ic)))
4306 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4310 emitcode ("mov", "a,#!constbyte",0xff);
4311 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4313 l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
4314 emitcode ("dec", "%s", l);
4318 if (!strcmp(l, "acc"))
4320 emitcode("jnz", "!tlabel", tlbl->key + 100);
4322 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4323 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4324 IS_AOP_PREG (IC_RESULT (ic)))
4326 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4330 emitcode ("mov", "a,#!constbyte",0xff);
4331 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4333 l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
4334 emitcode ("dec", "%s", l);
4338 emitcode ("", "!tlabeldef", tlbl->key + 100);
4343 /* if the sizes are greater than 1 then we cannot */
4344 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4345 AOP_SIZE (IC_LEFT (ic)) > 1)
4348 /* we can if the aops of the left & result match or
4349 if they are in registers and the registers are the
4352 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4353 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4354 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4357 _startLazyDPSEvaluation ();
4360 emitcode ("dec", "%s",
4361 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
4363 _endLazyDPSEvaluation ();
4371 /*-----------------------------------------------------------------*/
4372 /* addSign - complete with sign */
4373 /*-----------------------------------------------------------------*/
4375 addSign (operand * result, int offset, int sign)
4377 int size = (getDataSize (result) - offset);
4380 _startLazyDPSEvaluation();
4383 emitcode ("rlc", "a");
4384 emitcode ("subb", "a,acc");
4387 aopPut (AOP (result), "a", offset++);
4394 aopPut (AOP (result), zero, offset++);
4397 _endLazyDPSEvaluation();
4401 /*-----------------------------------------------------------------*/
4402 /* genMinusBits - generates code for subtraction of two bits */
4403 /*-----------------------------------------------------------------*/
4405 genMinusBits (iCode * ic)
4407 symbol *lbl = newiTempLabel (NULL);
4409 D (emitcode (";", "genMinusBits "););
4411 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4413 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4414 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4415 emitcode ("cpl", "c");
4416 emitcode ("", "!tlabeldef", (lbl->key + 100));
4417 outBitC (IC_RESULT (ic));
4421 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4422 emitcode ("subb", "a,acc");
4423 emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4424 emitcode ("inc", "a");
4425 emitcode ("", "!tlabeldef", (lbl->key + 100));
4426 aopPut (AOP (IC_RESULT (ic)), "a", 0);
4427 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4431 /*-----------------------------------------------------------------*/
4432 /* genMinus - generates code for subtraction */
4433 /*-----------------------------------------------------------------*/
4435 genMinus (iCode * ic)
4437 int size, offset = 0;
4442 D (emitcode (";", "genMinus "););
4444 AOP_OP_3_NOFATAL(ic, pushResult);
4448 /* special cases :- */
4449 /* if both left & right are in bit space */
4450 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4451 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4457 /* if I can do an decrement instead
4458 of subtract then GOOD for ME */
4459 if (genMinusDec (ic) == TRUE)
4464 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4466 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4472 lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4477 /* if literal, add a,#-lit, else normal subb */
4478 _startLazyDPSEvaluation ();
4480 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4481 if (AOP_USESDPTR(IC_RIGHT(ic))) {
4482 emitcode ("mov","b,%s",
4483 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4484 MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4485 emitcode ("subb","a,b");
4487 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4488 emitcode ("subb", "a,%s",
4489 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE,
4493 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4494 /* first add without previous c */
4496 if (!size && lit==-1) {
4497 emitcode ("dec", "a");
4499 emitcode ("add", "a,#!constbyte",
4500 (unsigned int) (lit & 0x0FFL));
4503 emitcode ("addc", "a,#!constbyte",
4504 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4509 emitcode ("push", "acc");
4511 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4515 _endLazyDPSEvaluation ();
4519 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4521 size = getDataSize (IC_LEFT (ic));
4522 rSize = getDataSize (IC_RESULT (ic));
4524 ADJUST_PUSHED_RESULT(size, rSize);
4526 _startLazyDPSEvaluation ();
4529 emitcode ("pop", "acc");
4530 aopPut (AOP (IC_RESULT (ic)), "a", size);
4532 _endLazyDPSEvaluation ();
4535 adjustArithmeticResult (ic);
4538 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4539 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4540 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4544 /*-----------------------------------------------------------------*/
4545 /* genMultbits :- multiplication of bits */
4546 /*-----------------------------------------------------------------*/
4548 genMultbits (operand * left,
4553 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4554 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4555 aopOp(result, ic, TRUE, FALSE);
4560 /*-----------------------------------------------------------------*/
4561 /* genMultOneByte : 8*8=8/16 bit multiplication */
4562 /*-----------------------------------------------------------------*/
4564 genMultOneByte (operand * left,
4569 sym_link *opetype = operandType (result);
4573 /* (if two literals: the value is computed before) */
4574 /* if one literal, literal on the right */
4575 if (AOP_TYPE (left) == AOP_LIT)
4580 emitcode (";", "swapped left and right");
4583 if (SPEC_USIGN(opetype)
4584 // ignore the sign of left and right, what else can we do?
4585 || (SPEC_USIGN(operandType(left)) &&
4586 SPEC_USIGN(operandType(right)))) {
4587 // just an unsigned 8*8=8/16 multiply
4588 //emitcode (";","unsigned");
4589 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4590 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4591 emitcode ("mul", "ab");
4593 _G.accInUse++; _G.bInUse++;
4594 aopOp(result, ic, TRUE, FALSE);
4596 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4598 // this should never happen
4599 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4600 AOP_SIZE(result), __FILE__, lineno);
4604 aopPut (AOP (result), "a", 0);
4605 _G.accInUse--; _G.bInUse--;
4606 if (AOP_SIZE(result)==2)
4608 aopPut (AOP (result), "b", 1);
4613 // we have to do a signed multiply
4615 emitcode (";", "signed");
4616 emitcode ("clr", "F0"); // reset sign flag
4617 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4619 lbl=newiTempLabel(NULL);
4620 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4621 // left side is negative, 8-bit two's complement, this fails for -128
4622 emitcode ("setb", "F0"); // set sign flag
4623 emitcode ("cpl", "a");
4624 emitcode ("inc", "a");
4626 emitcode ("", "!tlabeldef", lbl->key+100);
4629 if (AOP_TYPE(right)==AOP_LIT) {
4630 signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
4631 /* AND literal negative */
4632 if ((int) val < 0) {
4633 emitcode ("cpl", "F0"); // complement sign flag
4634 emitcode ("mov", "b,#!constbyte", -val);
4636 emitcode ("mov", "b,#!constbyte", val);
4639 lbl=newiTempLabel(NULL);
4640 emitcode ("mov", "b,a");
4641 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4642 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4643 // right side is negative, 8-bit two's complement
4644 emitcode ("cpl", "F0"); // complement sign flag
4645 emitcode ("cpl", "a");
4646 emitcode ("inc", "a");
4647 emitcode ("", "!tlabeldef", lbl->key+100);
4649 emitcode ("mul", "ab");
4651 _G.accInUse++;_G.bInUse++;
4652 aopOp(result, ic, TRUE, FALSE);
4654 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4656 // this should never happen
4657 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4658 AOP_SIZE(result), __FILE__, lineno);
4662 lbl=newiTempLabel(NULL);
4663 emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4664 // only ONE op was negative, we have to do a 8/16-bit two's complement
4665 emitcode ("cpl", "a"); // lsb
4666 if (AOP_SIZE(result)==1) {
4667 emitcode ("inc", "a");
4669 emitcode ("add", "a,#1");
4670 emitcode ("xch", "a,b");
4671 emitcode ("cpl", "a"); // msb
4672 emitcode ("addc", "a,#0");
4673 emitcode ("xch", "a,b");
4676 emitcode ("", "!tlabeldef", lbl->key+100);
4677 aopPut (AOP (result), "a", 0);
4678 _G.accInUse--;_G.bInUse--;
4679 if (AOP_SIZE(result)==2) {
4680 aopPut (AOP (result), "b", 1);
4684 /*-----------------------------------------------------------------*/
4685 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
4686 /*-----------------------------------------------------------------*/
4687 static void genMultTwoByte (operand *left, operand *right,
4688 operand *result, iCode *ic)
4690 sym_link *retype = getSpec(operandType(right));
4691 sym_link *letype = getSpec(operandType(left));
4692 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4695 if (AOP_TYPE (left) == AOP_LIT) {
4700 /* save EA bit in F1 */
4701 lbl = newiTempLabel(NULL);
4702 emitcode ("setb","F1");
4703 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4704 emitcode ("clr","F1");
4705 emitcode("","!tlabeldef",lbl->key+100);
4707 /* load up MB with right */
4709 emitcode("clr","F0");
4710 if (AOP_TYPE(right) == AOP_LIT) {
4711 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
4713 emitcode("setb","F0");
4716 emitcode ("mov","mb,#!constbyte",val & 0xff);
4717 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4719 lbl = newiTempLabel(NULL);
4720 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4721 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4722 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4723 emitcode ("xch", "a,b");
4724 emitcode ("cpl","a");
4725 emitcode ("add", "a,#1");
4726 emitcode ("xch", "a,b");
4727 emitcode ("cpl", "a"); // msb
4728 emitcode ("addc", "a,#0");
4729 emitcode ("setb","F0");
4730 emitcode ("","!tlabeldef",lbl->key+100);
4731 emitcode ("mov","mb,b");
4732 emitcode ("mov","mb,a");
4735 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4736 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4738 /* load up MA with left */
4740 lbl = newiTempLabel(NULL);
4741 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4742 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4743 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4744 emitcode ("xch", "a,b");
4745 emitcode ("cpl","a");
4746 emitcode ("add", "a,#1");
4747 emitcode ("xch", "a,b");
4748 emitcode ("cpl", "a"); // msb
4749 emitcode ("addc","a,#0");
4750 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4751 emitcode ("setb","F0");
4752 emitcode ("","!tlabeldef",lbl->key+100);
4753 emitcode ("mov","ma,b");
4754 emitcode ("mov","ma,a");
4756 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4757 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4759 /* wait for multiplication to finish */
4760 lbl = newiTempLabel(NULL);
4761 emitcode("","!tlabeldef", lbl->key+100);
4762 emitcode("mov","a,mcnt1");
4763 emitcode("anl","a,#!constbyte",0x80);
4764 emitcode("jnz","!tlabel",lbl->key+100);
4766 freeAsmop (left, NULL, ic, TRUE);
4767 freeAsmop (right, NULL, ic,TRUE);
4768 aopOp(result, ic, TRUE, FALSE);
4770 /* if unsigned then simple */
4772 emitcode ("mov","a,ma");
4773 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4774 emitcode ("mov","a,ma");
4775 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4776 aopPut(AOP(result),"ma",1);
4777 aopPut(AOP(result),"ma",0);
4779 emitcode("push","ma");
4780 emitcode("push","ma");
4781 emitcode("push","ma");
4783 /* negate result if needed */
4784 lbl = newiTempLabel(NULL);
4785 emitcode("jnb","F0,!tlabel",lbl->key+100);
4786 emitcode("cpl","a");
4787 emitcode("add","a,#1");
4788 emitcode("","!tlabeldef", lbl->key+100);
4789 if (AOP_TYPE(result) == AOP_ACC)
4791 D(emitcode(";", "ACC special case."););
4792 /* We know result is the only live aop, and
4793 * it's obviously not a DPTR2, so AP is available.
4795 emitcode("mov", "%s,acc", DP2_RESULT_REG);
4799 aopPut(AOP(result),"a",0);
4802 emitcode("pop","acc");
4803 lbl = newiTempLabel(NULL);
4804 emitcode("jnb","F0,!tlabel",lbl->key+100);
4805 emitcode("cpl","a");
4806 emitcode("addc","a,#0");
4807 emitcode("","!tlabeldef", lbl->key+100);
4808 aopPut(AOP(result),"a",1);
4809 emitcode("pop","acc");
4810 if (AOP_SIZE(result) >= 3) {
4811 lbl = newiTempLabel(NULL);
4812 emitcode("jnb","F0,!tlabel",lbl->key+100);
4813 emitcode("cpl","a");
4814 emitcode("addc","a,#0");
4815 emitcode("","!tlabeldef", lbl->key+100);
4816 aopPut(AOP(result),"a",2);
4818 emitcode("pop","acc");
4819 if (AOP_SIZE(result) >= 4) {
4820 lbl = newiTempLabel(NULL);
4821 emitcode("jnb","F0,!tlabel",lbl->key+100);
4822 emitcode("cpl","a");
4823 emitcode("addc","a,#0");
4824 emitcode("","!tlabeldef", lbl->key+100);
4825 aopPut(AOP(result),"a",3);
4827 if (AOP_TYPE(result) == AOP_ACC)
4829 /* We stashed the result away above. */
4830 emitcode("mov", "acc,%s", DP2_RESULT_REG);
4834 freeAsmop (result, NULL, ic, TRUE);
4836 /* restore EA bit in F1 */
4837 lbl = newiTempLabel(NULL);
4838 emitcode ("jnb","F1,!tlabel",lbl->key+100);
4839 emitcode ("setb","EA");
4840 emitcode("","!tlabeldef",lbl->key+100);
4844 /*-----------------------------------------------------------------*/
4845 /* genMult - generates code for multiplication */
4846 /*-----------------------------------------------------------------*/
4848 genMult (iCode * ic)
4850 operand *left = IC_LEFT (ic);
4851 operand *right = IC_RIGHT (ic);
4852 operand *result = IC_RESULT (ic);
4854 D (emitcode (";", "genMult "););
4856 /* assign the amsops */
4859 /* special cases first */
4861 if (AOP_TYPE (left) == AOP_CRY &&
4862 AOP_TYPE (right) == AOP_CRY)
4864 genMultbits (left, right, result, ic);
4868 /* if both are of size == 1 */
4869 if (AOP_SIZE (left) == 1 &&
4870 AOP_SIZE (right) == 1)
4872 genMultOneByte (left, right, result, ic);
4876 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4877 /* use the ds390 ARITHMETIC accel UNIT */
4878 genMultTwoByte (left, right, result, ic);
4881 /* should have been converted to function call */
4885 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4886 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4887 freeAsmop (result, NULL, ic, TRUE);
4890 /*-----------------------------------------------------------------*/
4891 /* genDivbits :- division of bits */
4892 /*-----------------------------------------------------------------*/
4894 genDivbits (operand * left,
4902 /* the result must be bit */
4903 LOAD_AB_FOR_DIV (left, right, l);
4904 emitcode ("div", "ab");
4905 emitcode ("rrc", "a");
4906 aopOp(result, ic, TRUE, FALSE);
4908 aopPut (AOP (result), "c", 0);
4911 /*-----------------------------------------------------------------*/
4912 /* genDivOneByte : 8 bit division */
4913 /*-----------------------------------------------------------------*/
4915 genDivOneByte (operand * left,
4920 sym_link *opetype = operandType (result);
4926 /* signed or unsigned */
4927 if (SPEC_USIGN (opetype))
4929 /* unsigned is easy */
4930 LOAD_AB_FOR_DIV (left, right, l);
4931 emitcode ("div", "ab");
4934 aopOp(result, ic, TRUE, FALSE);
4935 aopPut (AOP (result), "a", 0);
4938 size = AOP_SIZE (result) - 1;
4942 aopPut (AOP (result), zero, offset++);
4947 /* signed is a little bit more difficult */
4949 /* save the signs of the operands */
4950 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4951 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4952 emitcode ("push", "acc"); /* save it on the stack */
4954 /* now sign adjust for both left & right */
4955 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4956 lbl = newiTempLabel (NULL);
4957 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4958 emitcode ("cpl", "a");
4959 emitcode ("inc", "a");
4960 emitcode ("", "!tlabeldef", (lbl->key + 100));
4961 emitcode ("mov", "b,a");
4963 /* sign adjust left side */
4964 MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4966 lbl = newiTempLabel (NULL);
4967 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4968 emitcode ("cpl", "a");
4969 emitcode ("inc", "a");
4970 emitcode ("", "!tlabeldef", (lbl->key + 100));
4972 /* now the division */
4973 emitcode ("nop", "; workaround for DS80C390 div bug.");
4974 emitcode ("div", "ab");
4975 /* we are interested in the lower order
4977 emitcode ("mov", "b,a");
4978 lbl = newiTempLabel (NULL);
4979 emitcode ("pop", "acc");
4980 /* if there was an over flow we don't
4981 adjust the sign of the result */
4982 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4983 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4985 emitcode ("clr", "a");
4986 emitcode ("subb", "a,b");
4987 emitcode ("mov", "b,a");
4988 emitcode ("", "!tlabeldef", (lbl->key + 100));
4990 /* now we are done */
4991 _G.accInUse++; _G.bInUse++;
4992 aopOp(result, ic, TRUE, FALSE);
4994 aopPut (AOP (result), "b", 0);
4996 size = AOP_SIZE (result) - 1;
5000 emitcode ("mov", "c,b.7");
5001 emitcode ("subb", "a,acc");
5005 aopPut (AOP (result), "a", offset++);
5007 _G.accInUse--; _G.bInUse--;
5011 /*-----------------------------------------------------------------*/
5012 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
5013 /*-----------------------------------------------------------------*/
5014 static void genDivTwoByte (operand *left, operand *right,
5015 operand *result, iCode *ic)
5017 sym_link *retype = getSpec(operandType(right));
5018 sym_link *letype = getSpec(operandType(left));
5019 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5022 /* save EA bit in F1 */
5023 lbl = newiTempLabel(NULL);
5024 emitcode ("setb","F1");
5025 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5026 emitcode ("clr","F1");
5027 emitcode("","!tlabeldef",lbl->key+100);
5029 /* load up MA with left */
5031 emitcode("clr","F0");
5032 lbl = newiTempLabel(NULL);
5033 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5034 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5035 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5036 emitcode ("xch", "a,b");
5037 emitcode ("cpl","a");
5038 emitcode ("add", "a,#1");
5039 emitcode ("xch", "a,b");
5040 emitcode ("cpl", "a"); // msb
5041 emitcode ("addc","a,#0");
5042 emitcode ("setb","F0");
5043 emitcode ("","!tlabeldef",lbl->key+100);
5044 emitcode ("mov","ma,b");
5045 emitcode ("mov","ma,a");
5047 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5048 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5051 /* load up MB with right */
5053 if (AOP_TYPE(right) == AOP_LIT) {
5054 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5056 lbl = newiTempLabel(NULL);
5057 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5058 emitcode("setb","F0");
5059 emitcode ("","!tlabeldef",lbl->key+100);
5062 emitcode ("mov","mb,#!constbyte",val & 0xff);
5063 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5065 lbl = newiTempLabel(NULL);
5066 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5067 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5068 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5069 emitcode ("xch", "a,b");
5070 emitcode ("cpl","a");
5071 emitcode ("add", "a,#1");
5072 emitcode ("xch", "a,b");
5073 emitcode ("cpl", "a"); // msb
5074 emitcode ("addc", "a,#0");
5075 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5076 emitcode ("setb","F0");
5077 emitcode ("","!tlabeldef",lbl->key+100);
5078 emitcode ("mov","mb,b");
5079 emitcode ("mov","mb,a");
5082 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5083 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5086 /* wait for multiplication to finish */
5087 lbl = newiTempLabel(NULL);
5088 emitcode("","!tlabeldef", lbl->key+100);
5089 emitcode("mov","a,mcnt1");
5090 emitcode("anl","a,#!constbyte",0x80);
5091 emitcode("jnz","!tlabel",lbl->key+100);
5093 freeAsmop (left, NULL, ic, TRUE);
5094 freeAsmop (right, NULL, ic,TRUE);
5095 aopOp(result, ic, TRUE, FALSE);
5097 /* if unsigned then simple */
5099 aopPut(AOP(result),"ma",1);
5100 aopPut(AOP(result),"ma",0);
5102 emitcode("push","ma");
5104 /* negate result if needed */
5105 lbl = newiTempLabel(NULL);
5106 emitcode("jnb","F0,!tlabel",lbl->key+100);
5107 emitcode("cpl","a");
5108 emitcode("add","a,#1");
5109 emitcode("","!tlabeldef", lbl->key+100);
5110 aopPut(AOP(result),"a",0);
5111 emitcode("pop","acc");
5112 lbl = newiTempLabel(NULL);
5113 emitcode("jnb","F0,!tlabel",lbl->key+100);
5114 emitcode("cpl","a");
5115 emitcode("addc","a,#0");
5116 emitcode("","!tlabeldef", lbl->key+100);
5117 aopPut(AOP(result),"a",1);
5119 freeAsmop (result, NULL, ic, TRUE);
5120 /* restore EA bit in F1 */
5121 lbl = newiTempLabel(NULL);
5122 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5123 emitcode ("setb","EA");
5124 emitcode("","!tlabeldef",lbl->key+100);
5128 /*-----------------------------------------------------------------*/
5129 /* genDiv - generates code for division */
5130 /*-----------------------------------------------------------------*/
5134 operand *left = IC_LEFT (ic);
5135 operand *right = IC_RIGHT (ic);
5136 operand *result = IC_RESULT (ic);
5138 D (emitcode (";", "genDiv "););
5140 /* assign the amsops */
5143 /* special cases first */
5145 if (AOP_TYPE (left) == AOP_CRY &&
5146 AOP_TYPE (right) == AOP_CRY)
5148 genDivbits (left, right, result, ic);
5152 /* if both are of size == 1 */
5153 if (AOP_SIZE (left) == 1 &&
5154 AOP_SIZE (right) == 1)
5156 genDivOneByte (left, right, result, ic);
5160 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5161 /* use the ds390 ARITHMETIC accel UNIT */
5162 genDivTwoByte (left, right, result, ic);
5165 /* should have been converted to function call */
5168 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5169 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5170 freeAsmop (result, NULL, ic, TRUE);
5173 /*-----------------------------------------------------------------*/
5174 /* genModbits :- modulus of bits */
5175 /*-----------------------------------------------------------------*/
5177 genModbits (operand * left,
5185 /* the result must be bit */
5186 LOAD_AB_FOR_DIV (left, right, l);
5187 emitcode ("div", "ab");
5188 emitcode ("mov", "a,b");
5189 emitcode ("rrc", "a");
5190 aopOp(result, ic, TRUE, FALSE);
5191 aopPut (AOP (result), "c", 0);
5194 /*-----------------------------------------------------------------*/
5195 /* genModOneByte : 8 bit modulus */
5196 /*-----------------------------------------------------------------*/
5198 genModOneByte (operand * left,
5203 sym_link *opetype = operandType (result);
5207 /* signed or unsigned */
5208 if (SPEC_USIGN (opetype))
5210 /* unsigned is easy */
5211 LOAD_AB_FOR_DIV (left, right, l);
5212 emitcode ("div", "ab");
5213 aopOp(result, ic, TRUE, FALSE);
5214 aopPut (AOP (result), "b", 0);
5218 /* signed is a little bit more difficult */
5220 /* save the signs of the operands */
5221 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5223 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
5224 emitcode ("push", "acc"); /* save it on the stack */
5226 /* now sign adjust for both left & right */
5227 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5229 lbl = newiTempLabel (NULL);
5230 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5231 emitcode ("cpl", "a");
5232 emitcode ("inc", "a");
5233 emitcode ("", "!tlabeldef", (lbl->key + 100));
5234 emitcode ("mov", "b,a");
5236 /* sign adjust left side */
5237 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5239 lbl = newiTempLabel (NULL);
5240 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5241 emitcode ("cpl", "a");
5242 emitcode ("inc", "a");
5243 emitcode ("", "!tlabeldef", (lbl->key + 100));
5245 /* now the multiplication */
5246 emitcode ("nop", "; workaround for DS80C390 div bug.");
5247 emitcode ("div", "ab");
5248 /* we are interested in the lower order
5250 lbl = newiTempLabel (NULL);
5251 emitcode ("pop", "acc");
5252 /* if there was an over flow we don't
5253 adjust the sign of the result */
5254 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
5255 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5257 emitcode ("clr", "a");
5258 emitcode ("subb", "a,b");
5259 emitcode ("mov", "b,a");
5260 emitcode ("", "!tlabeldef", (lbl->key + 100));
5263 /* now we are done */
5264 aopOp(result, ic, TRUE, FALSE);
5265 aopPut (AOP (result), "b", 0);
5270 /*-----------------------------------------------------------------*/
5271 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
5272 /*-----------------------------------------------------------------*/
5273 static void genModTwoByte (operand *left, operand *right,
5274 operand *result, iCode *ic)
5276 sym_link *retype = getSpec(operandType(right));
5277 sym_link *letype = getSpec(operandType(left));
5278 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5281 /* load up MA with left */
5282 /* save EA bit in F1 */
5283 lbl = newiTempLabel(NULL);
5284 emitcode ("setb","F1");
5285 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5286 emitcode ("clr","F1");
5287 emitcode("","!tlabeldef",lbl->key+100);
5290 lbl = newiTempLabel(NULL);
5291 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5292 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5293 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5294 emitcode ("xch", "a,b");
5295 emitcode ("cpl","a");
5296 emitcode ("add", "a,#1");
5297 emitcode ("xch", "a,b");
5298 emitcode ("cpl", "a"); // msb
5299 emitcode ("addc","a,#0");
5300 emitcode ("","!tlabeldef",lbl->key+100);
5301 emitcode ("mov","ma,b");
5302 emitcode ("mov","ma,a");
5304 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5305 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5308 /* load up MB with right */
5310 if (AOP_TYPE(right) == AOP_LIT) {
5311 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5315 emitcode ("mov","mb,#!constbyte",val & 0xff);
5316 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5318 lbl = newiTempLabel(NULL);
5319 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5320 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5321 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5322 emitcode ("xch", "a,b");
5323 emitcode ("cpl","a");
5324 emitcode ("add", "a,#1");
5325 emitcode ("xch", "a,b");
5326 emitcode ("cpl", "a"); // msb
5327 emitcode ("addc", "a,#0");
5328 emitcode ("","!tlabeldef",lbl->key+100);
5329 emitcode ("mov","mb,b");
5330 emitcode ("mov","mb,a");
5333 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5334 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5337 /* wait for multiplication to finish */
5338 lbl = newiTempLabel(NULL);
5339 emitcode("","!tlabeldef", lbl->key+100);
5340 emitcode("mov","a,mcnt1");
5341 emitcode("anl","a,#!constbyte",0x80);
5342 emitcode("jnz","!tlabel",lbl->key+100);
5344 freeAsmop (left, NULL, ic, TRUE);
5345 freeAsmop (right, NULL, ic,TRUE);
5346 aopOp(result, ic, TRUE, FALSE);
5348 aopPut(AOP(result),"mb",1);
5349 aopPut(AOP(result),"mb",0);
5350 freeAsmop (result, NULL, ic, TRUE);
5352 /* restore EA bit in F1 */
5353 lbl = newiTempLabel(NULL);
5354 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5355 emitcode ("setb","EA");
5356 emitcode("","!tlabeldef",lbl->key+100);
5360 /*-----------------------------------------------------------------*/
5361 /* genMod - generates code for division */
5362 /*-----------------------------------------------------------------*/
5366 operand *left = IC_LEFT (ic);
5367 operand *right = IC_RIGHT (ic);
5368 operand *result = IC_RESULT (ic);
5370 D (emitcode (";", "genMod "); );
5372 /* assign the amsops */
5375 /* special cases first */
5377 if (AOP_TYPE (left) == AOP_CRY &&
5378 AOP_TYPE (right) == AOP_CRY)
5380 genModbits (left, right, result, ic);
5384 /* if both are of size == 1 */
5385 if (AOP_SIZE (left) == 1 &&
5386 AOP_SIZE (right) == 1)
5388 genModOneByte (left, right, result, ic);
5392 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5393 /* use the ds390 ARITHMETIC accel UNIT */
5394 genModTwoByte (left, right, result, ic);
5398 /* should have been converted to function call */
5402 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5403 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5404 freeAsmop (result, NULL, ic, TRUE);
5407 /*-----------------------------------------------------------------*/
5408 /* genIfxJump :- will create a jump depending on the ifx */
5409 /*-----------------------------------------------------------------*/
5411 genIfxJump (iCode * ic, char *jval)
5414 symbol *tlbl = newiTempLabel (NULL);
5417 D (emitcode (";", "genIfxJump"););
5419 /* if true label then we jump if condition
5423 jlbl = IC_TRUE (ic);
5424 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5425 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5429 /* false label is present */
5430 jlbl = IC_FALSE (ic);
5431 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5432 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5434 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5435 emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5437 emitcode (inst, "!tlabel", tlbl->key + 100);
5438 emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5439 emitcode ("", "!tlabeldef", tlbl->key + 100);
5441 /* mark the icode as generated */
5445 /*-----------------------------------------------------------------*/
5446 /* genCmp :- greater or less than comparison */
5447 /*-----------------------------------------------------------------*/
5449 genCmp (operand * left, operand * right,
5450 iCode * ic, iCode * ifx, int sign)
5452 int size, offset = 0;
5453 unsigned long lit = 0L;
5456 D (emitcode (";", "genCmp"););
5458 result = IC_RESULT (ic);
5460 /* if left & right are bit variables */
5461 if (AOP_TYPE (left) == AOP_CRY &&
5462 AOP_TYPE (right) == AOP_CRY)
5464 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5465 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5469 /* subtract right from left if at the
5470 end the carry flag is set then we know that
5471 left is greater than right */
5472 size = max (AOP_SIZE (left), AOP_SIZE (right));
5474 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5475 if ((size == 1) && !sign
5476 && (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5478 symbol *lbl = newiTempLabel (NULL);
5479 emitcode ("cjne", "%s,%s,!tlabel",
5480 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
5481 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5483 emitcode ("", "!tlabeldef", lbl->key + 100);
5487 if (AOP_TYPE (right) == AOP_LIT)
5489 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5490 /* optimize if(x < 0) or if(x >= 0) */
5499 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
5501 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5502 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5504 aopOp (result, ic, FALSE, FALSE);
5506 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5508 freeAsmop (result, NULL, ic, TRUE);
5509 genIfxJump (ifx, "acc.7");
5514 emitcode ("rlc", "a");
5516 goto release_freedLR;
5524 // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5525 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5526 // emitcode (";", "genCmp #2");
5527 if (sign && (size == 0))
5529 // emitcode (";", "genCmp #3");
5530 emitcode ("xrl", "a,#!constbyte",0x80);
5531 if (AOP_TYPE (right) == AOP_LIT)
5533 unsigned long lit = (unsigned long)
5534 floatFromVal (AOP (right)->aopu.aop_lit);
5535 // emitcode (";", "genCmp #3.1");
5536 emitcode ("subb", "a,#!constbyte",
5537 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5541 // emitcode (";", "genCmp #3.2");
5543 MOVB(aopGet (AOP (right), offset++, FALSE, FALSE, "b"));
5544 saveAccWarn = DEFAULT_ACC_WARNING;
5545 emitcode ("xrl", "b,#!constbyte",0x80);
5546 emitcode ("subb", "a,b");
5553 // emitcode (";", "genCmp #4");
5555 s = aopGet (AOP (right), offset++, FALSE, FALSE, "b");
5556 saveAccWarn = DEFAULT_ACC_WARNING;
5558 emitcode ("subb", "a,%s", s);
5565 /* Don't need the left & right operands any more; do need the result. */
5566 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5567 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5569 aopOp (result, ic, FALSE, FALSE);
5573 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5579 /* if the result is used in the next
5580 ifx conditional branch then generate
5581 code a little differently */
5584 genIfxJump (ifx, "c");
5590 /* leave the result in acc */
5592 freeAsmop (result, NULL, ic, TRUE);
5595 /*-----------------------------------------------------------------*/
5596 /* genCmpGt :- greater than comparison */
5597 /*-----------------------------------------------------------------*/
5599 genCmpGt (iCode * ic, iCode * ifx)
5601 operand *left, *right;
5602 sym_link *letype, *retype;
5605 D (emitcode (";", "genCmpGt ");
5608 left = IC_LEFT (ic);
5609 right = IC_RIGHT (ic);
5611 letype = getSpec (operandType (left));
5612 retype = getSpec (operandType (right));
5613 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5615 /* assign the left & right amsops */
5618 genCmp (right, left, ic, ifx, sign);
5621 /*-----------------------------------------------------------------*/
5622 /* genCmpLt - less than comparisons */
5623 /*-----------------------------------------------------------------*/
5625 genCmpLt (iCode * ic, iCode * ifx)
5627 operand *left, *right;
5628 sym_link *letype, *retype;
5631 D (emitcode (";", "genCmpLt "););
5633 left = IC_LEFT (ic);
5634 right = IC_RIGHT (ic);
5636 letype = getSpec (operandType (left));
5637 retype = getSpec (operandType (right));
5638 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5640 /* assign the left & right amsops */
5643 genCmp (left, right, ic, ifx, sign);
5646 /*-----------------------------------------------------------------*/
5647 /* gencjneshort - compare and jump if not equal */
5648 /*-----------------------------------------------------------------*/
5650 gencjneshort (operand * left, operand * right, symbol * lbl)
5652 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5654 unsigned long lit = 0L;
5656 D (emitcode (";", "gencjneshort");
5659 /* if the left side is a literal or
5660 if the right is in a pointer register and left
5662 if ((AOP_TYPE (left) == AOP_LIT) ||
5663 (AOP_TYPE (left) == AOP_IMMD) ||
5664 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5671 if (AOP_TYPE (right) == AOP_LIT)
5672 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5674 if (opIsGptr (left) || opIsGptr (right))
5676 /* We are comparing a generic pointer to something.
5677 * Exclude the generic type byte from the comparison.
5680 D (emitcode (";", "cjneshort: generic ptr special case."););
5684 /* if the right side is a literal then anything goes */
5685 if (AOP_TYPE (right) == AOP_LIT &&
5686 AOP_TYPE (left) != AOP_DIR)
5690 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5691 emitcode ("cjne", "a,%s,!tlabel",
5692 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5698 /* if the right side is in a register or in direct space or
5699 if the left is a pointer register & right is not */
5700 else if (AOP_TYPE (right) == AOP_REG ||
5701 AOP_TYPE (right) == AOP_DIR ||
5702 AOP_TYPE (right) == AOP_LIT ||
5703 AOP_TYPE (right) == AOP_IMMD ||
5704 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5705 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5709 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5710 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5711 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5712 emitcode ("jnz", "!tlabel", lbl->key + 100);
5714 emitcode ("cjne", "a,%s,!tlabel",
5715 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
5722 /* right is a pointer reg need both a & b */
5725 MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5726 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
5727 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5733 /*-----------------------------------------------------------------*/
5734 /* gencjne - compare and jump if not equal */
5735 /*-----------------------------------------------------------------*/
5737 gencjne (operand * left, operand * right, symbol * lbl)
5739 symbol *tlbl = newiTempLabel (NULL);
5741 D (emitcode (";", "gencjne");
5744 gencjneshort (left, right, lbl);
5746 emitcode ("mov", "a,%s", one);
5747 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5748 emitcode ("", "!tlabeldef", lbl->key + 100);
5749 emitcode ("clr", "a");
5750 emitcode ("", "!tlabeldef", tlbl->key + 100);
5753 /*-----------------------------------------------------------------*/
5754 /* genCmpEq - generates code for equal to */
5755 /*-----------------------------------------------------------------*/
5757 genCmpEq (iCode * ic, iCode * ifx)
5759 operand *left, *right, *result;
5761 D (emitcode (";", "genCmpEq ");
5765 AOP_SET_LOCALS (ic);
5767 /* if literal, literal on the right or
5768 if the right is in a pointer register and left
5770 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5771 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5773 operand *t = IC_RIGHT (ic);
5774 IC_RIGHT (ic) = IC_LEFT (ic);
5778 if (ifx && /* !AOP_SIZE(result) */
5779 OP_SYMBOL (result) &&
5780 OP_SYMBOL (result)->regType == REG_CND)
5783 /* if they are both bit variables */
5784 if (AOP_TYPE (left) == AOP_CRY &&
5785 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5787 if (AOP_TYPE (right) == AOP_LIT)
5789 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5792 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5793 emitcode ("cpl", "c");
5797 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5801 emitcode ("clr", "c");
5803 /* AOP_TYPE(right) == AOP_CRY */
5807 symbol *lbl = newiTempLabel (NULL);
5808 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5809 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5810 emitcode ("cpl", "c");
5811 emitcode ("", "!tlabeldef", (lbl->key + 100));
5813 /* if true label then we jump if condition
5815 tlbl = newiTempLabel (NULL);
5818 emitcode ("jnc", "!tlabel", tlbl->key + 100);
5819 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5823 emitcode ("jc", "!tlabel", tlbl->key + 100);
5824 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5826 emitcode ("", "!tlabeldef", tlbl->key + 100);
5830 tlbl = newiTempLabel (NULL);
5831 gencjneshort (left, right, tlbl);
5834 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5835 emitcode ("", "!tlabeldef", tlbl->key + 100);
5839 symbol *lbl = newiTempLabel (NULL);
5840 emitcode ("sjmp", "!tlabel", lbl->key + 100);
5841 emitcode ("", "!tlabeldef", tlbl->key + 100);
5842 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5843 emitcode ("", "!tlabeldef", lbl->key + 100);
5846 /* mark the icode as generated */
5849 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5850 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5854 /* if they are both bit variables */
5855 if (AOP_TYPE (left) == AOP_CRY &&
5856 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5858 if (AOP_TYPE (right) == AOP_LIT)
5860 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5863 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5864 emitcode ("cpl", "c");
5868 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5872 emitcode ("clr", "c");
5874 /* AOP_TYPE(right) == AOP_CRY */
5878 symbol *lbl = newiTempLabel (NULL);
5879 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5880 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5881 emitcode ("cpl", "c");
5882 emitcode ("", "!tlabeldef", (lbl->key + 100));
5885 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5886 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5888 aopOp (result, ic, TRUE, FALSE);
5891 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5898 genIfxJump (ifx, "c");
5901 /* if the result is used in an arithmetic operation
5902 then put the result in place */
5907 gencjne (left, right, newiTempLabel (NULL));
5909 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5910 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5912 aopOp (result, ic, TRUE, FALSE);
5914 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5916 aopPut (AOP (result), "a", 0);
5921 genIfxJump (ifx, "a");
5924 /* if the result is used in an arithmetic operation
5925 then put the result in place */
5926 if (AOP_TYPE (result) != AOP_CRY)
5928 /* leave the result in acc */
5932 freeAsmop (result, NULL, ic, TRUE);
5935 /*-----------------------------------------------------------------*/
5936 /* ifxForOp - returns the icode containing the ifx for operand */
5937 /*-----------------------------------------------------------------*/
5939 ifxForOp (operand * op, iCode * ic)
5941 /* if true symbol then needs to be assigned */
5942 if (IS_TRUE_SYMOP (op))
5945 /* if this has register type condition and
5946 the next instruction is ifx with the same operand
5947 and live to of the operand is upto the ifx only then */
5949 ic->next->op == IFX &&
5950 IC_COND (ic->next)->key == op->key &&
5951 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5956 /*-----------------------------------------------------------------*/
5957 /* hasInc - operand is incremented before any other use */
5958 /*-----------------------------------------------------------------*/
5960 hasInc (operand *op, iCode *ic, int osize)
5962 sym_link *type = operandType(op);
5963 sym_link *retype = getSpec (type);
5964 iCode *lic = ic->next;
5967 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5968 if (!IS_SYMOP(op)) return NULL;
5970 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5971 if (IS_AGGREGATE(type->next)) return NULL;
5972 if (osize != (isize = getSize(type->next))) return NULL;
5975 /* if operand of the form op = op + <sizeof *op> */
5976 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5977 isOperandEqual(IC_RESULT(lic),op) &&
5978 isOperandLiteral(IC_RIGHT(lic)) &&
5979 operandLitValue(IC_RIGHT(lic)) == isize) {
5982 /* if the operand used or deffed */
5983 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5986 /* if GOTO or IFX */
5987 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5993 /*-----------------------------------------------------------------*/
5994 /* genAndOp - for && operation */
5995 /*-----------------------------------------------------------------*/
5997 genAndOp (iCode * ic)
5999 operand *left, *right, *result;
6002 D (emitcode (";", "genAndOp "););
6004 /* note here that && operations that are in an
6005 if statement are taken away by backPatchLabels
6006 only those used in arthmetic operations remain */
6008 AOP_SET_LOCALS (ic);
6010 /* if both are bit variables */
6011 if (AOP_TYPE (left) == AOP_CRY &&
6012 AOP_TYPE (right) == AOP_CRY)
6014 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6015 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6016 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6017 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6019 aopOp (result,ic,FALSE, FALSE);
6024 tlbl = newiTempLabel (NULL);
6026 emitcode ("jz", "!tlabel", tlbl->key + 100);
6028 emitcode ("", "!tlabeldef", tlbl->key + 100);
6029 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6030 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6032 aopOp (result,ic,FALSE, FALSE);
6035 freeAsmop (result, NULL, ic, TRUE);
6039 /*-----------------------------------------------------------------*/
6040 /* genOrOp - for || operation */
6041 /*-----------------------------------------------------------------*/
6043 genOrOp (iCode * ic)
6045 operand *left, *right, *result;
6048 D (emitcode (";", "genOrOp "););
6050 /* note here that || operations that are in an
6051 if statement are taken away by backPatchLabels
6052 only those used in arthmetic operations remain */
6054 AOP_SET_LOCALS (ic);
6056 /* if both are bit variables */
6057 if (AOP_TYPE (left) == AOP_CRY &&
6058 AOP_TYPE (right) == AOP_CRY)
6060 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6061 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6062 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6063 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6065 aopOp (result,ic,FALSE, FALSE);
6071 tlbl = newiTempLabel (NULL);
6073 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6075 emitcode ("", "!tlabeldef", tlbl->key + 100);
6076 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6077 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6079 aopOp (result,ic,FALSE, FALSE);
6084 freeAsmop (result, NULL, ic, TRUE);
6087 /*-----------------------------------------------------------------*/
6088 /* isLiteralBit - test if lit == 2^n */
6089 /*-----------------------------------------------------------------*/
6091 isLiteralBit (unsigned long lit)
6093 unsigned long pw[32] =
6094 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6095 0x100L, 0x200L, 0x400L, 0x800L,
6096 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6097 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6098 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6099 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6100 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6103 for (idx = 0; idx < 32; idx++)
6109 /*-----------------------------------------------------------------*/
6110 /* continueIfTrue - */
6111 /*-----------------------------------------------------------------*/
6113 continueIfTrue (iCode * ic)
6116 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6120 /*-----------------------------------------------------------------*/
6122 /*-----------------------------------------------------------------*/
6124 jumpIfTrue (iCode * ic)
6127 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6131 /*-----------------------------------------------------------------*/
6132 /* jmpTrueOrFalse - */
6133 /*-----------------------------------------------------------------*/
6135 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6137 // ugly but optimized by peephole
6140 symbol *nlbl = newiTempLabel (NULL);
6141 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6142 emitcode ("", "!tlabeldef", tlbl->key + 100);
6143 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6144 emitcode ("", "!tlabeldef", nlbl->key + 100);
6148 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6149 emitcode ("", "!tlabeldef", tlbl->key + 100);
6154 // Generate code to perform a bit-wise logic operation
6155 // on two operands in far space (assumed to already have been
6156 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6157 // in far space. This requires pushing the result on the stack
6158 // then popping it into the result.
6160 genFarFarLogicOp(iCode *ic, char *logicOp)
6162 int size, resultSize, compSize;
6166 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6167 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
6168 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6170 _startLazyDPSEvaluation();
6171 for (size = compSize; (size--); offset++)
6173 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6174 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6175 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6177 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6178 emitcode ("push", "acc");
6180 _endLazyDPSEvaluation();
6182 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6183 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6184 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6186 resultSize = AOP_SIZE(IC_RESULT(ic));
6188 ADJUST_PUSHED_RESULT(compSize, resultSize);
6190 _startLazyDPSEvaluation();
6193 emitcode ("pop", "acc");
6194 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6196 _endLazyDPSEvaluation();
6197 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6201 /*-----------------------------------------------------------------*/
6202 /* genAnd - code for and */
6203 /*-----------------------------------------------------------------*/
6205 genAnd (iCode * ic, iCode * ifx)
6207 operand *left, *right, *result;
6208 int size, offset = 0;
6209 unsigned long lit = 0L;
6214 D (emitcode (";", "genAnd "););
6216 AOP_OP_3_NOFATAL (ic, pushResult);
6217 AOP_SET_LOCALS (ic);
6221 genFarFarLogicOp(ic, "anl");
6226 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6228 AOP_TYPE (left), AOP_TYPE (right));
6229 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6231 AOP_SIZE (left), AOP_SIZE (right));
6234 /* if left is a literal & right is not then exchange them */
6235 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6236 #ifdef LOGIC_OPS_BROKEN
6237 || AOP_NEEDSACC (left)
6241 operand *tmp = right;
6246 /* if result = right then exchange them */
6247 if (sameRegs (AOP (result), AOP (right)))
6249 operand *tmp = right;
6254 /* if right is bit then exchange them */
6255 if (AOP_TYPE (right) == AOP_CRY &&
6256 AOP_TYPE (left) != AOP_CRY)
6258 operand *tmp = right;
6262 if (AOP_TYPE (right) == AOP_LIT)
6263 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6265 size = AOP_SIZE (result);
6268 // result = bit & yy;
6269 if (AOP_TYPE (left) == AOP_CRY)
6271 // c = bit & literal;
6272 if (AOP_TYPE (right) == AOP_LIT)
6276 if (size && sameRegs (AOP (result), AOP (left)))
6279 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6284 if (size && (AOP_TYPE (result) == AOP_CRY))
6286 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6289 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6294 emitcode ("clr", "c");
6299 if (AOP_TYPE (right) == AOP_CRY)
6302 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6303 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6308 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6310 emitcode ("rrc", "a");
6311 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6319 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6320 genIfxJump (ifx, "c");
6324 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6325 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6326 if ((AOP_TYPE (right) == AOP_LIT) &&
6327 (AOP_TYPE (result) == AOP_CRY) &&
6328 (AOP_TYPE (left) != AOP_CRY))
6330 int posbit = isLiteralBit (lit);
6335 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6338 emitcode ("mov", "c,acc.%d", posbit & 0x07);
6344 SNPRINTF (buff, sizeof(buff),
6345 "acc.%d", posbit & 0x07);
6346 genIfxJump (ifx, buff);
6350 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6357 symbol *tlbl = newiTempLabel (NULL);
6358 int sizel = AOP_SIZE (left);
6360 emitcode ("setb", "c");
6363 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6365 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6367 if ((posbit = isLiteralBit (bytelit)) != 0)
6368 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6371 if (bytelit != 0x0FFL)
6372 emitcode ("anl", "a,%s",
6373 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6374 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6379 // bit = left & literal
6382 emitcode ("clr", "c");
6383 emitcode ("", "!tlabeldef", tlbl->key + 100);
6385 // if(left & literal)
6389 jmpTrueOrFalse (ifx, tlbl);
6397 /* if left is same as result */
6398 if (sameRegs (AOP (result), AOP (left)))
6400 for (; size--; offset++)
6402 if (AOP_TYPE (right) == AOP_LIT)
6404 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6406 else if (bytelit == 0)
6407 aopPut (AOP (result), zero, offset);
6408 else if (IS_AOP_PREG (result))
6410 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6411 emitcode ("anl", "a,%s",
6412 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6413 aopPut (AOP (result), "a", offset);
6416 emitcode ("anl", "%s,%s",
6417 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6418 aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6422 if (AOP_TYPE (left) == AOP_ACC)
6423 emitcode ("anl", "a,%s",
6424 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6427 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6428 if (IS_AOP_PREG (result))
6430 emitcode ("anl", "a,%s",
6431 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6432 aopPut (AOP (result), "a", offset);
6435 emitcode ("anl", "%s,a",
6436 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6443 // left & result in different registers
6444 if (AOP_TYPE (result) == AOP_CRY)
6447 // if(size), result in bit
6448 // if(!size && ifx), conditional oper: if(left & right)
6449 symbol *tlbl = newiTempLabel (NULL);
6450 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6452 emitcode ("setb", "c");
6455 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6456 emitcode ("anl", "a,%s",
6457 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6459 if (AOP_TYPE(left)==AOP_ACC) {
6460 emitcode("mov", "b,a");
6461 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6462 emitcode("anl", "a,b");
6464 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6465 emitcode ("anl", "a,%s",
6466 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6469 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6475 emitcode ("", "!tlabeldef", tlbl->key + 100);
6479 jmpTrueOrFalse (ifx, tlbl);
6483 for (; (size--); offset++)
6486 // result = left & right
6487 if (AOP_TYPE (right) == AOP_LIT)
6489 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6491 aopPut (AOP (result),
6492 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6496 else if (bytelit == 0)
6498 aopPut (AOP (result), zero, offset);
6501 D (emitcode (";", "better literal AND."););
6502 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6503 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6504 FALSE, FALSE, DP2_RESULT_REG));
6509 // faster than result <- left, anl result,right
6510 // and better if result is SFR
6511 if (AOP_TYPE (left) == AOP_ACC)
6513 emitcode ("anl", "a,%s",
6514 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6518 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6519 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6521 emitcode("mov", "b,a");
6525 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6526 emitcode ("anl", "a,%s", rOp);
6529 aopPut (AOP (result), "a", offset);
6535 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6536 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6537 freeAsmop (result, NULL, ic, TRUE);
6541 /*-----------------------------------------------------------------*/
6542 /* genOr - code for or */
6543 /*-----------------------------------------------------------------*/
6545 genOr (iCode * ic, iCode * ifx)
6547 operand *left, *right, *result;
6548 int size, offset = 0;
6549 unsigned long lit = 0L;
6552 D (emitcode (";", "genOr "););
6554 AOP_OP_3_NOFATAL (ic, pushResult);
6555 AOP_SET_LOCALS (ic);
6559 genFarFarLogicOp(ic, "orl");
6565 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6567 AOP_TYPE (left), AOP_TYPE (right));
6568 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6570 AOP_SIZE (left), AOP_SIZE (right));
6573 /* if left is a literal & right is not then exchange them */
6574 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6575 #ifdef LOGIC_OPS_BROKEN
6576 || AOP_NEEDSACC (left) // I think this is a net loss now.
6580 operand *tmp = right;
6585 /* if result = right then exchange them */
6586 if (sameRegs (AOP (result), AOP (right)))
6588 operand *tmp = right;
6593 /* if right is bit then exchange them */
6594 if (AOP_TYPE (right) == AOP_CRY &&
6595 AOP_TYPE (left) != AOP_CRY)
6597 operand *tmp = right;
6601 if (AOP_TYPE (right) == AOP_LIT)
6602 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6604 size = AOP_SIZE (result);
6608 if (AOP_TYPE (left) == AOP_CRY)
6610 if (AOP_TYPE (right) == AOP_LIT)
6612 // c = bit & literal;
6615 // lit != 0 => result = 1
6616 if (AOP_TYPE (result) == AOP_CRY)
6619 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6621 continueIfTrue (ifx);
6624 emitcode ("setb", "c");
6628 // lit == 0 => result = left
6629 if (size && sameRegs (AOP (result), AOP (left)))
6631 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6636 if (AOP_TYPE (right) == AOP_CRY)
6639 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6640 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6645 symbol *tlbl = newiTempLabel (NULL);
6646 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6647 emitcode ("setb", "c");
6648 emitcode ("jb", "%s,!tlabel",
6649 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6651 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6652 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6654 jmpTrueOrFalse (ifx, tlbl);
6660 emitcode ("", "!tlabeldef", tlbl->key + 100);
6669 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6670 genIfxJump (ifx, "c");
6674 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6675 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6676 if ((AOP_TYPE (right) == AOP_LIT) &&
6677 (AOP_TYPE (result) == AOP_CRY) &&
6678 (AOP_TYPE (left) != AOP_CRY))
6684 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6686 continueIfTrue (ifx);
6691 // lit = 0, result = boolean(left)
6693 emitcode ("setb", "c");
6697 symbol *tlbl = newiTempLabel (NULL);
6698 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6700 emitcode ("", "!tlabeldef", tlbl->key + 100);
6704 genIfxJump (ifx, "a");
6712 /* if left is same as result */
6713 if (sameRegs (AOP (result), AOP (left)))
6715 for (; size--; offset++)
6717 if (AOP_TYPE (right) == AOP_LIT)
6719 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6725 if (IS_AOP_PREG (left))
6727 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6728 emitcode ("orl", "a,%s",
6729 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6730 aopPut (AOP (result), "a", offset);
6734 emitcode ("orl", "%s,%s",
6735 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6736 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6742 if (AOP_TYPE (left) == AOP_ACC)
6744 emitcode ("orl", "a,%s",
6745 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6749 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6750 if (IS_AOP_PREG (left))
6752 emitcode ("orl", "a,%s",
6753 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6754 aopPut (AOP (result), "a", offset);
6758 emitcode ("orl", "%s,a",
6759 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6767 // left & result in different registers
6768 if (AOP_TYPE (result) == AOP_CRY)
6771 // if(size), result in bit
6772 // if(!size && ifx), conditional oper: if(left | right)
6773 symbol *tlbl = newiTempLabel (NULL);
6774 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6776 emitcode ("setb", "c");
6779 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6780 emitcode ("orl", "a,%s",
6781 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6783 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6784 emitcode ("orl", "a,%s",
6785 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6787 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6793 emitcode ("", "!tlabeldef", tlbl->key + 100);
6797 jmpTrueOrFalse (ifx, tlbl);
6801 _startLazyDPSEvaluation();
6802 for (; (size--); offset++)
6805 // result = left & right
6806 if (AOP_TYPE (right) == AOP_LIT)
6808 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6810 aopPut (AOP (result),
6811 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6815 D (emitcode (";", "better literal OR."););
6816 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6817 emitcode ("orl", "a, %s",
6818 aopGet (AOP (right), offset,
6819 FALSE, FALSE, DP2_RESULT_REG));
6824 // faster than result <- left, anl result,right
6825 // and better if result is SFR
6826 if (AOP_TYPE (left) == AOP_ACC)
6828 emitcode ("orl", "a,%s",
6829 aopGet (AOP (right), offset,
6830 FALSE, FALSE, DP2_RESULT_REG));
6834 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6836 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6838 emitcode("mov", "b,a");
6842 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6843 emitcode ("orl", "a,%s", rOp);
6846 aopPut (AOP (result), "a", offset);
6848 _endLazyDPSEvaluation();
6853 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6854 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6855 freeAsmop (result, NULL, ic, TRUE);
6858 /*-----------------------------------------------------------------*/
6859 /* genXor - code for xclusive or */
6860 /*-----------------------------------------------------------------*/
6862 genXor (iCode * ic, iCode * ifx)
6864 operand *left, *right, *result;
6865 int size, offset = 0;
6866 unsigned long lit = 0L;
6869 D (emitcode (";", "genXor "););
6871 AOP_OP_3_NOFATAL (ic, pushResult);
6872 AOP_SET_LOCALS (ic);
6876 genFarFarLogicOp(ic, "xrl");
6881 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6883 AOP_TYPE (left), AOP_TYPE (right));
6884 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6886 AOP_SIZE (left), AOP_SIZE (right));
6889 /* if left is a literal & right is not ||
6890 if left needs acc & right does not */
6891 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6892 #ifdef LOGIC_OPS_BROKEN
6893 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6897 operand *tmp = right;
6902 /* if result = right then exchange them */
6903 if (sameRegs (AOP (result), AOP (right)))
6905 operand *tmp = right;
6910 /* if right is bit then exchange them */
6911 if (AOP_TYPE (right) == AOP_CRY &&
6912 AOP_TYPE (left) != AOP_CRY)
6914 operand *tmp = right;
6918 if (AOP_TYPE (right) == AOP_LIT)
6919 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6921 size = AOP_SIZE (result);
6925 if (AOP_TYPE (left) == AOP_CRY)
6927 if (AOP_TYPE (right) == AOP_LIT)
6929 // c = bit & literal;
6932 // lit>>1 != 0 => result = 1
6933 if (AOP_TYPE (result) == AOP_CRY)
6936 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6938 continueIfTrue (ifx);
6941 emitcode ("setb", "c");
6948 // lit == 0, result = left
6949 if (size && sameRegs (AOP (result), AOP (left)))
6951 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6955 // lit == 1, result = not(left)
6956 if (size && sameRegs (AOP (result), AOP (left)))
6958 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6963 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6964 emitcode ("cpl", "c");
6973 symbol *tlbl = newiTempLabel (NULL);
6974 if (AOP_TYPE (right) == AOP_CRY)
6977 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6981 int sizer = AOP_SIZE (right);
6983 // if val>>1 != 0, result = 1
6984 emitcode ("setb", "c");
6987 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
6989 // test the msb of the lsb
6990 emitcode ("anl", "a,#!constbyte",0xfe);
6991 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6995 emitcode ("rrc", "a");
6997 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6998 emitcode ("cpl", "c");
6999 emitcode ("", "!tlabeldef", (tlbl->key + 100));
7006 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7007 genIfxJump (ifx, "c");
7011 if (sameRegs (AOP (result), AOP (left)))
7013 /* if left is same as result */
7014 for (; size--; offset++)
7016 if (AOP_TYPE (right) == AOP_LIT)
7018 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7020 else if (IS_AOP_PREG (left))
7022 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7023 emitcode ("xrl", "a,%s",
7024 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7025 aopPut (AOP (result), "a", offset);
7028 emitcode ("xrl", "%s,%s",
7029 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
7030 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7034 if (AOP_TYPE (left) == AOP_ACC)
7035 emitcode ("xrl", "a,%s",
7036 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7039 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7040 if (IS_AOP_PREG (left))
7042 emitcode ("xrl", "a,%s",
7043 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7044 aopPut (AOP (result), "a", offset);
7047 emitcode ("xrl", "%s,a",
7048 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7055 // left & result in different registers
7056 if (AOP_TYPE (result) == AOP_CRY)
7059 // if(size), result in bit
7060 // if(!size && ifx), conditional oper: if(left ^ right)
7061 symbol *tlbl = newiTempLabel (NULL);
7062 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7065 emitcode ("setb", "c");
7068 if ((AOP_TYPE (right) == AOP_LIT) &&
7069 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7071 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7075 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7076 emitcode ("xrl", "a,%s",
7077 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7079 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7080 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7082 emitcode("mov", "b,a");
7086 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7087 emitcode ("xrl", "a,%s", rOp);
7090 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7096 emitcode ("", "!tlabeldef", tlbl->key + 100);
7100 jmpTrueOrFalse (ifx, tlbl);
7104 for (; (size--); offset++)
7107 // result = left & right
7108 if (AOP_TYPE (right) == AOP_LIT)
7110 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7112 aopPut (AOP (result),
7113 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7117 D (emitcode (";", "better literal XOR."););
7118 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7119 emitcode ("xrl", "a, %s",
7120 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7124 // faster than result <- left, anl result,right
7125 // and better if result is SFR
7126 if (AOP_TYPE (left) == AOP_ACC)
7128 emitcode ("xrl", "a,%s",
7129 aopGet (AOP (right), offset,
7130 FALSE, FALSE, DP2_RESULT_REG));
7134 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7135 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7137 emitcode("mov", "b,a");
7141 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7142 emitcode ("xrl", "a,%s", rOp);
7145 aopPut (AOP (result), "a", offset);
7152 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7153 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7154 freeAsmop (result, NULL, ic, TRUE);
7157 /*-----------------------------------------------------------------*/
7158 /* genInline - write the inline code out */
7159 /*-----------------------------------------------------------------*/
7161 genInline (iCode * ic)
7163 char *buffer, *bp, *bp1;
7165 D (emitcode (";", "genInline "); );
7167 _G.inLine += (!options.asmpeep);
7169 buffer = Safe_strdup(IC_INLINE(ic));
7173 /* emit each line as a code */
7198 /* emitcode("",buffer); */
7199 _G.inLine -= (!options.asmpeep);
7202 /*-----------------------------------------------------------------*/
7203 /* genRRC - rotate right with carry */
7204 /*-----------------------------------------------------------------*/
7208 operand *left, *result;
7211 D (emitcode (";", "genRRC "););
7213 /* rotate right with carry */
7214 left = IC_LEFT (ic);
7215 result = IC_RESULT (ic);
7216 aopOp (left, ic, FALSE, FALSE);
7217 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7219 /* move it to the result */
7220 size = AOP_SIZE (result);
7224 _startLazyDPSEvaluation ();
7227 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7228 emitcode ("rrc", "a");
7229 if (AOP_SIZE (result) > 1)
7230 aopPut (AOP (result), "a", offset--);
7232 _endLazyDPSEvaluation ();
7234 /* now we need to put the carry into the
7235 highest order byte of the result */
7236 if (AOP_SIZE (result) > 1)
7238 MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7240 emitcode ("mov", "acc.7,c");
7241 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7242 freeAsmop (left, NULL, ic, TRUE);
7243 freeAsmop (result, NULL, ic, TRUE);
7246 /*-----------------------------------------------------------------*/
7247 /* genRLC - generate code for rotate left with carry */
7248 /*-----------------------------------------------------------------*/
7252 operand *left, *result;
7256 D (emitcode (";", "genRLC "););
7258 /* rotate right with carry */
7259 left = IC_LEFT (ic);
7260 result = IC_RESULT (ic);
7261 aopOp (left, ic, FALSE, FALSE);
7262 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7264 /* move it to the result */
7265 size = AOP_SIZE (result);
7269 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7271 emitcode ("add", "a,acc");
7272 if (AOP_SIZE (result) > 1)
7274 aopPut (AOP (result), "a", offset++);
7277 _startLazyDPSEvaluation ();
7280 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7282 emitcode ("rlc", "a");
7283 if (AOP_SIZE (result) > 1)
7284 aopPut (AOP (result), "a", offset++);
7286 _endLazyDPSEvaluation ();
7288 /* now we need to put the carry into the
7289 highest order byte of the result */
7290 if (AOP_SIZE (result) > 1)
7292 l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7295 emitcode ("mov", "acc.0,c");
7296 aopPut (AOP (result), "a", 0);
7297 freeAsmop (left, NULL, ic, TRUE);
7298 freeAsmop (result, NULL, ic, TRUE);
7301 /*-----------------------------------------------------------------*/
7302 /* genGetHbit - generates code get highest order bit */
7303 /*-----------------------------------------------------------------*/
7305 genGetHbit (iCode * ic)
7307 operand *left, *result;
7308 left = IC_LEFT (ic);
7309 result = IC_RESULT (ic);
7310 aopOp (left, ic, FALSE, FALSE);
7311 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7313 D (emitcode (";", "genGetHbit "););
7315 /* get the highest order byte into a */
7316 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7317 if (AOP_TYPE (result) == AOP_CRY)
7319 emitcode ("rlc", "a");
7324 emitcode ("rl", "a");
7325 emitcode ("anl", "a,#1");
7330 freeAsmop (left, NULL, ic, TRUE);
7331 freeAsmop (result, NULL, ic, TRUE);
7334 /*-----------------------------------------------------------------*/
7335 /* AccRol - rotate left accumulator by known count */
7336 /*-----------------------------------------------------------------*/
7338 AccRol (int shCount)
7340 shCount &= 0x0007; // shCount : 0..7
7347 emitcode ("rl", "a");
7350 emitcode ("rl", "a");
7351 emitcode ("rl", "a");
7354 emitcode ("swap", "a");
7355 emitcode ("rr", "a");
7358 emitcode ("swap", "a");
7361 emitcode ("swap", "a");
7362 emitcode ("rl", "a");
7365 emitcode ("rr", "a");
7366 emitcode ("rr", "a");
7369 emitcode ("rr", "a");
7374 /*-----------------------------------------------------------------*/
7375 /* AccLsh - left shift accumulator by known count */
7376 /*-----------------------------------------------------------------*/
7378 AccLsh (int shCount)
7383 emitcode ("add", "a,acc");
7384 else if (shCount == 2)
7386 emitcode ("add", "a,acc");
7387 emitcode ("add", "a,acc");
7391 /* rotate left accumulator */
7393 /* and kill the lower order bits */
7394 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7399 /*-----------------------------------------------------------------*/
7400 /* AccRsh - right shift accumulator by known count */
7401 /*-----------------------------------------------------------------*/
7403 AccRsh (int shCount)
7410 emitcode ("rrc", "a");
7414 /* rotate right accumulator */
7415 AccRol (8 - shCount);
7416 /* and kill the higher order bits */
7417 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7422 #ifdef BETTER_LITERAL_SHIFT
7423 /*-----------------------------------------------------------------*/
7424 /* AccSRsh - signed right shift accumulator by known count */
7425 /*-----------------------------------------------------------------*/
7427 AccSRsh (int shCount)
7434 emitcode ("mov", "c,acc.7");
7435 emitcode ("rrc", "a");
7437 else if (shCount == 2)
7439 emitcode ("mov", "c,acc.7");
7440 emitcode ("rrc", "a");
7441 emitcode ("mov", "c,acc.7");
7442 emitcode ("rrc", "a");
7446 tlbl = newiTempLabel (NULL);
7447 /* rotate right accumulator */
7448 AccRol (8 - shCount);
7449 /* and kill the higher order bits */
7450 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7451 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7452 emitcode ("orl", "a,#!constbyte",
7453 (unsigned char) ~SRMask[shCount]);
7454 emitcode ("", "!tlabeldef", tlbl->key + 100);
7460 #ifdef BETTER_LITERAL_SHIFT
7461 /*-----------------------------------------------------------------*/
7462 /* shiftR1Left2Result - shift right one byte from left to result */
7463 /*-----------------------------------------------------------------*/
7465 shiftR1Left2Result (operand * left, int offl,
7466 operand * result, int offr,
7467 int shCount, int sign)
7469 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7470 /* shift right accumulator */
7475 aopPut (AOP (result), "a", offr);
7479 #ifdef BETTER_LITERAL_SHIFT
7480 /*-----------------------------------------------------------------*/
7481 /* shiftL1Left2Result - shift left one byte from left to result */
7482 /*-----------------------------------------------------------------*/
7484 shiftL1Left2Result (operand * left, int offl,
7485 operand * result, int offr, int shCount)
7487 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7488 /* shift left accumulator */
7490 aopPut (AOP (result), "a", offr);
7494 #ifdef BETTER_LITERAL_SHIFT
7495 /*-----------------------------------------------------------------*/
7496 /* movLeft2Result - move byte from left to result */
7497 /*-----------------------------------------------------------------*/
7499 movLeft2Result (operand * left, int offl,
7500 operand * result, int offr, int sign)
7503 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7505 l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
7507 if (*l == '@' && (IS_AOP_PREG (result)))
7509 emitcode ("mov", "a,%s", l);
7510 aopPut (AOP (result), "a", offr);
7516 aopPut (AOP (result), l, offr);
7520 /* MSB sign in acc.7 ! */
7521 if (getDataSize (left) == offl + 1)
7523 emitcode ("mov", "a,%s", l);
7524 aopPut (AOP (result), "a", offr);
7532 #ifdef BETTER_LITERAL_SHIFT
7533 /*-----------------------------------------------------------------*/
7534 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7535 /*-----------------------------------------------------------------*/
7539 emitcode ("rrc", "a");
7540 emitcode ("xch", "a,%s", x);
7541 emitcode ("rrc", "a");
7542 emitcode ("xch", "a,%s", x);
7546 #ifdef BETTER_LITERAL_SHIFT
7548 /*-----------------------------------------------------------------*/
7549 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7550 /*-----------------------------------------------------------------*/
7554 emitcode ("xch", "a,%s", x);
7555 emitcode ("rlc", "a");
7556 emitcode ("xch", "a,%s", x);
7557 emitcode ("rlc", "a");
7561 #ifdef BETTER_LITERAL_SHIFT
7562 /*-----------------------------------------------------------------*/
7563 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7564 /*-----------------------------------------------------------------*/
7568 emitcode ("xch", "a,%s", x);
7569 emitcode ("add", "a,acc");
7570 emitcode ("xch", "a,%s", x);
7571 emitcode ("rlc", "a");
7575 #ifdef BETTER_LITERAL_SHIFT
7576 /*-----------------------------------------------------------------*/
7577 /* AccAXLsh - left shift a:x by known count (0..7) */
7578 /*-----------------------------------------------------------------*/
7580 AccAXLsh (char *x, int shCount)
7595 case 5: // AAAAABBB:CCCCCDDD
7597 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7599 emitcode ("anl", "a,#!constbyte",
7600 SLMask[shCount]); // BBB00000:CCCCCDDD
7602 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7604 AccRol (shCount); // DDDCCCCC:BBB00000
7606 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7608 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7610 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7612 emitcode ("anl", "a,#!constbyte",
7613 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7615 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7617 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7620 case 6: // AAAAAABB:CCCCCCDD
7621 emitcode ("anl", "a,#!constbyte",
7622 SRMask[shCount]); // 000000BB:CCCCCCDD
7623 emitcode ("mov", "c,acc.0"); // c = B
7624 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7626 AccAXRrl1 (x); // BCCCCCCD:D000000B
7627 AccAXRrl1 (x); // BBCCCCCC:DD000000
7629 emitcode("rrc","a");
7630 emitcode("xch","a,%s", x);
7631 emitcode("rrc","a");
7632 emitcode("mov","c,acc.0"); //<< get correct bit
7633 emitcode("xch","a,%s", x);
7635 emitcode("rrc","a");
7636 emitcode("xch","a,%s", x);
7637 emitcode("rrc","a");
7638 emitcode("xch","a,%s", x);
7641 case 7: // a:x <<= 7
7643 emitcode ("anl", "a,#!constbyte",
7644 SRMask[shCount]); // 0000000B:CCCCCCCD
7646 emitcode ("mov", "c,acc.0"); // c = B
7648 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7650 AccAXRrl1 (x); // BCCCCCCC:D0000000
7659 #ifdef BETTER_LITERAL_SHIFT
7661 /*-----------------------------------------------------------------*/
7662 /* AccAXRsh - right shift a:x known count (0..7) */
7663 /*-----------------------------------------------------------------*/
7665 AccAXRsh (char *x, int shCount)
7673 AccAXRrl1 (x); // 0->a:x
7678 AccAXRrl1 (x); // 0->a:x
7681 AccAXRrl1 (x); // 0->a:x
7686 case 5: // AAAAABBB:CCCCCDDD = a:x
7688 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7690 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7692 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7694 emitcode ("anl", "a,#!constbyte",
7695 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7697 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7699 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7701 emitcode ("anl", "a,#!constbyte",
7702 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7704 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7706 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7708 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7711 case 6: // AABBBBBB:CCDDDDDD
7713 emitcode ("mov", "c,acc.7");
7714 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7716 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7718 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7720 emitcode ("anl", "a,#!constbyte",
7721 SRMask[shCount]); // 000000AA:BBBBBBCC
7724 case 7: // ABBBBBBB:CDDDDDDD
7726 emitcode ("mov", "c,acc.7"); // c = A
7728 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7730 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7732 emitcode ("anl", "a,#!constbyte",
7733 SRMask[shCount]); // 0000000A:BBBBBBBC
7742 #ifdef BETTER_LITERAL_SHIFT
7743 /*-----------------------------------------------------------------*/
7744 /* AccAXRshS - right shift signed a:x known count (0..7) */
7745 /*-----------------------------------------------------------------*/
7747 AccAXRshS (char *x, int shCount)
7755 emitcode ("mov", "c,acc.7");
7756 AccAXRrl1 (x); // s->a:x
7760 emitcode ("mov", "c,acc.7");
7761 AccAXRrl1 (x); // s->a:x
7763 emitcode ("mov", "c,acc.7");
7764 AccAXRrl1 (x); // s->a:x
7769 case 5: // AAAAABBB:CCCCCDDD = a:x
7771 tlbl = newiTempLabel (NULL);
7772 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7774 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7776 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7778 emitcode ("anl", "a,#!constbyte",
7779 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7781 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7783 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7785 emitcode ("anl", "a,#!constbyte",
7786 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7788 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7790 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7792 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7794 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7795 emitcode ("orl", "a,#!constbyte",
7796 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7798 emitcode ("", "!tlabeldef", tlbl->key + 100);
7799 break; // SSSSAAAA:BBBCCCCC
7801 case 6: // AABBBBBB:CCDDDDDD
7803 tlbl = newiTempLabel (NULL);
7804 emitcode ("mov", "c,acc.7");
7805 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7807 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7809 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7811 emitcode ("anl", "a,#!constbyte",
7812 SRMask[shCount]); // 000000AA:BBBBBBCC
7814 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7815 emitcode ("orl", "a,#!constbyte",
7816 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7818 emitcode ("", "!tlabeldef", tlbl->key + 100);
7820 case 7: // ABBBBBBB:CDDDDDDD
7822 tlbl = newiTempLabel (NULL);
7823 emitcode ("mov", "c,acc.7"); // c = A
7825 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7827 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7829 emitcode ("anl", "a,#!constbyte",
7830 SRMask[shCount]); // 0000000A:BBBBBBBC
7832 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7833 emitcode ("orl", "a,#!constbyte",
7834 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7836 emitcode ("", "!tlabeldef", tlbl->key + 100);
7844 #ifdef BETTER_LITERAL_SHIFT
7846 _loadLeftIntoAx(char **lsb,
7852 // Get the initial value from left into a pair of registers.
7853 // MSB must be in A, LSB can be any register.
7855 // If the result is held in registers, it is an optimization
7856 // if the LSB can be held in the register which will hold the,
7857 // result LSB since this saves us from having to copy it into
7858 // the result following AccAXLsh.
7860 // If the result is addressed indirectly, this is not a gain.
7861 if (AOP_NEEDSACC(result))
7865 _startLazyDPSEvaluation();
7866 if (AOP_TYPE(left) == AOP_DPTR2)
7869 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
7870 // get LSB in DP2_RESULT_REG.
7871 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
7872 assert(!strcmp(leftByte, DP2_RESULT_REG));
7876 // get LSB into DP2_RESULT_REG
7877 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
7878 if (strcmp(leftByte, DP2_RESULT_REG))
7881 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7884 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
7885 assert(strcmp(leftByte, DP2_RESULT_REG));
7888 _endLazyDPSEvaluation();
7889 *lsb = DP2_RESULT_REG;
7893 if (sameRegs (AOP (result), AOP (left)) &&
7894 ((offl + MSB16) == offr))
7896 /* don't crash result[offr] */
7897 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
7898 emitcode ("xch", "a,%s",
7899 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
7903 movLeft2Result (left, offl, result, offr, 0);
7904 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
7906 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
7907 assert(strcmp(*lsb,"a"));
7912 _storeAxResults(char *lsb,
7916 _startLazyDPSEvaluation();
7917 if (AOP_NEEDSACC(result))
7919 /* We have to explicitly update the result LSB.
7921 emitcode("xch","a,%s", lsb);
7922 aopPut(AOP(result), "a", offr);
7923 emitcode("mov","a,%s", lsb);
7925 if (getDataSize (result) > 1)
7927 aopPut (AOP (result), "a", offr + MSB16);
7929 _endLazyDPSEvaluation();
7932 /*-----------------------------------------------------------------*/
7933 /* shiftL2Left2Result - shift left two bytes from left to result */
7934 /*-----------------------------------------------------------------*/
7936 shiftL2Left2Result (operand * left, int offl,
7937 operand * result, int offr, int shCount)
7941 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7943 AccAXLsh (lsb, shCount);
7945 _storeAxResults(lsb, result, offr);
7949 #ifdef BETTER_LITERAL_SHIFT
7950 /*-----------------------------------------------------------------*/
7951 /* shiftR2Left2Result - shift right two bytes from left to result */
7952 /*-----------------------------------------------------------------*/
7954 shiftR2Left2Result (operand * left, int offl,
7955 operand * result, int offr,
7956 int shCount, int sign)
7960 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7962 /* a:x >> shCount (x = lsb(result)) */
7965 AccAXRshS(lsb, shCount);
7969 AccAXRsh(lsb, shCount);
7972 _storeAxResults(lsb, result, offr);
7976 /*-----------------------------------------------------------------*/
7977 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7978 /*-----------------------------------------------------------------*/
7980 shiftLLeftOrResult (operand * left, int offl,
7981 operand * result, int offr, int shCount)
7983 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7984 /* shift left accumulator */
7986 /* or with result */
7987 emitcode ("orl", "a,%s",
7988 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7989 /* back to result */
7990 aopPut (AOP (result), "a", offr);
7995 /*-----------------------------------------------------------------*/
7996 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7997 /*-----------------------------------------------------------------*/
7999 shiftRLeftOrResult (operand * left, int offl,
8000 operand * result, int offr, int shCount)
8002 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8003 /* shift right accumulator */
8005 /* or with result */
8006 emitcode ("orl", "a,%s",
8007 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8008 /* back to result */
8009 aopPut (AOP (result), "a", offr);
8013 #ifdef BETTER_LITERAL_SHIFT
8014 /*-----------------------------------------------------------------*/
8015 /* genlshOne - left shift a one byte quantity by known count */
8016 /*-----------------------------------------------------------------*/
8018 genlshOne (operand * result, operand * left, int shCount)
8020 D (emitcode (";", "genlshOne "););
8021 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8025 #ifdef BETTER_LITERAL_SHIFT
8026 /*-----------------------------------------------------------------*/
8027 /* genlshTwo - left shift two bytes by known amount != 0 */
8028 /*-----------------------------------------------------------------*/
8030 genlshTwo (operand * result, operand * left, int shCount)
8034 D (emitcode (";", "genlshTwo "););
8036 size = getDataSize (result);
8038 /* if shCount >= 8 */
8043 _startLazyDPSEvaluation();
8049 _endLazyDPSEvaluation();
8050 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8051 aopPut (AOP (result), zero, LSB);
8055 movLeft2Result (left, LSB, result, MSB16, 0);
8056 aopPut (AOP (result), zero, LSB);
8057 _endLazyDPSEvaluation();
8062 aopPut (AOP (result), zero, LSB);
8063 _endLazyDPSEvaluation();
8067 /* 1 <= shCount <= 7 */
8072 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8076 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8084 /*-----------------------------------------------------------------*/
8085 /* shiftLLong - shift left one long from left to result */
8086 /* offl = LSB or MSB16 */
8087 /*-----------------------------------------------------------------*/
8089 shiftLLong (operand * left, operand * result, int offr)
8092 int size = AOP_SIZE (result);
8094 if (size >= LSB + offr)
8096 l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8098 emitcode ("add", "a,acc");
8099 if (sameRegs (AOP (left), AOP (result)) &&
8100 size >= MSB16 + offr && offr != LSB)
8101 emitcode ("xch", "a,%s",
8102 aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8104 aopPut (AOP (result), "a", LSB + offr);
8107 if (size >= MSB16 + offr)
8109 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8111 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8113 emitcode ("rlc", "a");
8114 if (sameRegs (AOP (left), AOP (result)) &&
8115 size >= MSB24 + offr && offr != LSB)
8116 emitcode ("xch", "a,%s",
8117 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8119 aopPut (AOP (result), "a", MSB16 + offr);
8122 if (size >= MSB24 + offr)
8124 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8126 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8128 emitcode ("rlc", "a");
8129 if (sameRegs (AOP (left), AOP (result)) &&
8130 size >= MSB32 + offr && offr != LSB)
8131 emitcode ("xch", "a,%s",
8132 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8134 aopPut (AOP (result), "a", MSB24 + offr);
8137 if (size > MSB32 + offr)
8139 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8141 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8143 emitcode ("rlc", "a");
8144 aopPut (AOP (result), "a", MSB32 + offr);
8147 aopPut (AOP (result), zero, LSB);
8153 /*-----------------------------------------------------------------*/
8154 /* genlshFour - shift four byte by a known amount != 0 */
8155 /*-----------------------------------------------------------------*/
8157 genlshFour (operand * result, operand * left, int shCount)
8161 D (emitcode (";", "genlshFour ");
8164 size = AOP_SIZE (result);
8166 /* if shifting more that 3 bytes */
8171 /* lowest order of left goes to the highest
8172 order of the destination */
8173 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8175 movLeft2Result (left, LSB, result, MSB32, 0);
8176 aopPut (AOP (result), zero, LSB);
8177 aopPut (AOP (result), zero, MSB16);
8178 aopPut (AOP (result), zero, MSB24);
8182 /* more than two bytes */
8183 else if (shCount >= 16)
8185 /* lower order two bytes goes to higher order two bytes */
8187 /* if some more remaining */
8189 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8192 movLeft2Result (left, MSB16, result, MSB32, 0);
8193 movLeft2Result (left, LSB, result, MSB24, 0);
8195 aopPut (AOP (result), zero, MSB16);
8196 aopPut (AOP (result), zero, LSB);
8200 /* if more than 1 byte */
8201 else if (shCount >= 8)
8203 /* lower order three bytes goes to higher order three bytes */
8208 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8210 movLeft2Result (left, LSB, result, MSB16, 0);
8216 movLeft2Result (left, MSB24, result, MSB32, 0);
8217 movLeft2Result (left, MSB16, result, MSB24, 0);
8218 movLeft2Result (left, LSB, result, MSB16, 0);
8219 aopPut (AOP (result), zero, LSB);
8221 else if (shCount == 1)
8222 shiftLLong (left, result, MSB16);
8225 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8226 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8227 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8228 aopPut (AOP (result), zero, LSB);
8233 /* 1 <= shCount <= 7 */
8234 else if (shCount <= 2)
8236 shiftLLong (left, result, LSB);
8238 shiftLLong (result, result, LSB);
8240 /* 3 <= shCount <= 7, optimize */
8243 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8244 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8245 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8250 #ifdef BETTER_LITERAL_SHIFT
8251 /*-----------------------------------------------------------------*/
8252 /* genLeftShiftLiteral - left shifting by known count */
8253 /*-----------------------------------------------------------------*/
8255 genLeftShiftLiteral (operand * left,
8260 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8263 size = getSize (operandType (result));
8265 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8267 /* We only handle certain easy cases so far. */
8269 && (shCount < (size * 8))
8273 D(emitcode (";", "genLeftShiftLiteral wimping out"););
8277 freeAsmop (right, NULL, ic, TRUE);
8279 aopOp(left, ic, FALSE, FALSE);
8280 aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8283 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8285 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8286 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8288 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8291 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8293 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8294 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8296 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8302 emitcode ("; shift left ", "result %d, left %d", size,
8306 /* I suppose that the left size >= result size */
8309 _startLazyDPSEvaluation();
8312 movLeft2Result (left, size, result, size, 0);
8314 _endLazyDPSEvaluation();
8316 else if (shCount >= (size * 8))
8318 _startLazyDPSEvaluation();
8321 aopPut (AOP (result), zero, size);
8323 _endLazyDPSEvaluation();
8330 genlshOne (result, left, shCount);
8334 genlshTwo (result, left, shCount);
8338 genlshFour (result, left, shCount);
8342 fprintf(stderr, "*** ack! mystery literal shift!\n");
8346 freeAsmop (left, NULL, ic, TRUE);
8347 freeAsmop (result, NULL, ic, TRUE);
8352 /*-----------------------------------------------------------------*/
8353 /* genLeftShift - generates code for left shifting */
8354 /*-----------------------------------------------------------------*/
8356 genLeftShift (iCode * ic)
8358 operand *left, *right, *result;
8361 symbol *tlbl, *tlbl1;
8363 D (emitcode (";", "genLeftShift "););
8365 right = IC_RIGHT (ic);
8366 left = IC_LEFT (ic);
8367 result = IC_RESULT (ic);
8369 aopOp (right, ic, FALSE, FALSE);
8372 #ifdef BETTER_LITERAL_SHIFT
8373 /* if the shift count is known then do it
8374 as efficiently as possible */
8375 if (AOP_TYPE (right) == AOP_LIT)
8377 if (genLeftShiftLiteral (left, right, result, ic))
8384 /* shift count is unknown then we have to form
8385 a loop get the loop count in B : Note: we take
8386 only the lower order byte since shifting
8387 more that 32 bits make no sense anyway, ( the
8388 largest size of an object can be only 32 bits ) */
8390 if (AOP_TYPE (right) == AOP_LIT)
8392 /* Really should be handled by genLeftShiftLiteral,
8393 * but since I'm too lazy to fix that today, at least we can make
8394 * some small improvement.
8396 emitcode("mov", "b,#!constbyte",
8397 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8401 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8402 emitcode ("inc", "b");
8404 freeAsmop (right, NULL, ic, TRUE);
8405 aopOp (left, ic, FALSE, FALSE);
8406 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8408 /* now move the left to the result if they are not the
8410 if (!sameRegs (AOP (left), AOP (result)) &&
8411 AOP_SIZE (result) > 1)
8414 size = AOP_SIZE (result);
8416 _startLazyDPSEvaluation ();
8419 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8420 if (*l == '@' && (IS_AOP_PREG (result)))
8423 emitcode ("mov", "a,%s", l);
8424 aopPut (AOP (result), "a", offset);
8427 aopPut (AOP (result), l, offset);
8430 _endLazyDPSEvaluation ();
8433 tlbl = newiTempLabel (NULL);
8434 size = AOP_SIZE (result);
8436 tlbl1 = newiTempLabel (NULL);
8438 /* if it is only one byte then */
8441 symbol *tlbl1 = newiTempLabel (NULL);
8443 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8444 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8445 emitcode ("", "!tlabeldef", tlbl->key + 100);
8446 emitcode ("add", "a,acc");
8447 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8448 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8449 aopPut (AOP (result), "a", 0);
8453 reAdjustPreg (AOP (result));
8455 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8456 emitcode ("", "!tlabeldef", tlbl->key + 100);
8457 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8458 emitcode ("add", "a,acc");
8459 aopPut (AOP (result), "a", offset++);
8460 _startLazyDPSEvaluation ();
8463 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8464 emitcode ("rlc", "a");
8465 aopPut (AOP (result), "a", offset++);
8467 _endLazyDPSEvaluation ();
8468 reAdjustPreg (AOP (result));
8470 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8471 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8473 freeAsmop (left, NULL, ic, TRUE);
8474 freeAsmop (result, NULL, ic, TRUE);
8477 #ifdef BETTER_LITERAL_SHIFT
8478 /*-----------------------------------------------------------------*/
8479 /* genrshOne - right shift a one byte quantity by known count */
8480 /*-----------------------------------------------------------------*/
8482 genrshOne (operand * result, operand * left,
8483 int shCount, int sign)
8485 D (emitcode (";", "genrshOne"););
8486 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8490 #ifdef BETTER_LITERAL_SHIFT
8491 /*-----------------------------------------------------------------*/
8492 /* genrshTwo - right shift two bytes by known amount != 0 */
8493 /*-----------------------------------------------------------------*/
8495 genrshTwo (operand * result, operand * left,
8496 int shCount, int sign)
8498 D (emitcode (";", "genrshTwo"););
8500 /* if shCount >= 8 */
8504 _startLazyDPSEvaluation();
8507 shiftR1Left2Result (left, MSB16, result, LSB,
8512 movLeft2Result (left, MSB16, result, LSB, sign);
8514 addSign (result, MSB16, sign);
8515 _endLazyDPSEvaluation();
8518 /* 1 <= shCount <= 7 */
8521 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8526 /*-----------------------------------------------------------------*/
8527 /* shiftRLong - shift right one long from left to result */
8528 /* offl = LSB or MSB16 */
8529 /*-----------------------------------------------------------------*/
8531 shiftRLong (operand * left, int offl,
8532 operand * result, int sign)
8534 int isSameRegs=sameRegs(AOP(left),AOP(result));
8536 if (isSameRegs && offl>1) {
8537 // we are in big trouble, but this shouldn't happen
8538 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8541 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8546 emitcode ("rlc", "a");
8547 emitcode ("subb", "a,acc");
8548 emitcode ("xch", "a,%s",
8549 aopGet(AOP(left), MSB32, FALSE, FALSE, DP2_RESULT_REG));
8551 aopPut (AOP(result), zero, MSB32);
8556 emitcode ("clr", "c");
8558 emitcode ("mov", "c,acc.7");
8561 emitcode ("rrc", "a");
8563 if (isSameRegs && offl==MSB16) {
8565 "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE, DP2_RESULT_REG));
8567 aopPut (AOP (result), "a", MSB32);
8568 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8571 emitcode ("rrc", "a");
8572 if (isSameRegs && offl==1) {
8573 emitcode ("xch", "a,%s",
8574 aopGet (AOP (left), MSB16, FALSE, FALSE, DP2_RESULT_REG));
8576 aopPut (AOP (result), "a", MSB24);
8577 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, NULL));
8579 emitcode ("rrc", "a");
8580 aopPut (AOP (result), "a", MSB16 - offl);
8584 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, NULL));
8585 emitcode ("rrc", "a");
8586 aopPut (AOP (result), "a", LSB);
8590 /*-----------------------------------------------------------------*/
8591 /* genrshFour - shift four byte by a known amount != 0 */
8592 /*-----------------------------------------------------------------*/
8594 genrshFour (operand * result, operand * left,
8595 int shCount, int sign)
8597 D (emitcode (";", "genrshFour"););
8599 /* if shifting more that 3 bytes */
8603 _startLazyDPSEvaluation();
8605 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8607 movLeft2Result (left, MSB32, result, LSB, sign);
8608 addSign (result, MSB16, sign);
8609 _endLazyDPSEvaluation();
8611 else if (shCount >= 16)
8614 _startLazyDPSEvaluation();
8616 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8619 movLeft2Result (left, MSB24, result, LSB, 0);
8620 movLeft2Result (left, MSB32, result, MSB16, sign);
8622 addSign (result, MSB24, sign);
8623 _endLazyDPSEvaluation();
8625 else if (shCount >= 8)
8628 _startLazyDPSEvaluation();
8631 shiftRLong (left, MSB16, result, sign);
8633 else if (shCount == 0)
8635 movLeft2Result (left, MSB16, result, LSB, 0);
8636 movLeft2Result (left, MSB24, result, MSB16, 0);
8637 movLeft2Result (left, MSB32, result, MSB24, sign);
8638 addSign (result, MSB32, sign);
8642 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8643 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8644 /* the last shift is signed */
8645 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8646 addSign (result, MSB32, sign);
8648 _endLazyDPSEvaluation();
8652 /* 1 <= shCount <= 7 */
8655 shiftRLong (left, LSB, result, sign);
8657 shiftRLong (result, LSB, result, sign);
8661 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8662 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8663 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8668 #ifdef BETTER_LITERAL_SHIFT
8669 /*-----------------------------------------------------------------*/
8670 /* genRightShiftLiteral - right shifting by known count */
8671 /*-----------------------------------------------------------------*/
8673 genRightShiftLiteral (operand * left,
8679 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8682 size = getSize (operandType (result));
8684 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8686 /* We only handle certain easy cases so far. */
8688 && (shCount < (size * 8))
8693 D(emitcode (";", "genRightShiftLiteral wimping out"););
8697 freeAsmop (right, NULL, ic, TRUE);
8699 aopOp (left, ic, FALSE, FALSE);
8700 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8703 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8707 /* test the LEFT size !!! */
8709 /* I suppose that the left size >= result size */
8712 size = getDataSize (result);
8713 _startLazyDPSEvaluation();
8716 movLeft2Result (left, size, result, size, 0);
8718 _endLazyDPSEvaluation();
8720 else if (shCount >= (size * 8))
8724 /* get sign in acc.7 */
8725 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
8727 addSign (result, LSB, sign);
8734 genrshOne (result, left, shCount, sign);
8738 genrshTwo (result, left, shCount, sign);
8742 genrshFour (result, left, shCount, sign);
8749 freeAsmop (left, NULL, ic, TRUE);
8750 freeAsmop (result, NULL, ic, TRUE);
8756 /*-----------------------------------------------------------------*/
8757 /* genSignedRightShift - right shift of signed number */
8758 /*-----------------------------------------------------------------*/
8760 genSignedRightShift (iCode * ic)
8762 operand *right, *left, *result;
8765 symbol *tlbl, *tlbl1;
8767 D (emitcode (";", "genSignedRightShift "););
8769 /* we do it the hard way put the shift count in b
8770 and loop thru preserving the sign */
8772 right = IC_RIGHT (ic);
8773 left = IC_LEFT (ic);
8774 result = IC_RESULT (ic);
8776 aopOp (right, ic, FALSE, FALSE);
8778 #ifdef BETTER_LITERAL_SHIFT
8779 if (AOP_TYPE (right) == AOP_LIT)
8781 if (genRightShiftLiteral (left, right, result, ic, 1))
8787 /* shift count is unknown then we have to form
8788 a loop get the loop count in B : Note: we take
8789 only the lower order byte since shifting
8790 more that 32 bits make no sense anyway, ( the
8791 largest size of an object can be only 32 bits ) */
8793 if (AOP_TYPE (right) == AOP_LIT)
8795 /* Really should be handled by genRightShiftLiteral,
8796 * but since I'm too lazy to fix that today, at least we can make
8797 * some small improvement.
8799 emitcode("mov", "b,#!constbyte",
8800 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8804 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8805 emitcode ("inc", "b");
8807 freeAsmop (right, NULL, ic, TRUE);
8808 aopOp (left, ic, FALSE, FALSE);
8809 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8811 /* now move the left to the result if they are not the
8813 if (!sameRegs (AOP (left), AOP (result)) &&
8814 AOP_SIZE (result) > 1)
8817 size = AOP_SIZE (result);
8819 _startLazyDPSEvaluation ();
8822 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8823 if (*l == '@' && IS_AOP_PREG (result))
8826 emitcode ("mov", "a,%s", l);
8827 aopPut (AOP (result), "a", offset);
8830 aopPut (AOP (result), l, offset);
8833 _endLazyDPSEvaluation ();
8836 /* mov the highest order bit to OVR */
8837 tlbl = newiTempLabel (NULL);
8838 tlbl1 = newiTempLabel (NULL);
8840 size = AOP_SIZE (result);
8842 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
8843 emitcode ("rlc", "a");
8844 emitcode ("mov", "ov,c");
8845 /* if it is only one byte then */
8848 MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8849 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8850 emitcode ("", "!tlabeldef", tlbl->key + 100);
8851 emitcode ("mov", "c,ov");
8852 emitcode ("rrc", "a");
8853 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8854 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8855 aopPut (AOP (result), "a", 0);
8859 reAdjustPreg (AOP (result));
8860 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8861 emitcode ("", "!tlabeldef", tlbl->key + 100);
8862 emitcode ("mov", "c,ov");
8863 _startLazyDPSEvaluation ();
8866 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8867 emitcode ("rrc", "a");
8868 aopPut (AOP (result), "a", offset--);
8870 _endLazyDPSEvaluation ();
8871 reAdjustPreg (AOP (result));
8872 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8873 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8876 freeAsmop (left, NULL, ic, TRUE);
8877 freeAsmop (result, NULL, ic, TRUE);
8880 /*-----------------------------------------------------------------*/
8881 /* genRightShift - generate code for right shifting */
8882 /*-----------------------------------------------------------------*/
8884 genRightShift (iCode * ic)
8886 operand *right, *left, *result;
8890 symbol *tlbl, *tlbl1;
8892 D (emitcode (";", "genRightShift "););
8894 /* if signed then we do it the hard way preserve the
8895 sign bit moving it inwards */
8896 retype = getSpec (operandType (IC_RESULT (ic)));
8898 if (!SPEC_USIGN (retype))
8900 genSignedRightShift (ic);
8904 /* signed & unsigned types are treated the same : i.e. the
8905 signed is NOT propagated inwards : quoting from the
8906 ANSI - standard : "for E1 >> E2, is equivalent to division
8907 by 2**E2 if unsigned or if it has a non-negative value,
8908 otherwise the result is implementation defined ", MY definition
8909 is that the sign does not get propagated */
8911 right = IC_RIGHT (ic);
8912 left = IC_LEFT (ic);
8913 result = IC_RESULT (ic);
8915 aopOp (right, ic, FALSE, FALSE);
8917 #ifdef BETTER_LITERAL_SHIFT
8918 /* if the shift count is known then do it
8919 as efficiently as possible */
8920 if (AOP_TYPE (right) == AOP_LIT)
8922 if (genRightShiftLiteral (left, right, result, ic, 0))
8929 /* shift count is unknown then we have to form
8930 a loop get the loop count in B : Note: we take
8931 only the lower order byte since shifting
8932 more that 32 bits make no sense anyway, ( the
8933 largest size of an object can be only 32 bits ) */
8935 if (AOP_TYPE (right) == AOP_LIT)
8937 /* Really should be handled by genRightShiftLiteral,
8938 * but since I'm too lazy to fix that today, at least we can make
8939 * some small improvement.
8941 emitcode("mov", "b,#!constbyte",
8942 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8946 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8947 emitcode ("inc", "b");
8949 freeAsmop (right, NULL, ic, TRUE);
8950 aopOp (left, ic, FALSE, FALSE);
8951 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8953 /* now move the left to the result if they are not the
8955 if (!sameRegs (AOP (left), AOP (result)) &&
8956 AOP_SIZE (result) > 1)
8959 size = AOP_SIZE (result);
8961 _startLazyDPSEvaluation ();
8964 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8965 if (*l == '@' && IS_AOP_PREG (result))
8968 emitcode ("mov", "a,%s", l);
8969 aopPut (AOP (result), "a", offset);
8972 aopPut (AOP (result), l, offset);
8975 _endLazyDPSEvaluation ();
8978 tlbl = newiTempLabel (NULL);
8979 tlbl1 = newiTempLabel (NULL);
8980 size = AOP_SIZE (result);
8983 /* if it is only one byte then */
8986 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8987 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8988 emitcode ("", "!tlabeldef", tlbl->key + 100);
8990 emitcode ("rrc", "a");
8991 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8992 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8993 aopPut (AOP (result), "a", 0);
8997 reAdjustPreg (AOP (result));
8998 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8999 emitcode ("", "!tlabeldef", tlbl->key + 100);
9001 _startLazyDPSEvaluation ();
9004 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
9005 emitcode ("rrc", "a");
9006 aopPut (AOP (result), "a", offset--);
9008 _endLazyDPSEvaluation ();
9009 reAdjustPreg (AOP (result));
9011 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9012 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9015 freeAsmop (left, NULL, ic, TRUE);
9016 freeAsmop (result, NULL, ic, TRUE);
9020 /*-----------------------------------------------------------------*/
9021 /* emitPtrByteGet - emits code to get a byte into A through a */
9022 /* pointer register (R0, R1, or DPTR). The */
9023 /* original value of A can be preserved in B. */
9024 /*-----------------------------------------------------------------*/
9026 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9033 emitcode ("mov", "b,a");
9034 emitcode ("mov", "a,@%s", rname);
9039 emitcode ("mov", "b,a");
9040 emitcode ("movx", "a,@%s", rname);
9045 emitcode ("mov", "b,a");
9046 emitcode ("movx", "a,@dptr");
9051 emitcode ("mov", "b,a");
9052 emitcode ("clr", "a");
9053 emitcode ("movc", "a,@a+dptr");
9059 emitcode ("push", "b");
9060 emitcode ("push", "acc");
9062 emitcode ("lcall", "__gptrget");
9064 emitcode ("pop", "b");
9069 /*-----------------------------------------------------------------*/
9070 /* emitPtrByteSet - emits code to set a byte from src through a */
9071 /* pointer register (R0, R1, or DPTR). */
9072 /*-----------------------------------------------------------------*/
9074 emitPtrByteSet (char *rname, int p_type, char *src)
9083 emitcode ("mov", "@%s,a", rname);
9086 emitcode ("mov", "@%s,%s", rname, src);
9091 emitcode ("movx", "@%s,a", rname);
9096 emitcode ("movx", "@dptr,a");
9101 emitcode ("lcall", "__gptrput");
9106 /*-----------------------------------------------------------------*/
9107 /* genUnpackBits - generates code for unpacking bits */
9108 /*-----------------------------------------------------------------*/
9110 genUnpackBits (operand * result, char *rname, int ptype)
9112 int offset = 0; /* result byte offset */
9113 int rsize; /* result size */
9114 int rlen = 0; /* remaining bitfield length */
9115 sym_link *etype; /* bitfield type information */
9116 int blen; /* bitfield length */
9117 int bstr; /* bitfield starting bit within byte */
9119 D(emitcode ("; genUnpackBits",""));
9121 etype = getSpec (operandType (result));
9122 rsize = getSize (operandType (result));
9123 blen = SPEC_BLEN (etype);
9124 bstr = SPEC_BSTR (etype);
9126 /* If the bitfield length is less than a byte */
9129 emitPtrByteGet (rname, ptype, FALSE);
9131 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
9132 aopPut (AOP (result), "a", offset++);
9136 /* Bit field did not fit in a byte. Copy all
9137 but the partial byte at the end. */
9138 for (rlen=blen;rlen>=8;rlen-=8)
9140 emitPtrByteGet (rname, ptype, FALSE);
9141 aopPut (AOP (result), "a", offset++);
9143 emitcode ("inc", "%s", rname);
9146 /* Handle the partial byte at the end */
9149 emitPtrByteGet (rname, ptype, FALSE);
9150 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
9151 aopPut (AOP (result), "a", offset++);
9159 aopPut (AOP (result), zero, offset++);
9164 /*-----------------------------------------------------------------*/
9165 /* genDataPointerGet - generates code when ptr offset is known */
9166 /*-----------------------------------------------------------------*/
9168 genDataPointerGet (operand * left,
9174 int size, offset = 0;
9175 aopOp (result, ic, TRUE, FALSE);
9177 /* get the string representation of the name */
9178 l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9179 size = AOP_SIZE (result);
9180 _startLazyDPSEvaluation ();
9185 SNPRINTF (buff, sizeof(buff),
9186 "(%s + %d)", l + 1, offset);
9190 SNPRINTF (buff, sizeof(buff),
9193 aopPut (AOP (result), buff, offset++);
9195 _endLazyDPSEvaluation ();
9197 freeAsmop (left, NULL, ic, TRUE);
9198 freeAsmop (result, NULL, ic, TRUE);
9201 /*-----------------------------------------------------------------*/
9202 /* genNearPointerGet - emitcode for near pointer fetch */
9203 /*-----------------------------------------------------------------*/
9205 genNearPointerGet (operand * left,
9213 sym_link *rtype, *retype, *letype;
9214 sym_link *ltype = operandType (left);
9217 rtype = operandType (result);
9218 retype = getSpec (rtype);
9219 letype = getSpec (ltype);
9221 aopOp (left, ic, FALSE, FALSE);
9223 /* if left is rematerialisable and
9224 result is not bit variable type and
9225 the left is pointer to data space i.e
9226 lower 128 bytes of space */
9227 if (AOP_TYPE (left) == AOP_IMMD &&
9228 !IS_BITVAR (retype) &&
9229 !IS_BITVAR (letype) &&
9230 DCL_TYPE (ltype) == POINTER)
9232 genDataPointerGet (left, result, ic);
9236 /* if the value is already in a pointer register
9237 then don't need anything more */
9238 if (!AOP_INPREG (AOP (left)))
9240 /* otherwise get a free pointer register */
9242 preg = getFreePtr (ic, &aop, FALSE);
9243 emitcode ("mov", "%s,%s",
9245 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9249 rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9251 freeAsmop (left, NULL, ic, TRUE);
9252 aopOp (result, ic, FALSE, FALSE);
9254 /* if bitfield then unpack the bits */
9255 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9256 genUnpackBits (result, rname, POINTER);
9259 /* we have can just get the values */
9260 int size = AOP_SIZE (result);
9265 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9268 emitcode ("mov", "a,@%s", rname);
9269 aopPut (AOP (result), "a", offset);
9273 SNPRINTF (buff, sizeof(buff), "@%s", rname);
9274 aopPut (AOP (result), buff, offset);
9279 emitcode ("inc", "%s", rname);
9284 /* now some housekeeping stuff */
9287 /* we had to allocate for this iCode */
9288 if (pi) { /* post increment present */
9289 aopPut(AOP ( left ),rname,0);
9291 freeAsmop (NULL, aop, ic, TRUE);
9295 /* we did not allocate which means left
9296 already in a pointer register, then
9297 if size > 0 && this could be used again
9298 we have to point it back to where it
9300 if (AOP_SIZE (result) > 1 &&
9301 !OP_SYMBOL (left)->remat &&
9302 (OP_SYMBOL (left)->liveTo > ic->seq ||
9306 int size = AOP_SIZE (result) - 1;
9308 emitcode ("dec", "%s", rname);
9313 freeAsmop (result, NULL, ic, TRUE);
9314 if (pi) pi->generated = 1;
9317 /*-----------------------------------------------------------------*/
9318 /* genPagedPointerGet - emitcode for paged pointer fetch */
9319 /*-----------------------------------------------------------------*/
9321 genPagedPointerGet (operand * left,
9329 sym_link *rtype, *retype, *letype;
9331 rtype = operandType (result);
9332 retype = getSpec (rtype);
9333 letype = getSpec (operandType (left));
9334 aopOp (left, ic, FALSE, FALSE);
9336 /* if the value is already in a pointer register
9337 then don't need anything more */
9338 if (!AOP_INPREG (AOP (left)))
9340 /* otherwise get a free pointer register */
9342 preg = getFreePtr (ic, &aop, FALSE);
9343 emitcode ("mov", "%s,%s",
9345 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9349 rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9351 freeAsmop (left, NULL, ic, TRUE);
9352 aopOp (result, ic, FALSE, FALSE);
9354 /* if bitfield then unpack the bits */
9355 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9356 genUnpackBits (result, rname, PPOINTER);
9359 /* we have can just get the values */
9360 int size = AOP_SIZE (result);
9366 emitcode ("movx", "a,@%s", rname);
9367 aopPut (AOP (result), "a", offset);
9372 emitcode ("inc", "%s", rname);
9376 /* now some housekeeping stuff */
9379 /* we had to allocate for this iCode */
9380 if (pi) aopPut ( AOP (left), rname, 0);
9381 freeAsmop (NULL, aop, ic, TRUE);
9385 /* we did not allocate which means left
9386 already in a pointer register, then
9387 if size > 0 && this could be used again
9388 we have to point it back to where it
9390 if (AOP_SIZE (result) > 1 &&
9391 !OP_SYMBOL (left)->remat &&
9392 (OP_SYMBOL (left)->liveTo > ic->seq ||
9396 int size = AOP_SIZE (result) - 1;
9398 emitcode ("dec", "%s", rname);
9403 freeAsmop (result, NULL, ic, TRUE);
9404 if (pi) pi->generated = 1;
9407 /*-----------------------------------------------------------------*/
9408 /* genFarPointerGet - gget value from far space */
9409 /*-----------------------------------------------------------------*/
9411 genFarPointerGet (operand * left,
9412 operand * result, iCode * ic, iCode *pi)
9414 int size, offset, dopi=1;
9415 sym_link *retype = getSpec (operandType (result));
9416 sym_link *letype = getSpec (operandType (left));
9417 D (emitcode (";", "genFarPointerGet"););
9419 aopOp (left, ic, FALSE, FALSE);
9421 /* if the operand is already in dptr
9422 then we do nothing else we move the value to dptr */
9423 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9425 /* if this is remateriazable */
9426 if (AOP_TYPE (left) == AOP_IMMD)
9428 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9432 /* we need to get it byte by byte */
9433 _startLazyDPSEvaluation ();
9434 if (AOP_TYPE (left) != AOP_DPTR)
9436 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9437 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9438 if (options.model == MODEL_FLAT24)
9439 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9443 /* We need to generate a load to DPTR indirect through DPTR. */
9444 D (emitcode (";", "genFarPointerGet -- indirection special case."););
9445 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9446 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9447 if (options.model == MODEL_FLAT24)
9448 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9449 emitcode ("pop", "dph");
9450 emitcode ("pop", "dpl");
9453 _endLazyDPSEvaluation ();
9456 /* so dptr know contains the address */
9457 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9459 /* if bit then unpack */
9460 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9461 if (AOP_INDPTRn(left)) {
9462 genSetDPTR(AOP(left)->aopu.dptr);
9464 genUnpackBits (result, "dptr", FPOINTER);
9465 if (AOP_INDPTRn(left)) {
9470 size = AOP_SIZE (result);
9473 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9475 genSetDPTR(AOP(left)->aopu.dptr);
9476 emitcode ("movx", "a,@dptr");
9477 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9478 emitcode ("inc", "dptr");
9480 aopPut (AOP (result), "a", offset++);
9483 _startLazyDPSEvaluation ();
9485 if (AOP_INDPTRn(left)) {
9486 genSetDPTR(AOP(left)->aopu.dptr);
9492 emitcode ("movx", "a,@dptr");
9493 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9494 emitcode ("inc", "dptr");
9496 aopPut (AOP (result), "a", offset++);
9498 _endLazyDPSEvaluation ();
9501 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9502 if (!AOP_INDPTRn(left)) {
9503 _startLazyDPSEvaluation ();
9504 aopPut ( AOP (left), "dpl", 0);
9505 aopPut ( AOP (left), "dph", 1);
9506 if (options.model == MODEL_FLAT24)
9507 aopPut ( AOP (left), "dpx", 2);
9508 _endLazyDPSEvaluation ();
9511 } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) &&
9512 AOP_SIZE(result) > 1 &&
9514 (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
9516 size = AOP_SIZE (result) - 1;
9517 if (AOP_INDPTRn(left)) {
9518 genSetDPTR(AOP(left)->aopu.dptr);
9520 while (size--) emitcode ("lcall","__decdptr");
9521 if (AOP_INDPTRn(left)) {
9526 freeAsmop (left, NULL, ic, TRUE);
9527 freeAsmop (result, NULL, ic, TRUE);
9530 /*-----------------------------------------------------------------*/
9531 /* genCodePointerGet - get value from code space */
9532 /*-----------------------------------------------------------------*/
9534 genCodePointerGet (operand * left,
9535 operand * result, iCode * ic, iCode *pi)
9537 int size, offset, dopi=1;
9538 sym_link *retype = getSpec (operandType (result));
9540 aopOp (left, ic, FALSE, FALSE);
9542 /* if the operand is already in dptr
9543 then we do nothing else we move the value to dptr */
9544 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
9546 /* if this is remateriazable */
9547 if (AOP_TYPE (left) == AOP_IMMD)
9549 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9552 { /* we need to get it byte by byte */
9553 _startLazyDPSEvaluation ();
9554 if (AOP_TYPE (left) != AOP_DPTR)
9556 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9557 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9558 if (options.model == MODEL_FLAT24)
9559 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9563 /* We need to generate a load to DPTR indirect through DPTR. */
9564 D (emitcode (";", "gencodePointerGet -- indirection special case."););
9565 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9566 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9567 if (options.model == MODEL_FLAT24)
9568 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9569 emitcode ("pop", "dph");
9570 emitcode ("pop", "dpl");
9573 _endLazyDPSEvaluation ();
9576 /* so dptr know contains the address */
9577 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9579 /* if bit then unpack */
9580 if (IS_BITVAR (retype)) {
9581 if (AOP_INDPTRn(left)) {
9582 genSetDPTR(AOP(left)->aopu.dptr);
9584 genUnpackBits (result, "dptr", CPOINTER);
9585 if (AOP_INDPTRn(left)) {
9590 size = AOP_SIZE (result);
9592 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9594 genSetDPTR(AOP(left)->aopu.dptr);
9595 emitcode ("clr", "a");
9596 emitcode ("movc", "a,@a+dptr");
9597 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9598 emitcode ("inc", "dptr");
9600 aopPut (AOP (result), "a", offset++);
9603 _startLazyDPSEvaluation ();
9606 if (AOP_INDPTRn(left)) {
9607 genSetDPTR(AOP(left)->aopu.dptr);
9613 emitcode ("clr", "a");
9614 emitcode ("movc", "a,@a+dptr");
9615 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9616 emitcode ("inc", "dptr");
9617 aopPut (AOP (result), "a", offset++);
9619 _endLazyDPSEvaluation ();
9622 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9623 if (!AOP_INDPTRn(left)) {
9624 _startLazyDPSEvaluation ();
9626 aopPut ( AOP (left), "dpl", 0);
9627 aopPut ( AOP (left), "dph", 1);
9628 if (options.model == MODEL_FLAT24)
9629 aopPut ( AOP (left), "dpx", 2);
9631 _endLazyDPSEvaluation ();
9634 } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
9635 AOP_SIZE(result) > 1 &&
9636 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9638 size = AOP_SIZE (result) - 1;
9639 if (AOP_INDPTRn(left)) {
9640 genSetDPTR(AOP(left)->aopu.dptr);
9642 while (size--) emitcode ("lcall","__decdptr");
9643 if (AOP_INDPTRn(left)) {
9648 freeAsmop (left, NULL, ic, TRUE);
9649 freeAsmop (result, NULL, ic, TRUE);
9652 /*-----------------------------------------------------------------*/
9653 /* genGenPointerGet - gget value from generic pointer space */
9654 /*-----------------------------------------------------------------*/
9656 genGenPointerGet (operand * left,
9657 operand * result, iCode * ic, iCode * pi)
9660 sym_link *retype = getSpec (operandType (result));
9661 sym_link *letype = getSpec (operandType (left));
9663 D (emitcode (";", "genGenPointerGet "); );
9665 aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
9667 /* if the operand is already in dptr
9668 then we do nothing else we move the value to dptr */
9669 if (AOP_TYPE (left) != AOP_STR)
9671 /* if this is remateriazable */
9672 if (AOP_TYPE (left) == AOP_IMMD)
9674 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9675 if (AOP(left)->aopu.aop_immd.from_cast_remat)
9677 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
9681 emitcode ("mov", "b,#%d", pointerCode (retype));
9685 { /* we need to get it byte by byte */
9686 _startLazyDPSEvaluation ();
9687 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
9688 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
9689 if (options.model == MODEL_FLAT24) {
9690 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9691 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
9693 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9695 _endLazyDPSEvaluation ();
9699 /* so dptr-b now contains the address */
9701 aopOp (result, ic, FALSE, TRUE);
9704 /* if bit then unpack */
9705 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9707 genUnpackBits (result, "dptr", GPOINTER);
9711 size = AOP_SIZE (result);
9718 // Get two bytes at a time, results in _AP & A.
9719 // dptr will be incremented ONCE by __gptrgetWord.
9721 // Note: any change here must be coordinated
9722 // with the implementation of __gptrgetWord
9723 // in device/lib/_gptrget.c
9724 emitcode ("lcall", "__gptrgetWord");
9725 aopPut (AOP (result), DP2_RESULT_REG, offset++);
9726 aopPut (AOP (result), "a", offset++);
9731 // Only one byte to get.
9732 emitcode ("lcall", "__gptrget");
9733 aopPut (AOP (result), "a", offset++);
9736 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9738 emitcode ("inc", "dptr");
9743 if (pi && AOP_TYPE (left) != AOP_IMMD) {
9744 _startLazyDPSEvaluation ();
9746 aopPut ( AOP (left), "dpl", 0);
9747 aopPut ( AOP (left), "dph", 1);
9748 if (options.model == MODEL_FLAT24) {
9749 aopPut ( AOP (left), "dpx", 2);
9750 aopPut ( AOP (left), "b", 3);
9751 } else aopPut ( AOP (left), "b", 2);
9753 _endLazyDPSEvaluation ();
9756 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9757 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9759 size = AOP_SIZE (result) - 1;
9760 while (size--) emitcode ("lcall","__decdptr");
9763 freeAsmop (left, NULL, ic, TRUE);
9764 freeAsmop (result, NULL, ic, TRUE);
9767 /*-----------------------------------------------------------------*/
9768 /* genPointerGet - generate code for pointer get */
9769 /*-----------------------------------------------------------------*/
9771 genPointerGet (iCode * ic, iCode *pi)
9773 operand *left, *result;
9774 sym_link *type, *etype;
9777 D (emitcode (";", "genPointerGet ");
9780 left = IC_LEFT (ic);
9781 result = IC_RESULT (ic);
9783 /* depending on the type of pointer we need to
9784 move it to the correct pointer register */
9785 type = operandType (left);
9786 etype = getSpec (type);
9787 /* if left is of type of pointer then it is simple */
9788 if (IS_PTR (type) && !IS_FUNC (type->next))
9789 p_type = DCL_TYPE (type);
9792 /* we have to go by the storage class */
9793 p_type = PTR_TYPE (SPEC_OCLS (etype));
9795 /* special case when cast remat */
9796 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9797 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9798 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9799 type = operandType (left);
9800 p_type = DCL_TYPE (type);
9802 /* now that we have the pointer type we assign
9803 the pointer values */
9809 genNearPointerGet (left, result, ic, pi);
9813 genPagedPointerGet (left, result, ic, pi);
9817 genFarPointerGet (left, result, ic, pi);
9821 genCodePointerGet (left, result, ic, pi);
9825 genGenPointerGet (left, result, ic, pi);
9831 /*-----------------------------------------------------------------*/
9832 /* genPackBits - generates code for packed bit storage */
9833 /*-----------------------------------------------------------------*/
9835 genPackBits (sym_link * etype,
9837 char *rname, int p_type)
9839 int offset = 0; /* source byte offset */
9840 int rlen = 0; /* remaining bitfield length */
9841 int blen; /* bitfield length */
9842 int bstr; /* bitfield starting bit within byte */
9843 int litval; /* source literal value (if AOP_LIT) */
9844 unsigned char mask; /* bitmask within current byte */
9846 D(emitcode ("; genPackBits",""));
9848 blen = SPEC_BLEN (etype);
9849 bstr = SPEC_BSTR (etype);
9851 /* If the bitfield length is less than a byte */
9854 mask = ((unsigned char) (0xFF << (blen + bstr)) |
9855 (unsigned char) (0xFF >> (8 - bstr)));
9857 if (AOP_TYPE (right) == AOP_LIT)
9859 /* Case with a bitfield length <8 and literal source
9861 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9863 litval &= (~mask) & 0xff;
9864 emitPtrByteGet (rname, p_type, FALSE);
9865 if ((mask|litval)!=0xff)
9866 emitcode ("anl","a,#!constbyte", mask);
9868 emitcode ("orl","a,#!constbyte", litval);
9872 if ((blen==1) && (p_type!=GPOINTER))
9874 /* Case with a bitfield length == 1 and no generic pointer
9876 if (AOP_TYPE (right) == AOP_CRY)
9877 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9880 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
9881 emitcode ("rrc","a");
9883 emitPtrByteGet (rname, p_type, FALSE);
9884 emitcode ("mov","acc.%d,c",bstr);
9888 /* Case with a bitfield length < 8 and arbitrary source
9890 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
9891 /* shift and mask source value */
9893 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
9895 /* transfer A to B and get next byte */
9896 emitPtrByteGet (rname, p_type, TRUE);
9898 emitcode ("anl", "a,#!constbyte", mask);
9899 emitcode ("orl", "a,b");
9900 if (p_type == GPOINTER)
9901 emitcode ("pop", "b");
9905 emitPtrByteSet (rname, p_type, "a");
9909 /* Bit length is greater than 7 bits. In this case, copy */
9910 /* all except the partial byte at the end */
9911 for (rlen=blen;rlen>=8;rlen-=8)
9913 emitPtrByteSet (rname, p_type,
9914 aopGet (AOP (right), offset++, FALSE, TRUE, NULL) );
9916 emitcode ("inc", "%s", rname);
9919 /* If there was a partial byte at the end */
9922 mask = (((unsigned char) -1 << rlen) & 0xff);
9924 if (AOP_TYPE (right) == AOP_LIT)
9926 /* Case with partial byte and literal source
9928 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9929 litval >>= (blen-rlen);
9930 litval &= (~mask) & 0xff;
9931 emitPtrByteGet (rname, p_type, FALSE);
9932 if ((mask|litval)!=0xff)
9933 emitcode ("anl","a,#!constbyte", mask);
9935 emitcode ("orl","a,#!constbyte", litval);
9939 /* Case with partial byte and arbitrary source
9941 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9942 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
9944 /* transfer A to B and get next byte */
9945 emitPtrByteGet (rname, p_type, TRUE);
9947 emitcode ("anl", "a,#!constbyte", mask);
9948 emitcode ("orl", "a,b");
9949 if (p_type == GPOINTER)
9950 emitcode ("pop", "b");
9952 emitPtrByteSet (rname, p_type, "a");
9958 /*-----------------------------------------------------------------*/
9959 /* genDataPointerSet - remat pointer to data space */
9960 /*-----------------------------------------------------------------*/
9962 genDataPointerSet (operand * right,
9966 int size, offset = 0;
9969 aopOp (right, ic, FALSE, FALSE);
9971 l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
9972 size = AOP_SIZE (right);
9977 SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
9981 SNPRINTF (buff, sizeof(buff), "%s", l + 1);
9984 emitcode ("mov", "%s,%s", buff,
9985 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9988 freeAsmop (right, NULL, ic, TRUE);
9989 freeAsmop (result, NULL, ic, TRUE);
9992 /*-----------------------------------------------------------------*/
9993 /* genNearPointerSet - emitcode for near pointer put */
9994 /*-----------------------------------------------------------------*/
9996 genNearPointerSet (operand * right,
10003 sym_link *retype, *letype;
10004 sym_link *ptype = operandType (result);
10006 retype = getSpec (operandType (right));
10007 letype = getSpec (ptype);
10009 aopOp (result, ic, FALSE, FALSE);
10011 /* if the result is rematerializable &
10012 in data space & not a bit variable */
10013 if (AOP_TYPE (result) == AOP_IMMD &&
10014 DCL_TYPE (ptype) == POINTER &&
10015 !IS_BITVAR (retype) &&
10016 !IS_BITVAR (letype))
10018 genDataPointerSet (right, result, ic);
10022 /* if the value is already in a pointer register
10023 then don't need anything more */
10024 if (!AOP_INPREG (AOP (result)))
10026 /* otherwise get a free pointer register */
10029 aop = newAsmop (0);
10030 preg = getFreePtr (ic, &aop, FALSE);
10031 emitcode ("mov", "%s,%s",
10033 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10034 rname = preg->name;
10037 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10039 aopOp (right, ic, FALSE, FALSE);
10041 /* if bitfield then unpack the bits */
10042 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10043 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
10046 /* we have can just get the values */
10047 int size = AOP_SIZE (right);
10052 l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
10056 emitcode ("mov", "@%s,a", rname);
10059 emitcode ("mov", "@%s,%s", rname, l);
10061 emitcode ("inc", "%s", rname);
10066 /* now some housekeeping stuff */
10069 /* we had to allocate for this iCode */
10070 if (pi) aopPut (AOP (result),rname,0);
10071 freeAsmop (NULL, aop, ic, TRUE);
10075 /* we did not allocate which means left
10076 already in a pointer register, then
10077 if size > 0 && this could be used again
10078 we have to point it back to where it
10080 if (AOP_SIZE (right) > 1 &&
10081 !OP_SYMBOL (result)->remat &&
10082 (OP_SYMBOL (result)->liveTo > ic->seq ||
10086 int size = AOP_SIZE (right) - 1;
10088 emitcode ("dec", "%s", rname);
10093 if (pi) pi->generated = 1;
10094 freeAsmop (result, NULL, ic, TRUE);
10095 freeAsmop (right, NULL, ic, TRUE);
10100 /*-----------------------------------------------------------------*/
10101 /* genPagedPointerSet - emitcode for Paged pointer put */
10102 /*-----------------------------------------------------------------*/
10104 genPagedPointerSet (operand * right,
10111 sym_link *retype, *letype;
10113 retype = getSpec (operandType (right));
10114 letype = getSpec (operandType (result));
10116 aopOp (result, ic, FALSE, FALSE);
10118 /* if the value is already in a pointer register
10119 then don't need anything more */
10120 if (!AOP_INPREG (AOP (result)))
10122 /* otherwise get a free pointer register */
10125 aop = newAsmop (0);
10126 preg = getFreePtr (ic, &aop, FALSE);
10127 emitcode ("mov", "%s,%s",
10129 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10130 rname = preg->name;
10133 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10135 aopOp (right, ic, FALSE, FALSE);
10137 /* if bitfield then unpack the bits */
10138 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10139 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
10142 /* we have can just get the values */
10143 int size = AOP_SIZE (right);
10148 MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10150 emitcode ("movx", "@%s,a", rname);
10153 emitcode ("inc", "%s", rname);
10159 /* now some housekeeping stuff */
10162 if (pi) aopPut (AOP (result),rname,0);
10163 /* we had to allocate for this iCode */
10164 freeAsmop (NULL, aop, ic, TRUE);
10168 /* we did not allocate which means left
10169 already in a pointer register, then
10170 if size > 0 && this could be used again
10171 we have to point it back to where it
10173 if (AOP_SIZE (right) > 1 &&
10174 !OP_SYMBOL (result)->remat &&
10175 (OP_SYMBOL (result)->liveTo > ic->seq ||
10179 int size = AOP_SIZE (right) - 1;
10181 emitcode ("dec", "%s", rname);
10186 if (pi) pi->generated = 1;
10187 freeAsmop (result, NULL, ic, TRUE);
10188 freeAsmop (right, NULL, ic, TRUE);
10193 /*-----------------------------------------------------------------*/
10194 /* genFarPointerSet - set value from far space */
10195 /*-----------------------------------------------------------------*/
10197 genFarPointerSet (operand * right,
10198 operand * result, iCode * ic, iCode *pi)
10200 int size, offset, dopi=1;
10201 sym_link *retype = getSpec (operandType (right));
10202 sym_link *letype = getSpec (operandType (result));
10204 aopOp (result, ic, FALSE, FALSE);
10206 /* if the operand is already in dptr
10207 then we do nothing else we move the value to dptr */
10208 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10210 /* if this is remateriazable */
10211 if (AOP_TYPE (result) == AOP_IMMD)
10212 emitcode ("mov", "dptr,%s",
10213 aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10216 /* we need to get it byte by byte */
10217 _startLazyDPSEvaluation ();
10218 if (AOP_TYPE (result) != AOP_DPTR)
10220 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10221 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10222 if (options.model == MODEL_FLAT24)
10223 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10227 /* We need to generate a load to DPTR indirect through DPTR. */
10228 D (emitcode (";", "genFarPointerSet -- indirection special case."););
10230 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10231 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10232 if (options.model == MODEL_FLAT24)
10233 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10234 emitcode ("pop", "dph");
10235 emitcode ("pop", "dpl");
10238 _endLazyDPSEvaluation ();
10241 /* so dptr know contains the address */
10242 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10244 /* if bit then unpack */
10245 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
10246 if (AOP_INDPTRn(result)) {
10247 genSetDPTR(AOP(result)->aopu.dptr);
10249 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
10250 if (AOP_INDPTRn(result)) {
10254 size = AOP_SIZE (right);
10256 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10258 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10260 genSetDPTR(AOP(result)->aopu.dptr);
10261 emitcode ("movx", "@dptr,a");
10262 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10263 emitcode ("inc", "dptr");
10267 _startLazyDPSEvaluation ();
10269 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10271 if (AOP_INDPTRn(result)) {
10272 genSetDPTR(AOP(result)->aopu.dptr);
10278 emitcode ("movx", "@dptr,a");
10279 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10280 emitcode ("inc", "dptr");
10282 _endLazyDPSEvaluation ();
10286 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10287 if (!AOP_INDPTRn(result)) {
10288 _startLazyDPSEvaluation ();
10290 aopPut (AOP(result),"dpl",0);
10291 aopPut (AOP(result),"dph",1);
10292 if (options.model == MODEL_FLAT24)
10293 aopPut (AOP(result),"dpx",2);
10295 _endLazyDPSEvaluation ();
10298 } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
10299 AOP_SIZE(right) > 1 &&
10300 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10302 size = AOP_SIZE (right) - 1;
10303 if (AOP_INDPTRn(result)) {
10304 genSetDPTR(AOP(result)->aopu.dptr);
10306 while (size--) emitcode ("lcall","__decdptr");
10307 if (AOP_INDPTRn(result)) {
10311 freeAsmop (result, NULL, ic, TRUE);
10312 freeAsmop (right, NULL, ic, TRUE);
10315 /*-----------------------------------------------------------------*/
10316 /* genGenPointerSet - set value from generic pointer space */
10317 /*-----------------------------------------------------------------*/
10319 genGenPointerSet (operand * right,
10320 operand * result, iCode * ic, iCode *pi)
10323 sym_link *retype = getSpec (operandType (right));
10324 sym_link *letype = getSpec (operandType (result));
10326 aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10328 /* if the operand is already in dptr
10329 then we do nothing else we move the value to dptr */
10330 if (AOP_TYPE (result) != AOP_STR)
10332 _startLazyDPSEvaluation ();
10333 /* if this is remateriazable */
10334 if (AOP_TYPE (result) == AOP_IMMD)
10336 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10337 if (AOP(result)->aopu.aop_immd.from_cast_remat)
10339 MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10344 "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10348 { /* we need to get it byte by byte */
10349 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10350 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10351 if (options.model == MODEL_FLAT24) {
10352 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10353 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10355 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10358 _endLazyDPSEvaluation ();
10360 /* so dptr + b now contains the address */
10362 aopOp (right, ic, FALSE, TRUE);
10366 /* if bit then unpack */
10367 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10369 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
10373 size = AOP_SIZE (right);
10376 _startLazyDPSEvaluation ();
10381 // Set two bytes at a time, passed in _AP & A.
10382 // dptr will be incremented ONCE by __gptrputWord.
10384 // Note: any change here must be coordinated
10385 // with the implementation of __gptrputWord
10386 // in device/lib/_gptrput.c
10387 emitcode("mov", "_ap, %s",
10388 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10389 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10393 emitcode ("lcall", "__gptrputWord");
10398 // Only one byte to put.
10399 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10403 emitcode ("lcall", "__gptrput");
10406 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10408 emitcode ("inc", "dptr");
10411 _endLazyDPSEvaluation ();
10414 if (pi && AOP_TYPE (result) != AOP_IMMD) {
10415 _startLazyDPSEvaluation ();
10417 aopPut (AOP(result),"dpl",0);
10418 aopPut (AOP(result),"dph",1);
10419 if (options.model == MODEL_FLAT24) {
10420 aopPut (AOP(result),"dpx",2);
10421 aopPut (AOP(result),"b",3);
10423 aopPut (AOP(result),"b",2);
10425 _endLazyDPSEvaluation ();
10428 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10429 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10431 size = AOP_SIZE (right) - 1;
10432 while (size--) emitcode ("lcall","__decdptr");
10434 freeAsmop (result, NULL, ic, TRUE);
10435 freeAsmop (right, NULL, ic, TRUE);
10438 /*-----------------------------------------------------------------*/
10439 /* genPointerSet - stores the value into a pointer location */
10440 /*-----------------------------------------------------------------*/
10442 genPointerSet (iCode * ic, iCode *pi)
10444 operand *right, *result;
10445 sym_link *type, *etype;
10448 D (emitcode (";", "genPointerSet "););
10450 right = IC_RIGHT (ic);
10451 result = IC_RESULT (ic);
10453 /* depending on the type of pointer we need to
10454 move it to the correct pointer register */
10455 type = operandType (result);
10456 etype = getSpec (type);
10457 /* if left is of type of pointer then it is simple */
10458 if (IS_PTR (type) && !IS_FUNC (type->next))
10460 p_type = DCL_TYPE (type);
10464 /* we have to go by the storage class */
10465 p_type = PTR_TYPE (SPEC_OCLS (etype));
10467 /* special case when cast remat */
10468 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10469 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10470 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10471 type = operandType (result);
10472 p_type = DCL_TYPE (type);
10475 /* now that we have the pointer type we assign
10476 the pointer values */
10482 genNearPointerSet (right, result, ic, pi);
10486 genPagedPointerSet (right, result, ic, pi);
10490 genFarPointerSet (right, result, ic, pi);
10494 genGenPointerSet (right, result, ic, pi);
10498 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10499 "genPointerSet: illegal pointer type");
10504 /*-----------------------------------------------------------------*/
10505 /* genIfx - generate code for Ifx statement */
10506 /*-----------------------------------------------------------------*/
10508 genIfx (iCode * ic, iCode * popIc)
10510 operand *cond = IC_COND (ic);
10513 D (emitcode (";", "genIfx "););
10515 aopOp (cond, ic, FALSE, FALSE);
10517 /* get the value into acc */
10518 if (AOP_TYPE (cond) != AOP_CRY)
10527 /* the result is now in the accumulator */
10528 freeAsmop (cond, NULL, ic, TRUE);
10530 /* if there was something to be popped then do it */
10534 /* if the condition is a bit variable */
10535 if (isbit && IS_ITEMP (cond) &&
10538 genIfxJump (ic, SPIL_LOC (cond)->rname);
10540 else if (isbit && !IS_ITEMP (cond))
10542 genIfxJump (ic, OP_SYMBOL (cond)->rname);
10546 genIfxJump (ic, "a");
10552 /*-----------------------------------------------------------------*/
10553 /* genAddrOf - generates code for address of */
10554 /*-----------------------------------------------------------------*/
10556 genAddrOf (iCode * ic)
10558 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10561 D (emitcode (";", "genAddrOf ");
10564 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10566 /* if the operand is on the stack then we
10567 need to get the stack offset of this
10569 if (sym->onStack) {
10571 /* if 10 bit stack */
10572 if (options.stack10bit) {
10576 tsprintf(buff, sizeof(buff),
10577 "#!constbyte",(options.stack_loc >> 16) & 0xff);
10578 /* if it has an offset then we need to compute it */
10579 /* emitcode ("subb", "a,#!constbyte", */
10580 /* -((sym->stack < 0) ? */
10581 /* ((short) (sym->stack - _G.nRegsSaved)) : */
10582 /* ((short) sym->stack)) & 0xff); */
10583 /* emitcode ("mov","b,a"); */
10584 /* emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
10585 /* ((short) (sym->stack - _G.nRegsSaved)) : */
10586 /* ((short) sym->stack)) >> 8) & 0xff); */
10588 emitcode ("mov", "a,_bpx");
10589 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
10590 ((char) (sym->stack - _G.nRegsSaved)) :
10591 ((char) sym->stack )) & 0xff);
10592 emitcode ("mov", "b,a");
10593 emitcode ("mov", "a,_bpx+1");
10595 offset = (((sym->stack < 0) ?
10596 ((short) (sym->stack - _G.nRegsSaved)) :
10597 ((short) sym->stack )) >> 8) & 0xff;
10599 emitcode ("addc","a,#!constbyte", offset);
10601 aopPut (AOP (IC_RESULT (ic)), "b", 0);
10602 aopPut (AOP (IC_RESULT (ic)), "a", 1);
10603 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10605 /* we can just move _bp */
10606 aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10607 aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10608 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10611 /* if it has an offset then we need to compute it */
10613 emitcode ("mov", "a,_bp");
10614 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10615 aopPut (AOP (IC_RESULT (ic)), "a", 0);
10617 /* we can just move _bp */
10618 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10620 /* fill the result with zero */
10621 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10624 if (options.stack10bit && size < (FPTRSIZE - 1)) {
10626 "*** warning: pointer to stack var truncated.\n");
10631 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10637 /* object not on stack then we need the name */
10638 size = AOP_SIZE (IC_RESULT (ic));
10643 char s[SDCC_NAME_MAX];
10647 tsprintf(s, sizeof(s), "#!his",sym->rname);
10650 tsprintf(s, sizeof(s), "#!hihis",sym->rname);
10653 tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
10655 default: /* should not need this (just in case) */
10656 SNPRINTF (s, sizeof(s), "#(%s >> %d)",
10663 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10666 aopPut (AOP (IC_RESULT (ic)), s, offset++);
10670 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10674 #if 0 // obsolete, and buggy for != xdata
10675 /*-----------------------------------------------------------------*/
10676 /* genArrayInit - generates code for address of */
10677 /*-----------------------------------------------------------------*/
10679 genArrayInit (iCode * ic)
10681 literalList *iLoop;
10683 int elementSize = 0, eIndex;
10684 unsigned val, lastVal;
10686 operand *left=IC_LEFT(ic);
10688 D (emitcode (";", "genArrayInit "););
10690 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10692 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10694 // Load immediate value into DPTR.
10695 emitcode("mov", "dptr, %s",
10696 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
10698 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10701 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10702 "Unexpected operand to genArrayInit.\n");
10705 // a regression because of SDCCcse.c:1.52
10706 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10707 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10708 if (options.model == MODEL_FLAT24)
10709 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10713 type = operandType(IC_LEFT(ic));
10715 if (type && type->next)
10717 elementSize = getSize(type->next);
10721 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10722 "can't determine element size in genArrayInit.\n");
10726 iLoop = IC_ARRAYILIST(ic);
10731 bool firstpass = TRUE;
10733 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
10734 iLoop->count, (int)iLoop->literalValue, elementSize);
10740 symbol *tlbl = NULL;
10742 count = ix > 256 ? 256 : ix;
10746 tlbl = newiTempLabel (NULL);
10747 if (firstpass || (count & 0xff))
10749 emitcode("mov", "b, #!constbyte", count & 0xff);
10752 emitcode ("", "!tlabeldef", tlbl->key + 100);
10757 for (eIndex = 0; eIndex < elementSize; eIndex++)
10759 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10760 if (val != lastVal)
10762 emitcode("mov", "a, #!constbyte", val);
10766 emitcode("movx", "@dptr, a");
10767 emitcode("inc", "dptr");
10772 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10778 iLoop = iLoop->next;
10781 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10785 /*-----------------------------------------------------------------*/
10786 /* genFarFarAssign - assignment when both are in far space */
10787 /*-----------------------------------------------------------------*/
10789 genFarFarAssign (operand * result, operand * right, iCode * ic)
10791 int size = AOP_SIZE (right);
10793 symbol *rSym = NULL;
10797 /* quick & easy case. */
10798 D(emitcode(";","genFarFarAssign (1 byte case)"););
10799 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
10800 freeAsmop (right, NULL, ic, FALSE);
10801 /* now assign DPTR to result */
10803 aopOp(result, ic, FALSE, FALSE);
10805 aopPut(AOP(result), "a", 0);
10806 freeAsmop(result, NULL, ic, FALSE);
10810 /* See if we've got an underlying symbol to abuse. */
10811 if (IS_SYMOP(result) && OP_SYMBOL(result))
10813 if (IS_TRUE_SYMOP(result))
10815 rSym = OP_SYMBOL(result);
10817 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10819 rSym = OP_SYMBOL(result)->usl.spillLoc;
10823 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10825 /* We can use the '390 auto-toggle feature to good effect here. */
10827 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10828 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
10829 emitcode ("mov", "dptr,#%s", rSym->rname);
10830 /* DP2 = result, DP1 = right, DP1 is current. */
10833 emitcode("movx", "a,@dptr");
10834 emitcode("movx", "@dptr,a");
10837 emitcode("inc", "dptr");
10838 emitcode("inc", "dptr");
10841 emitcode("mov", "dps,#0");
10842 freeAsmop (right, NULL, ic, FALSE);
10844 some alternative code for processors without auto-toggle
10845 no time to test now, so later well put in...kpb
10846 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10847 emitcode("mov", "dps,#1"); /* Select DPTR2. */
10848 emitcode ("mov", "dptr,#%s", rSym->rname);
10849 /* DP2 = result, DP1 = right, DP1 is current. */
10853 emitcode("movx", "a,@dptr");
10855 emitcode("inc", "dptr");
10856 emitcode("inc", "dps");
10857 emitcode("movx", "@dptr,a");
10859 emitcode("inc", "dptr");
10860 emitcode("inc", "dps");
10862 emitcode("mov", "dps,#0");
10863 freeAsmop (right, NULL, ic, FALSE);
10868 D (emitcode (";", "genFarFarAssign"););
10869 aopOp (result, ic, TRUE, TRUE);
10871 _startLazyDPSEvaluation ();
10875 aopPut (AOP (result),
10876 aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
10879 _endLazyDPSEvaluation ();
10880 freeAsmop (result, NULL, ic, FALSE);
10881 freeAsmop (right, NULL, ic, FALSE);
10885 /*-----------------------------------------------------------------*/
10886 /* genAssign - generate code for assignment */
10887 /*-----------------------------------------------------------------*/
10889 genAssign (iCode * ic)
10891 operand *result, *right;
10893 unsigned long lit = 0L;
10895 D (emitcode (";", "genAssign ");
10898 result = IC_RESULT (ic);
10899 right = IC_RIGHT (ic);
10901 /* if they are the same */
10902 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10905 aopOp (right, ic, FALSE, FALSE);
10907 emitcode (";", "genAssign: resultIsFar = %s",
10908 isOperandInFarSpace (result) ?
10911 /* special case both in far space */
10912 if ((AOP_TYPE (right) == AOP_DPTR ||
10913 AOP_TYPE (right) == AOP_DPTR2) &&
10914 /* IS_TRUE_SYMOP(result) && */
10915 isOperandInFarSpace (result))
10917 genFarFarAssign (result, right, ic);
10921 aopOp (result, ic, TRUE, FALSE);
10923 /* if they are the same registers */
10924 if (sameRegs (AOP (right), AOP (result)))
10927 /* if the result is a bit */
10928 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10930 /* if the right size is a literal then
10931 we know what the value is */
10932 if (AOP_TYPE (right) == AOP_LIT)
10934 if (((int) operandLitValue (right)))
10935 aopPut (AOP (result), one, 0);
10937 aopPut (AOP (result), zero, 0);
10941 /* the right is also a bit variable */
10942 if (AOP_TYPE (right) == AOP_CRY)
10944 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10945 aopPut (AOP (result), "c", 0);
10949 /* we need to or */
10951 aopPut (AOP (result), "a", 0);
10955 /* bit variables done */
10957 size = AOP_SIZE (result);
10959 if (AOP_TYPE (right) == AOP_LIT)
10960 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10963 (AOP_TYPE (result) != AOP_REG) &&
10964 (AOP_TYPE (right) == AOP_LIT) &&
10965 !IS_FLOAT (operandType (right)))
10967 _startLazyDPSEvaluation ();
10968 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10970 aopPut (AOP (result),
10971 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10976 /* And now fill the rest with zeros. */
10979 emitcode ("clr", "a");
10983 aopPut (AOP (result), "a", offset++);
10985 _endLazyDPSEvaluation ();
10989 _startLazyDPSEvaluation ();
10992 aopPut (AOP (result),
10993 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10997 _endLazyDPSEvaluation ();
11001 freeAsmop (right, NULL, ic, FALSE);
11002 freeAsmop (result, NULL, ic, TRUE);
11005 /*-----------------------------------------------------------------*/
11006 /* genJumpTab - generates code for jump table */
11007 /*-----------------------------------------------------------------*/
11009 genJumpTab (iCode * ic)
11014 D (emitcode (";", "genJumpTab ");
11017 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
11018 /* get the condition into accumulator */
11019 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
11021 /* multiply by four! */
11022 emitcode ("add", "a,acc");
11023 emitcode ("add", "a,acc");
11024 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11026 jtab = newiTempLabel (NULL);
11027 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
11028 emitcode ("jmp", "@a+dptr");
11029 emitcode ("", "!tlabeldef", jtab->key + 100);
11030 /* now generate the jump labels */
11031 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11032 jtab = setNextItem (IC_JTLABELS (ic)))
11033 emitcode ("ljmp", "!tlabel", jtab->key + 100);
11037 /*-----------------------------------------------------------------*/
11038 /* genCast - gen code for casting */
11039 /*-----------------------------------------------------------------*/
11041 genCast (iCode * ic)
11043 operand *result = IC_RESULT (ic);
11044 sym_link *ctype = operandType (IC_LEFT (ic));
11045 sym_link *rtype = operandType (IC_RIGHT (ic));
11046 operand *right = IC_RIGHT (ic);
11049 D (emitcode (";", "genCast "););
11051 /* if they are equivalent then do nothing */
11052 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11055 aopOp (right, ic, FALSE, FALSE);
11056 aopOp (result, ic, FALSE, (AOP_TYPE(right) == AOP_DPTR));
11058 /* if the result is a bit */
11059 if (IS_BITVAR (OP_SYMBOL (result)->type)
11060 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
11062 /* if the right size is a literal then
11063 we know what the value is */
11064 if (AOP_TYPE (right) == AOP_LIT)
11066 if (((int) operandLitValue (right)))
11067 aopPut (AOP (result), one, 0);
11069 aopPut (AOP (result), zero, 0);
11074 /* the right is also a bit variable */
11075 if (AOP_TYPE (right) == AOP_CRY)
11077 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11078 aopPut (AOP (result), "c", 0);
11082 /* we need to or */
11084 aopPut (AOP (result), "a", 0);
11088 /* if they are the same size : or less */
11089 if (AOP_SIZE (result) <= AOP_SIZE (right))
11092 /* if they are in the same place */
11093 if (sameRegs (AOP (right), AOP (result)))
11096 /* if they in different places then copy */
11097 size = AOP_SIZE (result);
11099 _startLazyDPSEvaluation ();
11102 aopPut (AOP (result),
11103 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11107 _endLazyDPSEvaluation ();
11112 /* if the result is of type pointer */
11113 if (IS_PTR (ctype))
11117 sym_link *type = operandType (right);
11119 /* pointer to generic pointer */
11120 if (IS_GENPTR (ctype))
11124 p_type = DCL_TYPE (type);
11128 #if OLD_CAST_BEHAVIOR
11129 /* KV: we are converting a non-pointer type to
11130 * a generic pointer. This (ifdef'd out) code
11131 * says that the resulting generic pointer
11132 * should have the same class as the storage
11133 * location of the non-pointer variable.
11135 * For example, converting an int (which happens
11136 * to be stored in DATA space) to a pointer results
11137 * in a DATA generic pointer; if the original int
11138 * in XDATA space, so will be the resulting pointer.
11140 * I don't like that behavior, and thus this change:
11141 * all such conversions will be forced to XDATA and
11142 * throw a warning. If you want some non-XDATA
11143 * type, or you want to suppress the warning, you
11144 * must go through an intermediate cast, like so:
11146 * char _generic *gp = (char _xdata *)(intVar);
11148 sym_link *etype = getSpec (type);
11150 /* we have to go by the storage class */
11151 if (SPEC_OCLS (etype) != generic)
11153 p_type = PTR_TYPE (SPEC_OCLS (etype));
11158 /* Converting unknown class (i.e. register variable)
11159 * to generic pointer. This is not good, but
11160 * we'll make a guess (and throw a warning).
11163 werror (W_INT_TO_GEN_PTR_CAST);
11167 /* the first two bytes are known */
11168 size = GPTRSIZE - 1;
11170 _startLazyDPSEvaluation ();
11173 aopPut (AOP (result),
11174 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11178 _endLazyDPSEvaluation ();
11180 /* the last byte depending on type */
11182 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11187 // pointerTypeToGPByte will have bitched.
11191 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11192 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11197 /* just copy the pointers */
11198 size = AOP_SIZE (result);
11200 _startLazyDPSEvaluation ();
11203 aopPut (AOP (result),
11204 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11208 _endLazyDPSEvaluation ();
11212 /* so we now know that the size of destination is greater
11213 than the size of the source */
11214 /* we move to result for the size of source */
11215 size = AOP_SIZE (right);
11217 _startLazyDPSEvaluation ();
11220 aopPut (AOP (result),
11221 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11225 _endLazyDPSEvaluation ();
11227 /* now depending on the sign of the source && destination */
11228 size = AOP_SIZE (result) - AOP_SIZE (right);
11229 /* if unsigned or not an integral type */
11230 /* also, if the source is a bit, we don't need to sign extend, because
11231 * it can't possibly have set the sign bit.
11233 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
11237 aopPut (AOP (result), zero, offset++);
11242 /* we need to extend the sign :{ */
11243 MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11244 FALSE, FALSE, NULL));
11245 emitcode ("rlc", "a");
11246 emitcode ("subb", "a,acc");
11248 aopPut (AOP (result), "a", offset++);
11251 /* we are done hurray !!!! */
11254 freeAsmop (right, NULL, ic, TRUE);
11255 freeAsmop (result, NULL, ic, TRUE);
11259 /*-----------------------------------------------------------------*/
11260 /* genDjnz - generate decrement & jump if not zero instrucion */
11261 /*-----------------------------------------------------------------*/
11263 genDjnz (iCode * ic, iCode * ifx)
11265 symbol *lbl, *lbl1;
11269 /* if the if condition has a false label
11270 then we cannot save */
11271 if (IC_FALSE (ifx))
11274 /* if the minus is not of the form
11276 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11277 !IS_OP_LITERAL (IC_RIGHT (ic)))
11280 if (operandLitValue (IC_RIGHT (ic)) != 1)
11283 /* if the size of this greater than one then no
11285 if (getSize (operandType (IC_RESULT (ic))) > 1)
11288 /* otherwise we can save BIG */
11289 D(emitcode(";", "genDjnz"););
11291 lbl = newiTempLabel (NULL);
11292 lbl1 = newiTempLabel (NULL);
11294 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11296 if (AOP_NEEDSACC(IC_RESULT(ic)))
11298 /* If the result is accessed indirectly via
11299 * the accumulator, we must explicitly write
11300 * it back after the decrement.
11302 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11304 if (strcmp(rByte, "a"))
11306 /* Something is hopelessly wrong */
11307 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11308 __FILE__, __LINE__);
11309 /* We can just give up; the generated code will be inefficient,
11310 * but what the hey.
11312 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11315 emitcode ("dec", "%s", rByte);
11316 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11317 emitcode ("jnz", "!tlabel", lbl->key + 100);
11319 else if (IS_AOP_PREG (IC_RESULT (ic)))
11321 emitcode ("dec", "%s",
11322 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11323 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11324 emitcode ("jnz", "!tlabel", lbl->key + 100);
11328 emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11331 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11332 emitcode ("", "!tlabeldef", lbl->key + 100);
11333 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11334 emitcode ("", "!tlabeldef", lbl1->key + 100);
11336 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11337 ifx->generated = 1;
11341 /*-----------------------------------------------------------------*/
11342 /* genReceive - generate code for a receive iCode */
11343 /*-----------------------------------------------------------------*/
11345 genReceive (iCode * ic)
11347 int size = getSize (operandType (IC_RESULT (ic)));
11351 D (emitcode (";", "genReceive "););
11353 if (ic->argreg == 1)
11355 /* first parameter */
11356 if (AOP_IS_STR(IC_RESULT(ic)))
11358 /* Nothing to do: it's already in the proper place. */
11365 useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11366 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11367 IS_TRUE_SYMOP (IC_RESULT (ic)));
11370 aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11373 /* Sanity checking... */
11374 if (AOP_USESDPTR(IC_RESULT(ic)))
11376 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11377 "genReceive got unexpected DPTR.");
11379 assignResultValue (IC_RESULT (ic));
11384 /* second receive onwards */
11385 /* this gets a little tricky since unused recevies will be
11386 eliminated, we have saved the reg in the type field . and
11387 we use that to figure out which register to use */
11388 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11389 rb1off = ic->argreg;
11392 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11395 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11398 /*-----------------------------------------------------------------*/
11399 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
11400 /*-----------------------------------------------------------------*/
11401 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11403 operand *from , *to , *count;
11408 /* we know it has to be 3 parameters */
11409 assert (nparms == 3);
11411 rsave = newBitVect(16);
11412 /* save DPTR if it needs to be saved */
11413 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11414 if (bitVectBitValue(ic->rMask,i))
11415 rsave = bitVectSetBit(rsave,i);
11417 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11418 ds390_rUmaskForOp (IC_RESULT(ic))));
11425 aopOp (from, ic->next, FALSE, FALSE);
11427 /* get from into DPTR1 */
11428 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11429 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11430 if (options.model == MODEL_FLAT24) {
11431 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11434 freeAsmop (from, NULL, ic, FALSE);
11435 aopOp (to, ic, FALSE, FALSE);
11436 /* get "to" into DPTR */
11437 /* if the operand is already in dptr
11438 then we do nothing else we move the value to dptr */
11439 if (AOP_TYPE (to) != AOP_STR) {
11440 /* if already in DPTR then we need to push */
11441 if (AOP_TYPE(to) == AOP_DPTR) {
11442 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11443 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11444 if (options.model == MODEL_FLAT24)
11445 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11446 emitcode ("pop", "dph");
11447 emitcode ("pop", "dpl");
11449 _startLazyDPSEvaluation ();
11450 /* if this is remateriazable */
11451 if (AOP_TYPE (to) == AOP_IMMD) {
11452 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11453 } else { /* we need to get it byte by byte */
11454 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11455 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11456 if (options.model == MODEL_FLAT24) {
11457 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11460 _endLazyDPSEvaluation ();
11463 freeAsmop (to, NULL, ic, FALSE);
11464 _G.dptrInUse = _G.dptr1InUse = 1;
11465 aopOp (count, ic->next->next, FALSE,FALSE);
11466 lbl =newiTempLabel(NULL);
11468 /* now for the actual copy */
11469 if (AOP_TYPE(count) == AOP_LIT &&
11470 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11471 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11473 emitcode ("lcall","__bi_memcpyc2x_s");
11475 emitcode ("lcall","__bi_memcpyx2x_s");
11477 freeAsmop (count, NULL, ic, FALSE);
11479 symbol *lbl1 = newiTempLabel(NULL);
11481 emitcode (";"," Auto increment but no djnz");
11482 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11483 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11484 freeAsmop (count, NULL, ic, FALSE);
11485 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11486 emitcode ("","!tlabeldef",lbl->key+100);
11488 emitcode ("clr","a");
11489 emitcode ("movc", "a,@a+dptr");
11491 emitcode ("movx", "a,@dptr");
11492 emitcode ("movx", "@dptr,a");
11493 emitcode ("inc", "dptr");
11494 emitcode ("inc", "dptr");
11495 emitcode ("mov","a,b");
11496 emitcode ("orl","a,_ap");
11497 emitcode ("jz","!tlabel",lbl1->key+100);
11498 emitcode ("mov","a,_ap");
11499 emitcode ("add","a,#!constbyte",0xFF);
11500 emitcode ("mov","_ap,a");
11501 emitcode ("mov","a,b");
11502 emitcode ("addc","a,#!constbyte",0xFF);
11503 emitcode ("mov","b,a");
11504 emitcode ("sjmp","!tlabel",lbl->key+100);
11505 emitcode ("","!tlabeldef",lbl1->key+100);
11507 emitcode ("mov", "dps,#0");
11508 _G.dptrInUse = _G.dptr1InUse = 0;
11509 unsavermask(rsave);
11513 /*-----------------------------------------------------------------*/
11514 /* genMemcmpX2X - gen code for memcmp xdata to xdata */
11515 /*-----------------------------------------------------------------*/
11516 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11518 operand *from , *to , *count;
11523 /* we know it has to be 3 parameters */
11524 assert (nparms == 3);
11526 rsave = newBitVect(16);
11527 /* save DPTR if it needs to be saved */
11528 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11529 if (bitVectBitValue(ic->rMask,i))
11530 rsave = bitVectSetBit(rsave,i);
11532 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11533 ds390_rUmaskForOp (IC_RESULT(ic))));
11540 aopOp (from, ic->next, FALSE, FALSE);
11542 /* get from into DPTR1 */
11543 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11544 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11545 if (options.model == MODEL_FLAT24) {
11546 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11549 freeAsmop (from, NULL, ic, FALSE);
11550 aopOp (to, ic, FALSE, FALSE);
11551 /* get "to" into DPTR */
11552 /* if the operand is already in dptr
11553 then we do nothing else we move the value to dptr */
11554 if (AOP_TYPE (to) != AOP_STR) {
11555 /* if already in DPTR then we need to push */
11556 if (AOP_TYPE(to) == AOP_DPTR) {
11557 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11558 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11559 if (options.model == MODEL_FLAT24)
11560 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11561 emitcode ("pop", "dph");
11562 emitcode ("pop", "dpl");
11564 _startLazyDPSEvaluation ();
11565 /* if this is remateriazable */
11566 if (AOP_TYPE (to) == AOP_IMMD) {
11567 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11568 } else { /* we need to get it byte by byte */
11569 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11570 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11571 if (options.model == MODEL_FLAT24) {
11572 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11575 _endLazyDPSEvaluation ();
11578 freeAsmop (to, NULL, ic, FALSE);
11579 _G.dptrInUse = _G.dptr1InUse = 1;
11580 aopOp (count, ic->next->next, FALSE,FALSE);
11581 lbl =newiTempLabel(NULL);
11582 lbl2 =newiTempLabel(NULL);
11584 /* now for the actual compare */
11585 if (AOP_TYPE(count) == AOP_LIT &&
11586 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11587 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11589 emitcode("lcall","__bi_memcmpc2x_s");
11591 emitcode("lcall","__bi_memcmpx2x_s");
11592 freeAsmop (count, NULL, ic, FALSE);
11593 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11594 aopPut(AOP(IC_RESULT(ic)),"a",0);
11595 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11597 symbol *lbl1 = newiTempLabel(NULL);
11599 emitcode("push","ar0");
11600 emitcode (";"," Auto increment but no djnz");
11601 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11602 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11603 freeAsmop (count, NULL, ic, FALSE);
11604 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11605 emitcode ("","!tlabeldef",lbl->key+100);
11607 emitcode ("clr","a");
11608 emitcode ("movc", "a,@a+dptr");
11610 emitcode ("movx", "a,@dptr");
11611 emitcode ("mov","r0,a");
11612 emitcode ("movx", "a,@dptr");
11613 emitcode ("clr","c");
11614 emitcode ("subb","a,r0");
11615 emitcode ("jnz","!tlabel",lbl2->key+100);
11616 emitcode ("inc", "dptr");
11617 emitcode ("inc", "dptr");
11618 emitcode ("mov","a,b");
11619 emitcode ("orl","a,_ap");
11620 emitcode ("jz","!tlabel",lbl1->key+100);
11621 emitcode ("mov","a,_ap");
11622 emitcode ("add","a,#!constbyte",0xFF);
11623 emitcode ("mov","_ap,a");
11624 emitcode ("mov","a,b");
11625 emitcode ("addc","a,#!constbyte",0xFF);
11626 emitcode ("mov","b,a");
11627 emitcode ("sjmp","!tlabel",lbl->key+100);
11628 emitcode ("","!tlabeldef",lbl1->key+100);
11629 emitcode ("clr","a");
11630 emitcode ("","!tlabeldef",lbl2->key+100);
11631 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11632 aopPut(AOP(IC_RESULT(ic)),"a",0);
11633 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11634 emitcode("pop","ar0");
11635 emitcode ("mov", "dps,#0");
11637 _G.dptrInUse = _G.dptr1InUse = 0;
11638 unsavermask(rsave);
11642 /*-----------------------------------------------------------------*/
11643 /* genInp - gen code for __builtin_inp read data from a mem mapped */
11644 /* port, first parameter output area second parameter pointer to */
11645 /* port third parameter count */
11646 /*-----------------------------------------------------------------*/
11647 static void genInp( iCode *ic, int nparms, operand **parms)
11649 operand *from , *to , *count;
11654 /* we know it has to be 3 parameters */
11655 assert (nparms == 3);
11657 rsave = newBitVect(16);
11658 /* save DPTR if it needs to be saved */
11659 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11660 if (bitVectBitValue(ic->rMask,i))
11661 rsave = bitVectSetBit(rsave,i);
11663 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11664 ds390_rUmaskForOp (IC_RESULT(ic))));
11671 aopOp (from, ic->next, FALSE, FALSE);
11673 /* get from into DPTR1 */
11674 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11675 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11676 if (options.model == MODEL_FLAT24) {
11677 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11680 freeAsmop (from, NULL, ic, FALSE);
11681 aopOp (to, ic, FALSE, FALSE);
11682 /* get "to" into DPTR */
11683 /* if the operand is already in dptr
11684 then we do nothing else we move the value to dptr */
11685 if (AOP_TYPE (to) != AOP_STR) {
11686 /* if already in DPTR then we need to push */
11687 if (AOP_TYPE(to) == AOP_DPTR) {
11688 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11689 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11690 if (options.model == MODEL_FLAT24)
11691 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11692 emitcode ("pop", "dph");
11693 emitcode ("pop", "dpl");
11695 _startLazyDPSEvaluation ();
11696 /* if this is remateriazable */
11697 if (AOP_TYPE (to) == AOP_IMMD) {
11698 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11699 } else { /* we need to get it byte by byte */
11700 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11701 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11702 if (options.model == MODEL_FLAT24) {
11703 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11706 _endLazyDPSEvaluation ();
11709 freeAsmop (to, NULL, ic, FALSE);
11711 _G.dptrInUse = _G.dptr1InUse = 1;
11712 aopOp (count, ic->next->next, FALSE,FALSE);
11713 lbl =newiTempLabel(NULL);
11715 /* now for the actual copy */
11716 if (AOP_TYPE(count) == AOP_LIT &&
11717 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11718 emitcode (";","OH JOY auto increment with djnz (very fast)");
11719 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11720 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11721 freeAsmop (count, NULL, ic, FALSE);
11722 emitcode ("","!tlabeldef",lbl->key+100);
11723 emitcode ("movx", "a,@dptr"); /* read data from port */
11724 emitcode ("dec","dps"); /* switch to DPTR */
11725 emitcode ("movx", "@dptr,a"); /* save into location */
11726 emitcode ("inc", "dptr"); /* point to next area */
11727 emitcode ("inc","dps"); /* switch to DPTR2 */
11728 emitcode ("djnz","b,!tlabel",lbl->key+100);
11730 symbol *lbl1 = newiTempLabel(NULL);
11732 emitcode (";"," Auto increment but no djnz");
11733 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11734 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11735 freeAsmop (count, NULL, ic, FALSE);
11736 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11737 emitcode ("","!tlabeldef",lbl->key+100);
11738 emitcode ("movx", "a,@dptr");
11739 emitcode ("dec","dps"); /* switch to DPTR */
11740 emitcode ("movx", "@dptr,a");
11741 emitcode ("inc", "dptr");
11742 emitcode ("inc","dps"); /* switch to DPTR2 */
11743 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
11744 /* emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
11745 emitcode ("mov","a,b");
11746 emitcode ("orl","a,_ap");
11747 emitcode ("jz","!tlabel",lbl1->key+100);
11748 emitcode ("mov","a,_ap");
11749 emitcode ("add","a,#!constbyte",0xFF);
11750 emitcode ("mov","_ap,a");
11751 emitcode ("mov","a,b");
11752 emitcode ("addc","a,#!constbyte",0xFF);
11753 emitcode ("mov","b,a");
11754 emitcode ("sjmp","!tlabel",lbl->key+100);
11755 emitcode ("","!tlabeldef",lbl1->key+100);
11757 emitcode ("mov", "dps,#0");
11758 _G.dptrInUse = _G.dptr1InUse = 0;
11759 unsavermask(rsave);
11763 /*-----------------------------------------------------------------*/
11764 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
11765 /* port, first parameter output area second parameter pointer to */
11766 /* port third parameter count */
11767 /*-----------------------------------------------------------------*/
11768 static void genOutp( iCode *ic, int nparms, operand **parms)
11770 operand *from , *to , *count;
11775 /* we know it has to be 3 parameters */
11776 assert (nparms == 3);
11778 rsave = newBitVect(16);
11779 /* save DPTR if it needs to be saved */
11780 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11781 if (bitVectBitValue(ic->rMask,i))
11782 rsave = bitVectSetBit(rsave,i);
11784 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11785 ds390_rUmaskForOp (IC_RESULT(ic))));
11792 aopOp (from, ic->next, FALSE, FALSE);
11794 /* get from into DPTR1 */
11795 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11796 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11797 if (options.model == MODEL_FLAT24) {
11798 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11801 freeAsmop (from, NULL, ic, FALSE);
11802 aopOp (to, ic, FALSE, FALSE);
11803 /* get "to" into DPTR */
11804 /* if the operand is already in dptr
11805 then we do nothing else we move the value to dptr */
11806 if (AOP_TYPE (to) != AOP_STR) {
11807 /* if already in DPTR then we need to push */
11808 if (AOP_TYPE(to) == AOP_DPTR) {
11809 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11810 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11811 if (options.model == MODEL_FLAT24)
11812 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11813 emitcode ("pop", "dph");
11814 emitcode ("pop", "dpl");
11816 _startLazyDPSEvaluation ();
11817 /* if this is remateriazable */
11818 if (AOP_TYPE (to) == AOP_IMMD) {
11819 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11820 } else { /* we need to get it byte by byte */
11821 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11822 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11823 if (options.model == MODEL_FLAT24) {
11824 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11827 _endLazyDPSEvaluation ();
11830 freeAsmop (to, NULL, ic, FALSE);
11832 _G.dptrInUse = _G.dptr1InUse = 1;
11833 aopOp (count, ic->next->next, FALSE,FALSE);
11834 lbl =newiTempLabel(NULL);
11836 /* now for the actual copy */
11837 if (AOP_TYPE(count) == AOP_LIT &&
11838 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11839 emitcode (";","OH JOY auto increment with djnz (very fast)");
11840 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
11841 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11842 emitcode ("","!tlabeldef",lbl->key+100);
11843 emitcode ("movx", "a,@dptr"); /* read data from port */
11844 emitcode ("inc","dps"); /* switch to DPTR2 */
11845 emitcode ("movx", "@dptr,a"); /* save into location */
11846 emitcode ("inc", "dptr"); /* point to next area */
11847 emitcode ("dec","dps"); /* switch to DPTR */
11848 emitcode ("djnz","b,!tlabel",lbl->key+100);
11849 freeAsmop (count, NULL, ic, FALSE);
11851 symbol *lbl1 = newiTempLabel(NULL);
11853 emitcode (";"," Auto increment but no djnz");
11854 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11855 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11856 freeAsmop (count, NULL, ic, FALSE);
11857 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
11858 emitcode ("","!tlabeldef",lbl->key+100);
11859 emitcode ("movx", "a,@dptr");
11860 emitcode ("inc", "dptr");
11861 emitcode ("inc","dps"); /* switch to DPTR2 */
11862 emitcode ("movx", "@dptr,a");
11863 emitcode ("dec","dps"); /* switch to DPTR */
11864 emitcode ("mov","a,b");
11865 emitcode ("orl","a,_ap");
11866 emitcode ("jz","!tlabel",lbl1->key+100);
11867 emitcode ("mov","a,_ap");
11868 emitcode ("add","a,#!constbyte",0xFF);
11869 emitcode ("mov","_ap,a");
11870 emitcode ("mov","a,b");
11871 emitcode ("addc","a,#!constbyte",0xFF);
11872 emitcode ("mov","b,a");
11873 emitcode ("sjmp","!tlabel",lbl->key+100);
11874 emitcode ("","!tlabeldef",lbl1->key+100);
11876 emitcode ("mov", "dps,#0");
11877 _G.dptrInUse = _G.dptr1InUse = 0;
11878 unsavermask(rsave);
11882 /*-----------------------------------------------------------------*/
11883 /* genSwapW - swap lower & high order bytes */
11884 /*-----------------------------------------------------------------*/
11885 static void genSwapW(iCode *ic, int nparms, operand **parms)
11889 assert (nparms==1);
11892 dest=IC_RESULT(ic);
11894 assert(getSize(operandType(src))==2);
11896 aopOp (src, ic, FALSE, FALSE);
11897 emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
11899 MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
11901 freeAsmop (src, NULL, ic, FALSE);
11903 aopOp (dest,ic, FALSE, FALSE);
11904 aopPut(AOP(dest),"b",0);
11905 aopPut(AOP(dest),"a",1);
11906 freeAsmop (dest, NULL, ic, FALSE);
11909 /*-----------------------------------------------------------------*/
11910 /* genMemsetX - gencode for memSetX data */
11911 /*-----------------------------------------------------------------*/
11912 static void genMemsetX(iCode *ic, int nparms, operand **parms)
11914 operand *to , *val , *count;
11920 /* we know it has to be 3 parameters */
11921 assert (nparms == 3);
11927 /* save DPTR if it needs to be saved */
11928 rsave = newBitVect(16);
11929 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11930 if (bitVectBitValue(ic->rMask,i))
11931 rsave = bitVectSetBit(rsave,i);
11933 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11934 ds390_rUmaskForOp (IC_RESULT(ic))));
11937 aopOp (to, ic, FALSE, FALSE);
11938 /* get "to" into DPTR */
11939 /* if the operand is already in dptr
11940 then we do nothing else we move the value to dptr */
11941 if (AOP_TYPE (to) != AOP_STR) {
11942 /* if already in DPTR then we need to push */
11943 if (AOP_TYPE(to) == AOP_DPTR) {
11944 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11945 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11946 if (options.model == MODEL_FLAT24)
11947 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11948 emitcode ("pop", "dph");
11949 emitcode ("pop", "dpl");
11951 _startLazyDPSEvaluation ();
11952 /* if this is remateriazable */
11953 if (AOP_TYPE (to) == AOP_IMMD) {
11954 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11955 } else { /* we need to get it byte by byte */
11956 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11957 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11958 if (options.model == MODEL_FLAT24) {
11959 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11962 _endLazyDPSEvaluation ();
11965 freeAsmop (to, NULL, ic, FALSE);
11967 aopOp (val, ic->next->next, FALSE,FALSE);
11968 aopOp (count, ic->next->next, FALSE,FALSE);
11969 lbl =newiTempLabel(NULL);
11970 /* now for the actual copy */
11971 if (AOP_TYPE(count) == AOP_LIT &&
11972 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11973 l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
11974 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11976 emitcode ("","!tlabeldef",lbl->key+100);
11977 emitcode ("movx", "@dptr,a");
11978 emitcode ("inc", "dptr");
11979 emitcode ("djnz","b,!tlabel",lbl->key+100);
11981 symbol *lbl1 = newiTempLabel(NULL);
11983 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11984 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11985 emitcode ("","!tlabeldef",lbl->key+100);
11986 MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
11987 emitcode ("movx", "@dptr,a");
11988 emitcode ("inc", "dptr");
11989 emitcode ("mov","a,b");
11990 emitcode ("orl","a,_ap");
11991 emitcode ("jz","!tlabel",lbl1->key+100);
11992 emitcode ("mov","a,_ap");
11993 emitcode ("add","a,#!constbyte",0xFF);
11994 emitcode ("mov","_ap,a");
11995 emitcode ("mov","a,b");
11996 emitcode ("addc","a,#!constbyte",0xFF);
11997 emitcode ("mov","b,a");
11998 emitcode ("sjmp","!tlabel",lbl->key+100);
11999 emitcode ("","!tlabeldef",lbl1->key+100);
12001 freeAsmop (count, NULL, ic, FALSE);
12002 unsavermask(rsave);
12005 /*-----------------------------------------------------------------*/
12006 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
12007 /*-----------------------------------------------------------------*/
12008 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
12011 operand *pnum, *result;
12014 assert (nparms==1);
12015 /* save registers that need to be saved */
12016 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12017 ds390_rUmaskForOp (IC_RESULT(ic))));
12020 aopOp (pnum, ic, FALSE, FALSE);
12021 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12022 freeAsmop (pnum, NULL, ic, FALSE);
12023 emitcode ("lcall","NatLib_LoadPrimitive");
12024 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12025 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
12026 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
12027 for (i = (size-1) ; i >= 0 ; i-- ) {
12028 emitcode ("push","a%s",javaRet[i]);
12030 for (i=0; i < size ; i++ ) {
12031 emitcode ("pop","a%s",
12032 aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
12035 for (i = 0 ; i < size ; i++ ) {
12036 aopPut(AOP(result),javaRet[i],i);
12039 freeAsmop (result, NULL, ic, FALSE);
12040 unsavermask(rsave);
12043 /*-----------------------------------------------------------------*/
12044 /* genNatLibLoadPointer - calls TINI api function to load pointer */
12045 /*-----------------------------------------------------------------*/
12046 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
12049 operand *pnum, *result;
12053 assert (nparms==1);
12054 /* save registers that need to be saved */
12055 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12056 ds390_rUmaskForOp (IC_RESULT(ic))));
12059 aopOp (pnum, ic, FALSE, FALSE);
12060 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12061 freeAsmop (pnum, NULL, ic, FALSE);
12062 emitcode ("lcall","NatLib_LoadPointer");
12063 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12064 if (AOP_TYPE(result)!=AOP_STR) {
12065 for (i = 0 ; i < size ; i++ ) {
12066 aopPut(AOP(result),fReturn[i],i);
12069 freeAsmop (result, NULL, ic, FALSE);
12070 unsavermask(rsave);
12073 /*-----------------------------------------------------------------*/
12074 /* genNatLibInstallStateBlock - */
12075 /*-----------------------------------------------------------------*/
12076 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
12077 operand **parms, const char *name)
12080 operand *psb, *handle;
12081 assert (nparms==2);
12083 /* save registers that need to be saved */
12084 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12085 ds390_rUmaskForOp (IC_RESULT(ic))));
12089 /* put pointer to state block into DPTR1 */
12090 aopOp (psb, ic, FALSE, FALSE);
12091 if (AOP_TYPE (psb) == AOP_IMMD) {
12092 emitcode ("mov","dps,#1");
12093 emitcode ("mov", "dptr,%s",
12094 aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12095 emitcode ("mov","dps,#0");
12097 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12098 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12099 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12101 freeAsmop (psb, NULL, ic, FALSE);
12103 /* put libraryID into DPTR */
12104 emitcode ("mov","dptr,#LibraryID");
12106 /* put handle into r3:r2 */
12107 aopOp (handle, ic, FALSE, FALSE);
12108 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12109 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12110 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12111 emitcode ("pop","ar3");
12112 emitcode ("pop","ar2");
12114 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12115 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12117 freeAsmop (psb, NULL, ic, FALSE);
12119 /* make the call */
12120 emitcode ("lcall","NatLib_Install%sStateBlock",name);
12122 /* put return value into place*/
12124 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12126 aopPut(AOP(IC_RESULT(ic)),"a",0);
12127 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12128 unsavermask(rsave);
12131 /*-----------------------------------------------------------------*/
12132 /* genNatLibRemoveStateBlock - */
12133 /*-----------------------------------------------------------------*/
12134 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
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 unsavermask(rsave);
12151 /*-----------------------------------------------------------------*/
12152 /* genNatLibGetStateBlock - */
12153 /*-----------------------------------------------------------------*/
12154 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12155 operand **parms,const char *name)
12158 symbol *lbl = newiTempLabel(NULL);
12161 /* save registers that need to be saved */
12162 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12163 ds390_rUmaskForOp (IC_RESULT(ic))));
12165 /* put libraryID into DPTR */
12166 emitcode ("mov","dptr,#LibraryID");
12167 /* make the call */
12168 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12169 emitcode ("jnz","!tlabel",lbl->key+100);
12171 /* put return value into place */
12172 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12173 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12174 emitcode ("push","ar3");
12175 emitcode ("push","ar2");
12176 emitcode ("pop","%s",
12177 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12178 emitcode ("pop","%s",
12179 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12181 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12182 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12184 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12185 emitcode ("","!tlabeldef",lbl->key+100);
12186 unsavermask(rsave);
12189 /*-----------------------------------------------------------------*/
12190 /* genMMMalloc - */
12191 /*-----------------------------------------------------------------*/
12192 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12193 int size, const char *name)
12198 symbol *lbl = newiTempLabel(NULL);
12200 assert (nparms == 1);
12201 /* save registers that need to be saved */
12202 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12203 ds390_rUmaskForOp (IC_RESULT(ic))));
12206 aopOp (bsize,ic,FALSE,FALSE);
12208 /* put the size in R4-R2 */
12209 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12210 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12211 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12213 emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12214 emitcode("pop","ar4");
12216 emitcode("pop","ar3");
12217 emitcode("pop","ar2");
12219 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12220 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12222 emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12225 freeAsmop (bsize, NULL, ic, FALSE);
12227 /* make the call */
12228 emitcode ("lcall","MM_%s",name);
12229 emitcode ("jz","!tlabel",lbl->key+100);
12230 emitcode ("mov","r2,#!constbyte",0xff);
12231 emitcode ("mov","r3,#!constbyte",0xff);
12232 emitcode ("","!tlabeldef",lbl->key+100);
12233 /* we don't care about the pointer : we just save the handle */
12234 rsym = OP_SYMBOL(IC_RESULT(ic));
12235 if (rsym->liveFrom != rsym->liveTo) {
12236 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12237 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12238 emitcode ("push","ar3");
12239 emitcode ("push","ar2");
12240 emitcode ("pop","%s",
12241 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12242 emitcode ("pop","%s",
12243 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12245 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12246 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12248 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12250 unsavermask(rsave);
12253 /*-----------------------------------------------------------------*/
12255 /*-----------------------------------------------------------------*/
12256 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12261 assert (nparms == 1);
12262 /* save registers that need to be saved */
12263 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12264 ds390_rUmaskForOp (IC_RESULT(ic))));
12267 aopOp (handle,ic,FALSE,FALSE);
12269 /* put the size in R4-R2 */
12270 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12271 emitcode("push","%s",
12272 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12273 emitcode("push","%s",
12274 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12275 emitcode("pop","ar3");
12276 emitcode("pop","ar2");
12278 emitcode ("mov","r2,%s",
12279 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12280 emitcode ("mov","r3,%s",
12281 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12283 freeAsmop (handle, NULL, ic, FALSE);
12285 /* make the call */
12286 emitcode ("lcall","MM_Deref");
12289 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12290 if (rsym->liveFrom != rsym->liveTo) {
12291 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12292 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12293 _startLazyDPSEvaluation ();
12295 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12296 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12297 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12299 _endLazyDPSEvaluation ();
12304 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12305 unsavermask(rsave);
12308 /*-----------------------------------------------------------------*/
12309 /* genMMUnrestrictedPersist - */
12310 /*-----------------------------------------------------------------*/
12311 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12316 assert (nparms == 1);
12317 /* save registers that need to be saved */
12318 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12319 ds390_rUmaskForOp (IC_RESULT(ic))));
12322 aopOp (handle,ic,FALSE,FALSE);
12324 /* put the size in R3-R2 */
12325 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12326 emitcode("push","%s",
12327 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12328 emitcode("push","%s",
12329 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12330 emitcode("pop","ar3");
12331 emitcode("pop","ar2");
12333 emitcode ("mov","r2,%s",
12334 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12335 emitcode ("mov","r3,%s",
12336 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12338 freeAsmop (handle, NULL, ic, FALSE);
12340 /* make the call */
12341 emitcode ("lcall","MM_UnrestrictedPersist");
12344 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12345 if (rsym->liveFrom != rsym->liveTo) {
12346 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12347 aopPut(AOP(IC_RESULT(ic)),"a",0);
12348 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12351 unsavermask(rsave);
12354 /*-----------------------------------------------------------------*/
12355 /* genSystemExecJavaProcess - */
12356 /*-----------------------------------------------------------------*/
12357 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12360 operand *handle, *pp;
12362 assert (nparms==2);
12363 /* save registers that need to be saved */
12364 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12365 ds390_rUmaskForOp (IC_RESULT(ic))));
12370 /* put the handle in R3-R2 */
12371 aopOp (handle,ic,FALSE,FALSE);
12372 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12373 emitcode("push","%s",
12374 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12375 emitcode("push","%s",
12376 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12377 emitcode("pop","ar3");
12378 emitcode("pop","ar2");
12380 emitcode ("mov","r2,%s",
12381 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12382 emitcode ("mov","r3,%s",
12383 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12385 freeAsmop (handle, NULL, ic, FALSE);
12387 /* put pointer in DPTR */
12388 aopOp (pp,ic,FALSE,FALSE);
12389 if (AOP_TYPE(pp) == AOP_IMMD) {
12390 emitcode ("mov", "dptr,%s",
12391 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12392 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12393 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12394 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12395 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12397 freeAsmop (handle, NULL, ic, FALSE);
12399 /* make the call */
12400 emitcode ("lcall","System_ExecJavaProcess");
12402 /* put result in place */
12404 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12405 if (rsym->liveFrom != rsym->liveTo) {
12406 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12407 aopPut(AOP(IC_RESULT(ic)),"a",0);
12408 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12412 unsavermask(rsave);
12415 /*-----------------------------------------------------------------*/
12416 /* genSystemRTCRegisters - */
12417 /*-----------------------------------------------------------------*/
12418 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12424 assert (nparms==1);
12425 /* save registers that need to be saved */
12426 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12427 ds390_rUmaskForOp (IC_RESULT(ic))));
12430 /* put pointer in DPTR */
12431 aopOp (pp,ic,FALSE,FALSE);
12432 if (AOP_TYPE (pp) == AOP_IMMD) {
12433 emitcode ("mov","dps,#1");
12434 emitcode ("mov", "dptr,%s",
12435 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12436 emitcode ("mov","dps,#0");
12438 emitcode ("mov","dpl1,%s",
12439 aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12440 emitcode ("mov","dph1,%s",
12441 aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12442 emitcode ("mov","dpx1,%s",
12443 aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12445 freeAsmop (pp, NULL, ic, FALSE);
12447 /* make the call */
12448 emitcode ("lcall","System_%sRTCRegisters",name);
12450 unsavermask(rsave);
12453 /*-----------------------------------------------------------------*/
12454 /* genSystemThreadSleep - */
12455 /*-----------------------------------------------------------------*/
12456 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12461 assert (nparms==1);
12462 /* save registers that need to be saved */
12463 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12464 ds390_rUmaskForOp (IC_RESULT(ic))));
12467 aopOp(to,ic,FALSE,FALSE);
12468 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12469 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12470 emitcode ("push","%s",
12471 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12472 emitcode ("push","%s",
12473 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12474 emitcode ("push","%s",
12475 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12476 emitcode ("push","%s",
12477 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12478 emitcode ("pop","ar3");
12479 emitcode ("pop","ar2");
12480 emitcode ("pop","ar1");
12481 emitcode ("pop","ar0");
12483 emitcode ("mov","r0,%s",
12484 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12485 emitcode ("mov","r1,%s",
12486 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12487 emitcode ("mov","r2,%s",
12488 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12489 emitcode ("mov","r3,%s",
12490 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12492 freeAsmop (to, NULL, ic, FALSE);
12494 /* suspend in acc */
12496 aopOp(s,ic,FALSE,FALSE);
12497 emitcode ("mov","a,%s",
12498 aopGet(AOP(s),0,FALSE,TRUE,NULL));
12499 freeAsmop (s, NULL, ic, FALSE);
12501 /* make the call */
12502 emitcode ("lcall","System_%s",name);
12504 unsavermask(rsave);
12507 /*-----------------------------------------------------------------*/
12508 /* genSystemThreadResume - */
12509 /*-----------------------------------------------------------------*/
12510 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12515 assert (nparms==2);
12516 /* save registers that need to be saved */
12517 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12518 ds390_rUmaskForOp (IC_RESULT(ic))));
12524 aopOp(pid,ic,FALSE,FALSE);
12525 emitcode ("mov","r0,%s",
12526 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12527 freeAsmop (pid, NULL, ic, FALSE);
12530 aopOp(tid,ic,FALSE,FALSE);
12531 emitcode ("mov","a,%s",
12532 aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
12533 freeAsmop (tid, NULL, ic, FALSE);
12535 emitcode ("lcall","System_ThreadResume");
12537 /* put result into place */
12539 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12540 if (rsym->liveFrom != rsym->liveTo) {
12541 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12542 aopPut(AOP(IC_RESULT(ic)),"a",0);
12543 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12546 unsavermask(rsave);
12549 /*-----------------------------------------------------------------*/
12550 /* genSystemProcessResume - */
12551 /*-----------------------------------------------------------------*/
12552 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
12557 assert (nparms==1);
12558 /* save registers that need to be saved */
12559 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12560 ds390_rUmaskForOp (IC_RESULT(ic))));
12565 aopOp(pid,ic,FALSE,FALSE);
12566 emitcode ("mov","a,%s",
12567 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12568 freeAsmop (pid, NULL, ic, FALSE);
12570 emitcode ("lcall","System_ProcessResume");
12572 unsavermask(rsave);
12575 /*-----------------------------------------------------------------*/
12577 /*-----------------------------------------------------------------*/
12578 static void genSystem (iCode *ic,int nparms,char *name)
12580 assert(nparms == 0);
12582 emitcode ("lcall","System_%s",name);
12585 /*-----------------------------------------------------------------*/
12586 /* genSystemPoll - */
12587 /*-----------------------------------------------------------------*/
12588 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
12593 assert (nparms==1);
12594 /* save registers that need to be saved */
12595 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12596 ds390_rUmaskForOp (IC_RESULT(ic))));
12599 aopOp (fp,ic,FALSE,FALSE);
12600 if (AOP_TYPE (fp) == AOP_IMMD) {
12601 emitcode ("mov", "dptr,%s",
12602 aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
12603 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
12604 emitcode ("mov","dpl,%s",
12605 aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
12606 emitcode ("mov","dph,%s",
12607 aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
12608 emitcode ("mov","dpx,%s",
12609 aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
12611 freeAsmop (fp, NULL, ic, FALSE);
12613 emitcode ("lcall","System_%sPoll",name);
12615 /* put result into place */
12617 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12618 if (rsym->liveFrom != rsym->liveTo) {
12619 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12620 aopPut(AOP(IC_RESULT(ic)),"a",0);
12621 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12624 unsavermask(rsave);
12627 /*-----------------------------------------------------------------*/
12628 /* genSystemGetCurrentID - */
12629 /*-----------------------------------------------------------------*/
12630 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
12632 assert (nparms==0);
12634 emitcode ("lcall","System_GetCurrent%sId",name);
12635 /* put result into place */
12637 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12638 if (rsym->liveFrom != rsym->liveTo) {
12639 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12640 aopPut(AOP(IC_RESULT(ic)),"a",0);
12641 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12646 /*-----------------------------------------------------------------*/
12647 /* genDummyRead - generate code for dummy read of volatiles */
12648 /*-----------------------------------------------------------------*/
12650 genDummyRead (iCode * ic)
12655 D(emitcode("; genDummyRead",""));
12657 right = IC_RIGHT (ic);
12659 aopOp (right, ic, FALSE, FALSE);
12661 /* if the result is a bit */
12662 if (AOP_TYPE (right) == AOP_CRY)
12664 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
12668 /* bit variables done */
12670 size = AOP_SIZE (right);
12674 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
12679 freeAsmop (right, NULL, ic, TRUE);
12682 /*-----------------------------------------------------------------*/
12683 /* genCritical - generate code for start of a critical sequence */
12684 /*-----------------------------------------------------------------*/
12686 genCritical (iCode *ic)
12688 symbol *tlbl = newiTempLabel (NULL);
12690 D(emitcode("; genCritical",""));
12692 if (IC_RESULT (ic))
12693 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
12695 emitcode ("setb", "c");
12696 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
12697 emitcode ("clr", "c");
12698 emitcode ("", "%05d$:", (tlbl->key + 100));
12700 if (IC_RESULT (ic))
12701 outBitC (IC_RESULT (ic)); /* save old ea in an operand */
12703 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
12705 if (IC_RESULT (ic))
12706 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
12709 /*-----------------------------------------------------------------*/
12710 /* genEndCritical - generate code for end of a critical sequence */
12711 /*-----------------------------------------------------------------*/
12713 genEndCritical (iCode *ic)
12715 D(emitcode("; genEndCritical",""));
12719 aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
12720 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
12722 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
12723 emitcode ("mov", "ea,c");
12727 MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE, FALSE));
12728 emitcode ("rrc", "a");
12729 emitcode ("mov", "ea,c");
12731 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
12735 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
12736 emitcode ("mov", "ea,c");
12742 /*-----------------------------------------------------------------*/
12743 /* genBuiltIn - calls the appropriate function to generating code */
12744 /* for a built in function */
12745 /*-----------------------------------------------------------------*/
12746 static void genBuiltIn (iCode *ic)
12748 operand *bi_parms[MAX_BUILTIN_ARGS];
12753 /* get all the arguments for a built in function */
12754 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
12756 /* which function is it */
12757 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
12758 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
12759 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
12760 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
12761 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
12762 } else if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
12763 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
12764 } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
12765 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
12766 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
12767 genMemsetX(bi_iCode,nbi_parms,bi_parms);
12768 } else if (strcmp(bif->name,"__builtin_inp")==0) {
12769 genInp(bi_iCode,nbi_parms,bi_parms);
12770 } else if (strcmp(bif->name,"__builtin_outp")==0) {
12771 genOutp(bi_iCode,nbi_parms,bi_parms);
12772 } else if (strcmp(bif->name,"__builtin_swapw")==0) {
12773 genSwapW(bi_iCode,nbi_parms,bi_parms);
12774 /* JavaNative builtIns */
12775 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
12776 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
12777 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
12778 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
12779 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
12780 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
12781 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
12782 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
12783 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
12784 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12785 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
12786 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12787 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
12788 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
12789 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
12790 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
12791 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
12792 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12793 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
12794 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12795 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
12796 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
12797 } else if (strcmp(bif->name,"MM_Malloc")==0) {
12798 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
12799 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
12800 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
12801 } else if (strcmp(bif->name,"MM_Free")==0) {
12802 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
12803 } else if (strcmp(bif->name,"MM_Deref")==0) {
12804 genMMDeref(bi_iCode,nbi_parms,bi_parms);
12805 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
12806 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
12807 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
12808 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
12809 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
12810 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
12811 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
12812 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
12813 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
12814 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
12815 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
12816 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
12817 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
12818 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
12819 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
12820 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
12821 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12822 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12823 } else if (strcmp(bif->name,"System_SaveThread")==0) {
12824 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12825 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12826 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12827 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
12828 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
12829 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
12830 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
12831 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
12832 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
12833 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
12834 genSystem(bi_iCode,nbi_parms,"ProcessYield");
12835 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
12836 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
12837 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
12838 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
12839 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
12840 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
12841 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
12842 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
12843 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
12844 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
12846 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
12852 /*-----------------------------------------------------------------*/
12853 /* gen390Code - generate code for Dallas 390 based controllers */
12854 /*-----------------------------------------------------------------*/
12856 gen390Code (iCode * lic)
12861 lineHead = lineCurr = NULL;
12862 dptrn[1][0] = "dpl1";
12863 dptrn[1][1] = "dph1";
12864 dptrn[1][2] = "dpx1";
12866 if (options.model == MODEL_FLAT24) {
12867 fReturnSizeDS390 = 5;
12868 fReturn = fReturn24;
12870 fReturnSizeDS390 = 4;
12871 fReturn = fReturn16;
12872 options.stack10bit=0;
12875 /* print the allocation information */
12876 if (allocInfo && currFunc)
12877 printAllocInfo (currFunc, codeOutFile);
12879 /* if debug information required */
12880 if (options.debug && currFunc)
12882 debugFile->writeFunction(currFunc);
12884 if (IS_STATIC (currFunc->etype))
12885 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
12887 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
12890 /* stack pointer name */
12891 if (options.useXstack)
12897 for (ic = lic; ic; ic = ic->next)
12900 if (ic->lineno && cln != ic->lineno)
12905 emitcode ("", "C$%s$%d$%d$%d ==.",
12906 FileBaseName (ic->filename), ic->lineno,
12907 ic->level, ic->block);
12910 if (!options.noCcodeInAsm) {
12911 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
12912 printCLine(ic->filename, ic->lineno));
12916 if (options.iCodeInAsm) {
12917 emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
12919 /* if the result is marked as
12920 spilt and rematerializable or code for
12921 this has already been generated then
12923 if (resultRemat (ic) || ic->generated)
12926 /* depending on the operation */
12946 /* IPOP happens only when trying to restore a
12947 spilt live range, if there is an ifx statement
12948 following this pop then the if statement might
12949 be using some of the registers being popped which
12950 would destory the contents of the register so
12951 we need to check for this condition and handle it */
12953 ic->next->op == IFX &&
12954 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
12955 genIfx (ic->next, ic);
12973 genEndFunction (ic);
12993 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
13010 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
13014 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
13021 /* note these two are xlated by algebraic equivalence
13022 during parsing SDCC.y */
13023 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
13024 "got '>=' or '<=' shouldn't have come here");
13028 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
13040 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
13044 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
13048 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
13072 genRightShift (ic);
13075 case GET_VALUE_AT_ADDRESS:
13076 genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
13080 if (POINTER_SET (ic))
13081 genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
13107 if (ic->builtinSEND) genBuiltIn(ic);
13108 else addSet (&_G.sendSet, ic);
13111 case DUMMY_READ_VOLATILE:
13120 genEndCritical (ic);
13123 #if 0 // obsolete, and buggy for != xdata
13135 /* now we are ready to call the
13136 peep hole optimizer */
13137 if (!options.nopeep)
13138 peepHole (&lineHead);
13140 /* now do the actual printing */
13141 printLine (lineHead, codeOutFile);