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 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5670 if (AOP_TYPE (right) == AOP_LIT)
5671 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5673 if (opIsGptr (left) || opIsGptr (right))
5675 /* We are comparing a generic pointer to something.
5676 * Exclude the generic type byte from the comparison.
5679 D (emitcode (";", "cjneshort: generic ptr special case."););
5683 /* if the right side is a literal then anything goes */
5684 if (AOP_TYPE (right) == AOP_LIT &&
5685 AOP_TYPE (left) != AOP_DIR)
5689 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5690 emitcode ("cjne", "a,%s,!tlabel",
5691 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5697 /* if the right side is in a register or in direct space or
5698 if the left is a pointer register & right is not */
5699 else if (AOP_TYPE (right) == AOP_REG ||
5700 AOP_TYPE (right) == AOP_DIR ||
5701 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5702 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5706 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5707 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5708 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5709 emitcode ("jnz", "!tlabel", lbl->key + 100);
5711 emitcode ("cjne", "a,%s,!tlabel",
5712 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
5719 /* right is a pointer reg need both a & b */
5722 MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5723 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
5724 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5730 /*-----------------------------------------------------------------*/
5731 /* gencjne - compare and jump if not equal */
5732 /*-----------------------------------------------------------------*/
5734 gencjne (operand * left, operand * right, symbol * lbl)
5736 symbol *tlbl = newiTempLabel (NULL);
5738 D (emitcode (";", "gencjne");
5741 gencjneshort (left, right, lbl);
5743 emitcode ("mov", "a,%s", one);
5744 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5745 emitcode ("", "!tlabeldef", lbl->key + 100);
5746 emitcode ("clr", "a");
5747 emitcode ("", "!tlabeldef", tlbl->key + 100);
5750 /*-----------------------------------------------------------------*/
5751 /* genCmpEq - generates code for equal to */
5752 /*-----------------------------------------------------------------*/
5754 genCmpEq (iCode * ic, iCode * ifx)
5756 operand *left, *right, *result;
5758 D (emitcode (";", "genCmpEq ");
5762 AOP_SET_LOCALS (ic);
5764 /* if literal, literal on the right or
5765 if the right is in a pointer register and left
5767 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5768 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5770 operand *t = IC_RIGHT (ic);
5771 IC_RIGHT (ic) = IC_LEFT (ic);
5775 if (ifx && /* !AOP_SIZE(result) */
5776 OP_SYMBOL (result) &&
5777 OP_SYMBOL (result)->regType == REG_CND)
5780 /* if they are both bit variables */
5781 if (AOP_TYPE (left) == AOP_CRY &&
5782 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5784 if (AOP_TYPE (right) == AOP_LIT)
5786 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5789 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5790 emitcode ("cpl", "c");
5794 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5798 emitcode ("clr", "c");
5800 /* AOP_TYPE(right) == AOP_CRY */
5804 symbol *lbl = newiTempLabel (NULL);
5805 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5806 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5807 emitcode ("cpl", "c");
5808 emitcode ("", "!tlabeldef", (lbl->key + 100));
5810 /* if true label then we jump if condition
5812 tlbl = newiTempLabel (NULL);
5815 emitcode ("jnc", "!tlabel", tlbl->key + 100);
5816 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5820 emitcode ("jc", "!tlabel", tlbl->key + 100);
5821 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5823 emitcode ("", "!tlabeldef", tlbl->key + 100);
5827 tlbl = newiTempLabel (NULL);
5828 gencjneshort (left, right, tlbl);
5831 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5832 emitcode ("", "!tlabeldef", tlbl->key + 100);
5836 symbol *lbl = newiTempLabel (NULL);
5837 emitcode ("sjmp", "!tlabel", lbl->key + 100);
5838 emitcode ("", "!tlabeldef", tlbl->key + 100);
5839 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5840 emitcode ("", "!tlabeldef", lbl->key + 100);
5843 /* mark the icode as generated */
5846 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5847 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5851 /* if they are both bit variables */
5852 if (AOP_TYPE (left) == AOP_CRY &&
5853 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5855 if (AOP_TYPE (right) == AOP_LIT)
5857 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5860 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5861 emitcode ("cpl", "c");
5865 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5869 emitcode ("clr", "c");
5871 /* AOP_TYPE(right) == AOP_CRY */
5875 symbol *lbl = newiTempLabel (NULL);
5876 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5877 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5878 emitcode ("cpl", "c");
5879 emitcode ("", "!tlabeldef", (lbl->key + 100));
5882 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5883 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5885 aopOp (result, ic, TRUE, FALSE);
5888 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5895 genIfxJump (ifx, "c");
5898 /* if the result is used in an arithmetic operation
5899 then put the result in place */
5904 gencjne (left, right, newiTempLabel (NULL));
5906 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5907 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5909 aopOp (result, ic, TRUE, FALSE);
5911 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5913 aopPut (AOP (result), "a", 0);
5918 genIfxJump (ifx, "a");
5921 /* if the result is used in an arithmetic operation
5922 then put the result in place */
5923 if (AOP_TYPE (result) != AOP_CRY)
5925 /* leave the result in acc */
5929 freeAsmop (result, NULL, ic, TRUE);
5932 /*-----------------------------------------------------------------*/
5933 /* ifxForOp - returns the icode containing the ifx for operand */
5934 /*-----------------------------------------------------------------*/
5936 ifxForOp (operand * op, iCode * ic)
5938 /* if true symbol then needs to be assigned */
5939 if (IS_TRUE_SYMOP (op))
5942 /* if this has register type condition and
5943 the next instruction is ifx with the same operand
5944 and live to of the operand is upto the ifx only then */
5946 ic->next->op == IFX &&
5947 IC_COND (ic->next)->key == op->key &&
5948 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5953 /*-----------------------------------------------------------------*/
5954 /* hasInc - operand is incremented before any other use */
5955 /*-----------------------------------------------------------------*/
5957 hasInc (operand *op, iCode *ic, int osize)
5959 sym_link *type = operandType(op);
5960 sym_link *retype = getSpec (type);
5961 iCode *lic = ic->next;
5964 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5965 if (!IS_SYMOP(op)) return NULL;
5967 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5968 if (IS_AGGREGATE(type->next)) return NULL;
5969 if (osize != (isize = getSize(type->next))) return NULL;
5972 /* if operand of the form op = op + <sizeof *op> */
5973 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5974 isOperandEqual(IC_RESULT(lic),op) &&
5975 isOperandLiteral(IC_RIGHT(lic)) &&
5976 operandLitValue(IC_RIGHT(lic)) == isize) {
5979 /* if the operand used or deffed */
5980 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5983 /* if GOTO or IFX */
5984 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5990 /*-----------------------------------------------------------------*/
5991 /* genAndOp - for && operation */
5992 /*-----------------------------------------------------------------*/
5994 genAndOp (iCode * ic)
5996 operand *left, *right, *result;
5999 D (emitcode (";", "genAndOp "););
6001 /* note here that && operations that are in an
6002 if statement are taken away by backPatchLabels
6003 only those used in arthmetic operations remain */
6005 AOP_SET_LOCALS (ic);
6007 /* if both are bit variables */
6008 if (AOP_TYPE (left) == AOP_CRY &&
6009 AOP_TYPE (right) == AOP_CRY)
6011 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6012 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6013 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6014 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6016 aopOp (result,ic,FALSE, FALSE);
6021 tlbl = newiTempLabel (NULL);
6023 emitcode ("jz", "!tlabel", tlbl->key + 100);
6025 emitcode ("", "!tlabeldef", tlbl->key + 100);
6026 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6027 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6029 aopOp (result,ic,FALSE, FALSE);
6032 freeAsmop (result, NULL, ic, TRUE);
6036 /*-----------------------------------------------------------------*/
6037 /* genOrOp - for || operation */
6038 /*-----------------------------------------------------------------*/
6040 genOrOp (iCode * ic)
6042 operand *left, *right, *result;
6045 D (emitcode (";", "genOrOp "););
6047 /* note here that || operations that are in an
6048 if statement are taken away by backPatchLabels
6049 only those used in arthmetic operations remain */
6051 AOP_SET_LOCALS (ic);
6053 /* if both are bit variables */
6054 if (AOP_TYPE (left) == AOP_CRY &&
6055 AOP_TYPE (right) == AOP_CRY)
6057 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6058 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6059 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6060 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6062 aopOp (result,ic,FALSE, FALSE);
6068 tlbl = newiTempLabel (NULL);
6070 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6072 emitcode ("", "!tlabeldef", tlbl->key + 100);
6073 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6074 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6076 aopOp (result,ic,FALSE, FALSE);
6081 freeAsmop (result, NULL, ic, TRUE);
6084 /*-----------------------------------------------------------------*/
6085 /* isLiteralBit - test if lit == 2^n */
6086 /*-----------------------------------------------------------------*/
6088 isLiteralBit (unsigned long lit)
6090 unsigned long pw[32] =
6091 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6092 0x100L, 0x200L, 0x400L, 0x800L,
6093 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6094 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6095 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6096 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6097 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6100 for (idx = 0; idx < 32; idx++)
6106 /*-----------------------------------------------------------------*/
6107 /* continueIfTrue - */
6108 /*-----------------------------------------------------------------*/
6110 continueIfTrue (iCode * ic)
6113 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6117 /*-----------------------------------------------------------------*/
6119 /*-----------------------------------------------------------------*/
6121 jumpIfTrue (iCode * ic)
6124 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6128 /*-----------------------------------------------------------------*/
6129 /* jmpTrueOrFalse - */
6130 /*-----------------------------------------------------------------*/
6132 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6134 // ugly but optimized by peephole
6137 symbol *nlbl = newiTempLabel (NULL);
6138 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6139 emitcode ("", "!tlabeldef", tlbl->key + 100);
6140 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6141 emitcode ("", "!tlabeldef", nlbl->key + 100);
6145 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6146 emitcode ("", "!tlabeldef", tlbl->key + 100);
6151 // Generate code to perform a bit-wise logic operation
6152 // on two operands in far space (assumed to already have been
6153 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6154 // in far space. This requires pushing the result on the stack
6155 // then popping it into the result.
6157 genFarFarLogicOp(iCode *ic, char *logicOp)
6159 int size, resultSize, compSize;
6163 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6164 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
6165 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6167 _startLazyDPSEvaluation();
6168 for (size = compSize; (size--); offset++)
6170 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6171 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6172 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6174 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6175 emitcode ("push", "acc");
6177 _endLazyDPSEvaluation();
6179 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6180 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6181 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6183 resultSize = AOP_SIZE(IC_RESULT(ic));
6185 ADJUST_PUSHED_RESULT(compSize, resultSize);
6187 _startLazyDPSEvaluation();
6190 emitcode ("pop", "acc");
6191 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6193 _endLazyDPSEvaluation();
6194 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6198 /*-----------------------------------------------------------------*/
6199 /* genAnd - code for and */
6200 /*-----------------------------------------------------------------*/
6202 genAnd (iCode * ic, iCode * ifx)
6204 operand *left, *right, *result;
6205 int size, offset = 0;
6206 unsigned long lit = 0L;
6211 D (emitcode (";", "genAnd "););
6213 AOP_OP_3_NOFATAL (ic, pushResult);
6214 AOP_SET_LOCALS (ic);
6218 genFarFarLogicOp(ic, "anl");
6223 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6225 AOP_TYPE (left), AOP_TYPE (right));
6226 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6228 AOP_SIZE (left), AOP_SIZE (right));
6231 /* if left is a literal & right is not then exchange them */
6232 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6233 #ifdef LOGIC_OPS_BROKEN
6234 || AOP_NEEDSACC (left)
6238 operand *tmp = right;
6243 /* if result = right then exchange them */
6244 if (sameRegs (AOP (result), AOP (right)))
6246 operand *tmp = right;
6251 /* if right is bit then exchange them */
6252 if (AOP_TYPE (right) == AOP_CRY &&
6253 AOP_TYPE (left) != AOP_CRY)
6255 operand *tmp = right;
6259 if (AOP_TYPE (right) == AOP_LIT)
6260 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6262 size = AOP_SIZE (result);
6265 // result = bit & yy;
6266 if (AOP_TYPE (left) == AOP_CRY)
6268 // c = bit & literal;
6269 if (AOP_TYPE (right) == AOP_LIT)
6273 if (size && sameRegs (AOP (result), AOP (left)))
6276 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6281 if (size && (AOP_TYPE (result) == AOP_CRY))
6283 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6286 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6291 emitcode ("clr", "c");
6296 if (AOP_TYPE (right) == AOP_CRY)
6299 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6300 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6305 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6307 emitcode ("rrc", "a");
6308 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6316 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6317 genIfxJump (ifx, "c");
6321 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6322 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6323 if ((AOP_TYPE (right) == AOP_LIT) &&
6324 (AOP_TYPE (result) == AOP_CRY) &&
6325 (AOP_TYPE (left) != AOP_CRY))
6327 int posbit = isLiteralBit (lit);
6332 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6335 emitcode ("mov", "c,acc.%d", posbit & 0x07);
6341 SNPRINTF (buff, sizeof(buff),
6342 "acc.%d", posbit & 0x07);
6343 genIfxJump (ifx, buff);
6347 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6354 symbol *tlbl = newiTempLabel (NULL);
6355 int sizel = AOP_SIZE (left);
6357 emitcode ("setb", "c");
6360 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6362 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6364 if ((posbit = isLiteralBit (bytelit)) != 0)
6365 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6368 if (bytelit != 0x0FFL)
6369 emitcode ("anl", "a,%s",
6370 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6371 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6376 // bit = left & literal
6379 emitcode ("clr", "c");
6380 emitcode ("", "!tlabeldef", tlbl->key + 100);
6382 // if(left & literal)
6386 jmpTrueOrFalse (ifx, tlbl);
6394 /* if left is same as result */
6395 if (sameRegs (AOP (result), AOP (left)))
6397 for (; size--; offset++)
6399 if (AOP_TYPE (right) == AOP_LIT)
6401 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6403 else if (bytelit == 0)
6404 aopPut (AOP (result), zero, offset);
6405 else if (IS_AOP_PREG (result))
6407 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6408 emitcode ("anl", "a,%s",
6409 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6410 aopPut (AOP (result), "a", offset);
6413 emitcode ("anl", "%s,%s",
6414 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6415 aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6419 if (AOP_TYPE (left) == AOP_ACC)
6420 emitcode ("anl", "a,%s",
6421 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6424 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6425 if (IS_AOP_PREG (result))
6427 emitcode ("anl", "a,%s",
6428 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6429 aopPut (AOP (result), "a", offset);
6432 emitcode ("anl", "%s,a",
6433 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6440 // left & result in different registers
6441 if (AOP_TYPE (result) == AOP_CRY)
6444 // if(size), result in bit
6445 // if(!size && ifx), conditional oper: if(left & right)
6446 symbol *tlbl = newiTempLabel (NULL);
6447 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6449 emitcode ("setb", "c");
6452 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6453 emitcode ("anl", "a,%s",
6454 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6456 if (AOP_TYPE(left)==AOP_ACC) {
6457 emitcode("mov", "b,a");
6458 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6459 emitcode("anl", "a,b");
6461 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6462 emitcode ("anl", "a,%s",
6463 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6466 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6472 emitcode ("", "!tlabeldef", tlbl->key + 100);
6476 jmpTrueOrFalse (ifx, tlbl);
6480 for (; (size--); offset++)
6483 // result = left & right
6484 if (AOP_TYPE (right) == AOP_LIT)
6486 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6488 aopPut (AOP (result),
6489 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6493 else if (bytelit == 0)
6495 aopPut (AOP (result), zero, offset);
6498 D (emitcode (";", "better literal AND."););
6499 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6500 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6501 FALSE, FALSE, DP2_RESULT_REG));
6506 // faster than result <- left, anl result,right
6507 // and better if result is SFR
6508 if (AOP_TYPE (left) == AOP_ACC)
6510 emitcode ("anl", "a,%s",
6511 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6515 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6516 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6518 emitcode("mov", "b,a");
6522 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6523 emitcode ("anl", "a,%s", rOp);
6526 aopPut (AOP (result), "a", offset);
6532 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6533 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6534 freeAsmop (result, NULL, ic, TRUE);
6538 /*-----------------------------------------------------------------*/
6539 /* genOr - code for or */
6540 /*-----------------------------------------------------------------*/
6542 genOr (iCode * ic, iCode * ifx)
6544 operand *left, *right, *result;
6545 int size, offset = 0;
6546 unsigned long lit = 0L;
6549 D (emitcode (";", "genOr "););
6551 AOP_OP_3_NOFATAL (ic, pushResult);
6552 AOP_SET_LOCALS (ic);
6556 genFarFarLogicOp(ic, "orl");
6562 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6564 AOP_TYPE (left), AOP_TYPE (right));
6565 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6567 AOP_SIZE (left), AOP_SIZE (right));
6570 /* if left is a literal & right is not then exchange them */
6571 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6572 #ifdef LOGIC_OPS_BROKEN
6573 || AOP_NEEDSACC (left) // I think this is a net loss now.
6577 operand *tmp = right;
6582 /* if result = right then exchange them */
6583 if (sameRegs (AOP (result), AOP (right)))
6585 operand *tmp = right;
6590 /* if right is bit then exchange them */
6591 if (AOP_TYPE (right) == AOP_CRY &&
6592 AOP_TYPE (left) != AOP_CRY)
6594 operand *tmp = right;
6598 if (AOP_TYPE (right) == AOP_LIT)
6599 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6601 size = AOP_SIZE (result);
6605 if (AOP_TYPE (left) == AOP_CRY)
6607 if (AOP_TYPE (right) == AOP_LIT)
6609 // c = bit & literal;
6612 // lit != 0 => result = 1
6613 if (AOP_TYPE (result) == AOP_CRY)
6616 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6618 continueIfTrue (ifx);
6621 emitcode ("setb", "c");
6625 // lit == 0 => result = left
6626 if (size && sameRegs (AOP (result), AOP (left)))
6628 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6633 if (AOP_TYPE (right) == AOP_CRY)
6636 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6637 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6642 symbol *tlbl = newiTempLabel (NULL);
6643 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6644 emitcode ("setb", "c");
6645 emitcode ("jb", "%s,!tlabel",
6646 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6648 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6649 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6651 jmpTrueOrFalse (ifx, tlbl);
6657 emitcode ("", "!tlabeldef", tlbl->key + 100);
6666 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6667 genIfxJump (ifx, "c");
6671 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6672 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6673 if ((AOP_TYPE (right) == AOP_LIT) &&
6674 (AOP_TYPE (result) == AOP_CRY) &&
6675 (AOP_TYPE (left) != AOP_CRY))
6681 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6683 continueIfTrue (ifx);
6688 // lit = 0, result = boolean(left)
6690 emitcode ("setb", "c");
6694 symbol *tlbl = newiTempLabel (NULL);
6695 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6697 emitcode ("", "!tlabeldef", tlbl->key + 100);
6701 genIfxJump (ifx, "a");
6709 /* if left is same as result */
6710 if (sameRegs (AOP (result), AOP (left)))
6712 for (; size--; offset++)
6714 if (AOP_TYPE (right) == AOP_LIT)
6716 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6722 if (IS_AOP_PREG (left))
6724 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6725 emitcode ("orl", "a,%s",
6726 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6727 aopPut (AOP (result), "a", offset);
6731 emitcode ("orl", "%s,%s",
6732 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6733 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6739 if (AOP_TYPE (left) == AOP_ACC)
6741 emitcode ("orl", "a,%s",
6742 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6746 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6747 if (IS_AOP_PREG (left))
6749 emitcode ("orl", "a,%s",
6750 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6751 aopPut (AOP (result), "a", offset);
6755 emitcode ("orl", "%s,a",
6756 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6764 // left & result in different registers
6765 if (AOP_TYPE (result) == AOP_CRY)
6768 // if(size), result in bit
6769 // if(!size && ifx), conditional oper: if(left | right)
6770 symbol *tlbl = newiTempLabel (NULL);
6771 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6773 emitcode ("setb", "c");
6776 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6777 emitcode ("orl", "a,%s",
6778 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6780 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6781 emitcode ("orl", "a,%s",
6782 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6784 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6790 emitcode ("", "!tlabeldef", tlbl->key + 100);
6794 jmpTrueOrFalse (ifx, tlbl);
6798 _startLazyDPSEvaluation();
6799 for (; (size--); offset++)
6802 // result = left & right
6803 if (AOP_TYPE (right) == AOP_LIT)
6805 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6807 aopPut (AOP (result),
6808 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6812 D (emitcode (";", "better literal OR."););
6813 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6814 emitcode ("orl", "a, %s",
6815 aopGet (AOP (right), offset,
6816 FALSE, FALSE, DP2_RESULT_REG));
6821 // faster than result <- left, anl result,right
6822 // and better if result is SFR
6823 if (AOP_TYPE (left) == AOP_ACC)
6825 emitcode ("orl", "a,%s",
6826 aopGet (AOP (right), offset,
6827 FALSE, FALSE, DP2_RESULT_REG));
6831 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6833 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6835 emitcode("mov", "b,a");
6839 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6840 emitcode ("orl", "a,%s", rOp);
6843 aopPut (AOP (result), "a", offset);
6845 _endLazyDPSEvaluation();
6850 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6851 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6852 freeAsmop (result, NULL, ic, TRUE);
6855 /*-----------------------------------------------------------------*/
6856 /* genXor - code for xclusive or */
6857 /*-----------------------------------------------------------------*/
6859 genXor (iCode * ic, iCode * ifx)
6861 operand *left, *right, *result;
6862 int size, offset = 0;
6863 unsigned long lit = 0L;
6866 D (emitcode (";", "genXor "););
6868 AOP_OP_3_NOFATAL (ic, pushResult);
6869 AOP_SET_LOCALS (ic);
6873 genFarFarLogicOp(ic, "xrl");
6878 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6880 AOP_TYPE (left), AOP_TYPE (right));
6881 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6883 AOP_SIZE (left), AOP_SIZE (right));
6886 /* if left is a literal & right is not ||
6887 if left needs acc & right does not */
6888 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6889 #ifdef LOGIC_OPS_BROKEN
6890 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6894 operand *tmp = right;
6899 /* if result = right then exchange them */
6900 if (sameRegs (AOP (result), AOP (right)))
6902 operand *tmp = right;
6907 /* if right is bit then exchange them */
6908 if (AOP_TYPE (right) == AOP_CRY &&
6909 AOP_TYPE (left) != AOP_CRY)
6911 operand *tmp = right;
6915 if (AOP_TYPE (right) == AOP_LIT)
6916 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6918 size = AOP_SIZE (result);
6922 if (AOP_TYPE (left) == AOP_CRY)
6924 if (AOP_TYPE (right) == AOP_LIT)
6926 // c = bit & literal;
6929 // lit>>1 != 0 => result = 1
6930 if (AOP_TYPE (result) == AOP_CRY)
6933 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6935 continueIfTrue (ifx);
6938 emitcode ("setb", "c");
6945 // lit == 0, result = left
6946 if (size && sameRegs (AOP (result), AOP (left)))
6948 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6952 // lit == 1, result = not(left)
6953 if (size && sameRegs (AOP (result), AOP (left)))
6955 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6960 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6961 emitcode ("cpl", "c");
6970 symbol *tlbl = newiTempLabel (NULL);
6971 if (AOP_TYPE (right) == AOP_CRY)
6974 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6978 int sizer = AOP_SIZE (right);
6980 // if val>>1 != 0, result = 1
6981 emitcode ("setb", "c");
6984 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
6986 // test the msb of the lsb
6987 emitcode ("anl", "a,#!constbyte",0xfe);
6988 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6992 emitcode ("rrc", "a");
6994 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6995 emitcode ("cpl", "c");
6996 emitcode ("", "!tlabeldef", (tlbl->key + 100));
7003 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7004 genIfxJump (ifx, "c");
7008 if (sameRegs (AOP (result), AOP (left)))
7010 /* if left is same as result */
7011 for (; size--; offset++)
7013 if (AOP_TYPE (right) == AOP_LIT)
7015 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7017 else if (IS_AOP_PREG (left))
7019 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7020 emitcode ("xrl", "a,%s",
7021 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7022 aopPut (AOP (result), "a", offset);
7025 emitcode ("xrl", "%s,%s",
7026 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
7027 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7031 if (AOP_TYPE (left) == AOP_ACC)
7032 emitcode ("xrl", "a,%s",
7033 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7036 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7037 if (IS_AOP_PREG (left))
7039 emitcode ("xrl", "a,%s",
7040 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7041 aopPut (AOP (result), "a", offset);
7044 emitcode ("xrl", "%s,a",
7045 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7052 // left & result in different registers
7053 if (AOP_TYPE (result) == AOP_CRY)
7056 // if(size), result in bit
7057 // if(!size && ifx), conditional oper: if(left ^ right)
7058 symbol *tlbl = newiTempLabel (NULL);
7059 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7062 emitcode ("setb", "c");
7065 if ((AOP_TYPE (right) == AOP_LIT) &&
7066 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7068 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7072 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7073 emitcode ("xrl", "a,%s",
7074 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7076 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7077 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7079 emitcode("mov", "b,a");
7083 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7084 emitcode ("xrl", "a,%s", rOp);
7087 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7093 emitcode ("", "!tlabeldef", tlbl->key + 100);
7097 jmpTrueOrFalse (ifx, tlbl);
7101 for (; (size--); offset++)
7104 // result = left & right
7105 if (AOP_TYPE (right) == AOP_LIT)
7107 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7109 aopPut (AOP (result),
7110 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7114 D (emitcode (";", "better literal XOR."););
7115 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7116 emitcode ("xrl", "a, %s",
7117 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7121 // faster than result <- left, anl result,right
7122 // and better if result is SFR
7123 if (AOP_TYPE (left) == AOP_ACC)
7125 emitcode ("xrl", "a,%s",
7126 aopGet (AOP (right), offset,
7127 FALSE, FALSE, DP2_RESULT_REG));
7131 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7132 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7134 emitcode("mov", "b,a");
7138 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7139 emitcode ("xrl", "a,%s", rOp);
7142 aopPut (AOP (result), "a", offset);
7149 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7150 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7151 freeAsmop (result, NULL, ic, TRUE);
7154 /*-----------------------------------------------------------------*/
7155 /* genInline - write the inline code out */
7156 /*-----------------------------------------------------------------*/
7158 genInline (iCode * ic)
7160 char *buffer, *bp, *bp1;
7162 D (emitcode (";", "genInline "); );
7164 _G.inLine += (!options.asmpeep);
7166 buffer = Safe_strdup(IC_INLINE(ic));
7170 /* emit each line as a code */
7195 /* emitcode("",buffer); */
7196 _G.inLine -= (!options.asmpeep);
7199 /*-----------------------------------------------------------------*/
7200 /* genRRC - rotate right with carry */
7201 /*-----------------------------------------------------------------*/
7205 operand *left, *result;
7208 D (emitcode (";", "genRRC "););
7210 /* rotate right with carry */
7211 left = IC_LEFT (ic);
7212 result = IC_RESULT (ic);
7213 aopOp (left, ic, FALSE, FALSE);
7214 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7216 /* move it to the result */
7217 size = AOP_SIZE (result);
7221 _startLazyDPSEvaluation ();
7224 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7225 emitcode ("rrc", "a");
7226 if (AOP_SIZE (result) > 1)
7227 aopPut (AOP (result), "a", offset--);
7229 _endLazyDPSEvaluation ();
7231 /* now we need to put the carry into the
7232 highest order byte of the result */
7233 if (AOP_SIZE (result) > 1)
7235 MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7237 emitcode ("mov", "acc.7,c");
7238 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7239 freeAsmop (left, NULL, ic, TRUE);
7240 freeAsmop (result, NULL, ic, TRUE);
7243 /*-----------------------------------------------------------------*/
7244 /* genRLC - generate code for rotate left with carry */
7245 /*-----------------------------------------------------------------*/
7249 operand *left, *result;
7253 D (emitcode (";", "genRLC "););
7255 /* rotate right with carry */
7256 left = IC_LEFT (ic);
7257 result = IC_RESULT (ic);
7258 aopOp (left, ic, FALSE, FALSE);
7259 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7261 /* move it to the result */
7262 size = AOP_SIZE (result);
7266 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7268 emitcode ("add", "a,acc");
7269 if (AOP_SIZE (result) > 1)
7271 aopPut (AOP (result), "a", offset++);
7274 _startLazyDPSEvaluation ();
7277 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7279 emitcode ("rlc", "a");
7280 if (AOP_SIZE (result) > 1)
7281 aopPut (AOP (result), "a", offset++);
7283 _endLazyDPSEvaluation ();
7285 /* now we need to put the carry into the
7286 highest order byte of the result */
7287 if (AOP_SIZE (result) > 1)
7289 l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7292 emitcode ("mov", "acc.0,c");
7293 aopPut (AOP (result), "a", 0);
7294 freeAsmop (left, NULL, ic, TRUE);
7295 freeAsmop (result, NULL, ic, TRUE);
7298 /*-----------------------------------------------------------------*/
7299 /* genGetHbit - generates code get highest order bit */
7300 /*-----------------------------------------------------------------*/
7302 genGetHbit (iCode * ic)
7304 operand *left, *result;
7305 left = IC_LEFT (ic);
7306 result = IC_RESULT (ic);
7307 aopOp (left, ic, FALSE, FALSE);
7308 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7310 D (emitcode (";", "genGetHbit "););
7312 /* get the highest order byte into a */
7313 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7314 if (AOP_TYPE (result) == AOP_CRY)
7316 emitcode ("rlc", "a");
7321 emitcode ("rl", "a");
7322 emitcode ("anl", "a,#1");
7327 freeAsmop (left, NULL, ic, TRUE);
7328 freeAsmop (result, NULL, ic, TRUE);
7331 /*-----------------------------------------------------------------*/
7332 /* AccRol - rotate left accumulator by known count */
7333 /*-----------------------------------------------------------------*/
7335 AccRol (int shCount)
7337 shCount &= 0x0007; // shCount : 0..7
7344 emitcode ("rl", "a");
7347 emitcode ("rl", "a");
7348 emitcode ("rl", "a");
7351 emitcode ("swap", "a");
7352 emitcode ("rr", "a");
7355 emitcode ("swap", "a");
7358 emitcode ("swap", "a");
7359 emitcode ("rl", "a");
7362 emitcode ("rr", "a");
7363 emitcode ("rr", "a");
7366 emitcode ("rr", "a");
7371 /*-----------------------------------------------------------------*/
7372 /* AccLsh - left shift accumulator by known count */
7373 /*-----------------------------------------------------------------*/
7375 AccLsh (int shCount)
7380 emitcode ("add", "a,acc");
7381 else if (shCount == 2)
7383 emitcode ("add", "a,acc");
7384 emitcode ("add", "a,acc");
7388 /* rotate left accumulator */
7390 /* and kill the lower order bits */
7391 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7396 /*-----------------------------------------------------------------*/
7397 /* AccRsh - right shift accumulator by known count */
7398 /*-----------------------------------------------------------------*/
7400 AccRsh (int shCount)
7407 emitcode ("rrc", "a");
7411 /* rotate right accumulator */
7412 AccRol (8 - shCount);
7413 /* and kill the higher order bits */
7414 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7419 #ifdef BETTER_LITERAL_SHIFT
7420 /*-----------------------------------------------------------------*/
7421 /* AccSRsh - signed right shift accumulator by known count */
7422 /*-----------------------------------------------------------------*/
7424 AccSRsh (int shCount)
7431 emitcode ("mov", "c,acc.7");
7432 emitcode ("rrc", "a");
7434 else if (shCount == 2)
7436 emitcode ("mov", "c,acc.7");
7437 emitcode ("rrc", "a");
7438 emitcode ("mov", "c,acc.7");
7439 emitcode ("rrc", "a");
7443 tlbl = newiTempLabel (NULL);
7444 /* rotate right accumulator */
7445 AccRol (8 - shCount);
7446 /* and kill the higher order bits */
7447 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7448 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7449 emitcode ("orl", "a,#!constbyte",
7450 (unsigned char) ~SRMask[shCount]);
7451 emitcode ("", "!tlabeldef", tlbl->key + 100);
7457 #ifdef BETTER_LITERAL_SHIFT
7458 /*-----------------------------------------------------------------*/
7459 /* shiftR1Left2Result - shift right one byte from left to result */
7460 /*-----------------------------------------------------------------*/
7462 shiftR1Left2Result (operand * left, int offl,
7463 operand * result, int offr,
7464 int shCount, int sign)
7466 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7467 /* shift right accumulator */
7472 aopPut (AOP (result), "a", offr);
7476 #ifdef BETTER_LITERAL_SHIFT
7477 /*-----------------------------------------------------------------*/
7478 /* shiftL1Left2Result - shift left one byte from left to result */
7479 /*-----------------------------------------------------------------*/
7481 shiftL1Left2Result (operand * left, int offl,
7482 operand * result, int offr, int shCount)
7484 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7485 /* shift left accumulator */
7487 aopPut (AOP (result), "a", offr);
7491 #ifdef BETTER_LITERAL_SHIFT
7492 /*-----------------------------------------------------------------*/
7493 /* movLeft2Result - move byte from left to result */
7494 /*-----------------------------------------------------------------*/
7496 movLeft2Result (operand * left, int offl,
7497 operand * result, int offr, int sign)
7500 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7502 l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
7504 if (*l == '@' && (IS_AOP_PREG (result)))
7506 emitcode ("mov", "a,%s", l);
7507 aopPut (AOP (result), "a", offr);
7513 aopPut (AOP (result), l, offr);
7517 /* MSB sign in acc.7 ! */
7518 if (getDataSize (left) == offl + 1)
7520 emitcode ("mov", "a,%s", l);
7521 aopPut (AOP (result), "a", offr);
7529 #ifdef BETTER_LITERAL_SHIFT
7530 /*-----------------------------------------------------------------*/
7531 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7532 /*-----------------------------------------------------------------*/
7536 emitcode ("rrc", "a");
7537 emitcode ("xch", "a,%s", x);
7538 emitcode ("rrc", "a");
7539 emitcode ("xch", "a,%s", x);
7543 #ifdef BETTER_LITERAL_SHIFT
7545 /*-----------------------------------------------------------------*/
7546 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7547 /*-----------------------------------------------------------------*/
7551 emitcode ("xch", "a,%s", x);
7552 emitcode ("rlc", "a");
7553 emitcode ("xch", "a,%s", x);
7554 emitcode ("rlc", "a");
7558 #ifdef BETTER_LITERAL_SHIFT
7559 /*-----------------------------------------------------------------*/
7560 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7561 /*-----------------------------------------------------------------*/
7565 emitcode ("xch", "a,%s", x);
7566 emitcode ("add", "a,acc");
7567 emitcode ("xch", "a,%s", x);
7568 emitcode ("rlc", "a");
7572 #ifdef BETTER_LITERAL_SHIFT
7573 /*-----------------------------------------------------------------*/
7574 /* AccAXLsh - left shift a:x by known count (0..7) */
7575 /*-----------------------------------------------------------------*/
7577 AccAXLsh (char *x, int shCount)
7592 case 5: // AAAAABBB:CCCCCDDD
7594 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7596 emitcode ("anl", "a,#!constbyte",
7597 SLMask[shCount]); // BBB00000:CCCCCDDD
7599 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7601 AccRol (shCount); // DDDCCCCC:BBB00000
7603 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7605 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7607 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7609 emitcode ("anl", "a,#!constbyte",
7610 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7612 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7614 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7617 case 6: // AAAAAABB:CCCCCCDD
7618 emitcode ("anl", "a,#!constbyte",
7619 SRMask[shCount]); // 000000BB:CCCCCCDD
7620 emitcode ("mov", "c,acc.0"); // c = B
7621 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7623 AccAXRrl1 (x); // BCCCCCCD:D000000B
7624 AccAXRrl1 (x); // BBCCCCCC:DD000000
7626 emitcode("rrc","a");
7627 emitcode("xch","a,%s", x);
7628 emitcode("rrc","a");
7629 emitcode("mov","c,acc.0"); //<< get correct bit
7630 emitcode("xch","a,%s", x);
7632 emitcode("rrc","a");
7633 emitcode("xch","a,%s", x);
7634 emitcode("rrc","a");
7635 emitcode("xch","a,%s", x);
7638 case 7: // a:x <<= 7
7640 emitcode ("anl", "a,#!constbyte",
7641 SRMask[shCount]); // 0000000B:CCCCCCCD
7643 emitcode ("mov", "c,acc.0"); // c = B
7645 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7647 AccAXRrl1 (x); // BCCCCCCC:D0000000
7656 #ifdef BETTER_LITERAL_SHIFT
7658 /*-----------------------------------------------------------------*/
7659 /* AccAXRsh - right shift a:x known count (0..7) */
7660 /*-----------------------------------------------------------------*/
7662 AccAXRsh (char *x, int shCount)
7670 AccAXRrl1 (x); // 0->a:x
7675 AccAXRrl1 (x); // 0->a:x
7678 AccAXRrl1 (x); // 0->a:x
7683 case 5: // AAAAABBB:CCCCCDDD = a:x
7685 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7687 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7689 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7691 emitcode ("anl", "a,#!constbyte",
7692 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7694 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7696 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7698 emitcode ("anl", "a,#!constbyte",
7699 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7701 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7703 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7705 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7708 case 6: // AABBBBBB:CCDDDDDD
7710 emitcode ("mov", "c,acc.7");
7711 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7713 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7715 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7717 emitcode ("anl", "a,#!constbyte",
7718 SRMask[shCount]); // 000000AA:BBBBBBCC
7721 case 7: // ABBBBBBB:CDDDDDDD
7723 emitcode ("mov", "c,acc.7"); // c = A
7725 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7727 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7729 emitcode ("anl", "a,#!constbyte",
7730 SRMask[shCount]); // 0000000A:BBBBBBBC
7739 #ifdef BETTER_LITERAL_SHIFT
7740 /*-----------------------------------------------------------------*/
7741 /* AccAXRshS - right shift signed a:x known count (0..7) */
7742 /*-----------------------------------------------------------------*/
7744 AccAXRshS (char *x, int shCount)
7752 emitcode ("mov", "c,acc.7");
7753 AccAXRrl1 (x); // s->a:x
7757 emitcode ("mov", "c,acc.7");
7758 AccAXRrl1 (x); // s->a:x
7760 emitcode ("mov", "c,acc.7");
7761 AccAXRrl1 (x); // s->a:x
7766 case 5: // AAAAABBB:CCCCCDDD = a:x
7768 tlbl = newiTempLabel (NULL);
7769 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7771 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7773 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7775 emitcode ("anl", "a,#!constbyte",
7776 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7778 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7780 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7782 emitcode ("anl", "a,#!constbyte",
7783 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7785 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7787 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7789 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7791 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7792 emitcode ("orl", "a,#!constbyte",
7793 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7795 emitcode ("", "!tlabeldef", tlbl->key + 100);
7796 break; // SSSSAAAA:BBBCCCCC
7798 case 6: // AABBBBBB:CCDDDDDD
7800 tlbl = newiTempLabel (NULL);
7801 emitcode ("mov", "c,acc.7");
7802 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7804 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7806 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7808 emitcode ("anl", "a,#!constbyte",
7809 SRMask[shCount]); // 000000AA:BBBBBBCC
7811 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7812 emitcode ("orl", "a,#!constbyte",
7813 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7815 emitcode ("", "!tlabeldef", tlbl->key + 100);
7817 case 7: // ABBBBBBB:CDDDDDDD
7819 tlbl = newiTempLabel (NULL);
7820 emitcode ("mov", "c,acc.7"); // c = A
7822 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7824 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7826 emitcode ("anl", "a,#!constbyte",
7827 SRMask[shCount]); // 0000000A:BBBBBBBC
7829 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7830 emitcode ("orl", "a,#!constbyte",
7831 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7833 emitcode ("", "!tlabeldef", tlbl->key + 100);
7841 #ifdef BETTER_LITERAL_SHIFT
7843 _loadLeftIntoAx(char **lsb,
7849 // Get the initial value from left into a pair of registers.
7850 // MSB must be in A, LSB can be any register.
7852 // If the result is held in registers, it is an optimization
7853 // if the LSB can be held in the register which will hold the,
7854 // result LSB since this saves us from having to copy it into
7855 // the result following AccAXLsh.
7857 // If the result is addressed indirectly, this is not a gain.
7858 if (AOP_NEEDSACC(result))
7862 _startLazyDPSEvaluation();
7863 if (AOP_TYPE(left) == AOP_DPTR2)
7866 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
7867 // get LSB in DP2_RESULT_REG.
7868 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
7869 assert(!strcmp(leftByte, DP2_RESULT_REG));
7873 // get LSB into DP2_RESULT_REG
7874 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
7875 if (strcmp(leftByte, DP2_RESULT_REG))
7878 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7881 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
7882 assert(strcmp(leftByte, DP2_RESULT_REG));
7885 _endLazyDPSEvaluation();
7886 *lsb = DP2_RESULT_REG;
7890 if (sameRegs (AOP (result), AOP (left)) &&
7891 ((offl + MSB16) == offr))
7893 /* don't crash result[offr] */
7894 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
7895 emitcode ("xch", "a,%s",
7896 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
7900 movLeft2Result (left, offl, result, offr, 0);
7901 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
7903 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
7904 assert(strcmp(*lsb,"a"));
7909 _storeAxResults(char *lsb,
7913 _startLazyDPSEvaluation();
7914 if (AOP_NEEDSACC(result))
7916 /* We have to explicitly update the result LSB.
7918 emitcode("xch","a,%s", lsb);
7919 aopPut(AOP(result), "a", offr);
7920 emitcode("mov","a,%s", lsb);
7922 if (getDataSize (result) > 1)
7924 aopPut (AOP (result), "a", offr + MSB16);
7926 _endLazyDPSEvaluation();
7929 /*-----------------------------------------------------------------*/
7930 /* shiftL2Left2Result - shift left two bytes from left to result */
7931 /*-----------------------------------------------------------------*/
7933 shiftL2Left2Result (operand * left, int offl,
7934 operand * result, int offr, int shCount)
7938 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7940 AccAXLsh (lsb, shCount);
7942 _storeAxResults(lsb, result, offr);
7946 #ifdef BETTER_LITERAL_SHIFT
7947 /*-----------------------------------------------------------------*/
7948 /* shiftR2Left2Result - shift right two bytes from left to result */
7949 /*-----------------------------------------------------------------*/
7951 shiftR2Left2Result (operand * left, int offl,
7952 operand * result, int offr,
7953 int shCount, int sign)
7957 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7959 /* a:x >> shCount (x = lsb(result)) */
7962 AccAXRshS(lsb, shCount);
7966 AccAXRsh(lsb, shCount);
7969 _storeAxResults(lsb, result, offr);
7973 /*-----------------------------------------------------------------*/
7974 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7975 /*-----------------------------------------------------------------*/
7977 shiftLLeftOrResult (operand * left, int offl,
7978 operand * result, int offr, int shCount)
7980 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7981 /* shift left accumulator */
7983 /* or with result */
7984 emitcode ("orl", "a,%s",
7985 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7986 /* back to result */
7987 aopPut (AOP (result), "a", offr);
7992 /*-----------------------------------------------------------------*/
7993 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7994 /*-----------------------------------------------------------------*/
7996 shiftRLeftOrResult (operand * left, int offl,
7997 operand * result, int offr, int shCount)
7999 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8000 /* shift right accumulator */
8002 /* or with result */
8003 emitcode ("orl", "a,%s",
8004 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8005 /* back to result */
8006 aopPut (AOP (result), "a", offr);
8010 #ifdef BETTER_LITERAL_SHIFT
8011 /*-----------------------------------------------------------------*/
8012 /* genlshOne - left shift a one byte quantity by known count */
8013 /*-----------------------------------------------------------------*/
8015 genlshOne (operand * result, operand * left, int shCount)
8017 D (emitcode (";", "genlshOne "););
8018 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8022 #ifdef BETTER_LITERAL_SHIFT
8023 /*-----------------------------------------------------------------*/
8024 /* genlshTwo - left shift two bytes by known amount != 0 */
8025 /*-----------------------------------------------------------------*/
8027 genlshTwo (operand * result, operand * left, int shCount)
8031 D (emitcode (";", "genlshTwo "););
8033 size = getDataSize (result);
8035 /* if shCount >= 8 */
8040 _startLazyDPSEvaluation();
8046 _endLazyDPSEvaluation();
8047 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8048 aopPut (AOP (result), zero, LSB);
8052 movLeft2Result (left, LSB, result, MSB16, 0);
8053 aopPut (AOP (result), zero, LSB);
8054 _endLazyDPSEvaluation();
8059 aopPut (AOP (result), zero, LSB);
8060 _endLazyDPSEvaluation();
8064 /* 1 <= shCount <= 7 */
8069 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8073 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8081 /*-----------------------------------------------------------------*/
8082 /* shiftLLong - shift left one long from left to result */
8083 /* offl = LSB or MSB16 */
8084 /*-----------------------------------------------------------------*/
8086 shiftLLong (operand * left, operand * result, int offr)
8089 int size = AOP_SIZE (result);
8091 if (size >= LSB + offr)
8093 l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8095 emitcode ("add", "a,acc");
8096 if (sameRegs (AOP (left), AOP (result)) &&
8097 size >= MSB16 + offr && offr != LSB)
8098 emitcode ("xch", "a,%s",
8099 aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8101 aopPut (AOP (result), "a", LSB + offr);
8104 if (size >= MSB16 + offr)
8106 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8108 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8110 emitcode ("rlc", "a");
8111 if (sameRegs (AOP (left), AOP (result)) &&
8112 size >= MSB24 + offr && offr != LSB)
8113 emitcode ("xch", "a,%s",
8114 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8116 aopPut (AOP (result), "a", MSB16 + offr);
8119 if (size >= MSB24 + offr)
8121 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8123 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8125 emitcode ("rlc", "a");
8126 if (sameRegs (AOP (left), AOP (result)) &&
8127 size >= MSB32 + offr && offr != LSB)
8128 emitcode ("xch", "a,%s",
8129 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8131 aopPut (AOP (result), "a", MSB24 + offr);
8134 if (size > MSB32 + offr)
8136 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8138 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8140 emitcode ("rlc", "a");
8141 aopPut (AOP (result), "a", MSB32 + offr);
8144 aopPut (AOP (result), zero, LSB);
8150 /*-----------------------------------------------------------------*/
8151 /* genlshFour - shift four byte by a known amount != 0 */
8152 /*-----------------------------------------------------------------*/
8154 genlshFour (operand * result, operand * left, int shCount)
8158 D (emitcode (";", "genlshFour ");
8161 size = AOP_SIZE (result);
8163 /* if shifting more that 3 bytes */
8168 /* lowest order of left goes to the highest
8169 order of the destination */
8170 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8172 movLeft2Result (left, LSB, result, MSB32, 0);
8173 aopPut (AOP (result), zero, LSB);
8174 aopPut (AOP (result), zero, MSB16);
8175 aopPut (AOP (result), zero, MSB24);
8179 /* more than two bytes */
8180 else if (shCount >= 16)
8182 /* lower order two bytes goes to higher order two bytes */
8184 /* if some more remaining */
8186 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8189 movLeft2Result (left, MSB16, result, MSB32, 0);
8190 movLeft2Result (left, LSB, result, MSB24, 0);
8192 aopPut (AOP (result), zero, MSB16);
8193 aopPut (AOP (result), zero, LSB);
8197 /* if more than 1 byte */
8198 else if (shCount >= 8)
8200 /* lower order three bytes goes to higher order three bytes */
8205 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8207 movLeft2Result (left, LSB, result, MSB16, 0);
8213 movLeft2Result (left, MSB24, result, MSB32, 0);
8214 movLeft2Result (left, MSB16, result, MSB24, 0);
8215 movLeft2Result (left, LSB, result, MSB16, 0);
8216 aopPut (AOP (result), zero, LSB);
8218 else if (shCount == 1)
8219 shiftLLong (left, result, MSB16);
8222 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8223 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8224 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8225 aopPut (AOP (result), zero, LSB);
8230 /* 1 <= shCount <= 7 */
8231 else if (shCount <= 2)
8233 shiftLLong (left, result, LSB);
8235 shiftLLong (result, result, LSB);
8237 /* 3 <= shCount <= 7, optimize */
8240 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8241 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8242 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8247 #ifdef BETTER_LITERAL_SHIFT
8248 /*-----------------------------------------------------------------*/
8249 /* genLeftShiftLiteral - left shifting by known count */
8250 /*-----------------------------------------------------------------*/
8252 genLeftShiftLiteral (operand * left,
8257 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8260 size = getSize (operandType (result));
8262 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8264 /* We only handle certain easy cases so far. */
8266 && (shCount < (size * 8))
8270 D(emitcode (";", "genLeftShiftLiteral wimping out"););
8274 freeAsmop (right, NULL, ic, TRUE);
8276 aopOp(left, ic, FALSE, FALSE);
8277 aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8280 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8282 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8283 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8285 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8288 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8290 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8291 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8293 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8299 emitcode ("; shift left ", "result %d, left %d", size,
8303 /* I suppose that the left size >= result size */
8306 _startLazyDPSEvaluation();
8309 movLeft2Result (left, size, result, size, 0);
8311 _endLazyDPSEvaluation();
8313 else if (shCount >= (size * 8))
8315 _startLazyDPSEvaluation();
8318 aopPut (AOP (result), zero, size);
8320 _endLazyDPSEvaluation();
8327 genlshOne (result, left, shCount);
8331 genlshTwo (result, left, shCount);
8335 genlshFour (result, left, shCount);
8339 fprintf(stderr, "*** ack! mystery literal shift!\n");
8343 freeAsmop (left, NULL, ic, TRUE);
8344 freeAsmop (result, NULL, ic, TRUE);
8349 /*-----------------------------------------------------------------*/
8350 /* genLeftShift - generates code for left shifting */
8351 /*-----------------------------------------------------------------*/
8353 genLeftShift (iCode * ic)
8355 operand *left, *right, *result;
8358 symbol *tlbl, *tlbl1;
8360 D (emitcode (";", "genLeftShift "););
8362 right = IC_RIGHT (ic);
8363 left = IC_LEFT (ic);
8364 result = IC_RESULT (ic);
8366 aopOp (right, ic, FALSE, FALSE);
8369 #ifdef BETTER_LITERAL_SHIFT
8370 /* if the shift count is known then do it
8371 as efficiently as possible */
8372 if (AOP_TYPE (right) == AOP_LIT)
8374 if (genLeftShiftLiteral (left, right, result, ic))
8381 /* shift count is unknown then we have to form
8382 a loop get the loop count in B : Note: we take
8383 only the lower order byte since shifting
8384 more that 32 bits make no sense anyway, ( the
8385 largest size of an object can be only 32 bits ) */
8387 if (AOP_TYPE (right) == AOP_LIT)
8389 /* Really should be handled by genLeftShiftLiteral,
8390 * but since I'm too lazy to fix that today, at least we can make
8391 * some small improvement.
8393 emitcode("mov", "b,#!constbyte",
8394 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8398 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8399 emitcode ("inc", "b");
8401 freeAsmop (right, NULL, ic, TRUE);
8402 aopOp (left, ic, FALSE, FALSE);
8403 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8405 /* now move the left to the result if they are not the
8407 if (!sameRegs (AOP (left), AOP (result)) &&
8408 AOP_SIZE (result) > 1)
8411 size = AOP_SIZE (result);
8413 _startLazyDPSEvaluation ();
8416 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8417 if (*l == '@' && (IS_AOP_PREG (result)))
8420 emitcode ("mov", "a,%s", l);
8421 aopPut (AOP (result), "a", offset);
8424 aopPut (AOP (result), l, offset);
8427 _endLazyDPSEvaluation ();
8430 tlbl = newiTempLabel (NULL);
8431 size = AOP_SIZE (result);
8433 tlbl1 = newiTempLabel (NULL);
8435 /* if it is only one byte then */
8438 symbol *tlbl1 = newiTempLabel (NULL);
8440 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8441 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8442 emitcode ("", "!tlabeldef", tlbl->key + 100);
8443 emitcode ("add", "a,acc");
8444 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8445 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8446 aopPut (AOP (result), "a", 0);
8450 reAdjustPreg (AOP (result));
8452 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8453 emitcode ("", "!tlabeldef", tlbl->key + 100);
8454 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8455 emitcode ("add", "a,acc");
8456 aopPut (AOP (result), "a", offset++);
8457 _startLazyDPSEvaluation ();
8460 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8461 emitcode ("rlc", "a");
8462 aopPut (AOP (result), "a", offset++);
8464 _endLazyDPSEvaluation ();
8465 reAdjustPreg (AOP (result));
8467 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8468 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8470 freeAsmop (left, NULL, ic, TRUE);
8471 freeAsmop (result, NULL, ic, TRUE);
8474 #ifdef BETTER_LITERAL_SHIFT
8475 /*-----------------------------------------------------------------*/
8476 /* genrshOne - right shift a one byte quantity by known count */
8477 /*-----------------------------------------------------------------*/
8479 genrshOne (operand * result, operand * left,
8480 int shCount, int sign)
8482 D (emitcode (";", "genrshOne"););
8483 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8487 #ifdef BETTER_LITERAL_SHIFT
8488 /*-----------------------------------------------------------------*/
8489 /* genrshTwo - right shift two bytes by known amount != 0 */
8490 /*-----------------------------------------------------------------*/
8492 genrshTwo (operand * result, operand * left,
8493 int shCount, int sign)
8495 D (emitcode (";", "genrshTwo"););
8497 /* if shCount >= 8 */
8501 _startLazyDPSEvaluation();
8504 shiftR1Left2Result (left, MSB16, result, LSB,
8509 movLeft2Result (left, MSB16, result, LSB, sign);
8511 addSign (result, MSB16, sign);
8512 _endLazyDPSEvaluation();
8515 /* 1 <= shCount <= 7 */
8518 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8523 /*-----------------------------------------------------------------*/
8524 /* shiftRLong - shift right one long from left to result */
8525 /* offl = LSB or MSB16 */
8526 /*-----------------------------------------------------------------*/
8528 shiftRLong (operand * left, int offl,
8529 operand * result, int sign)
8531 int isSameRegs=sameRegs(AOP(left),AOP(result));
8533 if (isSameRegs && offl>1) {
8534 // we are in big trouble, but this shouldn't happen
8535 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8538 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8543 emitcode ("rlc", "a");
8544 emitcode ("subb", "a,acc");
8545 emitcode ("xch", "a,%s",
8546 aopGet(AOP(left), MSB32, FALSE, FALSE, DP2_RESULT_REG));
8548 aopPut (AOP(result), zero, MSB32);
8553 emitcode ("clr", "c");
8555 emitcode ("mov", "c,acc.7");
8558 emitcode ("rrc", "a");
8560 if (isSameRegs && offl==MSB16) {
8562 "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE, DP2_RESULT_REG));
8564 aopPut (AOP (result), "a", MSB32);
8565 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8568 emitcode ("rrc", "a");
8569 if (isSameRegs && offl==1) {
8570 emitcode ("xch", "a,%s",
8571 aopGet (AOP (left), MSB16, FALSE, FALSE, DP2_RESULT_REG));
8573 aopPut (AOP (result), "a", MSB24);
8574 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, NULL));
8576 emitcode ("rrc", "a");
8577 aopPut (AOP (result), "a", MSB16 - offl);
8581 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, NULL));
8582 emitcode ("rrc", "a");
8583 aopPut (AOP (result), "a", LSB);
8587 /*-----------------------------------------------------------------*/
8588 /* genrshFour - shift four byte by a known amount != 0 */
8589 /*-----------------------------------------------------------------*/
8591 genrshFour (operand * result, operand * left,
8592 int shCount, int sign)
8594 D (emitcode (";", "genrshFour"););
8596 /* if shifting more that 3 bytes */
8600 _startLazyDPSEvaluation();
8602 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8604 movLeft2Result (left, MSB32, result, LSB, sign);
8605 addSign (result, MSB16, sign);
8606 _endLazyDPSEvaluation();
8608 else if (shCount >= 16)
8611 _startLazyDPSEvaluation();
8613 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8616 movLeft2Result (left, MSB24, result, LSB, 0);
8617 movLeft2Result (left, MSB32, result, MSB16, sign);
8619 addSign (result, MSB24, sign);
8620 _endLazyDPSEvaluation();
8622 else if (shCount >= 8)
8625 _startLazyDPSEvaluation();
8628 shiftRLong (left, MSB16, result, sign);
8630 else if (shCount == 0)
8632 movLeft2Result (left, MSB16, result, LSB, 0);
8633 movLeft2Result (left, MSB24, result, MSB16, 0);
8634 movLeft2Result (left, MSB32, result, MSB24, sign);
8635 addSign (result, MSB32, sign);
8639 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8640 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8641 /* the last shift is signed */
8642 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8643 addSign (result, MSB32, sign);
8645 _endLazyDPSEvaluation();
8649 /* 1 <= shCount <= 7 */
8652 shiftRLong (left, LSB, result, sign);
8654 shiftRLong (result, LSB, result, sign);
8658 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8659 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8660 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8665 #ifdef BETTER_LITERAL_SHIFT
8666 /*-----------------------------------------------------------------*/
8667 /* genRightShiftLiteral - right shifting by known count */
8668 /*-----------------------------------------------------------------*/
8670 genRightShiftLiteral (operand * left,
8676 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8679 size = getSize (operandType (result));
8681 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8683 /* We only handle certain easy cases so far. */
8685 && (shCount < (size * 8))
8690 D(emitcode (";", "genRightShiftLiteral wimping out"););
8694 freeAsmop (right, NULL, ic, TRUE);
8696 aopOp (left, ic, FALSE, FALSE);
8697 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8700 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8704 /* test the LEFT size !!! */
8706 /* I suppose that the left size >= result size */
8709 size = getDataSize (result);
8710 _startLazyDPSEvaluation();
8713 movLeft2Result (left, size, result, size, 0);
8715 _endLazyDPSEvaluation();
8717 else if (shCount >= (size * 8))
8721 /* get sign in acc.7 */
8722 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
8724 addSign (result, LSB, sign);
8731 genrshOne (result, left, shCount, sign);
8735 genrshTwo (result, left, shCount, sign);
8739 genrshFour (result, left, shCount, sign);
8746 freeAsmop (left, NULL, ic, TRUE);
8747 freeAsmop (result, NULL, ic, TRUE);
8753 /*-----------------------------------------------------------------*/
8754 /* genSignedRightShift - right shift of signed number */
8755 /*-----------------------------------------------------------------*/
8757 genSignedRightShift (iCode * ic)
8759 operand *right, *left, *result;
8762 symbol *tlbl, *tlbl1;
8764 D (emitcode (";", "genSignedRightShift "););
8766 /* we do it the hard way put the shift count in b
8767 and loop thru preserving the sign */
8769 right = IC_RIGHT (ic);
8770 left = IC_LEFT (ic);
8771 result = IC_RESULT (ic);
8773 aopOp (right, ic, FALSE, FALSE);
8775 #ifdef BETTER_LITERAL_SHIFT
8776 if (AOP_TYPE (right) == AOP_LIT)
8778 if (genRightShiftLiteral (left, right, result, ic, 1))
8784 /* shift count is unknown then we have to form
8785 a loop get the loop count in B : Note: we take
8786 only the lower order byte since shifting
8787 more that 32 bits make no sense anyway, ( the
8788 largest size of an object can be only 32 bits ) */
8790 if (AOP_TYPE (right) == AOP_LIT)
8792 /* Really should be handled by genRightShiftLiteral,
8793 * but since I'm too lazy to fix that today, at least we can make
8794 * some small improvement.
8796 emitcode("mov", "b,#!constbyte",
8797 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8801 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8802 emitcode ("inc", "b");
8804 freeAsmop (right, NULL, ic, TRUE);
8805 aopOp (left, ic, FALSE, FALSE);
8806 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8808 /* now move the left to the result if they are not the
8810 if (!sameRegs (AOP (left), AOP (result)) &&
8811 AOP_SIZE (result) > 1)
8814 size = AOP_SIZE (result);
8816 _startLazyDPSEvaluation ();
8819 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8820 if (*l == '@' && IS_AOP_PREG (result))
8823 emitcode ("mov", "a,%s", l);
8824 aopPut (AOP (result), "a", offset);
8827 aopPut (AOP (result), l, offset);
8830 _endLazyDPSEvaluation ();
8833 /* mov the highest order bit to OVR */
8834 tlbl = newiTempLabel (NULL);
8835 tlbl1 = newiTempLabel (NULL);
8837 size = AOP_SIZE (result);
8839 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
8840 emitcode ("rlc", "a");
8841 emitcode ("mov", "ov,c");
8842 /* if it is only one byte then */
8845 MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8846 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8847 emitcode ("", "!tlabeldef", tlbl->key + 100);
8848 emitcode ("mov", "c,ov");
8849 emitcode ("rrc", "a");
8850 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8851 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8852 aopPut (AOP (result), "a", 0);
8856 reAdjustPreg (AOP (result));
8857 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8858 emitcode ("", "!tlabeldef", tlbl->key + 100);
8859 emitcode ("mov", "c,ov");
8860 _startLazyDPSEvaluation ();
8863 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8864 emitcode ("rrc", "a");
8865 aopPut (AOP (result), "a", offset--);
8867 _endLazyDPSEvaluation ();
8868 reAdjustPreg (AOP (result));
8869 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8870 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8873 freeAsmop (left, NULL, ic, TRUE);
8874 freeAsmop (result, NULL, ic, TRUE);
8877 /*-----------------------------------------------------------------*/
8878 /* genRightShift - generate code for right shifting */
8879 /*-----------------------------------------------------------------*/
8881 genRightShift (iCode * ic)
8883 operand *right, *left, *result;
8887 symbol *tlbl, *tlbl1;
8889 D (emitcode (";", "genRightShift "););
8891 /* if signed then we do it the hard way preserve the
8892 sign bit moving it inwards */
8893 retype = getSpec (operandType (IC_RESULT (ic)));
8895 if (!SPEC_USIGN (retype))
8897 genSignedRightShift (ic);
8901 /* signed & unsigned types are treated the same : i.e. the
8902 signed is NOT propagated inwards : quoting from the
8903 ANSI - standard : "for E1 >> E2, is equivalent to division
8904 by 2**E2 if unsigned or if it has a non-negative value,
8905 otherwise the result is implementation defined ", MY definition
8906 is that the sign does not get propagated */
8908 right = IC_RIGHT (ic);
8909 left = IC_LEFT (ic);
8910 result = IC_RESULT (ic);
8912 aopOp (right, ic, FALSE, FALSE);
8914 #ifdef BETTER_LITERAL_SHIFT
8915 /* if the shift count is known then do it
8916 as efficiently as possible */
8917 if (AOP_TYPE (right) == AOP_LIT)
8919 if (genRightShiftLiteral (left, right, result, ic, 0))
8926 /* shift count is unknown then we have to form
8927 a loop get the loop count in B : Note: we take
8928 only the lower order byte since shifting
8929 more that 32 bits make no sense anyway, ( the
8930 largest size of an object can be only 32 bits ) */
8932 if (AOP_TYPE (right) == AOP_LIT)
8934 /* Really should be handled by genRightShiftLiteral,
8935 * but since I'm too lazy to fix that today, at least we can make
8936 * some small improvement.
8938 emitcode("mov", "b,#!constbyte",
8939 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8943 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8944 emitcode ("inc", "b");
8946 freeAsmop (right, NULL, ic, TRUE);
8947 aopOp (left, ic, FALSE, FALSE);
8948 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8950 /* now move the left to the result if they are not the
8952 if (!sameRegs (AOP (left), AOP (result)) &&
8953 AOP_SIZE (result) > 1)
8956 size = AOP_SIZE (result);
8958 _startLazyDPSEvaluation ();
8961 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8962 if (*l == '@' && IS_AOP_PREG (result))
8965 emitcode ("mov", "a,%s", l);
8966 aopPut (AOP (result), "a", offset);
8969 aopPut (AOP (result), l, offset);
8972 _endLazyDPSEvaluation ();
8975 tlbl = newiTempLabel (NULL);
8976 tlbl1 = newiTempLabel (NULL);
8977 size = AOP_SIZE (result);
8980 /* if it is only one byte then */
8983 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8984 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8985 emitcode ("", "!tlabeldef", tlbl->key + 100);
8987 emitcode ("rrc", "a");
8988 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8989 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8990 aopPut (AOP (result), "a", 0);
8994 reAdjustPreg (AOP (result));
8995 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8996 emitcode ("", "!tlabeldef", tlbl->key + 100);
8998 _startLazyDPSEvaluation ();
9001 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
9002 emitcode ("rrc", "a");
9003 aopPut (AOP (result), "a", offset--);
9005 _endLazyDPSEvaluation ();
9006 reAdjustPreg (AOP (result));
9008 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9009 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9012 freeAsmop (left, NULL, ic, TRUE);
9013 freeAsmop (result, NULL, ic, TRUE);
9017 /*-----------------------------------------------------------------*/
9018 /* emitPtrByteGet - emits code to get a byte into A through a */
9019 /* pointer register (R0, R1, or DPTR). The */
9020 /* original value of A can be preserved in B. */
9021 /*-----------------------------------------------------------------*/
9023 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9030 emitcode ("mov", "b,a");
9031 emitcode ("mov", "a,@%s", rname);
9036 emitcode ("mov", "b,a");
9037 emitcode ("movx", "a,@%s", rname);
9042 emitcode ("mov", "b,a");
9043 emitcode ("movx", "a,@dptr");
9048 emitcode ("mov", "b,a");
9049 emitcode ("clr", "a");
9050 emitcode ("movc", "a,@a+dptr");
9056 emitcode ("push", "b");
9057 emitcode ("push", "acc");
9059 emitcode ("lcall", "__gptrget");
9061 emitcode ("pop", "b");
9066 /*-----------------------------------------------------------------*/
9067 /* emitPtrByteSet - emits code to set a byte from src through a */
9068 /* pointer register (R0, R1, or DPTR). */
9069 /*-----------------------------------------------------------------*/
9071 emitPtrByteSet (char *rname, int p_type, char *src)
9080 emitcode ("mov", "@%s,a", rname);
9083 emitcode ("mov", "@%s,%s", rname, src);
9088 emitcode ("movx", "@%s,a", rname);
9093 emitcode ("movx", "@dptr,a");
9098 emitcode ("lcall", "__gptrput");
9103 /*-----------------------------------------------------------------*/
9104 /* genUnpackBits - generates code for unpacking bits */
9105 /*-----------------------------------------------------------------*/
9107 genUnpackBits (operand * result, char *rname, int ptype)
9109 int offset = 0; /* result byte offset */
9110 int rsize; /* result size */
9111 int rlen = 0; /* remaining bitfield length */
9112 sym_link *etype; /* bitfield type information */
9113 int blen; /* bitfield length */
9114 int bstr; /* bitfield starting bit within byte */
9116 D(emitcode ("; genUnpackBits",""));
9118 etype = getSpec (operandType (result));
9119 rsize = getSize (operandType (result));
9120 blen = SPEC_BLEN (etype);
9121 bstr = SPEC_BSTR (etype);
9123 /* If the bitfield length is less than a byte */
9126 emitPtrByteGet (rname, ptype, FALSE);
9128 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
9129 aopPut (AOP (result), "a", offset++);
9133 /* Bit field did not fit in a byte. Copy all
9134 but the partial byte at the end. */
9135 for (rlen=blen;rlen>=8;rlen-=8)
9137 emitPtrByteGet (rname, ptype, FALSE);
9138 aopPut (AOP (result), "a", offset++);
9140 emitcode ("inc", "%s", rname);
9143 /* Handle the partial byte at the end */
9146 emitPtrByteGet (rname, ptype, FALSE);
9147 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
9148 aopPut (AOP (result), "a", offset++);
9156 aopPut (AOP (result), zero, offset++);
9161 /*-----------------------------------------------------------------*/
9162 /* genDataPointerGet - generates code when ptr offset is known */
9163 /*-----------------------------------------------------------------*/
9165 genDataPointerGet (operand * left,
9171 int size, offset = 0;
9172 aopOp (result, ic, TRUE, FALSE);
9174 /* get the string representation of the name */
9175 l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9176 size = AOP_SIZE (result);
9177 _startLazyDPSEvaluation ();
9182 SNPRINTF (buff, sizeof(buff),
9183 "(%s + %d)", l + 1, offset);
9187 SNPRINTF (buff, sizeof(buff),
9190 aopPut (AOP (result), buff, offset++);
9192 _endLazyDPSEvaluation ();
9194 freeAsmop (left, NULL, ic, TRUE);
9195 freeAsmop (result, NULL, ic, TRUE);
9198 /*-----------------------------------------------------------------*/
9199 /* genNearPointerGet - emitcode for near pointer fetch */
9200 /*-----------------------------------------------------------------*/
9202 genNearPointerGet (operand * left,
9210 sym_link *rtype, *retype, *letype;
9211 sym_link *ltype = operandType (left);
9214 rtype = operandType (result);
9215 retype = getSpec (rtype);
9216 letype = getSpec (ltype);
9218 aopOp (left, ic, FALSE, FALSE);
9220 /* if left is rematerialisable and
9221 result is not bit variable type and
9222 the left is pointer to data space i.e
9223 lower 128 bytes of space */
9224 if (AOP_TYPE (left) == AOP_IMMD &&
9225 !IS_BITVAR (retype) &&
9226 !IS_BITVAR (letype) &&
9227 DCL_TYPE (ltype) == POINTER)
9229 genDataPointerGet (left, result, ic);
9233 /* if the value is already in a pointer register
9234 then don't need anything more */
9235 if (!AOP_INPREG (AOP (left)))
9237 /* otherwise get a free pointer register */
9239 preg = getFreePtr (ic, &aop, FALSE);
9240 emitcode ("mov", "%s,%s",
9242 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9246 rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9248 freeAsmop (left, NULL, ic, TRUE);
9249 aopOp (result, ic, FALSE, FALSE);
9251 /* if bitfield then unpack the bits */
9252 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9253 genUnpackBits (result, rname, POINTER);
9256 /* we have can just get the values */
9257 int size = AOP_SIZE (result);
9262 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9265 emitcode ("mov", "a,@%s", rname);
9266 aopPut (AOP (result), "a", offset);
9270 SNPRINTF (buff, sizeof(buff), "@%s", rname);
9271 aopPut (AOP (result), buff, offset);
9276 emitcode ("inc", "%s", rname);
9281 /* now some housekeeping stuff */
9284 /* we had to allocate for this iCode */
9285 if (pi) { /* post increment present */
9286 aopPut(AOP ( left ),rname,0);
9288 freeAsmop (NULL, aop, ic, TRUE);
9292 /* we did not allocate which means left
9293 already in a pointer register, then
9294 if size > 0 && this could be used again
9295 we have to point it back to where it
9297 if (AOP_SIZE (result) > 1 &&
9298 !OP_SYMBOL (left)->remat &&
9299 (OP_SYMBOL (left)->liveTo > ic->seq ||
9303 int size = AOP_SIZE (result) - 1;
9305 emitcode ("dec", "%s", rname);
9310 freeAsmop (result, NULL, ic, TRUE);
9311 if (pi) pi->generated = 1;
9314 /*-----------------------------------------------------------------*/
9315 /* genPagedPointerGet - emitcode for paged pointer fetch */
9316 /*-----------------------------------------------------------------*/
9318 genPagedPointerGet (operand * left,
9326 sym_link *rtype, *retype, *letype;
9328 rtype = operandType (result);
9329 retype = getSpec (rtype);
9330 letype = getSpec (operandType (left));
9331 aopOp (left, ic, FALSE, FALSE);
9333 /* if the value is already in a pointer register
9334 then don't need anything more */
9335 if (!AOP_INPREG (AOP (left)))
9337 /* otherwise get a free pointer register */
9339 preg = getFreePtr (ic, &aop, FALSE);
9340 emitcode ("mov", "%s,%s",
9342 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9346 rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9348 freeAsmop (left, NULL, ic, TRUE);
9349 aopOp (result, ic, FALSE, FALSE);
9351 /* if bitfield then unpack the bits */
9352 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9353 genUnpackBits (result, rname, PPOINTER);
9356 /* we have can just get the values */
9357 int size = AOP_SIZE (result);
9363 emitcode ("movx", "a,@%s", rname);
9364 aopPut (AOP (result), "a", offset);
9369 emitcode ("inc", "%s", rname);
9373 /* now some housekeeping stuff */
9376 /* we had to allocate for this iCode */
9377 if (pi) aopPut ( AOP (left), rname, 0);
9378 freeAsmop (NULL, aop, ic, TRUE);
9382 /* we did not allocate which means left
9383 already in a pointer register, then
9384 if size > 0 && this could be used again
9385 we have to point it back to where it
9387 if (AOP_SIZE (result) > 1 &&
9388 !OP_SYMBOL (left)->remat &&
9389 (OP_SYMBOL (left)->liveTo > ic->seq ||
9393 int size = AOP_SIZE (result) - 1;
9395 emitcode ("dec", "%s", rname);
9400 freeAsmop (result, NULL, ic, TRUE);
9401 if (pi) pi->generated = 1;
9404 /*-----------------------------------------------------------------*/
9405 /* genFarPointerGet - gget value from far space */
9406 /*-----------------------------------------------------------------*/
9408 genFarPointerGet (operand * left,
9409 operand * result, iCode * ic, iCode *pi)
9411 int size, offset, dopi=1;
9412 sym_link *retype = getSpec (operandType (result));
9413 sym_link *letype = getSpec (operandType (left));
9414 D (emitcode (";", "genFarPointerGet"););
9416 aopOp (left, ic, FALSE, FALSE);
9418 /* if the operand is already in dptr
9419 then we do nothing else we move the value to dptr */
9420 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9422 /* if this is remateriazable */
9423 if (AOP_TYPE (left) == AOP_IMMD)
9425 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9429 /* we need to get it byte by byte */
9430 _startLazyDPSEvaluation ();
9431 if (AOP_TYPE (left) != AOP_DPTR)
9433 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9434 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9435 if (options.model == MODEL_FLAT24)
9436 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9440 /* We need to generate a load to DPTR indirect through DPTR. */
9441 D (emitcode (";", "genFarPointerGet -- indirection special case."););
9442 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9443 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9444 if (options.model == MODEL_FLAT24)
9445 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9446 emitcode ("pop", "dph");
9447 emitcode ("pop", "dpl");
9450 _endLazyDPSEvaluation ();
9453 /* so dptr know contains the address */
9454 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9456 /* if bit then unpack */
9457 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9458 if (AOP_INDPTRn(left)) {
9459 genSetDPTR(AOP(left)->aopu.dptr);
9461 genUnpackBits (result, "dptr", FPOINTER);
9462 if (AOP_INDPTRn(left)) {
9467 size = AOP_SIZE (result);
9470 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9472 genSetDPTR(AOP(left)->aopu.dptr);
9473 emitcode ("movx", "a,@dptr");
9474 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9475 emitcode ("inc", "dptr");
9477 aopPut (AOP (result), "a", offset++);
9480 _startLazyDPSEvaluation ();
9482 if (AOP_INDPTRn(left)) {
9483 genSetDPTR(AOP(left)->aopu.dptr);
9489 emitcode ("movx", "a,@dptr");
9490 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9491 emitcode ("inc", "dptr");
9493 aopPut (AOP (result), "a", offset++);
9495 _endLazyDPSEvaluation ();
9498 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9499 if (!AOP_INDPTRn(left)) {
9500 _startLazyDPSEvaluation ();
9501 aopPut ( AOP (left), "dpl", 0);
9502 aopPut ( AOP (left), "dph", 1);
9503 if (options.model == MODEL_FLAT24)
9504 aopPut ( AOP (left), "dpx", 2);
9505 _endLazyDPSEvaluation ();
9508 } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) &&
9509 AOP_SIZE(result) > 1 &&
9511 (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
9513 size = AOP_SIZE (result) - 1;
9514 if (AOP_INDPTRn(left)) {
9515 genSetDPTR(AOP(left)->aopu.dptr);
9517 while (size--) emitcode ("lcall","__decdptr");
9518 if (AOP_INDPTRn(left)) {
9523 freeAsmop (left, NULL, ic, TRUE);
9524 freeAsmop (result, NULL, ic, TRUE);
9527 /*-----------------------------------------------------------------*/
9528 /* genCodePointerGet - get value from code space */
9529 /*-----------------------------------------------------------------*/
9531 genCodePointerGet (operand * left,
9532 operand * result, iCode * ic, iCode *pi)
9534 int size, offset, dopi=1;
9535 sym_link *retype = getSpec (operandType (result));
9537 aopOp (left, ic, FALSE, FALSE);
9539 /* if the operand is already in dptr
9540 then we do nothing else we move the value to dptr */
9541 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
9543 /* if this is remateriazable */
9544 if (AOP_TYPE (left) == AOP_IMMD)
9546 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9549 { /* we need to get it byte by byte */
9550 _startLazyDPSEvaluation ();
9551 if (AOP_TYPE (left) != AOP_DPTR)
9553 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9554 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9555 if (options.model == MODEL_FLAT24)
9556 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9560 /* We need to generate a load to DPTR indirect through DPTR. */
9561 D (emitcode (";", "gencodePointerGet -- indirection special case."););
9562 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9563 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9564 if (options.model == MODEL_FLAT24)
9565 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9566 emitcode ("pop", "dph");
9567 emitcode ("pop", "dpl");
9570 _endLazyDPSEvaluation ();
9573 /* so dptr know contains the address */
9574 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9576 /* if bit then unpack */
9577 if (IS_BITVAR (retype)) {
9578 if (AOP_INDPTRn(left)) {
9579 genSetDPTR(AOP(left)->aopu.dptr);
9581 genUnpackBits (result, "dptr", CPOINTER);
9582 if (AOP_INDPTRn(left)) {
9587 size = AOP_SIZE (result);
9589 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9591 genSetDPTR(AOP(left)->aopu.dptr);
9592 emitcode ("clr", "a");
9593 emitcode ("movc", "a,@a+dptr");
9594 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9595 emitcode ("inc", "dptr");
9597 aopPut (AOP (result), "a", offset++);
9600 _startLazyDPSEvaluation ();
9603 if (AOP_INDPTRn(left)) {
9604 genSetDPTR(AOP(left)->aopu.dptr);
9610 emitcode ("clr", "a");
9611 emitcode ("movc", "a,@a+dptr");
9612 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9613 emitcode ("inc", "dptr");
9614 aopPut (AOP (result), "a", offset++);
9616 _endLazyDPSEvaluation ();
9619 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9620 if (!AOP_INDPTRn(left)) {
9621 _startLazyDPSEvaluation ();
9623 aopPut ( AOP (left), "dpl", 0);
9624 aopPut ( AOP (left), "dph", 1);
9625 if (options.model == MODEL_FLAT24)
9626 aopPut ( AOP (left), "dpx", 2);
9628 _endLazyDPSEvaluation ();
9631 } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
9632 AOP_SIZE(result) > 1 &&
9633 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9635 size = AOP_SIZE (result) - 1;
9636 if (AOP_INDPTRn(left)) {
9637 genSetDPTR(AOP(left)->aopu.dptr);
9639 while (size--) emitcode ("lcall","__decdptr");
9640 if (AOP_INDPTRn(left)) {
9645 freeAsmop (left, NULL, ic, TRUE);
9646 freeAsmop (result, NULL, ic, TRUE);
9649 /*-----------------------------------------------------------------*/
9650 /* genGenPointerGet - gget value from generic pointer space */
9651 /*-----------------------------------------------------------------*/
9653 genGenPointerGet (operand * left,
9654 operand * result, iCode * ic, iCode * pi)
9657 sym_link *retype = getSpec (operandType (result));
9658 sym_link *letype = getSpec (operandType (left));
9660 D (emitcode (";", "genGenPointerGet "); );
9662 aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
9664 /* if the operand is already in dptr
9665 then we do nothing else we move the value to dptr */
9666 if (AOP_TYPE (left) != AOP_STR)
9668 /* if this is remateriazable */
9669 if (AOP_TYPE (left) == AOP_IMMD)
9671 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9672 if (AOP(left)->aopu.aop_immd.from_cast_remat)
9674 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
9678 emitcode ("mov", "b,#%d", pointerCode (retype));
9682 { /* we need to get it byte by byte */
9683 _startLazyDPSEvaluation ();
9684 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
9685 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
9686 if (options.model == MODEL_FLAT24) {
9687 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9688 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
9690 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9692 _endLazyDPSEvaluation ();
9696 /* so dptr-b now contains the address */
9698 aopOp (result, ic, FALSE, TRUE);
9701 /* if bit then unpack */
9702 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9704 genUnpackBits (result, "dptr", GPOINTER);
9708 size = AOP_SIZE (result);
9715 // Get two bytes at a time, results in _AP & A.
9716 // dptr will be incremented ONCE by __gptrgetWord.
9718 // Note: any change here must be coordinated
9719 // with the implementation of __gptrgetWord
9720 // in device/lib/_gptrget.c
9721 emitcode ("lcall", "__gptrgetWord");
9722 aopPut (AOP (result), DP2_RESULT_REG, offset++);
9723 aopPut (AOP (result), "a", offset++);
9728 // Only one byte to get.
9729 emitcode ("lcall", "__gptrget");
9730 aopPut (AOP (result), "a", offset++);
9733 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9735 emitcode ("inc", "dptr");
9740 if (pi && AOP_TYPE (left) != AOP_IMMD) {
9741 _startLazyDPSEvaluation ();
9743 aopPut ( AOP (left), "dpl", 0);
9744 aopPut ( AOP (left), "dph", 1);
9745 if (options.model == MODEL_FLAT24) {
9746 aopPut ( AOP (left), "dpx", 2);
9747 aopPut ( AOP (left), "b", 3);
9748 } else aopPut ( AOP (left), "b", 2);
9750 _endLazyDPSEvaluation ();
9753 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9754 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9756 size = AOP_SIZE (result) - 1;
9757 while (size--) emitcode ("lcall","__decdptr");
9760 freeAsmop (left, NULL, ic, TRUE);
9761 freeAsmop (result, NULL, ic, TRUE);
9764 /*-----------------------------------------------------------------*/
9765 /* genPointerGet - generate code for pointer get */
9766 /*-----------------------------------------------------------------*/
9768 genPointerGet (iCode * ic, iCode *pi)
9770 operand *left, *result;
9771 sym_link *type, *etype;
9774 D (emitcode (";", "genPointerGet ");
9777 left = IC_LEFT (ic);
9778 result = IC_RESULT (ic);
9780 /* depending on the type of pointer we need to
9781 move it to the correct pointer register */
9782 type = operandType (left);
9783 etype = getSpec (type);
9784 /* if left is of type of pointer then it is simple */
9785 if (IS_PTR (type) && !IS_FUNC (type->next))
9786 p_type = DCL_TYPE (type);
9789 /* we have to go by the storage class */
9790 p_type = PTR_TYPE (SPEC_OCLS (etype));
9792 /* special case when cast remat */
9793 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9794 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9795 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9796 type = operandType (left);
9797 p_type = DCL_TYPE (type);
9799 /* now that we have the pointer type we assign
9800 the pointer values */
9806 genNearPointerGet (left, result, ic, pi);
9810 genPagedPointerGet (left, result, ic, pi);
9814 genFarPointerGet (left, result, ic, pi);
9818 genCodePointerGet (left, result, ic, pi);
9822 genGenPointerGet (left, result, ic, pi);
9828 /*-----------------------------------------------------------------*/
9829 /* genPackBits - generates code for packed bit storage */
9830 /*-----------------------------------------------------------------*/
9832 genPackBits (sym_link * etype,
9834 char *rname, int p_type)
9836 int offset = 0; /* source byte offset */
9837 int rlen = 0; /* remaining bitfield length */
9838 int blen; /* bitfield length */
9839 int bstr; /* bitfield starting bit within byte */
9840 int litval; /* source literal value (if AOP_LIT) */
9841 unsigned char mask; /* bitmask within current byte */
9843 D(emitcode ("; genPackBits",""));
9845 blen = SPEC_BLEN (etype);
9846 bstr = SPEC_BSTR (etype);
9848 /* If the bitfield length is less than a byte */
9851 mask = ((unsigned char) (0xFF << (blen + bstr)) |
9852 (unsigned char) (0xFF >> (8 - bstr)));
9854 if (AOP_TYPE (right) == AOP_LIT)
9856 /* Case with a bitfield length <8 and literal source
9858 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9860 litval &= (~mask) & 0xff;
9861 emitPtrByteGet (rname, p_type, FALSE);
9862 if ((mask|litval)!=0xff)
9863 emitcode ("anl","a,#!constbyte", mask);
9865 emitcode ("orl","a,#!constbyte", litval);
9869 if ((blen==1) && (p_type!=GPOINTER))
9871 /* Case with a bitfield length == 1 and no generic pointer
9873 if (AOP_TYPE (right) == AOP_CRY)
9874 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9877 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
9878 emitcode ("rrc","a");
9880 emitPtrByteGet (rname, p_type, FALSE);
9881 emitcode ("mov","acc.%d,c",bstr);
9885 /* Case with a bitfield length < 8 and arbitrary source
9887 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
9888 /* shift and mask source value */
9890 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
9892 /* transfer A to B and get next byte */
9893 emitPtrByteGet (rname, p_type, TRUE);
9895 emitcode ("anl", "a,#!constbyte", mask);
9896 emitcode ("orl", "a,b");
9897 if (p_type == GPOINTER)
9898 emitcode ("pop", "b");
9902 emitPtrByteSet (rname, p_type, "a");
9906 /* Bit length is greater than 7 bits. In this case, copy */
9907 /* all except the partial byte at the end */
9908 for (rlen=blen;rlen>=8;rlen-=8)
9910 emitPtrByteSet (rname, p_type,
9911 aopGet (AOP (right), offset++, FALSE, TRUE, NULL) );
9913 emitcode ("inc", "%s", rname);
9916 /* If there was a partial byte at the end */
9919 mask = (((unsigned char) -1 << rlen) & 0xff);
9921 if (AOP_TYPE (right) == AOP_LIT)
9923 /* Case with partial byte and literal source
9925 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9926 litval >>= (blen-rlen);
9927 litval &= (~mask) & 0xff;
9928 emitPtrByteGet (rname, p_type, FALSE);
9929 if ((mask|litval)!=0xff)
9930 emitcode ("anl","a,#!constbyte", mask);
9932 emitcode ("orl","a,#!constbyte", litval);
9936 /* Case with partial byte and arbitrary source
9938 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9939 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
9941 /* transfer A to B and get next byte */
9942 emitPtrByteGet (rname, p_type, TRUE);
9944 emitcode ("anl", "a,#!constbyte", mask);
9945 emitcode ("orl", "a,b");
9946 if (p_type == GPOINTER)
9947 emitcode ("pop", "b");
9949 emitPtrByteSet (rname, p_type, "a");
9955 /*-----------------------------------------------------------------*/
9956 /* genDataPointerSet - remat pointer to data space */
9957 /*-----------------------------------------------------------------*/
9959 genDataPointerSet (operand * right,
9963 int size, offset = 0;
9966 aopOp (right, ic, FALSE, FALSE);
9968 l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
9969 size = AOP_SIZE (right);
9974 SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
9978 SNPRINTF (buff, sizeof(buff), "%s", l + 1);
9981 emitcode ("mov", "%s,%s", buff,
9982 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9985 freeAsmop (right, NULL, ic, TRUE);
9986 freeAsmop (result, NULL, ic, TRUE);
9989 /*-----------------------------------------------------------------*/
9990 /* genNearPointerSet - emitcode for near pointer put */
9991 /*-----------------------------------------------------------------*/
9993 genNearPointerSet (operand * right,
10000 sym_link *retype, *letype;
10001 sym_link *ptype = operandType (result);
10003 retype = getSpec (operandType (right));
10004 letype = getSpec (ptype);
10006 aopOp (result, ic, FALSE, FALSE);
10008 /* if the result is rematerializable &
10009 in data space & not a bit variable */
10010 if (AOP_TYPE (result) == AOP_IMMD &&
10011 DCL_TYPE (ptype) == POINTER &&
10012 !IS_BITVAR (retype) &&
10013 !IS_BITVAR (letype))
10015 genDataPointerSet (right, result, ic);
10019 /* if the value is already in a pointer register
10020 then don't need anything more */
10021 if (!AOP_INPREG (AOP (result)))
10023 /* otherwise get a free pointer register */
10026 aop = newAsmop (0);
10027 preg = getFreePtr (ic, &aop, FALSE);
10028 emitcode ("mov", "%s,%s",
10030 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10031 rname = preg->name;
10034 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10036 aopOp (right, ic, FALSE, FALSE);
10038 /* if bitfield then unpack the bits */
10039 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10040 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
10043 /* we have can just get the values */
10044 int size = AOP_SIZE (right);
10049 l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
10053 emitcode ("mov", "@%s,a", rname);
10056 emitcode ("mov", "@%s,%s", rname, l);
10058 emitcode ("inc", "%s", rname);
10063 /* now some housekeeping stuff */
10066 /* we had to allocate for this iCode */
10067 if (pi) aopPut (AOP (result),rname,0);
10068 freeAsmop (NULL, aop, ic, TRUE);
10072 /* we did not allocate which means left
10073 already in a pointer register, then
10074 if size > 0 && this could be used again
10075 we have to point it back to where it
10077 if (AOP_SIZE (right) > 1 &&
10078 !OP_SYMBOL (result)->remat &&
10079 (OP_SYMBOL (result)->liveTo > ic->seq ||
10083 int size = AOP_SIZE (right) - 1;
10085 emitcode ("dec", "%s", rname);
10090 if (pi) pi->generated = 1;
10091 freeAsmop (result, NULL, ic, TRUE);
10092 freeAsmop (right, NULL, ic, TRUE);
10097 /*-----------------------------------------------------------------*/
10098 /* genPagedPointerSet - emitcode for Paged pointer put */
10099 /*-----------------------------------------------------------------*/
10101 genPagedPointerSet (operand * right,
10108 sym_link *retype, *letype;
10110 retype = getSpec (operandType (right));
10111 letype = getSpec (operandType (result));
10113 aopOp (result, ic, FALSE, FALSE);
10115 /* if the value is already in a pointer register
10116 then don't need anything more */
10117 if (!AOP_INPREG (AOP (result)))
10119 /* otherwise get a free pointer register */
10122 aop = newAsmop (0);
10123 preg = getFreePtr (ic, &aop, FALSE);
10124 emitcode ("mov", "%s,%s",
10126 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10127 rname = preg->name;
10130 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10132 aopOp (right, ic, FALSE, FALSE);
10134 /* if bitfield then unpack the bits */
10135 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10136 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
10139 /* we have can just get the values */
10140 int size = AOP_SIZE (right);
10145 MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10147 emitcode ("movx", "@%s,a", rname);
10150 emitcode ("inc", "%s", rname);
10156 /* now some housekeeping stuff */
10159 if (pi) aopPut (AOP (result),rname,0);
10160 /* we had to allocate for this iCode */
10161 freeAsmop (NULL, aop, ic, TRUE);
10165 /* we did not allocate which means left
10166 already in a pointer register, then
10167 if size > 0 && this could be used again
10168 we have to point it back to where it
10170 if (AOP_SIZE (right) > 1 &&
10171 !OP_SYMBOL (result)->remat &&
10172 (OP_SYMBOL (result)->liveTo > ic->seq ||
10176 int size = AOP_SIZE (right) - 1;
10178 emitcode ("dec", "%s", rname);
10183 if (pi) pi->generated = 1;
10184 freeAsmop (result, NULL, ic, TRUE);
10185 freeAsmop (right, NULL, ic, TRUE);
10190 /*-----------------------------------------------------------------*/
10191 /* genFarPointerSet - set value from far space */
10192 /*-----------------------------------------------------------------*/
10194 genFarPointerSet (operand * right,
10195 operand * result, iCode * ic, iCode *pi)
10197 int size, offset, dopi=1;
10198 sym_link *retype = getSpec (operandType (right));
10199 sym_link *letype = getSpec (operandType (result));
10201 aopOp (result, ic, FALSE, FALSE);
10203 /* if the operand is already in dptr
10204 then we do nothing else we move the value to dptr */
10205 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10207 /* if this is remateriazable */
10208 if (AOP_TYPE (result) == AOP_IMMD)
10209 emitcode ("mov", "dptr,%s",
10210 aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10213 /* we need to get it byte by byte */
10214 _startLazyDPSEvaluation ();
10215 if (AOP_TYPE (result) != AOP_DPTR)
10217 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10218 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10219 if (options.model == MODEL_FLAT24)
10220 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10224 /* We need to generate a load to DPTR indirect through DPTR. */
10225 D (emitcode (";", "genFarPointerSet -- indirection special case."););
10227 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10228 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10229 if (options.model == MODEL_FLAT24)
10230 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10231 emitcode ("pop", "dph");
10232 emitcode ("pop", "dpl");
10235 _endLazyDPSEvaluation ();
10238 /* so dptr know contains the address */
10239 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10241 /* if bit then unpack */
10242 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
10243 if (AOP_INDPTRn(result)) {
10244 genSetDPTR(AOP(result)->aopu.dptr);
10246 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
10247 if (AOP_INDPTRn(result)) {
10251 size = AOP_SIZE (right);
10253 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10255 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10257 genSetDPTR(AOP(result)->aopu.dptr);
10258 emitcode ("movx", "@dptr,a");
10259 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10260 emitcode ("inc", "dptr");
10264 _startLazyDPSEvaluation ();
10266 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10268 if (AOP_INDPTRn(result)) {
10269 genSetDPTR(AOP(result)->aopu.dptr);
10275 emitcode ("movx", "@dptr,a");
10276 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10277 emitcode ("inc", "dptr");
10279 _endLazyDPSEvaluation ();
10283 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10284 if (!AOP_INDPTRn(result)) {
10285 _startLazyDPSEvaluation ();
10287 aopPut (AOP(result),"dpl",0);
10288 aopPut (AOP(result),"dph",1);
10289 if (options.model == MODEL_FLAT24)
10290 aopPut (AOP(result),"dpx",2);
10292 _endLazyDPSEvaluation ();
10295 } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
10296 AOP_SIZE(right) > 1 &&
10297 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10299 size = AOP_SIZE (right) - 1;
10300 if (AOP_INDPTRn(result)) {
10301 genSetDPTR(AOP(result)->aopu.dptr);
10303 while (size--) emitcode ("lcall","__decdptr");
10304 if (AOP_INDPTRn(result)) {
10308 freeAsmop (result, NULL, ic, TRUE);
10309 freeAsmop (right, NULL, ic, TRUE);
10312 /*-----------------------------------------------------------------*/
10313 /* genGenPointerSet - set value from generic pointer space */
10314 /*-----------------------------------------------------------------*/
10316 genGenPointerSet (operand * right,
10317 operand * result, iCode * ic, iCode *pi)
10320 sym_link *retype = getSpec (operandType (right));
10321 sym_link *letype = getSpec (operandType (result));
10323 aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10325 /* if the operand is already in dptr
10326 then we do nothing else we move the value to dptr */
10327 if (AOP_TYPE (result) != AOP_STR)
10329 _startLazyDPSEvaluation ();
10330 /* if this is remateriazable */
10331 if (AOP_TYPE (result) == AOP_IMMD)
10333 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10334 if (AOP(result)->aopu.aop_immd.from_cast_remat)
10336 MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10341 "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10345 { /* we need to get it byte by byte */
10346 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10347 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10348 if (options.model == MODEL_FLAT24) {
10349 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10350 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10352 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10355 _endLazyDPSEvaluation ();
10357 /* so dptr + b now contains the address */
10359 aopOp (right, ic, FALSE, TRUE);
10363 /* if bit then unpack */
10364 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10366 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
10370 size = AOP_SIZE (right);
10373 _startLazyDPSEvaluation ();
10378 // Set two bytes at a time, passed in _AP & A.
10379 // dptr will be incremented ONCE by __gptrputWord.
10381 // Note: any change here must be coordinated
10382 // with the implementation of __gptrputWord
10383 // in device/lib/_gptrput.c
10384 emitcode("mov", "_ap, %s",
10385 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10386 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10390 emitcode ("lcall", "__gptrputWord");
10395 // Only one byte to put.
10396 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10400 emitcode ("lcall", "__gptrput");
10403 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10405 emitcode ("inc", "dptr");
10408 _endLazyDPSEvaluation ();
10411 if (pi && AOP_TYPE (result) != AOP_IMMD) {
10412 _startLazyDPSEvaluation ();
10414 aopPut (AOP(result),"dpl",0);
10415 aopPut (AOP(result),"dph",1);
10416 if (options.model == MODEL_FLAT24) {
10417 aopPut (AOP(result),"dpx",2);
10418 aopPut (AOP(result),"b",3);
10420 aopPut (AOP(result),"b",2);
10422 _endLazyDPSEvaluation ();
10425 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10426 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10428 size = AOP_SIZE (right) - 1;
10429 while (size--) emitcode ("lcall","__decdptr");
10431 freeAsmop (result, NULL, ic, TRUE);
10432 freeAsmop (right, NULL, ic, TRUE);
10435 /*-----------------------------------------------------------------*/
10436 /* genPointerSet - stores the value into a pointer location */
10437 /*-----------------------------------------------------------------*/
10439 genPointerSet (iCode * ic, iCode *pi)
10441 operand *right, *result;
10442 sym_link *type, *etype;
10445 D (emitcode (";", "genPointerSet "););
10447 right = IC_RIGHT (ic);
10448 result = IC_RESULT (ic);
10450 /* depending on the type of pointer we need to
10451 move it to the correct pointer register */
10452 type = operandType (result);
10453 etype = getSpec (type);
10454 /* if left is of type of pointer then it is simple */
10455 if (IS_PTR (type) && !IS_FUNC (type->next))
10457 p_type = DCL_TYPE (type);
10461 /* we have to go by the storage class */
10462 p_type = PTR_TYPE (SPEC_OCLS (etype));
10464 /* special case when cast remat */
10465 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10466 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10467 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10468 type = operandType (result);
10469 p_type = DCL_TYPE (type);
10472 /* now that we have the pointer type we assign
10473 the pointer values */
10479 genNearPointerSet (right, result, ic, pi);
10483 genPagedPointerSet (right, result, ic, pi);
10487 genFarPointerSet (right, result, ic, pi);
10491 genGenPointerSet (right, result, ic, pi);
10495 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10496 "genPointerSet: illegal pointer type");
10501 /*-----------------------------------------------------------------*/
10502 /* genIfx - generate code for Ifx statement */
10503 /*-----------------------------------------------------------------*/
10505 genIfx (iCode * ic, iCode * popIc)
10507 operand *cond = IC_COND (ic);
10510 D (emitcode (";", "genIfx "););
10512 aopOp (cond, ic, FALSE, FALSE);
10514 /* get the value into acc */
10515 if (AOP_TYPE (cond) != AOP_CRY)
10524 /* the result is now in the accumulator */
10525 freeAsmop (cond, NULL, ic, TRUE);
10527 /* if there was something to be popped then do it */
10531 /* if the condition is a bit variable */
10532 if (isbit && IS_ITEMP (cond) &&
10535 genIfxJump (ic, SPIL_LOC (cond)->rname);
10537 else if (isbit && !IS_ITEMP (cond))
10539 genIfxJump (ic, OP_SYMBOL (cond)->rname);
10543 genIfxJump (ic, "a");
10549 /*-----------------------------------------------------------------*/
10550 /* genAddrOf - generates code for address of */
10551 /*-----------------------------------------------------------------*/
10553 genAddrOf (iCode * ic)
10555 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10558 D (emitcode (";", "genAddrOf ");
10561 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10563 /* if the operand is on the stack then we
10564 need to get the stack offset of this
10566 if (sym->onStack) {
10568 /* if 10 bit stack */
10569 if (options.stack10bit) {
10573 tsprintf(buff, sizeof(buff),
10574 "#!constbyte",(options.stack_loc >> 16) & 0xff);
10575 /* if it has an offset then we need to compute it */
10576 /* emitcode ("subb", "a,#!constbyte", */
10577 /* -((sym->stack < 0) ? */
10578 /* ((short) (sym->stack - _G.nRegsSaved)) : */
10579 /* ((short) sym->stack)) & 0xff); */
10580 /* emitcode ("mov","b,a"); */
10581 /* emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
10582 /* ((short) (sym->stack - _G.nRegsSaved)) : */
10583 /* ((short) sym->stack)) >> 8) & 0xff); */
10585 emitcode ("mov", "a,_bpx");
10586 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
10587 ((char) (sym->stack - _G.nRegsSaved)) :
10588 ((char) sym->stack )) & 0xff);
10589 emitcode ("mov", "b,a");
10590 emitcode ("mov", "a,_bpx+1");
10592 offset = (((sym->stack < 0) ?
10593 ((short) (sym->stack - _G.nRegsSaved)) :
10594 ((short) sym->stack )) >> 8) & 0xff;
10596 emitcode ("addc","a,#!constbyte", offset);
10598 aopPut (AOP (IC_RESULT (ic)), "b", 0);
10599 aopPut (AOP (IC_RESULT (ic)), "a", 1);
10600 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10602 /* we can just move _bp */
10603 aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10604 aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10605 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10608 /* if it has an offset then we need to compute it */
10610 emitcode ("mov", "a,_bp");
10611 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10612 aopPut (AOP (IC_RESULT (ic)), "a", 0);
10614 /* we can just move _bp */
10615 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10617 /* fill the result with zero */
10618 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10621 if (options.stack10bit && size < (FPTRSIZE - 1)) {
10623 "*** warning: pointer to stack var truncated.\n");
10628 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10634 /* object not on stack then we need the name */
10635 size = AOP_SIZE (IC_RESULT (ic));
10640 char s[SDCC_NAME_MAX];
10644 tsprintf(s, sizeof(s), "#!his",sym->rname);
10647 tsprintf(s, sizeof(s), "#!hihis",sym->rname);
10650 tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
10652 default: /* should not need this (just in case) */
10653 SNPRINTF (s, sizeof(s), "#(%s >> %d)",
10660 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10663 aopPut (AOP (IC_RESULT (ic)), s, offset++);
10667 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10671 #if 0 // obsolete, and buggy for != xdata
10672 /*-----------------------------------------------------------------*/
10673 /* genArrayInit - generates code for address of */
10674 /*-----------------------------------------------------------------*/
10676 genArrayInit (iCode * ic)
10678 literalList *iLoop;
10680 int elementSize = 0, eIndex;
10681 unsigned val, lastVal;
10683 operand *left=IC_LEFT(ic);
10685 D (emitcode (";", "genArrayInit "););
10687 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10689 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10691 // Load immediate value into DPTR.
10692 emitcode("mov", "dptr, %s",
10693 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
10695 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10698 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10699 "Unexpected operand to genArrayInit.\n");
10702 // a regression because of SDCCcse.c:1.52
10703 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10704 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10705 if (options.model == MODEL_FLAT24)
10706 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10710 type = operandType(IC_LEFT(ic));
10712 if (type && type->next)
10714 elementSize = getSize(type->next);
10718 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10719 "can't determine element size in genArrayInit.\n");
10723 iLoop = IC_ARRAYILIST(ic);
10728 bool firstpass = TRUE;
10730 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
10731 iLoop->count, (int)iLoop->literalValue, elementSize);
10737 symbol *tlbl = NULL;
10739 count = ix > 256 ? 256 : ix;
10743 tlbl = newiTempLabel (NULL);
10744 if (firstpass || (count & 0xff))
10746 emitcode("mov", "b, #!constbyte", count & 0xff);
10749 emitcode ("", "!tlabeldef", tlbl->key + 100);
10754 for (eIndex = 0; eIndex < elementSize; eIndex++)
10756 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10757 if (val != lastVal)
10759 emitcode("mov", "a, #!constbyte", val);
10763 emitcode("movx", "@dptr, a");
10764 emitcode("inc", "dptr");
10769 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10775 iLoop = iLoop->next;
10778 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10782 /*-----------------------------------------------------------------*/
10783 /* genFarFarAssign - assignment when both are in far space */
10784 /*-----------------------------------------------------------------*/
10786 genFarFarAssign (operand * result, operand * right, iCode * ic)
10788 int size = AOP_SIZE (right);
10790 symbol *rSym = NULL;
10794 /* quick & easy case. */
10795 D(emitcode(";","genFarFarAssign (1 byte case)"););
10796 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
10797 freeAsmop (right, NULL, ic, FALSE);
10798 /* now assign DPTR to result */
10800 aopOp(result, ic, FALSE, FALSE);
10802 aopPut(AOP(result), "a", 0);
10803 freeAsmop(result, NULL, ic, FALSE);
10807 /* See if we've got an underlying symbol to abuse. */
10808 if (IS_SYMOP(result) && OP_SYMBOL(result))
10810 if (IS_TRUE_SYMOP(result))
10812 rSym = OP_SYMBOL(result);
10814 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10816 rSym = OP_SYMBOL(result)->usl.spillLoc;
10820 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10822 /* We can use the '390 auto-toggle feature to good effect here. */
10824 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10825 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
10826 emitcode ("mov", "dptr,#%s", rSym->rname);
10827 /* DP2 = result, DP1 = right, DP1 is current. */
10830 emitcode("movx", "a,@dptr");
10831 emitcode("movx", "@dptr,a");
10834 emitcode("inc", "dptr");
10835 emitcode("inc", "dptr");
10838 emitcode("mov", "dps,#0");
10839 freeAsmop (right, NULL, ic, FALSE);
10841 some alternative code for processors without auto-toggle
10842 no time to test now, so later well put in...kpb
10843 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10844 emitcode("mov", "dps,#1"); /* Select DPTR2. */
10845 emitcode ("mov", "dptr,#%s", rSym->rname);
10846 /* DP2 = result, DP1 = right, DP1 is current. */
10850 emitcode("movx", "a,@dptr");
10852 emitcode("inc", "dptr");
10853 emitcode("inc", "dps");
10854 emitcode("movx", "@dptr,a");
10856 emitcode("inc", "dptr");
10857 emitcode("inc", "dps");
10859 emitcode("mov", "dps,#0");
10860 freeAsmop (right, NULL, ic, FALSE);
10865 D (emitcode (";", "genFarFarAssign"););
10866 aopOp (result, ic, TRUE, TRUE);
10868 _startLazyDPSEvaluation ();
10872 aopPut (AOP (result),
10873 aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
10876 _endLazyDPSEvaluation ();
10877 freeAsmop (result, NULL, ic, FALSE);
10878 freeAsmop (right, NULL, ic, FALSE);
10882 /*-----------------------------------------------------------------*/
10883 /* genAssign - generate code for assignment */
10884 /*-----------------------------------------------------------------*/
10886 genAssign (iCode * ic)
10888 operand *result, *right;
10890 unsigned long lit = 0L;
10892 D (emitcode (";", "genAssign ");
10895 result = IC_RESULT (ic);
10896 right = IC_RIGHT (ic);
10898 /* if they are the same */
10899 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10902 aopOp (right, ic, FALSE, FALSE);
10904 emitcode (";", "genAssign: resultIsFar = %s",
10905 isOperandInFarSpace (result) ?
10908 /* special case both in far space */
10909 if ((AOP_TYPE (right) == AOP_DPTR ||
10910 AOP_TYPE (right) == AOP_DPTR2) &&
10911 /* IS_TRUE_SYMOP(result) && */
10912 isOperandInFarSpace (result))
10914 genFarFarAssign (result, right, ic);
10918 aopOp (result, ic, TRUE, FALSE);
10920 /* if they are the same registers */
10921 if (sameRegs (AOP (right), AOP (result)))
10924 /* if the result is a bit */
10925 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10927 /* if the right size is a literal then
10928 we know what the value is */
10929 if (AOP_TYPE (right) == AOP_LIT)
10931 if (((int) operandLitValue (right)))
10932 aopPut (AOP (result), one, 0);
10934 aopPut (AOP (result), zero, 0);
10938 /* the right is also a bit variable */
10939 if (AOP_TYPE (right) == AOP_CRY)
10941 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10942 aopPut (AOP (result), "c", 0);
10946 /* we need to or */
10948 aopPut (AOP (result), "a", 0);
10952 /* bit variables done */
10954 size = AOP_SIZE (result);
10956 if (AOP_TYPE (right) == AOP_LIT)
10957 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10960 (AOP_TYPE (result) != AOP_REG) &&
10961 (AOP_TYPE (right) == AOP_LIT) &&
10962 !IS_FLOAT (operandType (right)))
10964 _startLazyDPSEvaluation ();
10965 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10967 aopPut (AOP (result),
10968 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10973 /* And now fill the rest with zeros. */
10976 emitcode ("clr", "a");
10980 aopPut (AOP (result), "a", offset++);
10982 _endLazyDPSEvaluation ();
10986 _startLazyDPSEvaluation ();
10989 aopPut (AOP (result),
10990 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10994 _endLazyDPSEvaluation ();
10998 freeAsmop (right, NULL, ic, FALSE);
10999 freeAsmop (result, NULL, ic, TRUE);
11002 /*-----------------------------------------------------------------*/
11003 /* genJumpTab - generates code for jump table */
11004 /*-----------------------------------------------------------------*/
11006 genJumpTab (iCode * ic)
11011 D (emitcode (";", "genJumpTab ");
11014 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
11015 /* get the condition into accumulator */
11016 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
11018 /* multiply by four! */
11019 emitcode ("add", "a,acc");
11020 emitcode ("add", "a,acc");
11021 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11023 jtab = newiTempLabel (NULL);
11024 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
11025 emitcode ("jmp", "@a+dptr");
11026 emitcode ("", "!tlabeldef", jtab->key + 100);
11027 /* now generate the jump labels */
11028 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11029 jtab = setNextItem (IC_JTLABELS (ic)))
11030 emitcode ("ljmp", "!tlabel", jtab->key + 100);
11034 /*-----------------------------------------------------------------*/
11035 /* genCast - gen code for casting */
11036 /*-----------------------------------------------------------------*/
11038 genCast (iCode * ic)
11040 operand *result = IC_RESULT (ic);
11041 sym_link *ctype = operandType (IC_LEFT (ic));
11042 sym_link *rtype = operandType (IC_RIGHT (ic));
11043 operand *right = IC_RIGHT (ic);
11046 D (emitcode (";", "genCast "););
11048 /* if they are equivalent then do nothing */
11049 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11052 aopOp (right, ic, FALSE, FALSE);
11053 aopOp (result, ic, FALSE, (AOP_TYPE(right) == AOP_DPTR));
11055 /* if the result is a bit */
11056 if (IS_BITVAR (OP_SYMBOL (result)->type)
11057 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
11059 /* if the right size is a literal then
11060 we know what the value is */
11061 if (AOP_TYPE (right) == AOP_LIT)
11063 if (((int) operandLitValue (right)))
11064 aopPut (AOP (result), one, 0);
11066 aopPut (AOP (result), zero, 0);
11071 /* the right is also a bit variable */
11072 if (AOP_TYPE (right) == AOP_CRY)
11074 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11075 aopPut (AOP (result), "c", 0);
11079 /* we need to or */
11081 aopPut (AOP (result), "a", 0);
11085 /* if they are the same size : or less */
11086 if (AOP_SIZE (result) <= AOP_SIZE (right))
11089 /* if they are in the same place */
11090 if (sameRegs (AOP (right), AOP (result)))
11093 /* if they in different places then copy */
11094 size = AOP_SIZE (result);
11096 _startLazyDPSEvaluation ();
11099 aopPut (AOP (result),
11100 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11104 _endLazyDPSEvaluation ();
11109 /* if the result is of type pointer */
11110 if (IS_PTR (ctype))
11114 sym_link *type = operandType (right);
11116 /* pointer to generic pointer */
11117 if (IS_GENPTR (ctype))
11121 p_type = DCL_TYPE (type);
11125 #if OLD_CAST_BEHAVIOR
11126 /* KV: we are converting a non-pointer type to
11127 * a generic pointer. This (ifdef'd out) code
11128 * says that the resulting generic pointer
11129 * should have the same class as the storage
11130 * location of the non-pointer variable.
11132 * For example, converting an int (which happens
11133 * to be stored in DATA space) to a pointer results
11134 * in a DATA generic pointer; if the original int
11135 * in XDATA space, so will be the resulting pointer.
11137 * I don't like that behavior, and thus this change:
11138 * all such conversions will be forced to XDATA and
11139 * throw a warning. If you want some non-XDATA
11140 * type, or you want to suppress the warning, you
11141 * must go through an intermediate cast, like so:
11143 * char _generic *gp = (char _xdata *)(intVar);
11145 sym_link *etype = getSpec (type);
11147 /* we have to go by the storage class */
11148 if (SPEC_OCLS (etype) != generic)
11150 p_type = PTR_TYPE (SPEC_OCLS (etype));
11155 /* Converting unknown class (i.e. register variable)
11156 * to generic pointer. This is not good, but
11157 * we'll make a guess (and throw a warning).
11160 werror (W_INT_TO_GEN_PTR_CAST);
11164 /* the first two bytes are known */
11165 size = GPTRSIZE - 1;
11167 _startLazyDPSEvaluation ();
11170 aopPut (AOP (result),
11171 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11175 _endLazyDPSEvaluation ();
11177 /* the last byte depending on type */
11179 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11184 // pointerTypeToGPByte will have bitched.
11188 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11189 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11194 /* just copy the pointers */
11195 size = AOP_SIZE (result);
11197 _startLazyDPSEvaluation ();
11200 aopPut (AOP (result),
11201 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11205 _endLazyDPSEvaluation ();
11209 /* so we now know that the size of destination is greater
11210 than the size of the source */
11211 /* we move to result for the size of source */
11212 size = AOP_SIZE (right);
11214 _startLazyDPSEvaluation ();
11217 aopPut (AOP (result),
11218 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11222 _endLazyDPSEvaluation ();
11224 /* now depending on the sign of the source && destination */
11225 size = AOP_SIZE (result) - AOP_SIZE (right);
11226 /* if unsigned or not an integral type */
11227 /* also, if the source is a bit, we don't need to sign extend, because
11228 * it can't possibly have set the sign bit.
11230 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
11234 aopPut (AOP (result), zero, offset++);
11239 /* we need to extend the sign :{ */
11240 MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11241 FALSE, FALSE, NULL));
11242 emitcode ("rlc", "a");
11243 emitcode ("subb", "a,acc");
11245 aopPut (AOP (result), "a", offset++);
11248 /* we are done hurray !!!! */
11251 freeAsmop (right, NULL, ic, TRUE);
11252 freeAsmop (result, NULL, ic, TRUE);
11256 /*-----------------------------------------------------------------*/
11257 /* genDjnz - generate decrement & jump if not zero instrucion */
11258 /*-----------------------------------------------------------------*/
11260 genDjnz (iCode * ic, iCode * ifx)
11262 symbol *lbl, *lbl1;
11266 /* if the if condition has a false label
11267 then we cannot save */
11268 if (IC_FALSE (ifx))
11271 /* if the minus is not of the form
11273 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11274 !IS_OP_LITERAL (IC_RIGHT (ic)))
11277 if (operandLitValue (IC_RIGHT (ic)) != 1)
11280 /* if the size of this greater than one then no
11282 if (getSize (operandType (IC_RESULT (ic))) > 1)
11285 /* otherwise we can save BIG */
11286 D(emitcode(";", "genDjnz"););
11288 lbl = newiTempLabel (NULL);
11289 lbl1 = newiTempLabel (NULL);
11291 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11293 if (AOP_NEEDSACC(IC_RESULT(ic)))
11295 /* If the result is accessed indirectly via
11296 * the accumulator, we must explicitly write
11297 * it back after the decrement.
11299 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11301 if (strcmp(rByte, "a"))
11303 /* Something is hopelessly wrong */
11304 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11305 __FILE__, __LINE__);
11306 /* We can just give up; the generated code will be inefficient,
11307 * but what the hey.
11309 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11312 emitcode ("dec", "%s", rByte);
11313 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11314 emitcode ("jnz", "!tlabel", lbl->key + 100);
11316 else if (IS_AOP_PREG (IC_RESULT (ic)))
11318 emitcode ("dec", "%s",
11319 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11320 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11321 emitcode ("jnz", "!tlabel", lbl->key + 100);
11325 emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11328 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11329 emitcode ("", "!tlabeldef", lbl->key + 100);
11330 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11331 emitcode ("", "!tlabeldef", lbl1->key + 100);
11333 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11334 ifx->generated = 1;
11338 /*-----------------------------------------------------------------*/
11339 /* genReceive - generate code for a receive iCode */
11340 /*-----------------------------------------------------------------*/
11342 genReceive (iCode * ic)
11344 int size = getSize (operandType (IC_RESULT (ic)));
11348 D (emitcode (";", "genReceive "););
11350 if (ic->argreg == 1)
11352 /* first parameter */
11353 if (AOP_IS_STR(IC_RESULT(ic)))
11355 /* Nothing to do: it's already in the proper place. */
11362 useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11363 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11364 IS_TRUE_SYMOP (IC_RESULT (ic)));
11367 aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11370 /* Sanity checking... */
11371 if (AOP_USESDPTR(IC_RESULT(ic)))
11373 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11374 "genReceive got unexpected DPTR.");
11376 assignResultValue (IC_RESULT (ic));
11381 /* second receive onwards */
11382 /* this gets a little tricky since unused recevies will be
11383 eliminated, we have saved the reg in the type field . and
11384 we use that to figure out which register to use */
11385 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11386 rb1off = ic->argreg;
11389 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11392 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11395 /*-----------------------------------------------------------------*/
11396 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
11397 /*-----------------------------------------------------------------*/
11398 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11400 operand *from , *to , *count;
11405 /* we know it has to be 3 parameters */
11406 assert (nparms == 3);
11408 rsave = newBitVect(16);
11409 /* save DPTR if it needs to be saved */
11410 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11411 if (bitVectBitValue(ic->rMask,i))
11412 rsave = bitVectSetBit(rsave,i);
11414 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11415 ds390_rUmaskForOp (IC_RESULT(ic))));
11422 aopOp (from, ic->next, FALSE, FALSE);
11424 /* get from into DPTR1 */
11425 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11426 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11427 if (options.model == MODEL_FLAT24) {
11428 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11431 freeAsmop (from, NULL, ic, FALSE);
11432 aopOp (to, ic, FALSE, FALSE);
11433 /* get "to" into DPTR */
11434 /* if the operand is already in dptr
11435 then we do nothing else we move the value to dptr */
11436 if (AOP_TYPE (to) != AOP_STR) {
11437 /* if already in DPTR then we need to push */
11438 if (AOP_TYPE(to) == AOP_DPTR) {
11439 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11440 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11441 if (options.model == MODEL_FLAT24)
11442 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11443 emitcode ("pop", "dph");
11444 emitcode ("pop", "dpl");
11446 _startLazyDPSEvaluation ();
11447 /* if this is remateriazable */
11448 if (AOP_TYPE (to) == AOP_IMMD) {
11449 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11450 } else { /* we need to get it byte by byte */
11451 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11452 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11453 if (options.model == MODEL_FLAT24) {
11454 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11457 _endLazyDPSEvaluation ();
11460 freeAsmop (to, NULL, ic, FALSE);
11461 _G.dptrInUse = _G.dptr1InUse = 1;
11462 aopOp (count, ic->next->next, FALSE,FALSE);
11463 lbl =newiTempLabel(NULL);
11465 /* now for the actual copy */
11466 if (AOP_TYPE(count) == AOP_LIT &&
11467 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11468 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11470 emitcode ("lcall","__bi_memcpyc2x_s");
11472 emitcode ("lcall","__bi_memcpyx2x_s");
11474 freeAsmop (count, NULL, ic, FALSE);
11476 symbol *lbl1 = newiTempLabel(NULL);
11478 emitcode (";"," Auto increment but no djnz");
11479 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11480 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11481 freeAsmop (count, NULL, ic, FALSE);
11482 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11483 emitcode ("","!tlabeldef",lbl->key+100);
11485 emitcode ("clr","a");
11486 emitcode ("movc", "a,@a+dptr");
11488 emitcode ("movx", "a,@dptr");
11489 emitcode ("movx", "@dptr,a");
11490 emitcode ("inc", "dptr");
11491 emitcode ("inc", "dptr");
11492 emitcode ("mov","a,b");
11493 emitcode ("orl","a,_ap");
11494 emitcode ("jz","!tlabel",lbl1->key+100);
11495 emitcode ("mov","a,_ap");
11496 emitcode ("add","a,#!constbyte",0xFF);
11497 emitcode ("mov","_ap,a");
11498 emitcode ("mov","a,b");
11499 emitcode ("addc","a,#!constbyte",0xFF);
11500 emitcode ("mov","b,a");
11501 emitcode ("sjmp","!tlabel",lbl->key+100);
11502 emitcode ("","!tlabeldef",lbl1->key+100);
11504 emitcode ("mov", "dps,#0");
11505 _G.dptrInUse = _G.dptr1InUse = 0;
11506 unsavermask(rsave);
11510 /*-----------------------------------------------------------------*/
11511 /* genMemcmpX2X - gen code for memcmp xdata to xdata */
11512 /*-----------------------------------------------------------------*/
11513 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11515 operand *from , *to , *count;
11520 /* we know it has to be 3 parameters */
11521 assert (nparms == 3);
11523 rsave = newBitVect(16);
11524 /* save DPTR if it needs to be saved */
11525 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11526 if (bitVectBitValue(ic->rMask,i))
11527 rsave = bitVectSetBit(rsave,i);
11529 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11530 ds390_rUmaskForOp (IC_RESULT(ic))));
11537 aopOp (from, ic->next, FALSE, FALSE);
11539 /* get from into DPTR1 */
11540 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11541 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11542 if (options.model == MODEL_FLAT24) {
11543 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11546 freeAsmop (from, NULL, ic, FALSE);
11547 aopOp (to, ic, FALSE, FALSE);
11548 /* get "to" into DPTR */
11549 /* if the operand is already in dptr
11550 then we do nothing else we move the value to dptr */
11551 if (AOP_TYPE (to) != AOP_STR) {
11552 /* if already in DPTR then we need to push */
11553 if (AOP_TYPE(to) == AOP_DPTR) {
11554 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11555 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11556 if (options.model == MODEL_FLAT24)
11557 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11558 emitcode ("pop", "dph");
11559 emitcode ("pop", "dpl");
11561 _startLazyDPSEvaluation ();
11562 /* if this is remateriazable */
11563 if (AOP_TYPE (to) == AOP_IMMD) {
11564 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11565 } else { /* we need to get it byte by byte */
11566 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11567 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11568 if (options.model == MODEL_FLAT24) {
11569 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11572 _endLazyDPSEvaluation ();
11575 freeAsmop (to, NULL, ic, FALSE);
11576 _G.dptrInUse = _G.dptr1InUse = 1;
11577 aopOp (count, ic->next->next, FALSE,FALSE);
11578 lbl =newiTempLabel(NULL);
11579 lbl2 =newiTempLabel(NULL);
11581 /* now for the actual compare */
11582 if (AOP_TYPE(count) == AOP_LIT &&
11583 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11584 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11586 emitcode("lcall","__bi_memcmpc2x_s");
11588 emitcode("lcall","__bi_memcmpx2x_s");
11589 freeAsmop (count, NULL, ic, FALSE);
11590 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11591 aopPut(AOP(IC_RESULT(ic)),"a",0);
11592 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11594 symbol *lbl1 = newiTempLabel(NULL);
11596 emitcode("push","ar0");
11597 emitcode (";"," Auto increment but no djnz");
11598 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11599 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11600 freeAsmop (count, NULL, ic, FALSE);
11601 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11602 emitcode ("","!tlabeldef",lbl->key+100);
11604 emitcode ("clr","a");
11605 emitcode ("movc", "a,@a+dptr");
11607 emitcode ("movx", "a,@dptr");
11608 emitcode ("mov","r0,a");
11609 emitcode ("movx", "a,@dptr");
11610 emitcode ("clr","c");
11611 emitcode ("subb","a,r0");
11612 emitcode ("jnz","!tlabel",lbl2->key+100);
11613 emitcode ("inc", "dptr");
11614 emitcode ("inc", "dptr");
11615 emitcode ("mov","a,b");
11616 emitcode ("orl","a,_ap");
11617 emitcode ("jz","!tlabel",lbl1->key+100);
11618 emitcode ("mov","a,_ap");
11619 emitcode ("add","a,#!constbyte",0xFF);
11620 emitcode ("mov","_ap,a");
11621 emitcode ("mov","a,b");
11622 emitcode ("addc","a,#!constbyte",0xFF);
11623 emitcode ("mov","b,a");
11624 emitcode ("sjmp","!tlabel",lbl->key+100);
11625 emitcode ("","!tlabeldef",lbl1->key+100);
11626 emitcode ("clr","a");
11627 emitcode ("","!tlabeldef",lbl2->key+100);
11628 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11629 aopPut(AOP(IC_RESULT(ic)),"a",0);
11630 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11631 emitcode("pop","ar0");
11632 emitcode ("mov", "dps,#0");
11634 _G.dptrInUse = _G.dptr1InUse = 0;
11635 unsavermask(rsave);
11639 /*-----------------------------------------------------------------*/
11640 /* genInp - gen code for __builtin_inp read data from a mem mapped */
11641 /* port, first parameter output area second parameter pointer to */
11642 /* port third parameter count */
11643 /*-----------------------------------------------------------------*/
11644 static void genInp( iCode *ic, int nparms, operand **parms)
11646 operand *from , *to , *count;
11651 /* we know it has to be 3 parameters */
11652 assert (nparms == 3);
11654 rsave = newBitVect(16);
11655 /* save DPTR if it needs to be saved */
11656 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11657 if (bitVectBitValue(ic->rMask,i))
11658 rsave = bitVectSetBit(rsave,i);
11660 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11661 ds390_rUmaskForOp (IC_RESULT(ic))));
11668 aopOp (from, ic->next, FALSE, FALSE);
11670 /* get from into DPTR1 */
11671 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11672 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11673 if (options.model == MODEL_FLAT24) {
11674 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11677 freeAsmop (from, NULL, ic, FALSE);
11678 aopOp (to, ic, FALSE, FALSE);
11679 /* get "to" into DPTR */
11680 /* if the operand is already in dptr
11681 then we do nothing else we move the value to dptr */
11682 if (AOP_TYPE (to) != AOP_STR) {
11683 /* if already in DPTR then we need to push */
11684 if (AOP_TYPE(to) == AOP_DPTR) {
11685 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11686 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11687 if (options.model == MODEL_FLAT24)
11688 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11689 emitcode ("pop", "dph");
11690 emitcode ("pop", "dpl");
11692 _startLazyDPSEvaluation ();
11693 /* if this is remateriazable */
11694 if (AOP_TYPE (to) == AOP_IMMD) {
11695 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11696 } else { /* we need to get it byte by byte */
11697 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11698 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11699 if (options.model == MODEL_FLAT24) {
11700 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11703 _endLazyDPSEvaluation ();
11706 freeAsmop (to, NULL, ic, FALSE);
11708 _G.dptrInUse = _G.dptr1InUse = 1;
11709 aopOp (count, ic->next->next, FALSE,FALSE);
11710 lbl =newiTempLabel(NULL);
11712 /* now for the actual copy */
11713 if (AOP_TYPE(count) == AOP_LIT &&
11714 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11715 emitcode (";","OH JOY auto increment with djnz (very fast)");
11716 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11717 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11718 freeAsmop (count, NULL, ic, FALSE);
11719 emitcode ("","!tlabeldef",lbl->key+100);
11720 emitcode ("movx", "a,@dptr"); /* read data from port */
11721 emitcode ("dec","dps"); /* switch to DPTR */
11722 emitcode ("movx", "@dptr,a"); /* save into location */
11723 emitcode ("inc", "dptr"); /* point to next area */
11724 emitcode ("inc","dps"); /* switch to DPTR2 */
11725 emitcode ("djnz","b,!tlabel",lbl->key+100);
11727 symbol *lbl1 = newiTempLabel(NULL);
11729 emitcode (";"," Auto increment but no djnz");
11730 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11731 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11732 freeAsmop (count, NULL, ic, FALSE);
11733 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11734 emitcode ("","!tlabeldef",lbl->key+100);
11735 emitcode ("movx", "a,@dptr");
11736 emitcode ("dec","dps"); /* switch to DPTR */
11737 emitcode ("movx", "@dptr,a");
11738 emitcode ("inc", "dptr");
11739 emitcode ("inc","dps"); /* switch to DPTR2 */
11740 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
11741 /* emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
11742 emitcode ("mov","a,b");
11743 emitcode ("orl","a,_ap");
11744 emitcode ("jz","!tlabel",lbl1->key+100);
11745 emitcode ("mov","a,_ap");
11746 emitcode ("add","a,#!constbyte",0xFF);
11747 emitcode ("mov","_ap,a");
11748 emitcode ("mov","a,b");
11749 emitcode ("addc","a,#!constbyte",0xFF);
11750 emitcode ("mov","b,a");
11751 emitcode ("sjmp","!tlabel",lbl->key+100);
11752 emitcode ("","!tlabeldef",lbl1->key+100);
11754 emitcode ("mov", "dps,#0");
11755 _G.dptrInUse = _G.dptr1InUse = 0;
11756 unsavermask(rsave);
11760 /*-----------------------------------------------------------------*/
11761 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
11762 /* port, first parameter output area second parameter pointer to */
11763 /* port third parameter count */
11764 /*-----------------------------------------------------------------*/
11765 static void genOutp( iCode *ic, int nparms, operand **parms)
11767 operand *from , *to , *count;
11772 /* we know it has to be 3 parameters */
11773 assert (nparms == 3);
11775 rsave = newBitVect(16);
11776 /* save DPTR if it needs to be saved */
11777 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11778 if (bitVectBitValue(ic->rMask,i))
11779 rsave = bitVectSetBit(rsave,i);
11781 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11782 ds390_rUmaskForOp (IC_RESULT(ic))));
11789 aopOp (from, ic->next, FALSE, FALSE);
11791 /* get from into DPTR1 */
11792 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11793 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11794 if (options.model == MODEL_FLAT24) {
11795 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11798 freeAsmop (from, NULL, ic, FALSE);
11799 aopOp (to, ic, FALSE, FALSE);
11800 /* get "to" into DPTR */
11801 /* if the operand is already in dptr
11802 then we do nothing else we move the value to dptr */
11803 if (AOP_TYPE (to) != AOP_STR) {
11804 /* if already in DPTR then we need to push */
11805 if (AOP_TYPE(to) == AOP_DPTR) {
11806 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11807 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11808 if (options.model == MODEL_FLAT24)
11809 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11810 emitcode ("pop", "dph");
11811 emitcode ("pop", "dpl");
11813 _startLazyDPSEvaluation ();
11814 /* if this is remateriazable */
11815 if (AOP_TYPE (to) == AOP_IMMD) {
11816 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11817 } else { /* we need to get it byte by byte */
11818 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11819 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11820 if (options.model == MODEL_FLAT24) {
11821 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11824 _endLazyDPSEvaluation ();
11827 freeAsmop (to, NULL, ic, FALSE);
11829 _G.dptrInUse = _G.dptr1InUse = 1;
11830 aopOp (count, ic->next->next, FALSE,FALSE);
11831 lbl =newiTempLabel(NULL);
11833 /* now for the actual copy */
11834 if (AOP_TYPE(count) == AOP_LIT &&
11835 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11836 emitcode (";","OH JOY auto increment with djnz (very fast)");
11837 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
11838 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11839 emitcode ("","!tlabeldef",lbl->key+100);
11840 emitcode ("movx", "a,@dptr"); /* read data from port */
11841 emitcode ("inc","dps"); /* switch to DPTR2 */
11842 emitcode ("movx", "@dptr,a"); /* save into location */
11843 emitcode ("inc", "dptr"); /* point to next area */
11844 emitcode ("dec","dps"); /* switch to DPTR */
11845 emitcode ("djnz","b,!tlabel",lbl->key+100);
11846 freeAsmop (count, NULL, ic, FALSE);
11848 symbol *lbl1 = newiTempLabel(NULL);
11850 emitcode (";"," Auto increment but no djnz");
11851 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11852 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11853 freeAsmop (count, NULL, ic, FALSE);
11854 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
11855 emitcode ("","!tlabeldef",lbl->key+100);
11856 emitcode ("movx", "a,@dptr");
11857 emitcode ("inc", "dptr");
11858 emitcode ("inc","dps"); /* switch to DPTR2 */
11859 emitcode ("movx", "@dptr,a");
11860 emitcode ("dec","dps"); /* switch to DPTR */
11861 emitcode ("mov","a,b");
11862 emitcode ("orl","a,_ap");
11863 emitcode ("jz","!tlabel",lbl1->key+100);
11864 emitcode ("mov","a,_ap");
11865 emitcode ("add","a,#!constbyte",0xFF);
11866 emitcode ("mov","_ap,a");
11867 emitcode ("mov","a,b");
11868 emitcode ("addc","a,#!constbyte",0xFF);
11869 emitcode ("mov","b,a");
11870 emitcode ("sjmp","!tlabel",lbl->key+100);
11871 emitcode ("","!tlabeldef",lbl1->key+100);
11873 emitcode ("mov", "dps,#0");
11874 _G.dptrInUse = _G.dptr1InUse = 0;
11875 unsavermask(rsave);
11879 /*-----------------------------------------------------------------*/
11880 /* genSwapW - swap lower & high order bytes */
11881 /*-----------------------------------------------------------------*/
11882 static void genSwapW(iCode *ic, int nparms, operand **parms)
11886 assert (nparms==1);
11889 dest=IC_RESULT(ic);
11891 assert(getSize(operandType(src))==2);
11893 aopOp (src, ic, FALSE, FALSE);
11894 emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
11896 MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
11898 freeAsmop (src, NULL, ic, FALSE);
11900 aopOp (dest,ic, FALSE, FALSE);
11901 aopPut(AOP(dest),"b",0);
11902 aopPut(AOP(dest),"a",1);
11903 freeAsmop (dest, NULL, ic, FALSE);
11906 /*-----------------------------------------------------------------*/
11907 /* genMemsetX - gencode for memSetX data */
11908 /*-----------------------------------------------------------------*/
11909 static void genMemsetX(iCode *ic, int nparms, operand **parms)
11911 operand *to , *val , *count;
11917 /* we know it has to be 3 parameters */
11918 assert (nparms == 3);
11924 /* save DPTR if it needs to be saved */
11925 rsave = newBitVect(16);
11926 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11927 if (bitVectBitValue(ic->rMask,i))
11928 rsave = bitVectSetBit(rsave,i);
11930 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11931 ds390_rUmaskForOp (IC_RESULT(ic))));
11934 aopOp (to, ic, FALSE, FALSE);
11935 /* get "to" into DPTR */
11936 /* if the operand is already in dptr
11937 then we do nothing else we move the value to dptr */
11938 if (AOP_TYPE (to) != AOP_STR) {
11939 /* if already in DPTR then we need to push */
11940 if (AOP_TYPE(to) == AOP_DPTR) {
11941 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11942 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11943 if (options.model == MODEL_FLAT24)
11944 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11945 emitcode ("pop", "dph");
11946 emitcode ("pop", "dpl");
11948 _startLazyDPSEvaluation ();
11949 /* if this is remateriazable */
11950 if (AOP_TYPE (to) == AOP_IMMD) {
11951 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11952 } else { /* we need to get it byte by byte */
11953 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11954 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11955 if (options.model == MODEL_FLAT24) {
11956 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11959 _endLazyDPSEvaluation ();
11962 freeAsmop (to, NULL, ic, FALSE);
11964 aopOp (val, ic->next->next, FALSE,FALSE);
11965 aopOp (count, ic->next->next, FALSE,FALSE);
11966 lbl =newiTempLabel(NULL);
11967 /* now for the actual copy */
11968 if (AOP_TYPE(count) == AOP_LIT &&
11969 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11970 l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
11971 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11973 emitcode ("","!tlabeldef",lbl->key+100);
11974 emitcode ("movx", "@dptr,a");
11975 emitcode ("inc", "dptr");
11976 emitcode ("djnz","b,!tlabel",lbl->key+100);
11978 symbol *lbl1 = newiTempLabel(NULL);
11980 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11981 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11982 emitcode ("","!tlabeldef",lbl->key+100);
11983 MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
11984 emitcode ("movx", "@dptr,a");
11985 emitcode ("inc", "dptr");
11986 emitcode ("mov","a,b");
11987 emitcode ("orl","a,_ap");
11988 emitcode ("jz","!tlabel",lbl1->key+100);
11989 emitcode ("mov","a,_ap");
11990 emitcode ("add","a,#!constbyte",0xFF);
11991 emitcode ("mov","_ap,a");
11992 emitcode ("mov","a,b");
11993 emitcode ("addc","a,#!constbyte",0xFF);
11994 emitcode ("mov","b,a");
11995 emitcode ("sjmp","!tlabel",lbl->key+100);
11996 emitcode ("","!tlabeldef",lbl1->key+100);
11998 freeAsmop (count, NULL, ic, FALSE);
11999 unsavermask(rsave);
12002 /*-----------------------------------------------------------------*/
12003 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
12004 /*-----------------------------------------------------------------*/
12005 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
12008 operand *pnum, *result;
12011 assert (nparms==1);
12012 /* save registers that need to be saved */
12013 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12014 ds390_rUmaskForOp (IC_RESULT(ic))));
12017 aopOp (pnum, ic, FALSE, FALSE);
12018 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12019 freeAsmop (pnum, NULL, ic, FALSE);
12020 emitcode ("lcall","NatLib_LoadPrimitive");
12021 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12022 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
12023 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
12024 for (i = (size-1) ; i >= 0 ; i-- ) {
12025 emitcode ("push","a%s",javaRet[i]);
12027 for (i=0; i < size ; i++ ) {
12028 emitcode ("pop","a%s",
12029 aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
12032 for (i = 0 ; i < size ; i++ ) {
12033 aopPut(AOP(result),javaRet[i],i);
12036 freeAsmop (result, NULL, ic, FALSE);
12037 unsavermask(rsave);
12040 /*-----------------------------------------------------------------*/
12041 /* genNatLibLoadPointer - calls TINI api function to load pointer */
12042 /*-----------------------------------------------------------------*/
12043 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
12046 operand *pnum, *result;
12050 assert (nparms==1);
12051 /* save registers that need to be saved */
12052 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12053 ds390_rUmaskForOp (IC_RESULT(ic))));
12056 aopOp (pnum, ic, FALSE, FALSE);
12057 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12058 freeAsmop (pnum, NULL, ic, FALSE);
12059 emitcode ("lcall","NatLib_LoadPointer");
12060 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12061 if (AOP_TYPE(result)!=AOP_STR) {
12062 for (i = 0 ; i < size ; i++ ) {
12063 aopPut(AOP(result),fReturn[i],i);
12066 freeAsmop (result, NULL, ic, FALSE);
12067 unsavermask(rsave);
12070 /*-----------------------------------------------------------------*/
12071 /* genNatLibInstallStateBlock - */
12072 /*-----------------------------------------------------------------*/
12073 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
12074 operand **parms, const char *name)
12077 operand *psb, *handle;
12078 assert (nparms==2);
12080 /* save registers that need to be saved */
12081 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12082 ds390_rUmaskForOp (IC_RESULT(ic))));
12086 /* put pointer to state block into DPTR1 */
12087 aopOp (psb, ic, FALSE, FALSE);
12088 if (AOP_TYPE (psb) == AOP_IMMD) {
12089 emitcode ("mov","dps,#1");
12090 emitcode ("mov", "dptr,%s",
12091 aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12092 emitcode ("mov","dps,#0");
12094 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12095 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12096 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12098 freeAsmop (psb, NULL, ic, FALSE);
12100 /* put libraryID into DPTR */
12101 emitcode ("mov","dptr,#LibraryID");
12103 /* put handle into r3:r2 */
12104 aopOp (handle, ic, FALSE, FALSE);
12105 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12106 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12107 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12108 emitcode ("pop","ar3");
12109 emitcode ("pop","ar2");
12111 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12112 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12114 freeAsmop (psb, NULL, ic, FALSE);
12116 /* make the call */
12117 emitcode ("lcall","NatLib_Install%sStateBlock",name);
12119 /* put return value into place*/
12121 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12123 aopPut(AOP(IC_RESULT(ic)),"a",0);
12124 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12125 unsavermask(rsave);
12128 /*-----------------------------------------------------------------*/
12129 /* genNatLibRemoveStateBlock - */
12130 /*-----------------------------------------------------------------*/
12131 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12137 /* save registers that need to be saved */
12138 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12139 ds390_rUmaskForOp (IC_RESULT(ic))));
12141 /* put libraryID into DPTR */
12142 emitcode ("mov","dptr,#LibraryID");
12143 /* make the call */
12144 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12145 unsavermask(rsave);
12148 /*-----------------------------------------------------------------*/
12149 /* genNatLibGetStateBlock - */
12150 /*-----------------------------------------------------------------*/
12151 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12152 operand **parms,const char *name)
12155 symbol *lbl = newiTempLabel(NULL);
12158 /* save registers that need to be saved */
12159 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12160 ds390_rUmaskForOp (IC_RESULT(ic))));
12162 /* put libraryID into DPTR */
12163 emitcode ("mov","dptr,#LibraryID");
12164 /* make the call */
12165 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12166 emitcode ("jnz","!tlabel",lbl->key+100);
12168 /* put return value into place */
12169 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12170 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12171 emitcode ("push","ar3");
12172 emitcode ("push","ar2");
12173 emitcode ("pop","%s",
12174 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12175 emitcode ("pop","%s",
12176 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12178 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12179 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12181 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12182 emitcode ("","!tlabeldef",lbl->key+100);
12183 unsavermask(rsave);
12186 /*-----------------------------------------------------------------*/
12187 /* genMMMalloc - */
12188 /*-----------------------------------------------------------------*/
12189 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12190 int size, const char *name)
12195 symbol *lbl = newiTempLabel(NULL);
12197 assert (nparms == 1);
12198 /* save registers that need to be saved */
12199 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12200 ds390_rUmaskForOp (IC_RESULT(ic))));
12203 aopOp (bsize,ic,FALSE,FALSE);
12205 /* put the size in R4-R2 */
12206 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12207 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12208 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12210 emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12211 emitcode("pop","ar4");
12213 emitcode("pop","ar3");
12214 emitcode("pop","ar2");
12216 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12217 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12219 emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12222 freeAsmop (bsize, NULL, ic, FALSE);
12224 /* make the call */
12225 emitcode ("lcall","MM_%s",name);
12226 emitcode ("jz","!tlabel",lbl->key+100);
12227 emitcode ("mov","r2,#!constbyte",0xff);
12228 emitcode ("mov","r3,#!constbyte",0xff);
12229 emitcode ("","!tlabeldef",lbl->key+100);
12230 /* we don't care about the pointer : we just save the handle */
12231 rsym = OP_SYMBOL(IC_RESULT(ic));
12232 if (rsym->liveFrom != rsym->liveTo) {
12233 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12234 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12235 emitcode ("push","ar3");
12236 emitcode ("push","ar2");
12237 emitcode ("pop","%s",
12238 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12239 emitcode ("pop","%s",
12240 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12242 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12243 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12245 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12247 unsavermask(rsave);
12250 /*-----------------------------------------------------------------*/
12252 /*-----------------------------------------------------------------*/
12253 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12258 assert (nparms == 1);
12259 /* save registers that need to be saved */
12260 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12261 ds390_rUmaskForOp (IC_RESULT(ic))));
12264 aopOp (handle,ic,FALSE,FALSE);
12266 /* put the size in R4-R2 */
12267 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12268 emitcode("push","%s",
12269 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12270 emitcode("push","%s",
12271 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12272 emitcode("pop","ar3");
12273 emitcode("pop","ar2");
12275 emitcode ("mov","r2,%s",
12276 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12277 emitcode ("mov","r3,%s",
12278 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12280 freeAsmop (handle, NULL, ic, FALSE);
12282 /* make the call */
12283 emitcode ("lcall","MM_Deref");
12286 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12287 if (rsym->liveFrom != rsym->liveTo) {
12288 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12289 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12290 _startLazyDPSEvaluation ();
12292 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12293 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12294 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12296 _endLazyDPSEvaluation ();
12301 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12302 unsavermask(rsave);
12305 /*-----------------------------------------------------------------*/
12306 /* genMMUnrestrictedPersist - */
12307 /*-----------------------------------------------------------------*/
12308 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12313 assert (nparms == 1);
12314 /* save registers that need to be saved */
12315 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12316 ds390_rUmaskForOp (IC_RESULT(ic))));
12319 aopOp (handle,ic,FALSE,FALSE);
12321 /* put the size in R3-R2 */
12322 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12323 emitcode("push","%s",
12324 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12325 emitcode("push","%s",
12326 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12327 emitcode("pop","ar3");
12328 emitcode("pop","ar2");
12330 emitcode ("mov","r2,%s",
12331 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12332 emitcode ("mov","r3,%s",
12333 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12335 freeAsmop (handle, NULL, ic, FALSE);
12337 /* make the call */
12338 emitcode ("lcall","MM_UnrestrictedPersist");
12341 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12342 if (rsym->liveFrom != rsym->liveTo) {
12343 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12344 aopPut(AOP(IC_RESULT(ic)),"a",0);
12345 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12348 unsavermask(rsave);
12351 /*-----------------------------------------------------------------*/
12352 /* genSystemExecJavaProcess - */
12353 /*-----------------------------------------------------------------*/
12354 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12357 operand *handle, *pp;
12359 assert (nparms==2);
12360 /* save registers that need to be saved */
12361 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12362 ds390_rUmaskForOp (IC_RESULT(ic))));
12367 /* put the handle in R3-R2 */
12368 aopOp (handle,ic,FALSE,FALSE);
12369 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12370 emitcode("push","%s",
12371 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12372 emitcode("push","%s",
12373 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12374 emitcode("pop","ar3");
12375 emitcode("pop","ar2");
12377 emitcode ("mov","r2,%s",
12378 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12379 emitcode ("mov","r3,%s",
12380 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12382 freeAsmop (handle, NULL, ic, FALSE);
12384 /* put pointer in DPTR */
12385 aopOp (pp,ic,FALSE,FALSE);
12386 if (AOP_TYPE(pp) == AOP_IMMD) {
12387 emitcode ("mov", "dptr,%s",
12388 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12389 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12390 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12391 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12392 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12394 freeAsmop (handle, NULL, ic, FALSE);
12396 /* make the call */
12397 emitcode ("lcall","System_ExecJavaProcess");
12399 /* put result in place */
12401 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12402 if (rsym->liveFrom != rsym->liveTo) {
12403 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12404 aopPut(AOP(IC_RESULT(ic)),"a",0);
12405 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12409 unsavermask(rsave);
12412 /*-----------------------------------------------------------------*/
12413 /* genSystemRTCRegisters - */
12414 /*-----------------------------------------------------------------*/
12415 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12421 assert (nparms==1);
12422 /* save registers that need to be saved */
12423 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12424 ds390_rUmaskForOp (IC_RESULT(ic))));
12427 /* put pointer in DPTR */
12428 aopOp (pp,ic,FALSE,FALSE);
12429 if (AOP_TYPE (pp) == AOP_IMMD) {
12430 emitcode ("mov","dps,#1");
12431 emitcode ("mov", "dptr,%s",
12432 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12433 emitcode ("mov","dps,#0");
12435 emitcode ("mov","dpl1,%s",
12436 aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12437 emitcode ("mov","dph1,%s",
12438 aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12439 emitcode ("mov","dpx1,%s",
12440 aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12442 freeAsmop (pp, NULL, ic, FALSE);
12444 /* make the call */
12445 emitcode ("lcall","System_%sRTCRegisters",name);
12447 unsavermask(rsave);
12450 /*-----------------------------------------------------------------*/
12451 /* genSystemThreadSleep - */
12452 /*-----------------------------------------------------------------*/
12453 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12458 assert (nparms==1);
12459 /* save registers that need to be saved */
12460 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12461 ds390_rUmaskForOp (IC_RESULT(ic))));
12464 aopOp(to,ic,FALSE,FALSE);
12465 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12466 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12467 emitcode ("push","%s",
12468 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12469 emitcode ("push","%s",
12470 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12471 emitcode ("push","%s",
12472 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12473 emitcode ("push","%s",
12474 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12475 emitcode ("pop","ar3");
12476 emitcode ("pop","ar2");
12477 emitcode ("pop","ar1");
12478 emitcode ("pop","ar0");
12480 emitcode ("mov","r0,%s",
12481 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12482 emitcode ("mov","r1,%s",
12483 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12484 emitcode ("mov","r2,%s",
12485 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12486 emitcode ("mov","r3,%s",
12487 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12489 freeAsmop (to, NULL, ic, FALSE);
12491 /* suspend in acc */
12493 aopOp(s,ic,FALSE,FALSE);
12494 emitcode ("mov","a,%s",
12495 aopGet(AOP(s),0,FALSE,TRUE,NULL));
12496 freeAsmop (s, NULL, ic, FALSE);
12498 /* make the call */
12499 emitcode ("lcall","System_%s",name);
12501 unsavermask(rsave);
12504 /*-----------------------------------------------------------------*/
12505 /* genSystemThreadResume - */
12506 /*-----------------------------------------------------------------*/
12507 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12512 assert (nparms==2);
12513 /* save registers that need to be saved */
12514 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12515 ds390_rUmaskForOp (IC_RESULT(ic))));
12521 aopOp(pid,ic,FALSE,FALSE);
12522 emitcode ("mov","r0,%s",
12523 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12524 freeAsmop (pid, NULL, ic, FALSE);
12527 aopOp(tid,ic,FALSE,FALSE);
12528 emitcode ("mov","a,%s",
12529 aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
12530 freeAsmop (tid, NULL, ic, FALSE);
12532 emitcode ("lcall","System_ThreadResume");
12534 /* put result into place */
12536 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12537 if (rsym->liveFrom != rsym->liveTo) {
12538 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12539 aopPut(AOP(IC_RESULT(ic)),"a",0);
12540 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12543 unsavermask(rsave);
12546 /*-----------------------------------------------------------------*/
12547 /* genSystemProcessResume - */
12548 /*-----------------------------------------------------------------*/
12549 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
12554 assert (nparms==1);
12555 /* save registers that need to be saved */
12556 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12557 ds390_rUmaskForOp (IC_RESULT(ic))));
12562 aopOp(pid,ic,FALSE,FALSE);
12563 emitcode ("mov","a,%s",
12564 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12565 freeAsmop (pid, NULL, ic, FALSE);
12567 emitcode ("lcall","System_ProcessResume");
12569 unsavermask(rsave);
12572 /*-----------------------------------------------------------------*/
12574 /*-----------------------------------------------------------------*/
12575 static void genSystem (iCode *ic,int nparms,char *name)
12577 assert(nparms == 0);
12579 emitcode ("lcall","System_%s",name);
12582 /*-----------------------------------------------------------------*/
12583 /* genSystemPoll - */
12584 /*-----------------------------------------------------------------*/
12585 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
12590 assert (nparms==1);
12591 /* save registers that need to be saved */
12592 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12593 ds390_rUmaskForOp (IC_RESULT(ic))));
12596 aopOp (fp,ic,FALSE,FALSE);
12597 if (AOP_TYPE (fp) == AOP_IMMD) {
12598 emitcode ("mov", "dptr,%s",
12599 aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
12600 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
12601 emitcode ("mov","dpl,%s",
12602 aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
12603 emitcode ("mov","dph,%s",
12604 aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
12605 emitcode ("mov","dpx,%s",
12606 aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
12608 freeAsmop (fp, NULL, ic, FALSE);
12610 emitcode ("lcall","System_%sPoll",name);
12612 /* put result into place */
12614 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12615 if (rsym->liveFrom != rsym->liveTo) {
12616 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12617 aopPut(AOP(IC_RESULT(ic)),"a",0);
12618 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12621 unsavermask(rsave);
12624 /*-----------------------------------------------------------------*/
12625 /* genSystemGetCurrentID - */
12626 /*-----------------------------------------------------------------*/
12627 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
12629 assert (nparms==0);
12631 emitcode ("lcall","System_GetCurrent%sId",name);
12632 /* put result into place */
12634 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12635 if (rsym->liveFrom != rsym->liveTo) {
12636 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12637 aopPut(AOP(IC_RESULT(ic)),"a",0);
12638 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12643 /*-----------------------------------------------------------------*/
12644 /* genDummyRead - generate code for dummy read of volatiles */
12645 /*-----------------------------------------------------------------*/
12647 genDummyRead (iCode * ic)
12652 D(emitcode("; genDummyRead",""));
12654 right = IC_RIGHT (ic);
12656 aopOp (right, ic, FALSE, FALSE);
12658 /* if the result is a bit */
12659 if (AOP_TYPE (right) == AOP_CRY)
12661 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
12665 /* bit variables done */
12667 size = AOP_SIZE (right);
12671 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
12676 freeAsmop (right, NULL, ic, TRUE);
12679 /*-----------------------------------------------------------------*/
12680 /* genCritical - generate code for start of a critical sequence */
12681 /*-----------------------------------------------------------------*/
12683 genCritical (iCode *ic)
12685 symbol *tlbl = newiTempLabel (NULL);
12687 D(emitcode("; genCritical",""));
12689 if (IC_RESULT (ic))
12690 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
12692 emitcode ("setb", "c");
12693 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
12694 emitcode ("clr", "c");
12695 emitcode ("", "%05d$:", (tlbl->key + 100));
12697 if (IC_RESULT (ic))
12698 outBitC (IC_RESULT (ic)); /* save old ea in an operand */
12700 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
12702 if (IC_RESULT (ic))
12703 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
12706 /*-----------------------------------------------------------------*/
12707 /* genEndCritical - generate code for end of a critical sequence */
12708 /*-----------------------------------------------------------------*/
12710 genEndCritical (iCode *ic)
12712 D(emitcode("; genEndCritical",""));
12716 aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
12717 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
12719 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
12720 emitcode ("mov", "ea,c");
12724 MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE, FALSE));
12725 emitcode ("rrc", "a");
12726 emitcode ("mov", "ea,c");
12728 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
12732 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
12733 emitcode ("mov", "ea,c");
12739 /*-----------------------------------------------------------------*/
12740 /* genBuiltIn - calls the appropriate function to generating code */
12741 /* for a built in function */
12742 /*-----------------------------------------------------------------*/
12743 static void genBuiltIn (iCode *ic)
12745 operand *bi_parms[MAX_BUILTIN_ARGS];
12750 /* get all the arguments for a built in function */
12751 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
12753 /* which function is it */
12754 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
12755 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
12756 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
12757 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
12758 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
12759 } else if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
12760 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
12761 } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
12762 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
12763 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
12764 genMemsetX(bi_iCode,nbi_parms,bi_parms);
12765 } else if (strcmp(bif->name,"__builtin_inp")==0) {
12766 genInp(bi_iCode,nbi_parms,bi_parms);
12767 } else if (strcmp(bif->name,"__builtin_outp")==0) {
12768 genOutp(bi_iCode,nbi_parms,bi_parms);
12769 } else if (strcmp(bif->name,"__builtin_swapw")==0) {
12770 genSwapW(bi_iCode,nbi_parms,bi_parms);
12771 /* JavaNative builtIns */
12772 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
12773 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
12774 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
12775 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
12776 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
12777 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
12778 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
12779 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
12780 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
12781 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12782 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
12783 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12784 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
12785 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
12786 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
12787 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
12788 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
12789 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12790 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
12791 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12792 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
12793 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
12794 } else if (strcmp(bif->name,"MM_Malloc")==0) {
12795 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
12796 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
12797 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
12798 } else if (strcmp(bif->name,"MM_Free")==0) {
12799 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
12800 } else if (strcmp(bif->name,"MM_Deref")==0) {
12801 genMMDeref(bi_iCode,nbi_parms,bi_parms);
12802 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
12803 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
12804 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
12805 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
12806 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
12807 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
12808 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
12809 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
12810 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
12811 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
12812 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
12813 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
12814 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
12815 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
12816 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
12817 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
12818 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12819 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12820 } else if (strcmp(bif->name,"System_SaveThread")==0) {
12821 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12822 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12823 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12824 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
12825 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
12826 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
12827 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
12828 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
12829 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
12830 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
12831 genSystem(bi_iCode,nbi_parms,"ProcessYield");
12832 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
12833 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
12834 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
12835 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
12836 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
12837 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
12838 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
12839 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
12840 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
12841 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
12843 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
12849 /*-----------------------------------------------------------------*/
12850 /* gen390Code - generate code for Dallas 390 based controllers */
12851 /*-----------------------------------------------------------------*/
12853 gen390Code (iCode * lic)
12858 lineHead = lineCurr = NULL;
12859 dptrn[1][0] = "dpl1";
12860 dptrn[1][1] = "dph1";
12861 dptrn[1][2] = "dpx1";
12863 if (options.model == MODEL_FLAT24) {
12864 fReturnSizeDS390 = 5;
12865 fReturn = fReturn24;
12867 fReturnSizeDS390 = 4;
12868 fReturn = fReturn16;
12869 options.stack10bit=0;
12872 /* print the allocation information */
12873 if (allocInfo && currFunc)
12874 printAllocInfo (currFunc, codeOutFile);
12876 /* if debug information required */
12877 if (options.debug && currFunc)
12879 debugFile->writeFunction(currFunc);
12881 if (IS_STATIC (currFunc->etype))
12882 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
12884 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
12887 /* stack pointer name */
12888 if (options.useXstack)
12894 for (ic = lic; ic; ic = ic->next)
12897 if (ic->lineno && cln != ic->lineno)
12902 emitcode ("", "C$%s$%d$%d$%d ==.",
12903 FileBaseName (ic->filename), ic->lineno,
12904 ic->level, ic->block);
12907 if (!options.noCcodeInAsm) {
12908 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
12909 printCLine(ic->filename, ic->lineno));
12913 if (options.iCodeInAsm) {
12914 emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
12916 /* if the result is marked as
12917 spilt and rematerializable or code for
12918 this has already been generated then
12920 if (resultRemat (ic) || ic->generated)
12923 /* depending on the operation */
12943 /* IPOP happens only when trying to restore a
12944 spilt live range, if there is an ifx statement
12945 following this pop then the if statement might
12946 be using some of the registers being popped which
12947 would destory the contents of the register so
12948 we need to check for this condition and handle it */
12950 ic->next->op == IFX &&
12951 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
12952 genIfx (ic->next, ic);
12970 genEndFunction (ic);
12990 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
13007 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
13011 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
13018 /* note these two are xlated by algebraic equivalence
13019 during parsing SDCC.y */
13020 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
13021 "got '>=' or '<=' shouldn't have come here");
13025 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
13037 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
13041 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
13045 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
13069 genRightShift (ic);
13072 case GET_VALUE_AT_ADDRESS:
13073 genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
13077 if (POINTER_SET (ic))
13078 genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
13104 if (ic->builtinSEND) genBuiltIn(ic);
13105 else addSet (&_G.sendSet, ic);
13108 case DUMMY_READ_VOLATILE:
13117 genEndCritical (ic);
13120 #if 0 // obsolete, and buggy for != xdata
13132 /* now we are ready to call the
13133 peep hole optimizer */
13134 if (!options.nopeep)
13135 peepHole (&lineHead);
13137 /* now do the actual printing */
13138 printLine (lineHead, codeOutFile);