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_TYPE(IC_LEFT (ic)) == AOP_DPTR));
1966 /* if both in bit space then special
1968 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1969 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1972 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1973 emitcode ("cpl", "c");
1974 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1978 optype = operandType (IC_LEFT (ic));
1980 /* if float then do float stuff */
1981 if (IS_FLOAT (optype))
1983 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1987 /* otherwise subtract from zero */
1988 size = AOP_SIZE (IC_LEFT (ic));
1990 _startLazyDPSEvaluation ();
1993 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL);
1994 if (!strcmp (l, "a"))
1998 emitcode ("cpl", "a");
1999 emitcode ("addc", "a,#0");
2005 emitcode ("clr", "a");
2006 emitcode ("subb", "a,%s", l);
2008 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2010 _endLazyDPSEvaluation ();
2012 /* if any remaining bytes in the result */
2013 /* we just need to propagate the sign */
2014 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic)))) != 0)
2016 emitcode ("rlc", "a");
2017 emitcode ("subb", "a,acc");
2019 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2023 /* release the aops */
2024 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2025 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2028 /*-----------------------------------------------------------------*/
2029 /* savermask - saves registers in the mask */
2030 /*-----------------------------------------------------------------*/
2031 static void savermask(bitVect *rs_mask)
2034 if (options.useXstack) {
2035 if (bitVectBitValue (rs_mask, R0_IDX))
2036 emitcode ("mov", "b,r0");
2037 emitcode ("mov", "r0,%s", spname);
2038 for (i = 0; i < ds390_nRegs; i++) {
2039 if (bitVectBitValue (rs_mask, i)) {
2041 emitcode ("mov", "a,b");
2043 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
2044 emitcode ("movx", "@r0,a");
2045 emitcode ("inc", "r0");
2048 emitcode ("mov", "%s,r0", spname);
2049 if (bitVectBitValue (rs_mask, R0_IDX))
2050 emitcode ("mov", "r0,b");
2052 for (i = 0; i < ds390_nRegs; i++) {
2053 if (bitVectBitValue (rs_mask, i))
2054 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2059 /*-----------------------------------------------------------------*/
2060 /* saveRegisters - will look for a call and save the registers */
2061 /*-----------------------------------------------------------------*/
2063 saveRegisters (iCode * lic)
2069 for (ic = lic; ic; ic = ic->next)
2070 if (ic->op == CALL || ic->op == PCALL)
2075 fprintf (stderr, "found parameter push with no function call\n");
2079 /* if the registers have been saved already then
2082 || (IS_SYMOP(IC_LEFT(ic)) && IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))) && !TARGET_IS_DS400) )
2085 /* special case if DPTR alive across a function call then must save it
2086 even though callee saves */
2087 if (IS_SYMOP(IC_LEFT(ic)) &&
2088 IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2090 rsave = newBitVect(ic->rMask->size);
2091 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2092 if (bitVectBitValue(ic->rMask,i))
2093 rsave = bitVectSetBit(rsave,i);
2095 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2097 /* safe the registers in use at this time but skip the
2098 ones for the result */
2099 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2100 ds390_rUmaskForOp (IC_RESULT(ic)));
2106 /*-----------------------------------------------------------------*/
2107 /* usavermask - restore registers with mask */
2108 /*-----------------------------------------------------------------*/
2109 static void unsavermask(bitVect *rs_mask)
2112 if (options.useXstack) {
2113 emitcode ("mov", "r0,%s", spname);
2114 for (i = ds390_nRegs; i >= 0; i--) {
2115 if (bitVectBitValue (rs_mask, i)) {
2116 emitcode ("dec", "r0");
2117 emitcode ("movx", "a,@r0");
2119 emitcode ("mov", "b,a");
2121 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
2124 emitcode ("mov", "%s,r0", spname);
2125 if (bitVectBitValue (rs_mask, R0_IDX))
2126 emitcode ("mov", "r0,b");
2128 for (i = ds390_nRegs; i >= 0; i--) {
2129 if (bitVectBitValue (rs_mask, i))
2130 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2135 /*-----------------------------------------------------------------*/
2136 /* unsaveRegisters - pop the pushed registers */
2137 /*-----------------------------------------------------------------*/
2139 unsaveRegisters (iCode * ic)
2143 if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2145 rsave = newBitVect(ic->rMask->size);
2146 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2147 if (bitVectBitValue(ic->rMask,i))
2148 rsave = bitVectSetBit(rsave,i);
2150 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2152 /* restore the registers in use at this time but skip the
2153 ones for the result */
2154 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2155 ds390_rUmaskForOp (IC_RESULT(ic)));
2161 /*-----------------------------------------------------------------*/
2163 /*-----------------------------------------------------------------*/
2165 pushSide (operand * oper, int size)
2168 _startLazyDPSEvaluation ();
2171 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, NULL);
2172 if (AOP_TYPE (oper) != AOP_REG &&
2173 AOP_TYPE (oper) != AOP_DIR &&
2176 emitcode ("mov", "a,%s", l);
2177 emitcode ("push", "acc");
2180 emitcode ("push", "%s", l);
2182 _endLazyDPSEvaluation ();
2185 /*-----------------------------------------------------------------*/
2186 /* assignResultValue - */
2187 /*-----------------------------------------------------------------*/
2189 assignResultValue (operand * oper)
2192 int size = AOP_SIZE (oper);
2193 bool pushedAcc = FALSE;
2195 if (size == fReturnSizeDS390)
2197 /* I don't think this case can ever happen... */
2198 /* ACC is the last part of this. If writing the result
2199 * uses AC, we must preserve it.
2201 if (AOP_NEEDSACC(oper))
2203 emitcode(";", "assignResultValue special case for ACC.");
2204 emitcode("push", "acc");
2211 _startLazyDPSEvaluation ();
2214 aopPut (AOP (oper), fReturn[offset], offset);
2217 _endLazyDPSEvaluation ();
2221 emitcode("pop", "acc");
2222 aopPut(AOP(oper), "a", offset);
2227 /*-----------------------------------------------------------------*/
2228 /* genXpush - pushes onto the external stack */
2229 /*-----------------------------------------------------------------*/
2231 genXpush (iCode * ic)
2233 asmop *aop = newAsmop (0);
2235 int size, offset = 0;
2237 D (emitcode (";", "genXpush ");
2240 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2241 r = getFreePtr (ic, &aop, FALSE);
2244 emitcode ("mov", "%s,_spx", r->name);
2246 size = AOP_SIZE (IC_LEFT (ic));
2247 _startLazyDPSEvaluation ();
2251 MOVA (aopGet (AOP (IC_LEFT (ic)),
2252 offset++, FALSE, FALSE, NULL));
2253 emitcode ("movx", "@%s,a", r->name);
2254 emitcode ("inc", "%s", r->name);
2257 _endLazyDPSEvaluation ();
2260 emitcode ("mov", "_spx,%s", r->name);
2262 freeAsmop (NULL, aop, ic, TRUE);
2263 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2266 /*-----------------------------------------------------------------*/
2267 /* genIpush - generate code for pushing this gets a little complex */
2268 /*-----------------------------------------------------------------*/
2270 genIpush (iCode * ic)
2272 int size, offset = 0;
2275 D (emitcode (";", "genIpush ");
2278 /* if this is not a parm push : ie. it is spill push
2279 and spill push is always done on the local stack */
2283 /* and the item is spilt then do nothing */
2284 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2287 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2288 size = AOP_SIZE (IC_LEFT (ic));
2289 /* push it on the stack */
2290 _startLazyDPSEvaluation ();
2293 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2299 emitcode ("push", "%s", l);
2301 _endLazyDPSEvaluation ();
2305 /* this is a paramter push: in this case we call
2306 the routine to find the call and save those
2307 registers that need to be saved */
2310 /* if use external stack then call the external
2311 stack pushing routine */
2312 if (options.useXstack)
2318 /* then do the push */
2319 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2321 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2322 size = AOP_SIZE (IC_LEFT (ic));
2324 _startLazyDPSEvaluation ();
2327 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2328 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2329 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2332 emitcode ("mov", "a,%s", l);
2333 emitcode ("push", "acc");
2337 emitcode ("push", "%s", l);
2340 _endLazyDPSEvaluation ();
2342 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2345 /*-----------------------------------------------------------------*/
2346 /* genIpop - recover the registers: can happen only for spilling */
2347 /*-----------------------------------------------------------------*/
2349 genIpop (iCode * ic)
2353 D (emitcode (";", "genIpop ");
2357 /* if the temp was not pushed then */
2358 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2361 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2362 size = AOP_SIZE (IC_LEFT (ic));
2363 offset = (size - 1);
2364 _startLazyDPSEvaluation ();
2367 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2368 FALSE, TRUE, NULL));
2370 _endLazyDPSEvaluation ();
2372 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2375 /*-----------------------------------------------------------------*/
2376 /* unsaveRBank - restores the resgister bank from stack */
2377 /*-----------------------------------------------------------------*/
2379 unsaveRBank (int bank, iCode * ic, bool popPsw)
2385 if (options.useXstack)
2389 /* Assume r0 is available for use. */
2390 r = ds390_regWithIdx (R0_IDX);;
2395 r = getFreePtr (ic, &aop, FALSE);
2397 emitcode ("mov", "%s,_spx", r->name);
2402 if (options.useXstack)
2404 emitcode ("movx", "a,@%s", r->name);
2405 emitcode ("mov", "psw,a");
2406 emitcode ("dec", "%s", r->name);
2410 emitcode ("pop", "psw");
2414 for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2416 if (options.useXstack)
2418 emitcode ("movx", "a,@%s", r->name);
2419 emitcode ("mov", "(%s+%d),a",
2420 regs390[i].base, 8 * bank + regs390[i].offset);
2421 emitcode ("dec", "%s", r->name);
2425 emitcode ("pop", "(%s+%d)",
2426 regs390[i].base, 8 * bank + regs390[i].offset);
2429 if (options.useXstack)
2431 emitcode ("mov", "_spx,%s", r->name);
2436 freeAsmop (NULL, aop, ic, TRUE);
2440 /*-----------------------------------------------------------------*/
2441 /* saveRBank - saves an entire register bank on the stack */
2442 /*-----------------------------------------------------------------*/
2444 saveRBank (int bank, iCode * ic, bool pushPsw)
2450 if (options.useXstack)
2454 /* Assume r0 is available for use. */
2455 r = ds390_regWithIdx (R0_IDX);;
2460 r = getFreePtr (ic, &aop, FALSE);
2462 emitcode ("mov", "%s,_spx", r->name);
2465 for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2467 if (options.useXstack)
2469 emitcode ("inc", "%s", r->name);
2470 emitcode ("mov", "a,(%s+%d)",
2471 regs390[i].base, 8 * bank + regs390[i].offset);
2472 emitcode ("movx", "@%s,a", r->name);
2475 emitcode ("push", "(%s+%d)",
2476 regs390[i].base, 8 * bank + regs390[i].offset);
2481 if (options.useXstack)
2483 emitcode ("mov", "a,psw");
2484 emitcode ("movx", "@%s,a", r->name);
2485 emitcode ("inc", "%s", r->name);
2486 emitcode ("mov", "_spx,%s", r->name);
2490 emitcode ("push", "psw");
2493 emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2498 freeAsmop (NULL, aop, ic, TRUE);
2507 /*-----------------------------------------------------------------*/
2508 /* genSend - gen code for SEND */
2509 /*-----------------------------------------------------------------*/
2510 static void genSend(set *sendSet)
2514 static int rb1_count = 0;
2516 for (sic = setFirstItem (sendSet); sic;
2517 sic = setNextItem (sendSet)) {
2518 int size, offset = 0;
2520 size=getSize(operandType(IC_LEFT(sic)));
2521 D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2522 if (sendCount == 0) { /* first parameter */
2523 // we know that dpl(hxb) is the result, so
2525 _startLazyDPSEvaluation ();
2527 aopOp (IC_LEFT (sic), sic, FALSE,
2528 (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2530 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2533 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2534 FALSE, FALSE, NULL);
2535 if (strcmp (l, fReturn[offset])) {
2536 emitcode ("mov", "%s,%s",
2542 _endLazyDPSEvaluation ();
2543 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2545 } else { /* if more parameter in registers */
2546 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2548 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
2549 FALSE, FALSE, NULL));
2551 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2558 adjustEsp(const char *reg)
2560 emitcode ("anl","%s,#3", reg);
2561 if (TARGET_IS_DS400)
2563 emitcode ("orl","%s,#!constbyte",
2565 (options.stack_loc >> 8) & 0xff);
2569 /*-----------------------------------------------------------------*/
2570 /* genCall - generates a call statement */
2571 /*-----------------------------------------------------------------*/
2573 genCall (iCode * ic)
2576 bool restoreBank = FALSE;
2577 bool swapBanks = FALSE;
2579 D (emitcode (";", "genCall "););
2581 /* if we are calling a not _naked function that is not using
2582 the same register bank then we need to save the
2583 destination registers on the stack */
2584 dtype = operandType (IC_LEFT (ic));
2585 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2586 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2587 IFFUNC_ISISR (currFunc->type))
2591 /* This is unexpected; the bank should have been saved in
2594 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2600 /* if caller saves & we have not saved then */
2604 /* if send set is not empty the assign */
2605 /* We've saved all the registers we care about;
2606 * therefore, we may clobber any register not used
2607 * in the calling convention (i.e. anything not in
2612 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2613 genSend(reverseSet(_G.sendSet));
2615 genSend(_G.sendSet);
2622 emitcode ("mov", "psw,#!constbyte",
2623 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2627 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2628 OP_SYMBOL (IC_LEFT (ic))->rname :
2629 OP_SYMBOL (IC_LEFT (ic))->name));
2633 emitcode ("mov", "psw,#!constbyte",
2634 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2637 /* if we need assign a result value */
2638 if ((IS_ITEMP (IC_RESULT (ic)) &&
2639 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2640 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2641 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2642 IS_TRUE_SYMOP (IC_RESULT (ic)))
2644 if (isOperandInFarSpace (IC_RESULT (ic))
2645 && getSize (operandType (IC_RESULT (ic))) <= 2)
2647 int size = getSize (operandType (IC_RESULT (ic)));
2649 /* Special case for 1 or 2 byte return in far space. */
2653 emitcode ("mov", "b,%s", fReturn[1]);
2656 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2657 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2661 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2663 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2668 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2671 assignResultValue (IC_RESULT (ic));
2673 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2677 /* adjust the stack for parameters if
2679 if (ic->parmBytes) {
2681 if (options.stack10bit) {
2682 if (ic->parmBytes <= 10) {
2683 emitcode(";","stack adjustment for parms");
2684 for (i=0; i < ic->parmBytes ; i++) {
2685 emitcode("pop","acc");
2689 emitcode ("clr","c");
2690 emitcode ("mov","a,sp");
2691 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2692 emitcode ("mov","sp,a");
2693 emitcode ("mov","a,esp");
2695 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2696 emitcode ("mov","esp,a");
2700 if (ic->parmBytes > 3) {
2701 emitcode ("mov", "a,%s", spname);
2702 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2703 emitcode ("mov", "%s,a", spname);
2705 for (i = 0; i < ic->parmBytes; i++)
2706 emitcode ("dec", "%s", spname);
2710 /* if we hade saved some registers then unsave them */
2712 unsaveRegisters (ic);
2714 /* if register bank was saved then pop them */
2716 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2719 /*-----------------------------------------------------------------*/
2720 /* genPcall - generates a call by pointer statement */
2721 /*-----------------------------------------------------------------*/
2723 genPcall (iCode * ic)
2726 symbol *rlbl = newiTempLabel (NULL);
2727 bool restoreBank=FALSE;
2729 D (emitcode (";", "genPcall ");
2733 /* if caller saves & we have not saved then */
2737 /* if we are calling a function that is not using
2738 the same register bank then we need to save the
2739 destination registers on the stack */
2740 dtype = operandType (IC_LEFT (ic));
2741 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2742 IFFUNC_ISISR (currFunc->type) &&
2743 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2744 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2748 /* push the return address on to the stack */
2749 emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2750 emitcode ("push", "acc");
2751 emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2752 emitcode ("push", "acc");
2754 if (options.model == MODEL_FLAT24)
2756 emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2757 emitcode ("push", "acc");
2760 /* now push the calling address */
2761 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2763 pushSide (IC_LEFT (ic), FPTRSIZE);
2765 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2767 /* if send set is not empty the assign */
2770 genSend(reverseSet(_G.sendSet));
2774 emitcode ("ret", "");
2775 emitcode ("", "!tlabeldef", (rlbl->key + 100));
2778 /* if we need assign a result value */
2779 if ((IS_ITEMP (IC_RESULT (ic)) &&
2780 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2781 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2782 IS_TRUE_SYMOP (IC_RESULT (ic)))
2786 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2789 assignResultValue (IC_RESULT (ic));
2791 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2794 /* adjust the stack for parameters if
2799 if (options.stack10bit) {
2800 if (ic->parmBytes <= 10) {
2801 emitcode(";","stack adjustment for parms");
2802 for (i=0; i < ic->parmBytes ; i++) {
2803 emitcode("pop","acc");
2807 emitcode ("clr","c");
2808 emitcode ("mov","a,sp");
2809 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2810 emitcode ("mov","sp,a");
2811 emitcode ("mov","a,esp");
2813 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2814 emitcode ("mov","esp,a");
2818 if (ic->parmBytes > 3) {
2819 emitcode ("mov", "a,%s", spname);
2820 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2821 emitcode ("mov", "%s,a", spname);
2824 for (i = 0; i < ic->parmBytes; i++)
2825 emitcode ("dec", "%s", spname);
2829 /* if register bank was saved then unsave them */
2831 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2833 /* if we hade saved some registers then
2836 unsaveRegisters (ic);
2840 /*-----------------------------------------------------------------*/
2841 /* resultRemat - result is rematerializable */
2842 /*-----------------------------------------------------------------*/
2844 resultRemat (iCode * ic)
2846 if (SKIP_IC (ic) || ic->op == IFX)
2849 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2851 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2852 if (sym->remat && !POINTER_SET (ic))
2859 #if defined(__BORLANDC__) || defined(_MSC_VER)
2860 #define STRCASECMP stricmp
2862 #define STRCASECMP strcasecmp
2865 /*-----------------------------------------------------------------*/
2866 /* inExcludeList - return 1 if the string is in exclude Reg list */
2867 /*-----------------------------------------------------------------*/
2869 regsCmp(void *p1, void *p2)
2871 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2875 inExcludeList (char *s)
2877 const char *p = setFirstItem(options.excludeRegsSet);
2879 if (p == NULL || STRCASECMP(p, "none") == 0)
2883 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2886 /*-----------------------------------------------------------------*/
2887 /* genFunction - generated code for function entry */
2888 /*-----------------------------------------------------------------*/
2890 genFunction (iCode * ic)
2894 bool switchedPSW = FALSE;
2896 D (emitcode (";", "genFunction "););
2899 /* create the function header */
2900 emitcode (";", "-----------------------------------------");
2901 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2902 emitcode (";", "-----------------------------------------");
2904 emitcode ("", "%s:", sym->rname);
2905 ftype = operandType (IC_LEFT (ic));
2907 if (IFFUNC_ISNAKED(ftype))
2909 emitcode(";", "naked function: no prologue.");
2913 if (options.stack_probe)
2914 emitcode ("lcall","__stack_probe");
2916 /* here we need to generate the equates for the
2917 register bank if required */
2918 if (FUNC_REGBANK (ftype) != rbank)
2922 rbank = FUNC_REGBANK (ftype);
2923 for (i = 0; i < ds390_nRegs; i++)
2925 if (regs390[i].print) {
2926 if (strcmp (regs390[i].base, "0") == 0)
2927 emitcode ("", "%s !equ !constbyte",
2929 8 * rbank + regs390[i].offset);
2931 emitcode ("", "%s !equ %s + !constbyte",
2934 8 * rbank + regs390[i].offset);
2939 /* if this is an interrupt service routine then
2940 save acc, b, dpl, dph */
2941 if (IFFUNC_ISISR (sym->type))
2943 if (!inExcludeList ("acc"))
2944 emitcode ("push", "acc");
2945 if (!inExcludeList ("b"))
2946 emitcode ("push", "b");
2947 if (!inExcludeList ("dpl"))
2948 emitcode ("push", "dpl");
2949 if (!inExcludeList ("dph"))
2950 emitcode ("push", "dph");
2951 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2953 emitcode ("push", "dpx");
2954 /* Make sure we're using standard DPTR */
2955 emitcode ("push", "dps");
2956 emitcode ("mov", "dps,#0");
2957 if (options.stack10bit)
2959 /* This ISR could conceivably use DPTR2. Better save it. */
2960 emitcode ("push", "dpl1");
2961 emitcode ("push", "dph1");
2962 emitcode ("push", "dpx1");
2963 emitcode ("push", DP2_RESULT_REG);
2966 /* if this isr has no bank i.e. is going to
2967 run with bank 0 , then we need to save more
2969 if (!FUNC_REGBANK (sym->type))
2973 /* if this function does not call any other
2974 function then we can be economical and
2975 save only those registers that are used */
2976 if (!IFFUNC_HASFCALL(sym->type))
2979 /* if any registers used */
2982 /* save the registers used */
2983 for (i = 0; i < sym->regsUsed->size; i++)
2985 if (bitVectBitValue (sym->regsUsed, i) ||
2986 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2987 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2994 /* this function has a function call cannot
2995 determines register usage so we will have to push the
2997 saveRBank (0, ic, FALSE);
2998 if (options.parms_in_bank1) {
2999 for (i=0; i < 8 ; i++ ) {
3000 emitcode ("push","%s",rb1regs[i]);
3007 /* This ISR uses a non-zero bank.
3009 * We assume that the bank is available for our
3012 * However, if this ISR calls a function which uses some
3013 * other bank, we must save that bank entirely.
3015 unsigned long banksToSave = 0;
3017 if (IFFUNC_HASFCALL(sym->type))
3020 #define MAX_REGISTER_BANKS 4
3025 for (i = ic; i; i = i->next)
3027 if (i->op == ENDFUNCTION)
3029 /* we got to the end OK. */
3037 dtype = operandType (IC_LEFT(i));
3039 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3041 /* Mark this bank for saving. */
3042 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3044 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3048 banksToSave |= (1 << FUNC_REGBANK(dtype));
3051 /* And note that we don't need to do it in
3059 /* This is a mess; we have no idea what
3060 * register bank the called function might
3063 * The only thing I can think of to do is
3064 * throw a warning and hope.
3066 werror(W_FUNCPTR_IN_USING_ISR);
3070 if (banksToSave && options.useXstack)
3072 /* Since we aren't passing it an ic,
3073 * saveRBank will assume r0 is available to abuse.
3075 * So switch to our (trashable) bank now, so
3076 * the caller's R0 isn't trashed.
3078 emitcode ("push", "psw");
3079 emitcode ("mov", "psw,#!constbyte",
3080 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3084 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3086 if (banksToSave & (1 << ix))
3088 saveRBank(ix, NULL, FALSE);
3092 // TODO: this needs a closer look
3093 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3098 /* if callee-save to be used for this function
3099 then save the registers being used in this function */
3100 if (IFFUNC_CALLEESAVES(sym->type))
3104 /* if any registers used */
3107 /* save the registers used */
3108 for (i = 0; i < sym->regsUsed->size; i++)
3110 if (bitVectBitValue (sym->regsUsed, i) ||
3111 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3113 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3121 /* set the register bank to the desired value */
3122 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3125 emitcode ("push", "psw");
3126 emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3129 if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3130 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3131 if (options.stack10bit) {
3132 emitcode ("push","_bpx");
3133 emitcode ("push","_bpx+1");
3134 emitcode ("mov","_bpx,%s",spname);
3135 emitcode ("mov","_bpx+1,esp");
3136 adjustEsp("_bpx+1");
3138 if (options.useXstack) {
3139 emitcode ("mov", "r0,%s", spname);
3140 emitcode ("mov", "a,_bp");
3141 emitcode ("movx", "@r0,a");
3142 emitcode ("inc", "%s", spname);
3144 /* set up the stack */
3145 emitcode ("push", "_bp"); /* save the callers stack */
3147 emitcode ("mov", "_bp,%s", spname);
3151 /* adjust the stack for the function */
3154 if (options.stack10bit) {
3155 if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
3156 assert (sym->recvSize <= 4);
3157 if (sym->stack <= 8) {
3158 while (i--) emitcode ("push","acc");
3161 emitcode ("mov","a,sp");
3162 emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3163 emitcode ("mov","sp,a");
3164 emitcode ("mov","a,esp");
3166 emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3167 emitcode ("mov","esp,a");
3172 werror (W_STACK_OVERFLOW, sym->name);
3174 if (i > 3 && sym->recvSize < 4) {
3176 emitcode ("mov", "a,sp");
3177 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3178 emitcode ("mov", "sp,a");
3182 emitcode ("inc", "sp");
3189 emitcode ("mov", "a,_spx");
3190 emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3191 emitcode ("mov", "_spx,a");
3194 /* if critical function then turn interrupts off */
3195 if (IFFUNC_ISCRITICAL (ftype))
3197 symbol *tlbl = newiTempLabel (NULL);
3198 emitcode ("setb", "c");
3199 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3200 emitcode ("clr", "c");
3201 emitcode ("", "%05d$:", (tlbl->key + 100));
3202 emitcode ("push", "psw"); /* save old ea via c in psw */
3207 /*-----------------------------------------------------------------*/
3208 /* genEndFunction - generates epilogue for functions */
3209 /*-----------------------------------------------------------------*/
3211 genEndFunction (iCode * ic)
3213 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3215 D (emitcode (";", "genEndFunction "););
3217 if (IFFUNC_ISNAKED(sym->type))
3219 emitcode(";", "naked function: no epilogue.");
3223 if (IFFUNC_ISCRITICAL (sym->type))
3225 emitcode ("pop", "psw"); /* restore ea via c in psw */
3226 emitcode ("mov", "ea,c");
3229 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3230 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3232 if (options.stack10bit) {
3234 emitcode ("mov", "sp,_bpx", spname);
3235 emitcode ("mov", "esp,_bpx+1", spname);
3238 emitcode ("mov", "%s,_bp", spname);
3242 /* if use external stack but some variables were
3243 added to the local stack then decrement the
3245 if (options.useXstack && sym->stack) {
3246 emitcode ("mov", "a,sp");
3247 emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3248 emitcode ("mov", "sp,a");
3252 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3253 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3255 if (options.useXstack) {
3256 emitcode ("mov", "r0,%s", spname);
3257 emitcode ("movx", "a,@r0");
3258 emitcode ("mov", "_bp,a");
3259 emitcode ("dec", "%s", spname);
3261 if (options.stack10bit) {
3262 emitcode ("pop", "_bpx+1");
3263 emitcode ("pop", "_bpx");
3265 emitcode ("pop", "_bp");
3270 /* restore the register bank */
3271 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3273 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3274 || !options.useXstack)
3276 /* Special case of ISR using non-zero bank with useXstack
3279 emitcode ("pop", "psw");
3283 if (IFFUNC_ISISR (sym->type))
3286 /* now we need to restore the registers */
3287 /* if this isr has no bank i.e. is going to
3288 run with bank 0 , then we need to save more
3290 if (!FUNC_REGBANK (sym->type))
3293 /* if this function does not call any other
3294 function then we can be economical and
3295 save only those registers that are used */
3296 if (!IFFUNC_HASFCALL(sym->type))
3299 /* if any registers used */
3302 /* save the registers used */
3303 for (i = sym->regsUsed->size; i >= 0; i--)
3305 if (bitVectBitValue (sym->regsUsed, i) ||
3306 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3307 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3314 /* this function has a function call cannot
3315 determines register usage so we will have to pop the
3317 if (options.parms_in_bank1) {
3318 for (i = 7 ; i >= 0 ; i-- ) {
3319 emitcode ("pop","%s",rb1regs[i]);
3322 unsaveRBank (0, ic, FALSE);
3327 /* This ISR uses a non-zero bank.
3329 * Restore any register banks saved by genFunction
3332 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3335 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3337 if (savedBanks & (1 << ix))
3339 unsaveRBank(ix, NULL, FALSE);
3343 if (options.useXstack)
3345 /* Restore bank AFTER calling unsaveRBank,
3346 * since it can trash r0.
3348 emitcode ("pop", "psw");
3352 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3354 if (options.stack10bit)
3356 emitcode ("pop", DP2_RESULT_REG);
3357 emitcode ("pop", "dpx1");
3358 emitcode ("pop", "dph1");
3359 emitcode ("pop", "dpl1");
3361 emitcode ("pop", "dps");
3362 emitcode ("pop", "dpx");
3364 if (!inExcludeList ("dph"))
3365 emitcode ("pop", "dph");
3366 if (!inExcludeList ("dpl"))
3367 emitcode ("pop", "dpl");
3368 if (!inExcludeList ("b"))
3369 emitcode ("pop", "b");
3370 if (!inExcludeList ("acc"))
3371 emitcode ("pop", "acc");
3373 /* if debug then send end of function */
3374 if (options.debug && currFunc) {
3376 emitcode ("", "C$%s$%d$%d$%d ==.",
3377 FileBaseName (ic->filename), currFunc->lastLine,
3378 ic->level, ic->block);
3379 if (IS_STATIC (currFunc->etype))
3380 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3382 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3386 emitcode ("reti", "");
3390 if (IFFUNC_CALLEESAVES(sym->type))
3394 /* if any registers used */
3397 /* save the registers used */
3398 for (i = sym->regsUsed->size; i >= 0; i--)
3400 if (bitVectBitValue (sym->regsUsed, i) ||
3401 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3402 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3408 /* if debug then send end of function */
3409 if (options.debug && currFunc)
3412 emitcode ("", "C$%s$%d$%d$%d ==.",
3413 FileBaseName (ic->filename), currFunc->lastLine,
3414 ic->level, ic->block);
3415 if (IS_STATIC (currFunc->etype))
3416 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3418 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3422 emitcode ("ret", "");
3427 /*-----------------------------------------------------------------*/
3428 /* genJavaNativeRet - generate code for return JavaNative */
3429 /*-----------------------------------------------------------------*/
3430 static void genJavaNativeRet(iCode *ic)
3434 aopOp (IC_LEFT (ic), ic, FALSE,
3435 AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
3436 size = AOP_SIZE (IC_LEFT (ic));
3440 /* it is assigned to GPR0-R3 then push them */
3441 if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3442 aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3443 for (i = 0 ; i < size ; i++ ) {
3444 emitcode ("push","%s",
3445 aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3447 for (i = (size-1) ; i >= 0 ; i--) {
3448 emitcode ("pop","a%s",javaRet[i]);
3451 for (i = 0 ; i < size ; i++)
3452 emitcode ("mov","%s,%s",javaRet[i],
3453 aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3455 for (i = size ; i < 4 ; i++ )
3456 emitcode ("mov","%s,#0",javaRet[i]);
3460 /*-----------------------------------------------------------------*/
3461 /* genRet - generate code for return statement */
3462 /*-----------------------------------------------------------------*/
3466 int size, offset = 0, pushed = 0;
3468 D (emitcode (";", "genRet "););
3470 /* if we have no return value then
3471 just generate the "ret" */
3475 /* if this is a JavaNative function then return
3476 value in different register */
3477 if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3478 genJavaNativeRet(ic);
3481 /* we have something to return then
3482 move the return value into place */
3483 aopOp (IC_LEFT (ic), ic, FALSE,
3484 (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
3485 size = AOP_SIZE (IC_LEFT (ic));
3487 _startLazyDPSEvaluation ();
3491 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3493 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3495 emitcode ("push", "%s", l);
3500 /* Since A is the last element of fReturn,
3501 * is is OK to clobber it in the aopGet.
3503 l = aopGet (AOP (IC_LEFT (ic)), offset,
3504 FALSE, FALSE, NULL);
3505 if (strcmp (fReturn[offset], l))
3506 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3509 _endLazyDPSEvaluation ();
3516 if (strcmp (fReturn[pushed], "a"))
3517 emitcode ("pop", fReturn[pushed]);
3519 emitcode ("pop", "acc");
3522 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3525 /* generate a jump to the return label
3526 if the next is not the return statement */
3527 if (!(ic->next && ic->next->op == LABEL &&
3528 IC_LABEL (ic->next) == returnLabel))
3530 emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3534 /*-----------------------------------------------------------------*/
3535 /* genLabel - generates a label */
3536 /*-----------------------------------------------------------------*/
3538 genLabel (iCode * ic)
3540 /* special case never generate */
3541 if (IC_LABEL (ic) == entryLabel)
3544 D (emitcode (";", "genLabel ");
3547 emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3550 /*-----------------------------------------------------------------*/
3551 /* genGoto - generates a ljmp */
3552 /*-----------------------------------------------------------------*/
3554 genGoto (iCode * ic)
3556 D (emitcode (";", "genGoto ");
3558 emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3561 /*-----------------------------------------------------------------*/
3562 /* findLabelBackwards: walks back through the iCode chain looking */
3563 /* for the given label. Returns number of iCode instructions */
3564 /* between that label and given ic. */
3565 /* Returns zero if label not found. */
3566 /*-----------------------------------------------------------------*/
3568 findLabelBackwards (iCode * ic, int key)
3577 /* If we have any pushes or pops, we cannot predict the distance.
3578 I don't like this at all, this should be dealt with in the
3580 if (ic->op == IPUSH || ic->op == IPOP) {
3584 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3586 /* printf("findLabelBackwards = %d\n", count); */
3594 /*-----------------------------------------------------------------*/
3595 /* genPlusIncr :- does addition with increment if possible */
3596 /*-----------------------------------------------------------------*/
3598 genPlusIncr (iCode * ic)
3600 unsigned int icount;
3601 unsigned int size = getDataSize (IC_RESULT (ic));
3603 /* will try to generate an increment */
3604 /* if the right side is not a literal
3606 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3609 /* if the literal value of the right hand side
3610 is greater than 4 then it is not worth it */
3611 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3614 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3615 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3617 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
3621 /* if increment 16 bits in register */
3623 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3624 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3625 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3634 /* If the next instruction is a goto and the goto target
3635 * is <= 5 instructions previous to this, we can generate
3636 * jumps straight to that target.
3638 if (ic->next && ic->next->op == GOTO
3639 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3642 D(emitcode (";", "tail increment optimized (range %d)", labelRange););
3643 tlbl = IC_LABEL (ic->next);
3648 tlbl = newiTempLabel (NULL);
3652 l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
3653 emitcode ("inc", "%s", l);
3655 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3656 IS_AOP_PREG (IC_RESULT (ic)))
3658 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3662 emitcode ("clr", "a");
3663 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3666 l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
3667 emitcode ("inc", "%s", l);
3670 if (!strcmp(l, "acc"))
3672 emitcode("jnz", "!tlabel", tlbl->key + 100);
3674 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3675 IS_AOP_PREG (IC_RESULT (ic)))
3677 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3681 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3684 l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
3685 emitcode ("inc", "%s", l);
3689 if (!strcmp(l, "acc"))
3691 emitcode("jnz", "!tlabel", tlbl->key + 100);
3693 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3694 IS_AOP_PREG (IC_RESULT (ic)))
3696 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3700 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3703 l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
3704 emitcode ("inc", "%s", l); }
3708 emitcode ("", "!tlabeldef", tlbl->key + 100);
3713 if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3714 !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 &&
3715 options.model == MODEL_FLAT24 ) {
3719 emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, NULL));
3721 emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, NULL));
3723 emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3726 while (icount--) emitcode ("inc","dptr");
3730 if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3731 AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3733 emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3734 while (icount--) emitcode ("inc","dptr");
3735 emitcode ("mov","dps,#0");
3739 /* if the sizes are greater than 1 then we cannot */
3740 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3741 AOP_SIZE (IC_LEFT (ic)) > 1)
3744 /* we can if the aops of the left & result match or
3745 if they are in registers and the registers are the
3748 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3749 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3750 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3755 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3756 emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3757 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3762 _startLazyDPSEvaluation ();
3765 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3767 _endLazyDPSEvaluation ();
3776 /*-----------------------------------------------------------------*/
3777 /* outBitAcc - output a bit in acc */
3778 /*-----------------------------------------------------------------*/
3780 outBitAcc (operand * result)
3782 symbol *tlbl = newiTempLabel (NULL);
3783 /* if the result is a bit */
3784 if (AOP_TYPE (result) == AOP_CRY)
3786 aopPut (AOP (result), "a", 0);
3790 emitcode ("jz", "!tlabel", tlbl->key + 100);
3791 emitcode ("mov", "a,%s", one);
3792 emitcode ("", "!tlabeldef", tlbl->key + 100);
3797 /*-----------------------------------------------------------------*/
3798 /* genPlusBits - generates code for addition of two bits */
3799 /*-----------------------------------------------------------------*/
3801 genPlusBits (iCode * ic)
3803 D (emitcode (";", "genPlusBits "););
3805 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3807 symbol *lbl = newiTempLabel (NULL);
3808 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3809 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3810 emitcode ("cpl", "c");
3811 emitcode ("", "!tlabeldef", (lbl->key + 100));
3812 outBitC (IC_RESULT (ic));
3816 emitcode ("clr", "a");
3817 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3818 emitcode ("rlc", "a");
3819 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3820 emitcode ("addc", "a,#0");
3821 outAcc (IC_RESULT (ic));
3826 adjustArithmeticResult (iCode * ic)
3828 if (opIsGptr (IC_RESULT (ic)) &&
3829 opIsGptr (IC_LEFT (ic)) &&
3830 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3832 aopPut (AOP (IC_RESULT (ic)),
3833 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3837 if (opIsGptr (IC_RESULT (ic)) &&
3838 opIsGptr (IC_RIGHT (ic)) &&
3839 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3841 aopPut (AOP (IC_RESULT (ic)),
3842 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3846 if (opIsGptr (IC_RESULT (ic)) &&
3847 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3848 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3849 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3850 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3853 SNPRINTF (buff, sizeof(buff),
3854 "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3855 aopPut (AOP (IC_RESULT (ic)), buff, GPTRSIZE - 1);
3859 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
3860 // generates the result if possible. If result is generated, returns TRUE; otherwise
3861 // returns false and caller must deal with fact that result isn't aopOp'd.
3862 bool aopOp3(iCode * ic)
3864 bool dp1InUse, dp2InUse;
3867 // First, generate the right opcode. DPTR may be used if neither left nor result are
3870 // D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
3871 // AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
3872 // AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
3873 // AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
3875 // D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
3876 // AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
3877 // AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
3878 // AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
3881 // Right uses DPTR unless left or result is an AOP_STR; however,
3882 // if right is an AOP_STR, it must use DPTR regardless.
3883 if ((AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)))
3884 && !AOP_IS_STR(IC_RIGHT(ic)))
3893 aopOp (IC_RIGHT(ic),ic,FALSE, useDp2);
3895 // if the right used DPTR, left MUST use DPTR2.
3896 // if the right used DPTR2, left MUST use DPTR.
3897 // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
3898 // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
3899 // enabling us to assign DPTR to result.
3901 if (AOP_USESDPTR(IC_RIGHT(ic)))
3905 else if (AOP_USESDPTR2(IC_RIGHT(ic)))
3911 if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
3921 aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
3923 // We've op'd the left & right. So, if left or right are the same operand as result,
3924 // we know aopOp will succeed, and we can just do it & bail.
3925 if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)) ||
3926 isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
3928 // D(emitcode(";", "aopOp3: (left | right) & result equal"););
3929 aopOp(IC_RESULT(ic),ic,TRUE, FALSE);
3933 // Note which dptrs are currently in use.
3934 dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
3935 dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
3937 // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot
3939 if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
3944 // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
3945 if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
3950 // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck
3951 if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
3956 aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
3958 // Some sanity checking...
3959 if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
3962 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
3963 __FILE__, __LINE__, ic->filename, ic->lineno);
3964 emitcode(";", ">>> unexpected DPTR here.");
3967 if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
3970 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
3971 __FILE__, __LINE__, ic->filename, ic->lineno);
3972 emitcode(";", ">>> unexpected DPTR2 here.");
3978 // Macro to aopOp all three operands of an ic. If this cannot be done,
3979 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3980 // will be set TRUE. The caller must then handle the case specially, noting
3981 // that the IC_RESULT operand is not aopOp'd.
3983 #define AOP_OP_3_NOFATAL(ic, rc) \
3984 do { rc = !aopOp3(ic); } while (0)
3986 // aopOp the left & right operands of an ic.
3987 #define AOP_OP_2(ic) \
3988 aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
3989 aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
3991 // convienience macro.
3992 #define AOP_SET_LOCALS(ic) \
3993 left = IC_LEFT(ic); \
3994 right = IC_RIGHT(ic); \
3995 result = IC_RESULT(ic);
3998 // Given an integer value of pushedSize bytes on the stack,
3999 // adjust it to be resultSize bytes, either by discarding
4000 // the most significant bytes or by zero-padding.
4002 // On exit from this macro, pushedSize will have been adjusted to
4003 // equal resultSize, and ACC may be trashed.
4004 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
4005 /* If the pushed data is bigger than the result, \
4006 * simply discard unused bytes. Icky, but works. \
4008 while (pushedSize > resultSize) \
4010 D (emitcode (";", "discarding unused result byte."););\
4011 emitcode ("pop", "acc"); \
4014 if (pushedSize < resultSize) \
4016 emitcode ("clr", "a"); \
4017 /* Conversly, we haven't pushed enough here. \
4018 * just zero-pad, and all is well. \
4020 while (pushedSize < resultSize) \
4022 emitcode("push", "acc"); \
4026 assert(pushedSize == resultSize);
4028 /*-----------------------------------------------------------------*/
4029 /* genPlus - generates code for addition */
4030 /*-----------------------------------------------------------------*/
4032 genPlus (iCode * ic)
4034 int size, offset = 0;
4038 D (emitcode (";", "genPlus "););
4040 /* special cases :- */
4041 if ( AOP_IS_STR(IC_LEFT(ic)) &&
4042 isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
4043 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
4044 size = (int)floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
4046 while (size--) emitcode ("inc","dptr");
4048 emitcode ("mov","a,dpl");
4049 emitcode ("add","a,#!constbyte",size & 0xff);
4050 emitcode ("mov","dpl,a");
4051 emitcode ("mov","a,dph");
4052 emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
4053 emitcode ("mov","dph,a");
4054 emitcode ("mov","a,dpx");
4055 emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
4056 emitcode ("mov","dpx,a");
4058 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
4061 if ( IS_SYMOP(IC_LEFT(ic)) &&
4062 OP_SYMBOL(IC_LEFT(ic))->remat &&
4063 isOperandInFarSpace(IC_RIGHT(ic))) {
4064 operand *op = IC_RIGHT(ic);
4065 IC_RIGHT(ic) = IC_LEFT(ic);
4069 AOP_OP_3_NOFATAL (ic, pushResult);
4073 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
4078 /* if literal, literal on the right or
4079 if left requires ACC or right is already
4081 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4082 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
4083 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4085 operand *t = IC_RIGHT (ic);
4086 IC_RIGHT (ic) = IC_LEFT (ic);
4088 emitcode (";", "Swapped plus args.");
4091 /* if both left & right are in bit
4093 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4094 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4100 /* if left in bit space & right literal */
4101 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4102 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4104 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4105 /* if result in bit space */
4106 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4108 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4109 emitcode ("cpl", "c");
4110 outBitC (IC_RESULT (ic));
4114 size = getDataSize (IC_RESULT (ic));
4115 _startLazyDPSEvaluation ();
4118 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4119 emitcode ("addc", "a,#0");
4120 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4122 _endLazyDPSEvaluation ();
4127 /* if I can do an increment instead
4128 of add then GOOD for ME */
4129 if (genPlusIncr (ic) == TRUE)
4131 emitcode (";", "did genPlusIncr");
4136 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4138 _startLazyDPSEvaluation ();
4141 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4143 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4145 emitcode ("add", "a,%s",
4146 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4148 emitcode ("addc", "a,%s",
4149 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4153 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4155 /* right is going to use ACC or we would have taken the
4158 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4160 D(emitcode(";", "+ AOP_ACC special case."););
4161 emitcode("xch", "a, %s", DP2_RESULT_REG);
4163 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4166 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4169 emitcode("add", "a, %s", DP2_RESULT_REG);
4173 emitcode ("add", "a,%s",
4174 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE,
4180 emitcode ("addc", "a,%s",
4181 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE,
4187 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4191 emitcode ("push", "acc");
4195 _endLazyDPSEvaluation ();
4199 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4201 size = getDataSize (IC_LEFT (ic));
4202 rSize = getDataSize (IC_RESULT (ic));
4204 ADJUST_PUSHED_RESULT(size, rSize);
4206 _startLazyDPSEvaluation ();
4209 emitcode ("pop", "acc");
4210 aopPut (AOP (IC_RESULT (ic)), "a", size);
4212 _endLazyDPSEvaluation ();
4215 adjustArithmeticResult (ic);
4218 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4219 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4220 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4223 /*-----------------------------------------------------------------*/
4224 /* genMinusDec :- does subtraction with deccrement if possible */
4225 /*-----------------------------------------------------------------*/
4227 genMinusDec (iCode * ic)
4229 unsigned int icount;
4230 unsigned int size = getDataSize (IC_RESULT (ic));
4232 /* will try to generate an increment */
4233 /* if the right side is not a literal
4235 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4238 /* if the literal value of the right hand side
4239 is greater than 4 then it is not worth it */
4240 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4243 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4244 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4246 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
4250 /* if decrement 16 bits in register */
4251 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4252 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4253 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4262 /* If the next instruction is a goto and the goto target
4263 * is <= 5 instructions previous to this, we can generate
4264 * jumps straight to that target.
4266 if (ic->next && ic->next->op == GOTO
4267 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4270 emitcode (";", "tail decrement optimized (range %d)", labelRange);
4271 tlbl = IC_LABEL (ic->next);
4276 tlbl = newiTempLabel (NULL);
4280 l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
4281 emitcode ("dec", "%s", l);
4283 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4284 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4285 IS_AOP_PREG (IC_RESULT (ic)))
4287 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4291 emitcode ("mov", "a,#!constbyte",0xff);
4292 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4294 l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
4295 emitcode ("dec", "%s", l);
4298 if (!strcmp(l, "acc"))
4300 emitcode("jnz", "!tlabel", tlbl->key + 100);
4302 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4303 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4304 IS_AOP_PREG (IC_RESULT (ic)))
4306 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4310 emitcode ("mov", "a,#!constbyte",0xff);
4311 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4313 l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
4314 emitcode ("dec", "%s", l);
4318 if (!strcmp(l, "acc"))
4320 emitcode("jnz", "!tlabel", tlbl->key + 100);
4322 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4323 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4324 IS_AOP_PREG (IC_RESULT (ic)))
4326 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4330 emitcode ("mov", "a,#!constbyte",0xff);
4331 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4333 l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
4334 emitcode ("dec", "%s", l);
4338 emitcode ("", "!tlabeldef", tlbl->key + 100);
4343 /* if the sizes are greater than 1 then we cannot */
4344 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4345 AOP_SIZE (IC_LEFT (ic)) > 1)
4348 /* we can if the aops of the left & result match or
4349 if they are in registers and the registers are the
4352 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4353 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4354 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4357 _startLazyDPSEvaluation ();
4360 emitcode ("dec", "%s",
4361 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
4363 _endLazyDPSEvaluation ();
4371 /*-----------------------------------------------------------------*/
4372 /* addSign - complete with sign */
4373 /*-----------------------------------------------------------------*/
4375 addSign (operand * result, int offset, int sign)
4377 int size = (getDataSize (result) - offset);
4380 _startLazyDPSEvaluation();
4383 emitcode ("rlc", "a");
4384 emitcode ("subb", "a,acc");
4387 aopPut (AOP (result), "a", offset++);
4394 aopPut (AOP (result), zero, offset++);
4397 _endLazyDPSEvaluation();
4401 /*-----------------------------------------------------------------*/
4402 /* genMinusBits - generates code for subtraction of two bits */
4403 /*-----------------------------------------------------------------*/
4405 genMinusBits (iCode * ic)
4407 symbol *lbl = newiTempLabel (NULL);
4409 D (emitcode (";", "genMinusBits "););
4411 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4413 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4414 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4415 emitcode ("cpl", "c");
4416 emitcode ("", "!tlabeldef", (lbl->key + 100));
4417 outBitC (IC_RESULT (ic));
4421 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4422 emitcode ("subb", "a,acc");
4423 emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4424 emitcode ("inc", "a");
4425 emitcode ("", "!tlabeldef", (lbl->key + 100));
4426 aopPut (AOP (IC_RESULT (ic)), "a", 0);
4427 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4431 /*-----------------------------------------------------------------*/
4432 /* genMinus - generates code for subtraction */
4433 /*-----------------------------------------------------------------*/
4435 genMinus (iCode * ic)
4437 int size, offset = 0;
4442 D (emitcode (";", "genMinus "););
4444 AOP_OP_3_NOFATAL(ic, pushResult);
4448 /* special cases :- */
4449 /* if both left & right are in bit space */
4450 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4451 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4457 /* if I can do an decrement instead
4458 of subtract then GOOD for ME */
4459 if (genMinusDec (ic) == TRUE)
4464 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4466 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4472 lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4477 /* if literal, add a,#-lit, else normal subb */
4478 _startLazyDPSEvaluation ();
4480 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4481 if (AOP_USESDPTR(IC_RIGHT(ic))) {
4482 emitcode ("mov","b,%s",
4483 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4484 MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4485 emitcode ("subb","a,b");
4487 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4488 emitcode ("subb", "a,%s",
4489 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE,
4493 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4494 /* first add without previous c */
4496 if (!size && lit==-1) {
4497 emitcode ("dec", "a");
4499 emitcode ("add", "a,#!constbyte",
4500 (unsigned int) (lit & 0x0FFL));
4503 emitcode ("addc", "a,#!constbyte",
4504 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4509 emitcode ("push", "acc");
4511 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4515 _endLazyDPSEvaluation ();
4519 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4521 size = getDataSize (IC_LEFT (ic));
4522 rSize = getDataSize (IC_RESULT (ic));
4524 ADJUST_PUSHED_RESULT(size, rSize);
4526 _startLazyDPSEvaluation ();
4529 emitcode ("pop", "acc");
4530 aopPut (AOP (IC_RESULT (ic)), "a", size);
4532 _endLazyDPSEvaluation ();
4535 adjustArithmeticResult (ic);
4538 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4539 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4540 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4544 /*-----------------------------------------------------------------*/
4545 /* genMultbits :- multiplication of bits */
4546 /*-----------------------------------------------------------------*/
4548 genMultbits (operand * left,
4553 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4554 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4555 aopOp(result, ic, TRUE, FALSE);
4560 /*-----------------------------------------------------------------*/
4561 /* genMultOneByte : 8*8=8/16 bit multiplication */
4562 /*-----------------------------------------------------------------*/
4564 genMultOneByte (operand * left,
4569 sym_link *opetype = operandType (result);
4573 /* (if two literals: the value is computed before) */
4574 /* if one literal, literal on the right */
4575 if (AOP_TYPE (left) == AOP_LIT)
4580 emitcode (";", "swapped left and right");
4583 if (SPEC_USIGN(opetype)
4584 // ignore the sign of left and right, what else can we do?
4585 || (SPEC_USIGN(operandType(left)) &&
4586 SPEC_USIGN(operandType(right)))) {
4587 // just an unsigned 8*8=8/16 multiply
4588 //emitcode (";","unsigned");
4589 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4590 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4591 emitcode ("mul", "ab");
4593 _G.accInUse++; _G.bInUse++;
4594 aopOp(result, ic, TRUE, FALSE);
4596 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4598 // this should never happen
4599 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4600 AOP_SIZE(result), __FILE__, lineno);
4604 aopPut (AOP (result), "a", 0);
4605 _G.accInUse--; _G.bInUse--;
4606 if (AOP_SIZE(result)==2)
4608 aopPut (AOP (result), "b", 1);
4613 // we have to do a signed multiply
4615 emitcode (";", "signed");
4616 emitcode ("clr", "F0"); // reset sign flag
4617 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4619 lbl=newiTempLabel(NULL);
4620 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4621 // left side is negative, 8-bit two's complement, this fails for -128
4622 emitcode ("setb", "F0"); // set sign flag
4623 emitcode ("cpl", "a");
4624 emitcode ("inc", "a");
4626 emitcode ("", "!tlabeldef", lbl->key+100);
4629 if (AOP_TYPE(right)==AOP_LIT) {
4630 signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
4631 /* AND literal negative */
4632 if ((int) val < 0) {
4633 emitcode ("cpl", "F0"); // complement sign flag
4634 emitcode ("mov", "b,#!constbyte", -val);
4636 emitcode ("mov", "b,#!constbyte", val);
4639 lbl=newiTempLabel(NULL);
4640 emitcode ("mov", "b,a");
4641 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4642 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4643 // right side is negative, 8-bit two's complement
4644 emitcode ("cpl", "F0"); // complement sign flag
4645 emitcode ("cpl", "a");
4646 emitcode ("inc", "a");
4647 emitcode ("", "!tlabeldef", lbl->key+100);
4649 emitcode ("mul", "ab");
4651 _G.accInUse++;_G.bInUse++;
4652 aopOp(result, ic, TRUE, FALSE);
4654 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4656 // this should never happen
4657 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4658 AOP_SIZE(result), __FILE__, lineno);
4662 lbl=newiTempLabel(NULL);
4663 emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4664 // only ONE op was negative, we have to do a 8/16-bit two's complement
4665 emitcode ("cpl", "a"); // lsb
4666 if (AOP_SIZE(result)==1) {
4667 emitcode ("inc", "a");
4669 emitcode ("add", "a,#1");
4670 emitcode ("xch", "a,b");
4671 emitcode ("cpl", "a"); // msb
4672 emitcode ("addc", "a,#0");
4673 emitcode ("xch", "a,b");
4676 emitcode ("", "!tlabeldef", lbl->key+100);
4677 aopPut (AOP (result), "a", 0);
4678 _G.accInUse--;_G.bInUse--;
4679 if (AOP_SIZE(result)==2) {
4680 aopPut (AOP (result), "b", 1);
4684 /*-----------------------------------------------------------------*/
4685 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
4686 /*-----------------------------------------------------------------*/
4687 static void genMultTwoByte (operand *left, operand *right,
4688 operand *result, iCode *ic)
4690 sym_link *retype = getSpec(operandType(right));
4691 sym_link *letype = getSpec(operandType(left));
4692 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4695 if (AOP_TYPE (left) == AOP_LIT) {
4700 /* save EA bit in F1 */
4701 lbl = newiTempLabel(NULL);
4702 emitcode ("setb","F1");
4703 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4704 emitcode ("clr","F1");
4705 emitcode("","!tlabeldef",lbl->key+100);
4707 /* load up MB with right */
4709 emitcode("clr","F0");
4710 if (AOP_TYPE(right) == AOP_LIT) {
4711 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
4713 emitcode("setb","F0");
4716 emitcode ("mov","mb,#!constbyte",val & 0xff);
4717 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4719 lbl = newiTempLabel(NULL);
4720 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4721 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4722 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4723 emitcode ("xch", "a,b");
4724 emitcode ("cpl","a");
4725 emitcode ("add", "a,#1");
4726 emitcode ("xch", "a,b");
4727 emitcode ("cpl", "a"); // msb
4728 emitcode ("addc", "a,#0");
4729 emitcode ("setb","F0");
4730 emitcode ("","!tlabeldef",lbl->key+100);
4731 emitcode ("mov","mb,b");
4732 emitcode ("mov","mb,a");
4735 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4736 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4738 /* load up MA with left */
4740 lbl = newiTempLabel(NULL);
4741 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4742 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4743 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4744 emitcode ("xch", "a,b");
4745 emitcode ("cpl","a");
4746 emitcode ("add", "a,#1");
4747 emitcode ("xch", "a,b");
4748 emitcode ("cpl", "a"); // msb
4749 emitcode ("addc","a,#0");
4750 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4751 emitcode ("setb","F0");
4752 emitcode ("","!tlabeldef",lbl->key+100);
4753 emitcode ("mov","ma,b");
4754 emitcode ("mov","ma,a");
4756 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4757 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4759 /* wait for multiplication to finish */
4760 lbl = newiTempLabel(NULL);
4761 emitcode("","!tlabeldef", lbl->key+100);
4762 emitcode("mov","a,mcnt1");
4763 emitcode("anl","a,#!constbyte",0x80);
4764 emitcode("jnz","!tlabel",lbl->key+100);
4766 freeAsmop (left, NULL, ic, TRUE);
4767 freeAsmop (right, NULL, ic,TRUE);
4768 aopOp(result, ic, TRUE, FALSE);
4770 /* if unsigned then simple */
4772 emitcode ("mov","a,ma");
4773 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4774 emitcode ("mov","a,ma");
4775 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4776 aopPut(AOP(result),"ma",1);
4777 aopPut(AOP(result),"ma",0);
4779 emitcode("push","ma");
4780 emitcode("push","ma");
4781 emitcode("push","ma");
4783 /* negate result if needed */
4784 lbl = newiTempLabel(NULL);
4785 emitcode("jnb","F0,!tlabel",lbl->key+100);
4786 emitcode("cpl","a");
4787 emitcode("add","a,#1");
4788 emitcode("","!tlabeldef", lbl->key+100);
4789 if (AOP_TYPE(result) == AOP_ACC)
4791 D(emitcode(";", "ACC special case."););
4792 /* We know result is the only live aop, and
4793 * it's obviously not a DPTR2, so AP is available.
4795 emitcode("mov", "%s,acc", DP2_RESULT_REG);
4799 aopPut(AOP(result),"a",0);
4802 emitcode("pop","acc");
4803 lbl = newiTempLabel(NULL);
4804 emitcode("jnb","F0,!tlabel",lbl->key+100);
4805 emitcode("cpl","a");
4806 emitcode("addc","a,#0");
4807 emitcode("","!tlabeldef", lbl->key+100);
4808 aopPut(AOP(result),"a",1);
4809 emitcode("pop","acc");
4810 if (AOP_SIZE(result) >= 3) {
4811 lbl = newiTempLabel(NULL);
4812 emitcode("jnb","F0,!tlabel",lbl->key+100);
4813 emitcode("cpl","a");
4814 emitcode("addc","a,#0");
4815 emitcode("","!tlabeldef", lbl->key+100);
4816 aopPut(AOP(result),"a",2);
4818 emitcode("pop","acc");
4819 if (AOP_SIZE(result) >= 4) {
4820 lbl = newiTempLabel(NULL);
4821 emitcode("jnb","F0,!tlabel",lbl->key+100);
4822 emitcode("cpl","a");
4823 emitcode("addc","a,#0");
4824 emitcode("","!tlabeldef", lbl->key+100);
4825 aopPut(AOP(result),"a",3);
4827 if (AOP_TYPE(result) == AOP_ACC)
4829 /* We stashed the result away above. */
4830 emitcode("mov", "acc,%s", DP2_RESULT_REG);
4834 freeAsmop (result, NULL, ic, TRUE);
4836 /* restore EA bit in F1 */
4837 lbl = newiTempLabel(NULL);
4838 emitcode ("jnb","F1,!tlabel",lbl->key+100);
4839 emitcode ("setb","EA");
4840 emitcode("","!tlabeldef",lbl->key+100);
4844 /*-----------------------------------------------------------------*/
4845 /* genMult - generates code for multiplication */
4846 /*-----------------------------------------------------------------*/
4848 genMult (iCode * ic)
4850 operand *left = IC_LEFT (ic);
4851 operand *right = IC_RIGHT (ic);
4852 operand *result = IC_RESULT (ic);
4854 D (emitcode (";", "genMult "););
4856 /* assign the amsops */
4859 /* special cases first */
4861 if (AOP_TYPE (left) == AOP_CRY &&
4862 AOP_TYPE (right) == AOP_CRY)
4864 genMultbits (left, right, result, ic);
4868 /* if both are of size == 1 */
4869 if (AOP_SIZE (left) == 1 &&
4870 AOP_SIZE (right) == 1)
4872 genMultOneByte (left, right, result, ic);
4876 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4877 /* use the ds390 ARITHMETIC accel UNIT */
4878 genMultTwoByte (left, right, result, ic);
4881 /* should have been converted to function call */
4885 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4886 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4887 freeAsmop (result, NULL, ic, TRUE);
4890 /*-----------------------------------------------------------------*/
4891 /* genDivbits :- division of bits */
4892 /*-----------------------------------------------------------------*/
4894 genDivbits (operand * left,
4902 /* the result must be bit */
4903 LOAD_AB_FOR_DIV (left, right, l);
4904 emitcode ("div", "ab");
4905 emitcode ("rrc", "a");
4906 aopOp(result, ic, TRUE, FALSE);
4908 aopPut (AOP (result), "c", 0);
4911 /*-----------------------------------------------------------------*/
4912 /* genDivOneByte : 8 bit division */
4913 /*-----------------------------------------------------------------*/
4915 genDivOneByte (operand * left,
4920 sym_link *opetype = operandType (result);
4926 /* signed or unsigned */
4927 if (SPEC_USIGN (opetype))
4929 /* unsigned is easy */
4930 LOAD_AB_FOR_DIV (left, right, l);
4931 emitcode ("div", "ab");
4934 aopOp(result, ic, TRUE, FALSE);
4935 aopPut (AOP (result), "a", 0);
4938 size = AOP_SIZE (result) - 1;
4942 aopPut (AOP (result), zero, offset++);
4947 /* signed is a little bit more difficult */
4949 /* save the signs of the operands */
4950 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4951 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4952 emitcode ("push", "acc"); /* save it on the stack */
4954 /* now sign adjust for both left & right */
4955 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4956 lbl = newiTempLabel (NULL);
4957 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4958 emitcode ("cpl", "a");
4959 emitcode ("inc", "a");
4960 emitcode ("", "!tlabeldef", (lbl->key + 100));
4961 emitcode ("mov", "b,a");
4963 /* sign adjust left side */
4964 MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4966 lbl = newiTempLabel (NULL);
4967 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4968 emitcode ("cpl", "a");
4969 emitcode ("inc", "a");
4970 emitcode ("", "!tlabeldef", (lbl->key + 100));
4972 /* now the division */
4973 emitcode ("nop", "; workaround for DS80C390 div bug.");
4974 emitcode ("div", "ab");
4975 /* we are interested in the lower order
4977 emitcode ("mov", "b,a");
4978 lbl = newiTempLabel (NULL);
4979 emitcode ("pop", "acc");
4980 /* if there was an over flow we don't
4981 adjust the sign of the result */
4982 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4983 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4985 emitcode ("clr", "a");
4986 emitcode ("subb", "a,b");
4987 emitcode ("mov", "b,a");
4988 emitcode ("", "!tlabeldef", (lbl->key + 100));
4990 /* now we are done */
4991 _G.accInUse++; _G.bInUse++;
4992 aopOp(result, ic, TRUE, FALSE);
4994 aopPut (AOP (result), "b", 0);
4996 size = AOP_SIZE (result) - 1;
5000 emitcode ("mov", "c,b.7");
5001 emitcode ("subb", "a,acc");
5005 aopPut (AOP (result), "a", offset++);
5007 _G.accInUse--; _G.bInUse--;
5011 /*-----------------------------------------------------------------*/
5012 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
5013 /*-----------------------------------------------------------------*/
5014 static void genDivTwoByte (operand *left, operand *right,
5015 operand *result, iCode *ic)
5017 sym_link *retype = getSpec(operandType(right));
5018 sym_link *letype = getSpec(operandType(left));
5019 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5022 /* save EA bit in F1 */
5023 lbl = newiTempLabel(NULL);
5024 emitcode ("setb","F1");
5025 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5026 emitcode ("clr","F1");
5027 emitcode("","!tlabeldef",lbl->key+100);
5029 /* load up MA with left */
5031 emitcode("clr","F0");
5032 lbl = newiTempLabel(NULL);
5033 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5034 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5035 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5036 emitcode ("xch", "a,b");
5037 emitcode ("cpl","a");
5038 emitcode ("add", "a,#1");
5039 emitcode ("xch", "a,b");
5040 emitcode ("cpl", "a"); // msb
5041 emitcode ("addc","a,#0");
5042 emitcode ("setb","F0");
5043 emitcode ("","!tlabeldef",lbl->key+100);
5044 emitcode ("mov","ma,b");
5045 emitcode ("mov","ma,a");
5047 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5048 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5051 /* load up MB with right */
5053 if (AOP_TYPE(right) == AOP_LIT) {
5054 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5056 lbl = newiTempLabel(NULL);
5057 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5058 emitcode("setb","F0");
5059 emitcode ("","!tlabeldef",lbl->key+100);
5062 emitcode ("mov","mb,#!constbyte",val & 0xff);
5063 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5065 lbl = newiTempLabel(NULL);
5066 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5067 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5068 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5069 emitcode ("xch", "a,b");
5070 emitcode ("cpl","a");
5071 emitcode ("add", "a,#1");
5072 emitcode ("xch", "a,b");
5073 emitcode ("cpl", "a"); // msb
5074 emitcode ("addc", "a,#0");
5075 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5076 emitcode ("setb","F0");
5077 emitcode ("","!tlabeldef",lbl->key+100);
5078 emitcode ("mov","mb,b");
5079 emitcode ("mov","mb,a");
5082 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5083 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5086 /* wait for multiplication to finish */
5087 lbl = newiTempLabel(NULL);
5088 emitcode("","!tlabeldef", lbl->key+100);
5089 emitcode("mov","a,mcnt1");
5090 emitcode("anl","a,#!constbyte",0x80);
5091 emitcode("jnz","!tlabel",lbl->key+100);
5093 freeAsmop (left, NULL, ic, TRUE);
5094 freeAsmop (right, NULL, ic,TRUE);
5095 aopOp(result, ic, TRUE, FALSE);
5097 /* if unsigned then simple */
5099 aopPut(AOP(result),"ma",1);
5100 aopPut(AOP(result),"ma",0);
5102 emitcode("push","ma");
5104 /* negate result if needed */
5105 lbl = newiTempLabel(NULL);
5106 emitcode("jnb","F0,!tlabel",lbl->key+100);
5107 emitcode("cpl","a");
5108 emitcode("add","a,#1");
5109 emitcode("","!tlabeldef", lbl->key+100);
5110 aopPut(AOP(result),"a",0);
5111 emitcode("pop","acc");
5112 lbl = newiTempLabel(NULL);
5113 emitcode("jnb","F0,!tlabel",lbl->key+100);
5114 emitcode("cpl","a");
5115 emitcode("addc","a,#0");
5116 emitcode("","!tlabeldef", lbl->key+100);
5117 aopPut(AOP(result),"a",1);
5119 freeAsmop (result, NULL, ic, TRUE);
5120 /* restore EA bit in F1 */
5121 lbl = newiTempLabel(NULL);
5122 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5123 emitcode ("setb","EA");
5124 emitcode("","!tlabeldef",lbl->key+100);
5128 /*-----------------------------------------------------------------*/
5129 /* genDiv - generates code for division */
5130 /*-----------------------------------------------------------------*/
5134 operand *left = IC_LEFT (ic);
5135 operand *right = IC_RIGHT (ic);
5136 operand *result = IC_RESULT (ic);
5138 D (emitcode (";", "genDiv "););
5140 /* assign the amsops */
5143 /* special cases first */
5145 if (AOP_TYPE (left) == AOP_CRY &&
5146 AOP_TYPE (right) == AOP_CRY)
5148 genDivbits (left, right, result, ic);
5152 /* if both are of size == 1 */
5153 if (AOP_SIZE (left) == 1 &&
5154 AOP_SIZE (right) == 1)
5156 genDivOneByte (left, right, result, ic);
5160 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5161 /* use the ds390 ARITHMETIC accel UNIT */
5162 genDivTwoByte (left, right, result, ic);
5165 /* should have been converted to function call */
5168 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5169 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5170 freeAsmop (result, NULL, ic, TRUE);
5173 /*-----------------------------------------------------------------*/
5174 /* genModbits :- modulus of bits */
5175 /*-----------------------------------------------------------------*/
5177 genModbits (operand * left,
5185 /* the result must be bit */
5186 LOAD_AB_FOR_DIV (left, right, l);
5187 emitcode ("div", "ab");
5188 emitcode ("mov", "a,b");
5189 emitcode ("rrc", "a");
5190 aopOp(result, ic, TRUE, FALSE);
5191 aopPut (AOP (result), "c", 0);
5194 /*-----------------------------------------------------------------*/
5195 /* genModOneByte : 8 bit modulus */
5196 /*-----------------------------------------------------------------*/
5198 genModOneByte (operand * left,
5203 sym_link *opetype = operandType (result);
5207 /* signed or unsigned */
5208 if (SPEC_USIGN (opetype))
5210 /* unsigned is easy */
5211 LOAD_AB_FOR_DIV (left, right, l);
5212 emitcode ("div", "ab");
5213 aopOp(result, ic, TRUE, FALSE);
5214 aopPut (AOP (result), "b", 0);
5218 /* signed is a little bit more difficult */
5220 /* save the signs of the operands */
5221 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5223 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
5224 emitcode ("push", "acc"); /* save it on the stack */
5226 /* now sign adjust for both left & right */
5227 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5229 lbl = newiTempLabel (NULL);
5230 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5231 emitcode ("cpl", "a");
5232 emitcode ("inc", "a");
5233 emitcode ("", "!tlabeldef", (lbl->key + 100));
5234 emitcode ("mov", "b,a");
5236 /* sign adjust left side */
5237 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5239 lbl = newiTempLabel (NULL);
5240 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5241 emitcode ("cpl", "a");
5242 emitcode ("inc", "a");
5243 emitcode ("", "!tlabeldef", (lbl->key + 100));
5245 /* now the multiplication */
5246 emitcode ("nop", "; workaround for DS80C390 div bug.");
5247 emitcode ("div", "ab");
5248 /* we are interested in the lower order
5250 lbl = newiTempLabel (NULL);
5251 emitcode ("pop", "acc");
5252 /* if there was an over flow we don't
5253 adjust the sign of the result */
5254 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
5255 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5257 emitcode ("clr", "a");
5258 emitcode ("subb", "a,b");
5259 emitcode ("mov", "b,a");
5260 emitcode ("", "!tlabeldef", (lbl->key + 100));
5263 /* now we are done */
5264 aopOp(result, ic, TRUE, FALSE);
5265 aopPut (AOP (result), "b", 0);
5270 /*-----------------------------------------------------------------*/
5271 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
5272 /*-----------------------------------------------------------------*/
5273 static void genModTwoByte (operand *left, operand *right,
5274 operand *result, iCode *ic)
5276 sym_link *retype = getSpec(operandType(right));
5277 sym_link *letype = getSpec(operandType(left));
5278 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5281 /* load up MA with left */
5282 /* save EA bit in F1 */
5283 lbl = newiTempLabel(NULL);
5284 emitcode ("setb","F1");
5285 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5286 emitcode ("clr","F1");
5287 emitcode("","!tlabeldef",lbl->key+100);
5290 lbl = newiTempLabel(NULL);
5291 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5292 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5293 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5294 emitcode ("xch", "a,b");
5295 emitcode ("cpl","a");
5296 emitcode ("add", "a,#1");
5297 emitcode ("xch", "a,b");
5298 emitcode ("cpl", "a"); // msb
5299 emitcode ("addc","a,#0");
5300 emitcode ("","!tlabeldef",lbl->key+100);
5301 emitcode ("mov","ma,b");
5302 emitcode ("mov","ma,a");
5304 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5305 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5308 /* load up MB with right */
5310 if (AOP_TYPE(right) == AOP_LIT) {
5311 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5315 emitcode ("mov","mb,#!constbyte",val & 0xff);
5316 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5318 lbl = newiTempLabel(NULL);
5319 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5320 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5321 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5322 emitcode ("xch", "a,b");
5323 emitcode ("cpl","a");
5324 emitcode ("add", "a,#1");
5325 emitcode ("xch", "a,b");
5326 emitcode ("cpl", "a"); // msb
5327 emitcode ("addc", "a,#0");
5328 emitcode ("","!tlabeldef",lbl->key+100);
5329 emitcode ("mov","mb,b");
5330 emitcode ("mov","mb,a");
5333 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5334 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5337 /* wait for multiplication to finish */
5338 lbl = newiTempLabel(NULL);
5339 emitcode("","!tlabeldef", lbl->key+100);
5340 emitcode("mov","a,mcnt1");
5341 emitcode("anl","a,#!constbyte",0x80);
5342 emitcode("jnz","!tlabel",lbl->key+100);
5344 freeAsmop (left, NULL, ic, TRUE);
5345 freeAsmop (right, NULL, ic,TRUE);
5346 aopOp(result, ic, TRUE, FALSE);
5348 aopPut(AOP(result),"mb",1);
5349 aopPut(AOP(result),"mb",0);
5350 freeAsmop (result, NULL, ic, TRUE);
5352 /* restore EA bit in F1 */
5353 lbl = newiTempLabel(NULL);
5354 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5355 emitcode ("setb","EA");
5356 emitcode("","!tlabeldef",lbl->key+100);
5360 /*-----------------------------------------------------------------*/
5361 /* genMod - generates code for division */
5362 /*-----------------------------------------------------------------*/
5366 operand *left = IC_LEFT (ic);
5367 operand *right = IC_RIGHT (ic);
5368 operand *result = IC_RESULT (ic);
5370 D (emitcode (";", "genMod "); );
5372 /* assign the amsops */
5375 /* special cases first */
5377 if (AOP_TYPE (left) == AOP_CRY &&
5378 AOP_TYPE (right) == AOP_CRY)
5380 genModbits (left, right, result, ic);
5384 /* if both are of size == 1 */
5385 if (AOP_SIZE (left) == 1 &&
5386 AOP_SIZE (right) == 1)
5388 genModOneByte (left, right, result, ic);
5392 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5393 /* use the ds390 ARITHMETIC accel UNIT */
5394 genModTwoByte (left, right, result, ic);
5398 /* should have been converted to function call */
5402 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5403 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5404 freeAsmop (result, NULL, ic, TRUE);
5407 /*-----------------------------------------------------------------*/
5408 /* genIfxJump :- will create a jump depending on the ifx */
5409 /*-----------------------------------------------------------------*/
5411 genIfxJump (iCode * ic, char *jval)
5414 symbol *tlbl = newiTempLabel (NULL);
5417 D (emitcode (";", "genIfxJump"););
5419 /* if true label then we jump if condition
5423 jlbl = IC_TRUE (ic);
5424 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5425 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5429 /* false label is present */
5430 jlbl = IC_FALSE (ic);
5431 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5432 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5434 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5435 emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5437 emitcode (inst, "!tlabel", tlbl->key + 100);
5438 emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5439 emitcode ("", "!tlabeldef", tlbl->key + 100);
5441 /* mark the icode as generated */
5445 /*-----------------------------------------------------------------*/
5446 /* genCmp :- greater or less than comparison */
5447 /*-----------------------------------------------------------------*/
5449 genCmp (operand * left, operand * right,
5450 iCode * ic, iCode * ifx, int sign)
5452 int size, offset = 0;
5453 unsigned long lit = 0L;
5456 D (emitcode (";", "genCmp"););
5458 result = IC_RESULT (ic);
5460 /* if left & right are bit variables */
5461 if (AOP_TYPE (left) == AOP_CRY &&
5462 AOP_TYPE (right) == AOP_CRY)
5464 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5465 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5469 /* subtract right from left if at the
5470 end the carry flag is set then we know that
5471 left is greater than right */
5472 size = max (AOP_SIZE (left), AOP_SIZE (right));
5474 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5475 if ((size == 1) && !sign
5476 && (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5478 symbol *lbl = newiTempLabel (NULL);
5479 emitcode ("cjne", "%s,%s,!tlabel",
5480 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
5481 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5483 emitcode ("", "!tlabeldef", lbl->key + 100);
5487 if (AOP_TYPE (right) == AOP_LIT)
5489 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5490 /* optimize if(x < 0) or if(x >= 0) */
5499 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
5501 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5502 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5504 aopOp (result, ic, FALSE, FALSE);
5506 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5508 freeAsmop (result, NULL, ic, TRUE);
5509 genIfxJump (ifx, "acc.7");
5514 emitcode ("rlc", "a");
5516 goto release_freedLR;
5524 // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5525 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5526 // emitcode (";", "genCmp #2");
5527 if (sign && (size == 0))
5529 // emitcode (";", "genCmp #3");
5530 emitcode ("xrl", "a,#!constbyte",0x80);
5531 if (AOP_TYPE (right) == AOP_LIT)
5533 unsigned long lit = (unsigned long)
5534 floatFromVal (AOP (right)->aopu.aop_lit);
5535 // emitcode (";", "genCmp #3.1");
5536 emitcode ("subb", "a,#!constbyte",
5537 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5541 // emitcode (";", "genCmp #3.2");
5543 MOVB(aopGet (AOP (right), offset++, FALSE, FALSE, "b"));
5544 saveAccWarn = DEFAULT_ACC_WARNING;
5545 emitcode ("xrl", "b,#!constbyte",0x80);
5546 emitcode ("subb", "a,b");
5553 // emitcode (";", "genCmp #4");
5555 s = aopGet (AOP (right), offset++, FALSE, FALSE, "b");
5556 saveAccWarn = DEFAULT_ACC_WARNING;
5558 emitcode ("subb", "a,%s", s);
5565 /* Don't need the left & right operands any more; do need the result. */
5566 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5567 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5569 aopOp (result, ic, FALSE, FALSE);
5573 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5579 /* if the result is used in the next
5580 ifx conditional branch then generate
5581 code a little differently */
5584 genIfxJump (ifx, "c");
5590 /* leave the result in acc */
5592 freeAsmop (result, NULL, ic, TRUE);
5595 /*-----------------------------------------------------------------*/
5596 /* genCmpGt :- greater than comparison */
5597 /*-----------------------------------------------------------------*/
5599 genCmpGt (iCode * ic, iCode * ifx)
5601 operand *left, *right;
5602 sym_link *letype, *retype;
5605 D (emitcode (";", "genCmpGt ");
5608 left = IC_LEFT (ic);
5609 right = IC_RIGHT (ic);
5611 letype = getSpec (operandType (left));
5612 retype = getSpec (operandType (right));
5613 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5615 /* assign the left & right amsops */
5618 genCmp (right, left, ic, ifx, sign);
5621 /*-----------------------------------------------------------------*/
5622 /* genCmpLt - less than comparisons */
5623 /*-----------------------------------------------------------------*/
5625 genCmpLt (iCode * ic, iCode * ifx)
5627 operand *left, *right;
5628 sym_link *letype, *retype;
5631 D (emitcode (";", "genCmpLt "););
5633 left = IC_LEFT (ic);
5634 right = IC_RIGHT (ic);
5636 letype = getSpec (operandType (left));
5637 retype = getSpec (operandType (right));
5638 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5640 /* assign the left & right amsops */
5643 genCmp (left, right, ic, ifx, sign);
5646 /*-----------------------------------------------------------------*/
5647 /* gencjneshort - compare and jump if not equal */
5648 /*-----------------------------------------------------------------*/
5650 gencjneshort (operand * left, operand * right, symbol * lbl)
5652 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5654 unsigned long lit = 0L;
5656 D (emitcode (";", "gencjneshort");
5659 /* if the left side is a literal or
5660 if the right is in a pointer register and left
5662 if ((AOP_TYPE (left) == AOP_LIT) ||
5663 (AOP_TYPE (left) == AOP_IMMD) ||
5664 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5671 if (AOP_TYPE (right) == AOP_LIT)
5672 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5674 if (opIsGptr (left) || opIsGptr (right))
5676 /* We are comparing a generic pointer to something.
5677 * Exclude the generic type byte from the comparison.
5680 D (emitcode (";", "cjneshort: generic ptr special case."););
5684 /* if the right side is a literal then anything goes */
5685 if (AOP_TYPE (right) == AOP_LIT &&
5686 AOP_TYPE (left) != AOP_DIR)
5690 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5691 emitcode ("cjne", "a,%s,!tlabel",
5692 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5698 /* if the right side is in a register or in direct space or
5699 if the left is a pointer register & right is not */
5700 else if (AOP_TYPE (right) == AOP_REG ||
5701 AOP_TYPE (right) == AOP_DIR ||
5702 AOP_TYPE (right) == AOP_LIT ||
5703 AOP_TYPE (right) == AOP_IMMD ||
5704 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5705 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5709 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5710 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5711 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5712 emitcode ("jnz", "!tlabel", lbl->key + 100);
5714 emitcode ("cjne", "a,%s,!tlabel",
5715 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
5722 /* right is a pointer reg need both a & b */
5725 MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5726 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
5727 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5733 /*-----------------------------------------------------------------*/
5734 /* gencjne - compare and jump if not equal */
5735 /*-----------------------------------------------------------------*/
5737 gencjne (operand * left, operand * right, symbol * lbl)
5739 symbol *tlbl = newiTempLabel (NULL);
5741 D (emitcode (";", "gencjne");
5744 gencjneshort (left, right, lbl);
5746 emitcode ("mov", "a,%s", one);
5747 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5748 emitcode ("", "!tlabeldef", lbl->key + 100);
5749 emitcode ("clr", "a");
5750 emitcode ("", "!tlabeldef", tlbl->key + 100);
5753 /*-----------------------------------------------------------------*/
5754 /* genCmpEq - generates code for equal to */
5755 /*-----------------------------------------------------------------*/
5757 genCmpEq (iCode * ic, iCode * ifx)
5759 operand *left, *right, *result;
5761 D (emitcode (";", "genCmpEq ");
5765 AOP_SET_LOCALS (ic);
5767 /* if literal, literal on the right or
5768 if the right is in a pointer register and left
5770 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5771 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5773 operand *t = IC_RIGHT (ic);
5774 IC_RIGHT (ic) = IC_LEFT (ic);
5778 if (ifx && /* !AOP_SIZE(result) */
5779 OP_SYMBOL (result) &&
5780 OP_SYMBOL (result)->regType == REG_CND)
5783 /* if they are both bit variables */
5784 if (AOP_TYPE (left) == AOP_CRY &&
5785 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5787 if (AOP_TYPE (right) == AOP_LIT)
5789 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5792 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5793 emitcode ("cpl", "c");
5797 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5801 emitcode ("clr", "c");
5803 /* AOP_TYPE(right) == AOP_CRY */
5807 symbol *lbl = newiTempLabel (NULL);
5808 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5809 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5810 emitcode ("cpl", "c");
5811 emitcode ("", "!tlabeldef", (lbl->key + 100));
5813 /* if true label then we jump if condition
5815 tlbl = newiTempLabel (NULL);
5818 emitcode ("jnc", "!tlabel", tlbl->key + 100);
5819 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5823 emitcode ("jc", "!tlabel", tlbl->key + 100);
5824 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5826 emitcode ("", "!tlabeldef", tlbl->key + 100);
5830 tlbl = newiTempLabel (NULL);
5831 gencjneshort (left, right, tlbl);
5834 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5835 emitcode ("", "!tlabeldef", tlbl->key + 100);
5839 symbol *lbl = newiTempLabel (NULL);
5840 emitcode ("sjmp", "!tlabel", lbl->key + 100);
5841 emitcode ("", "!tlabeldef", tlbl->key + 100);
5842 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5843 emitcode ("", "!tlabeldef", lbl->key + 100);
5846 /* mark the icode as generated */
5849 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5850 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5854 /* if they are both bit variables */
5855 if (AOP_TYPE (left) == AOP_CRY &&
5856 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5858 if (AOP_TYPE (right) == AOP_LIT)
5860 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5863 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5864 emitcode ("cpl", "c");
5868 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5872 emitcode ("clr", "c");
5874 /* AOP_TYPE(right) == AOP_CRY */
5878 symbol *lbl = newiTempLabel (NULL);
5879 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5880 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5881 emitcode ("cpl", "c");
5882 emitcode ("", "!tlabeldef", (lbl->key + 100));
5885 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5886 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5888 aopOp (result, ic, TRUE, FALSE);
5891 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5898 genIfxJump (ifx, "c");
5901 /* if the result is used in an arithmetic operation
5902 then put the result in place */
5907 gencjne (left, right, newiTempLabel (NULL));
5909 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5910 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5912 aopOp (result, ic, TRUE, FALSE);
5914 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5916 aopPut (AOP (result), "a", 0);
5921 genIfxJump (ifx, "a");
5924 /* if the result is used in an arithmetic operation
5925 then put the result in place */
5926 if (AOP_TYPE (result) != AOP_CRY)
5928 /* leave the result in acc */
5932 freeAsmop (result, NULL, ic, TRUE);
5935 /*-----------------------------------------------------------------*/
5936 /* ifxForOp - returns the icode containing the ifx for operand */
5937 /*-----------------------------------------------------------------*/
5939 ifxForOp (operand * op, iCode * ic)
5941 /* if true symbol then needs to be assigned */
5942 if (IS_TRUE_SYMOP (op))
5945 /* if this has register type condition and
5946 the next instruction is ifx with the same operand
5947 and live to of the operand is upto the ifx only then */
5949 ic->next->op == IFX &&
5950 IC_COND (ic->next)->key == op->key &&
5951 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5956 /*-----------------------------------------------------------------*/
5957 /* hasInc - operand is incremented before any other use */
5958 /*-----------------------------------------------------------------*/
5960 hasInc (operand *op, iCode *ic, int osize)
5962 sym_link *type = operandType(op);
5963 sym_link *retype = getSpec (type);
5964 iCode *lic = ic->next;
5967 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5968 if (!IS_SYMOP(op)) return NULL;
5970 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5971 if (IS_AGGREGATE(type->next)) return NULL;
5972 if (osize != (isize = getSize(type->next))) return NULL;
5975 /* if operand of the form op = op + <sizeof *op> */
5976 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5977 isOperandEqual(IC_RESULT(lic),op) &&
5978 isOperandLiteral(IC_RIGHT(lic)) &&
5979 operandLitValue(IC_RIGHT(lic)) == isize) {
5982 /* if the operand used or deffed */
5983 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5986 /* if GOTO or IFX */
5987 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5993 /*-----------------------------------------------------------------*/
5994 /* genAndOp - for && operation */
5995 /*-----------------------------------------------------------------*/
5997 genAndOp (iCode * ic)
5999 operand *left, *right, *result;
6002 D (emitcode (";", "genAndOp "););
6004 /* note here that && operations that are in an
6005 if statement are taken away by backPatchLabels
6006 only those used in arthmetic operations remain */
6008 AOP_SET_LOCALS (ic);
6010 /* if both are bit variables */
6011 if (AOP_TYPE (left) == AOP_CRY &&
6012 AOP_TYPE (right) == AOP_CRY)
6014 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6015 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6016 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6017 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6019 aopOp (result,ic,FALSE, FALSE);
6024 tlbl = newiTempLabel (NULL);
6026 emitcode ("jz", "!tlabel", tlbl->key + 100);
6028 emitcode ("", "!tlabeldef", tlbl->key + 100);
6029 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6030 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6032 aopOp (result,ic,FALSE, FALSE);
6035 freeAsmop (result, NULL, ic, TRUE);
6039 /*-----------------------------------------------------------------*/
6040 /* genOrOp - for || operation */
6041 /*-----------------------------------------------------------------*/
6043 genOrOp (iCode * ic)
6045 operand *left, *right, *result;
6048 D (emitcode (";", "genOrOp "););
6050 /* note here that || operations that are in an
6051 if statement are taken away by backPatchLabels
6052 only those used in arthmetic operations remain */
6054 AOP_SET_LOCALS (ic);
6056 /* if both are bit variables */
6057 if (AOP_TYPE (left) == AOP_CRY &&
6058 AOP_TYPE (right) == AOP_CRY)
6060 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6061 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6062 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6063 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6065 aopOp (result,ic,FALSE, FALSE);
6071 tlbl = newiTempLabel (NULL);
6073 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6075 emitcode ("", "!tlabeldef", tlbl->key + 100);
6076 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6077 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6079 aopOp (result,ic,FALSE, FALSE);
6084 freeAsmop (result, NULL, ic, TRUE);
6087 /*-----------------------------------------------------------------*/
6088 /* isLiteralBit - test if lit == 2^n */
6089 /*-----------------------------------------------------------------*/
6091 isLiteralBit (unsigned long lit)
6093 unsigned long pw[32] =
6094 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6095 0x100L, 0x200L, 0x400L, 0x800L,
6096 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6097 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6098 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6099 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6100 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6103 for (idx = 0; idx < 32; idx++)
6109 /*-----------------------------------------------------------------*/
6110 /* continueIfTrue - */
6111 /*-----------------------------------------------------------------*/
6113 continueIfTrue (iCode * ic)
6116 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6120 /*-----------------------------------------------------------------*/
6122 /*-----------------------------------------------------------------*/
6124 jumpIfTrue (iCode * ic)
6127 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6131 /*-----------------------------------------------------------------*/
6132 /* jmpTrueOrFalse - */
6133 /*-----------------------------------------------------------------*/
6135 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6137 // ugly but optimized by peephole
6140 symbol *nlbl = newiTempLabel (NULL);
6141 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6142 emitcode ("", "!tlabeldef", tlbl->key + 100);
6143 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6144 emitcode ("", "!tlabeldef", nlbl->key + 100);
6148 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6149 emitcode ("", "!tlabeldef", tlbl->key + 100);
6154 // Generate code to perform a bit-wise logic operation
6155 // on two operands in far space (assumed to already have been
6156 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6157 // in far space. This requires pushing the result on the stack
6158 // then popping it into the result.
6160 genFarFarLogicOp(iCode *ic, char *logicOp)
6162 int size, resultSize, compSize;
6166 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6167 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
6168 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6170 _startLazyDPSEvaluation();
6171 for (size = compSize; (size--); offset++)
6173 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6174 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6175 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6177 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6178 emitcode ("push", "acc");
6180 _endLazyDPSEvaluation();
6182 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6183 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6184 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6186 resultSize = AOP_SIZE(IC_RESULT(ic));
6188 ADJUST_PUSHED_RESULT(compSize, resultSize);
6190 _startLazyDPSEvaluation();
6193 emitcode ("pop", "acc");
6194 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6196 _endLazyDPSEvaluation();
6197 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6201 /*-----------------------------------------------------------------*/
6202 /* genAnd - code for and */
6203 /*-----------------------------------------------------------------*/
6205 genAnd (iCode * ic, iCode * ifx)
6207 operand *left, *right, *result;
6208 int size, offset = 0;
6209 unsigned long lit = 0L;
6214 D (emitcode (";", "genAnd "););
6216 AOP_OP_3_NOFATAL (ic, pushResult);
6217 AOP_SET_LOCALS (ic);
6221 genFarFarLogicOp(ic, "anl");
6226 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6228 AOP_TYPE (left), AOP_TYPE (right));
6229 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6231 AOP_SIZE (left), AOP_SIZE (right));
6234 /* if left is a literal & right is not then exchange them */
6235 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6236 #ifdef LOGIC_OPS_BROKEN
6237 || AOP_NEEDSACC (left)
6241 operand *tmp = right;
6246 /* if result = right then exchange them */
6247 if (sameRegs (AOP (result), AOP (right)))
6249 operand *tmp = right;
6254 /* if right is bit then exchange them */
6255 if (AOP_TYPE (right) == AOP_CRY &&
6256 AOP_TYPE (left) != AOP_CRY)
6258 operand *tmp = right;
6262 if (AOP_TYPE (right) == AOP_LIT)
6263 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6265 size = AOP_SIZE (result);
6268 // result = bit & yy;
6269 if (AOP_TYPE (left) == AOP_CRY)
6271 // c = bit & literal;
6272 if (AOP_TYPE (right) == AOP_LIT)
6276 if (size && sameRegs (AOP (result), AOP (left)))
6279 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6284 if (size && (AOP_TYPE (result) == AOP_CRY))
6286 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6289 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6294 emitcode ("clr", "c");
6299 if (AOP_TYPE (right) == AOP_CRY)
6302 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6303 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6308 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6310 emitcode ("rrc", "a");
6311 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6319 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6320 genIfxJump (ifx, "c");
6324 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6325 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6326 if ((AOP_TYPE (right) == AOP_LIT) &&
6327 (AOP_TYPE (result) == AOP_CRY) &&
6328 (AOP_TYPE (left) != AOP_CRY))
6330 int posbit = isLiteralBit (lit);
6335 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6338 emitcode ("mov", "c,acc.%d", posbit & 0x07);
6344 SNPRINTF (buff, sizeof(buff),
6345 "acc.%d", posbit & 0x07);
6346 genIfxJump (ifx, buff);
6350 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6357 symbol *tlbl = newiTempLabel (NULL);
6358 int sizel = AOP_SIZE (left);
6360 emitcode ("setb", "c");
6363 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6365 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6367 if ((posbit = isLiteralBit (bytelit)) != 0)
6368 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6371 if (bytelit != 0x0FFL)
6372 emitcode ("anl", "a,%s",
6373 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6374 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6379 // bit = left & literal
6382 emitcode ("clr", "c");
6383 emitcode ("", "!tlabeldef", tlbl->key + 100);
6385 // if(left & literal)
6389 jmpTrueOrFalse (ifx, tlbl);
6391 emitcode ("", "!tlabeldef", tlbl->key + 100);
6399 /* if left is same as result */
6400 if (sameRegs (AOP (result), AOP (left)))
6402 for (; size--; offset++)
6404 if (AOP_TYPE (right) == AOP_LIT)
6406 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6408 else if (bytelit == 0)
6409 aopPut (AOP (result), zero, offset);
6410 else if (IS_AOP_PREG (result))
6412 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6413 emitcode ("anl", "a,%s",
6414 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6415 aopPut (AOP (result), "a", offset);
6418 emitcode ("anl", "%s,%s",
6419 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6420 aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6424 if (AOP_TYPE (left) == AOP_ACC)
6425 emitcode ("anl", "a,%s",
6426 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6429 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6430 if (IS_AOP_PREG (result))
6432 emitcode ("anl", "a,%s",
6433 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6434 aopPut (AOP (result), "a", offset);
6437 emitcode ("anl", "%s,a",
6438 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6445 // left & result in different registers
6446 if (AOP_TYPE (result) == AOP_CRY)
6449 // if(size), result in bit
6450 // if(!size && ifx), conditional oper: if(left & right)
6451 symbol *tlbl = newiTempLabel (NULL);
6452 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6454 emitcode ("setb", "c");
6457 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6458 emitcode ("anl", "a,%s",
6459 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6461 if (AOP_TYPE(left)==AOP_ACC) {
6462 emitcode("mov", "b,a");
6463 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6464 emitcode("anl", "a,b");
6466 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6467 emitcode ("anl", "a,%s",
6468 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6471 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6477 emitcode ("", "!tlabeldef", tlbl->key + 100);
6481 jmpTrueOrFalse (ifx, tlbl);
6483 emitcode ("", "!tlabeldef", tlbl->key + 100);
6487 for (; (size--); offset++)
6490 // result = left & right
6491 if (AOP_TYPE (right) == AOP_LIT)
6493 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6495 aopPut (AOP (result),
6496 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6500 else if (bytelit == 0)
6502 aopPut (AOP (result), zero, offset);
6505 D (emitcode (";", "better literal AND."););
6506 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6507 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6508 FALSE, FALSE, DP2_RESULT_REG));
6513 // faster than result <- left, anl result,right
6514 // and better if result is SFR
6515 if (AOP_TYPE (left) == AOP_ACC)
6517 emitcode ("anl", "a,%s",
6518 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6522 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6523 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6525 emitcode("mov", "b,a");
6529 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6530 emitcode ("anl", "a,%s", rOp);
6533 aopPut (AOP (result), "a", offset);
6539 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6540 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6541 freeAsmop (result, NULL, ic, TRUE);
6545 /*-----------------------------------------------------------------*/
6546 /* genOr - code for or */
6547 /*-----------------------------------------------------------------*/
6549 genOr (iCode * ic, iCode * ifx)
6551 operand *left, *right, *result;
6552 int size, offset = 0;
6553 unsigned long lit = 0L;
6556 D (emitcode (";", "genOr "););
6558 AOP_OP_3_NOFATAL (ic, pushResult);
6559 AOP_SET_LOCALS (ic);
6563 genFarFarLogicOp(ic, "orl");
6569 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6571 AOP_TYPE (left), AOP_TYPE (right));
6572 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6574 AOP_SIZE (left), AOP_SIZE (right));
6577 /* if left is a literal & right is not then exchange them */
6578 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6579 #ifdef LOGIC_OPS_BROKEN
6580 || AOP_NEEDSACC (left) // I think this is a net loss now.
6584 operand *tmp = right;
6589 /* if result = right then exchange them */
6590 if (sameRegs (AOP (result), AOP (right)))
6592 operand *tmp = right;
6597 /* if right is bit then exchange them */
6598 if (AOP_TYPE (right) == AOP_CRY &&
6599 AOP_TYPE (left) != AOP_CRY)
6601 operand *tmp = right;
6605 if (AOP_TYPE (right) == AOP_LIT)
6606 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6608 size = AOP_SIZE (result);
6612 if (AOP_TYPE (left) == AOP_CRY)
6614 if (AOP_TYPE (right) == AOP_LIT)
6616 // c = bit & literal;
6619 // lit != 0 => result = 1
6620 if (AOP_TYPE (result) == AOP_CRY)
6623 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6625 continueIfTrue (ifx);
6628 emitcode ("setb", "c");
6632 // lit == 0 => result = left
6633 if (size && sameRegs (AOP (result), AOP (left)))
6635 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6640 if (AOP_TYPE (right) == AOP_CRY)
6643 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6644 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6649 symbol *tlbl = newiTempLabel (NULL);
6650 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6651 emitcode ("setb", "c");
6652 emitcode ("jb", "%s,!tlabel",
6653 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6655 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6656 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6658 jmpTrueOrFalse (ifx, tlbl);
6664 emitcode ("", "!tlabeldef", tlbl->key + 100);
6673 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6674 genIfxJump (ifx, "c");
6678 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6679 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6680 if ((AOP_TYPE (right) == AOP_LIT) &&
6681 (AOP_TYPE (result) == AOP_CRY) &&
6682 (AOP_TYPE (left) != AOP_CRY))
6688 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6690 continueIfTrue (ifx);
6695 // lit = 0, result = boolean(left)
6697 emitcode ("setb", "c");
6701 symbol *tlbl = newiTempLabel (NULL);
6702 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6704 emitcode ("", "!tlabeldef", tlbl->key + 100);
6708 genIfxJump (ifx, "a");
6716 /* if left is same as result */
6717 if (sameRegs (AOP (result), AOP (left)))
6719 for (; size--; offset++)
6721 if (AOP_TYPE (right) == AOP_LIT)
6723 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6729 if (IS_AOP_PREG (left))
6731 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6732 emitcode ("orl", "a,%s",
6733 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6734 aopPut (AOP (result), "a", offset);
6738 emitcode ("orl", "%s,%s",
6739 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6740 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6746 if (AOP_TYPE (left) == AOP_ACC)
6748 emitcode ("orl", "a,%s",
6749 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6753 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6754 if (IS_AOP_PREG (left))
6756 emitcode ("orl", "a,%s",
6757 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6758 aopPut (AOP (result), "a", offset);
6762 emitcode ("orl", "%s,a",
6763 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6771 // left & result in different registers
6772 if (AOP_TYPE (result) == AOP_CRY)
6775 // if(size), result in bit
6776 // if(!size && ifx), conditional oper: if(left | right)
6777 symbol *tlbl = newiTempLabel (NULL);
6778 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6780 emitcode ("setb", "c");
6783 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6784 emitcode ("orl", "a,%s",
6785 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6787 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6788 emitcode ("orl", "a,%s",
6789 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6791 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6797 emitcode ("", "!tlabeldef", tlbl->key + 100);
6801 jmpTrueOrFalse (ifx, tlbl);
6803 emitcode ("", "!tlabeldef", tlbl->key + 100);
6807 _startLazyDPSEvaluation();
6808 for (; (size--); offset++)
6811 // result = left & right
6812 if (AOP_TYPE (right) == AOP_LIT)
6814 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6816 aopPut (AOP (result),
6817 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6821 D (emitcode (";", "better literal OR."););
6822 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6823 emitcode ("orl", "a, %s",
6824 aopGet (AOP (right), offset,
6825 FALSE, FALSE, DP2_RESULT_REG));
6830 // faster than result <- left, anl result,right
6831 // and better if result is SFR
6832 if (AOP_TYPE (left) == AOP_ACC)
6834 emitcode ("orl", "a,%s",
6835 aopGet (AOP (right), offset,
6836 FALSE, FALSE, DP2_RESULT_REG));
6840 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6842 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6844 emitcode("mov", "b,a");
6848 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6849 emitcode ("orl", "a,%s", rOp);
6852 aopPut (AOP (result), "a", offset);
6854 _endLazyDPSEvaluation();
6859 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6860 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6861 freeAsmop (result, NULL, ic, TRUE);
6864 /*-----------------------------------------------------------------*/
6865 /* genXor - code for xclusive or */
6866 /*-----------------------------------------------------------------*/
6868 genXor (iCode * ic, iCode * ifx)
6870 operand *left, *right, *result;
6871 int size, offset = 0;
6872 unsigned long lit = 0L;
6875 D (emitcode (";", "genXor "););
6877 AOP_OP_3_NOFATAL (ic, pushResult);
6878 AOP_SET_LOCALS (ic);
6882 genFarFarLogicOp(ic, "xrl");
6887 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6889 AOP_TYPE (left), AOP_TYPE (right));
6890 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6892 AOP_SIZE (left), AOP_SIZE (right));
6895 /* if left is a literal & right is not ||
6896 if left needs acc & right does not */
6897 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6898 #ifdef LOGIC_OPS_BROKEN
6899 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6903 operand *tmp = right;
6908 /* if result = right then exchange them */
6909 if (sameRegs (AOP (result), AOP (right)))
6911 operand *tmp = right;
6916 /* if right is bit then exchange them */
6917 if (AOP_TYPE (right) == AOP_CRY &&
6918 AOP_TYPE (left) != AOP_CRY)
6920 operand *tmp = right;
6924 if (AOP_TYPE (right) == AOP_LIT)
6925 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6927 size = AOP_SIZE (result);
6931 if (AOP_TYPE (left) == AOP_CRY)
6933 if (AOP_TYPE (right) == AOP_LIT)
6935 // c = bit & literal;
6938 // lit>>1 != 0 => result = 1
6939 if (AOP_TYPE (result) == AOP_CRY)
6942 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6944 continueIfTrue (ifx);
6947 emitcode ("setb", "c");
6954 // lit == 0, result = left
6955 if (size && sameRegs (AOP (result), AOP (left)))
6957 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6961 // lit == 1, result = not(left)
6962 if (size && sameRegs (AOP (result), AOP (left)))
6964 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6969 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6970 emitcode ("cpl", "c");
6979 symbol *tlbl = newiTempLabel (NULL);
6980 if (AOP_TYPE (right) == AOP_CRY)
6983 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6987 int sizer = AOP_SIZE (right);
6989 // if val>>1 != 0, result = 1
6990 emitcode ("setb", "c");
6993 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
6995 // test the msb of the lsb
6996 emitcode ("anl", "a,#!constbyte",0xfe);
6997 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7001 emitcode ("rrc", "a");
7003 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7004 emitcode ("cpl", "c");
7005 emitcode ("", "!tlabeldef", (tlbl->key + 100));
7012 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7013 genIfxJump (ifx, "c");
7017 if (sameRegs (AOP (result), AOP (left)))
7019 /* if left is same as result */
7020 for (; size--; offset++)
7022 if (AOP_TYPE (right) == AOP_LIT)
7024 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7026 else if (IS_AOP_PREG (left))
7028 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7029 emitcode ("xrl", "a,%s",
7030 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7031 aopPut (AOP (result), "a", offset);
7034 emitcode ("xrl", "%s,%s",
7035 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
7036 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7040 if (AOP_TYPE (left) == AOP_ACC)
7041 emitcode ("xrl", "a,%s",
7042 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7045 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7046 if (IS_AOP_PREG (left))
7048 emitcode ("xrl", "a,%s",
7049 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7050 aopPut (AOP (result), "a", offset);
7053 emitcode ("xrl", "%s,a",
7054 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7061 // left & result in different registers
7062 if (AOP_TYPE (result) == AOP_CRY)
7065 // if(size), result in bit
7066 // if(!size && ifx), conditional oper: if(left ^ right)
7067 symbol *tlbl = newiTempLabel (NULL);
7068 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7071 emitcode ("setb", "c");
7074 if ((AOP_TYPE (right) == AOP_LIT) &&
7075 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7077 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7081 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7082 emitcode ("xrl", "a,%s",
7083 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7085 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7086 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7088 emitcode("mov", "b,a");
7092 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7093 emitcode ("xrl", "a,%s", rOp);
7096 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7102 emitcode ("", "!tlabeldef", tlbl->key + 100);
7106 jmpTrueOrFalse (ifx, tlbl);
7110 for (; (size--); offset++)
7113 // result = left & right
7114 if (AOP_TYPE (right) == AOP_LIT)
7116 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7118 aopPut (AOP (result),
7119 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7123 D (emitcode (";", "better literal XOR."););
7124 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7125 emitcode ("xrl", "a, %s",
7126 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7130 // faster than result <- left, anl result,right
7131 // and better if result is SFR
7132 if (AOP_TYPE (left) == AOP_ACC)
7134 emitcode ("xrl", "a,%s",
7135 aopGet (AOP (right), offset,
7136 FALSE, FALSE, DP2_RESULT_REG));
7140 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7141 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7143 emitcode("mov", "b,a");
7147 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7148 emitcode ("xrl", "a,%s", rOp);
7151 aopPut (AOP (result), "a", offset);
7158 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7159 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7160 freeAsmop (result, NULL, ic, TRUE);
7163 /*-----------------------------------------------------------------*/
7164 /* genInline - write the inline code out */
7165 /*-----------------------------------------------------------------*/
7167 genInline (iCode * ic)
7169 char *buffer, *bp, *bp1;
7171 D (emitcode (";", "genInline "); );
7173 _G.inLine += (!options.asmpeep);
7175 buffer = Safe_strdup(IC_INLINE(ic));
7179 /* emit each line as a code */
7204 /* emitcode("",buffer); */
7205 _G.inLine -= (!options.asmpeep);
7208 /*-----------------------------------------------------------------*/
7209 /* genRRC - rotate right with carry */
7210 /*-----------------------------------------------------------------*/
7214 operand *left, *result;
7217 D (emitcode (";", "genRRC "););
7219 /* rotate right with carry */
7220 left = IC_LEFT (ic);
7221 result = IC_RESULT (ic);
7222 aopOp (left, ic, FALSE, FALSE);
7223 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7225 /* move it to the result */
7226 size = AOP_SIZE (result);
7230 _startLazyDPSEvaluation ();
7233 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7234 emitcode ("rrc", "a");
7235 if (AOP_SIZE (result) > 1)
7236 aopPut (AOP (result), "a", offset--);
7238 _endLazyDPSEvaluation ();
7240 /* now we need to put the carry into the
7241 highest order byte of the result */
7242 if (AOP_SIZE (result) > 1)
7244 MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7246 emitcode ("mov", "acc.7,c");
7247 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7248 freeAsmop (left, NULL, ic, TRUE);
7249 freeAsmop (result, NULL, ic, TRUE);
7252 /*-----------------------------------------------------------------*/
7253 /* genRLC - generate code for rotate left with carry */
7254 /*-----------------------------------------------------------------*/
7258 operand *left, *result;
7262 D (emitcode (";", "genRLC "););
7264 /* rotate right with carry */
7265 left = IC_LEFT (ic);
7266 result = IC_RESULT (ic);
7267 aopOp (left, ic, FALSE, FALSE);
7268 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7270 /* move it to the result */
7271 size = AOP_SIZE (result);
7275 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7277 emitcode ("add", "a,acc");
7278 if (AOP_SIZE (result) > 1)
7280 aopPut (AOP (result), "a", offset++);
7283 _startLazyDPSEvaluation ();
7286 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7288 emitcode ("rlc", "a");
7289 if (AOP_SIZE (result) > 1)
7290 aopPut (AOP (result), "a", offset++);
7292 _endLazyDPSEvaluation ();
7294 /* now we need to put the carry into the
7295 highest order byte of the result */
7296 if (AOP_SIZE (result) > 1)
7298 l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7301 emitcode ("mov", "acc.0,c");
7302 aopPut (AOP (result), "a", 0);
7303 freeAsmop (left, NULL, ic, TRUE);
7304 freeAsmop (result, NULL, ic, TRUE);
7307 /*-----------------------------------------------------------------*/
7308 /* genGetHbit - generates code get highest order bit */
7309 /*-----------------------------------------------------------------*/
7311 genGetHbit (iCode * ic)
7313 operand *left, *result;
7314 left = IC_LEFT (ic);
7315 result = IC_RESULT (ic);
7316 aopOp (left, ic, FALSE, FALSE);
7317 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7319 D (emitcode (";", "genGetHbit "););
7321 /* get the highest order byte into a */
7322 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7323 if (AOP_TYPE (result) == AOP_CRY)
7325 emitcode ("rlc", "a");
7330 emitcode ("rl", "a");
7331 emitcode ("anl", "a,#1");
7336 freeAsmop (left, NULL, ic, TRUE);
7337 freeAsmop (result, NULL, ic, TRUE);
7340 /*-----------------------------------------------------------------*/
7341 /* genSwap - generates code to swap nibbles or bytes */
7342 /*-----------------------------------------------------------------*/
7344 genSwap (iCode * ic)
7346 operand *left, *result;
7348 D(emitcode ("; genSwap",""));
7350 left = IC_LEFT (ic);
7351 result = IC_RESULT (ic);
7352 aopOp (left, ic, FALSE, FALSE);
7353 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7355 _startLazyDPSEvaluation ();
7356 switch (AOP_SIZE (left))
7358 case 1: /* swap nibbles in byte */
7359 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7360 emitcode ("swap", "a");
7361 aopPut (AOP (result), "a", 0);
7363 case 2: /* swap bytes in word */
7364 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7366 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7367 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7368 aopPut (AOP (result), "a", 1);
7370 else if (operandsEqu (left, result))
7373 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7374 if (AOP_NEEDSACC (left) || AOP_NEEDSACC (result))
7376 emitcode ("mov", "b,a");
7380 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7381 aopPut (AOP (result), reg, 1);
7386 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7387 aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE, NULL), 1);
7391 wassertl(FALSE, "unsupported SWAP operand size");
7393 _endLazyDPSEvaluation ();
7395 freeAsmop (left, NULL, ic, TRUE);
7396 freeAsmop (result, NULL, ic, TRUE);
7399 /*-----------------------------------------------------------------*/
7400 /* AccRol - rotate left accumulator by known count */
7401 /*-----------------------------------------------------------------*/
7403 AccRol (int shCount)
7405 shCount &= 0x0007; // shCount : 0..7
7412 emitcode ("rl", "a");
7415 emitcode ("rl", "a");
7416 emitcode ("rl", "a");
7419 emitcode ("swap", "a");
7420 emitcode ("rr", "a");
7423 emitcode ("swap", "a");
7426 emitcode ("swap", "a");
7427 emitcode ("rl", "a");
7430 emitcode ("rr", "a");
7431 emitcode ("rr", "a");
7434 emitcode ("rr", "a");
7439 /*-----------------------------------------------------------------*/
7440 /* AccLsh - left shift accumulator by known count */
7441 /*-----------------------------------------------------------------*/
7443 AccLsh (int shCount)
7448 emitcode ("add", "a,acc");
7449 else if (shCount == 2)
7451 emitcode ("add", "a,acc");
7452 emitcode ("add", "a,acc");
7456 /* rotate left accumulator */
7458 /* and kill the lower order bits */
7459 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7464 /*-----------------------------------------------------------------*/
7465 /* AccRsh - right shift accumulator by known count */
7466 /*-----------------------------------------------------------------*/
7468 AccRsh (int shCount)
7475 emitcode ("rrc", "a");
7479 /* rotate right accumulator */
7480 AccRol (8 - shCount);
7481 /* and kill the higher order bits */
7482 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7487 #ifdef BETTER_LITERAL_SHIFT
7488 /*-----------------------------------------------------------------*/
7489 /* AccSRsh - signed right shift accumulator by known count */
7490 /*-----------------------------------------------------------------*/
7492 AccSRsh (int shCount)
7499 emitcode ("mov", "c,acc.7");
7500 emitcode ("rrc", "a");
7502 else if (shCount == 2)
7504 emitcode ("mov", "c,acc.7");
7505 emitcode ("rrc", "a");
7506 emitcode ("mov", "c,acc.7");
7507 emitcode ("rrc", "a");
7511 tlbl = newiTempLabel (NULL);
7512 /* rotate right accumulator */
7513 AccRol (8 - shCount);
7514 /* and kill the higher order bits */
7515 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7516 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7517 emitcode ("orl", "a,#!constbyte",
7518 (unsigned char) ~SRMask[shCount]);
7519 emitcode ("", "!tlabeldef", tlbl->key + 100);
7525 #ifdef BETTER_LITERAL_SHIFT
7526 /*-----------------------------------------------------------------*/
7527 /* shiftR1Left2Result - shift right one byte from left to result */
7528 /*-----------------------------------------------------------------*/
7530 shiftR1Left2Result (operand * left, int offl,
7531 operand * result, int offr,
7532 int shCount, int sign)
7534 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7535 /* shift right accumulator */
7540 aopPut (AOP (result), "a", offr);
7544 #ifdef BETTER_LITERAL_SHIFT
7545 /*-----------------------------------------------------------------*/
7546 /* shiftL1Left2Result - shift left one byte from left to result */
7547 /*-----------------------------------------------------------------*/
7549 shiftL1Left2Result (operand * left, int offl,
7550 operand * result, int offr, int shCount)
7552 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7553 /* shift left accumulator */
7555 aopPut (AOP (result), "a", offr);
7559 #ifdef BETTER_LITERAL_SHIFT
7560 /*-----------------------------------------------------------------*/
7561 /* movLeft2Result - move byte from left to result */
7562 /*-----------------------------------------------------------------*/
7564 movLeft2Result (operand * left, int offl,
7565 operand * result, int offr, int sign)
7568 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7570 l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
7572 if (*l == '@' && (IS_AOP_PREG (result)))
7574 emitcode ("mov", "a,%s", l);
7575 aopPut (AOP (result), "a", offr);
7581 aopPut (AOP (result), l, offr);
7585 /* MSB sign in acc.7 ! */
7586 if (getDataSize (left) == offl + 1)
7588 emitcode ("mov", "a,%s", l);
7589 aopPut (AOP (result), "a", offr);
7597 #ifdef BETTER_LITERAL_SHIFT
7598 /*-----------------------------------------------------------------*/
7599 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7600 /*-----------------------------------------------------------------*/
7604 emitcode ("rrc", "a");
7605 emitcode ("xch", "a,%s", x);
7606 emitcode ("rrc", "a");
7607 emitcode ("xch", "a,%s", x);
7611 #ifdef BETTER_LITERAL_SHIFT
7613 /*-----------------------------------------------------------------*/
7614 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7615 /*-----------------------------------------------------------------*/
7619 emitcode ("xch", "a,%s", x);
7620 emitcode ("rlc", "a");
7621 emitcode ("xch", "a,%s", x);
7622 emitcode ("rlc", "a");
7626 #ifdef BETTER_LITERAL_SHIFT
7627 /*-----------------------------------------------------------------*/
7628 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7629 /*-----------------------------------------------------------------*/
7633 emitcode ("xch", "a,%s", x);
7634 emitcode ("add", "a,acc");
7635 emitcode ("xch", "a,%s", x);
7636 emitcode ("rlc", "a");
7640 #ifdef BETTER_LITERAL_SHIFT
7641 /*-----------------------------------------------------------------*/
7642 /* AccAXLsh - left shift a:x by known count (0..7) */
7643 /*-----------------------------------------------------------------*/
7645 AccAXLsh (char *x, int shCount)
7660 case 5: // AAAAABBB:CCCCCDDD
7662 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7664 emitcode ("anl", "a,#!constbyte",
7665 SLMask[shCount]); // BBB00000:CCCCCDDD
7667 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7669 AccRol (shCount); // DDDCCCCC:BBB00000
7671 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7673 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7675 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7677 emitcode ("anl", "a,#!constbyte",
7678 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7680 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7682 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7685 case 6: // AAAAAABB:CCCCCCDD
7686 emitcode ("anl", "a,#!constbyte",
7687 SRMask[shCount]); // 000000BB:CCCCCCDD
7688 emitcode ("mov", "c,acc.0"); // c = B
7689 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7691 AccAXRrl1 (x); // BCCCCCCD:D000000B
7692 AccAXRrl1 (x); // BBCCCCCC:DD000000
7694 emitcode("rrc","a");
7695 emitcode("xch","a,%s", x);
7696 emitcode("rrc","a");
7697 emitcode("mov","c,acc.0"); //<< get correct bit
7698 emitcode("xch","a,%s", x);
7700 emitcode("rrc","a");
7701 emitcode("xch","a,%s", x);
7702 emitcode("rrc","a");
7703 emitcode("xch","a,%s", x);
7706 case 7: // a:x <<= 7
7708 emitcode ("anl", "a,#!constbyte",
7709 SRMask[shCount]); // 0000000B:CCCCCCCD
7711 emitcode ("mov", "c,acc.0"); // c = B
7713 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7715 AccAXRrl1 (x); // BCCCCCCC:D0000000
7724 #ifdef BETTER_LITERAL_SHIFT
7726 /*-----------------------------------------------------------------*/
7727 /* AccAXRsh - right shift a:x known count (0..7) */
7728 /*-----------------------------------------------------------------*/
7730 AccAXRsh (char *x, int shCount)
7738 AccAXRrl1 (x); // 0->a:x
7743 AccAXRrl1 (x); // 0->a:x
7746 AccAXRrl1 (x); // 0->a:x
7751 case 5: // AAAAABBB:CCCCCDDD = a:x
7753 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7755 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7757 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7759 emitcode ("anl", "a,#!constbyte",
7760 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7762 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7764 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7766 emitcode ("anl", "a,#!constbyte",
7767 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7769 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7771 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7773 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7776 case 6: // AABBBBBB:CCDDDDDD
7778 emitcode ("mov", "c,acc.7");
7779 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7781 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7783 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7785 emitcode ("anl", "a,#!constbyte",
7786 SRMask[shCount]); // 000000AA:BBBBBBCC
7789 case 7: // ABBBBBBB:CDDDDDDD
7791 emitcode ("mov", "c,acc.7"); // c = A
7793 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7795 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7797 emitcode ("anl", "a,#!constbyte",
7798 SRMask[shCount]); // 0000000A:BBBBBBBC
7807 #ifdef BETTER_LITERAL_SHIFT
7808 /*-----------------------------------------------------------------*/
7809 /* AccAXRshS - right shift signed a:x known count (0..7) */
7810 /*-----------------------------------------------------------------*/
7812 AccAXRshS (char *x, int shCount)
7820 emitcode ("mov", "c,acc.7");
7821 AccAXRrl1 (x); // s->a:x
7825 emitcode ("mov", "c,acc.7");
7826 AccAXRrl1 (x); // s->a:x
7828 emitcode ("mov", "c,acc.7");
7829 AccAXRrl1 (x); // s->a:x
7834 case 5: // AAAAABBB:CCCCCDDD = a:x
7836 tlbl = newiTempLabel (NULL);
7837 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7839 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7841 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7843 emitcode ("anl", "a,#!constbyte",
7844 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7846 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7848 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7850 emitcode ("anl", "a,#!constbyte",
7851 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7853 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7855 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7857 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7859 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7860 emitcode ("orl", "a,#!constbyte",
7861 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7863 emitcode ("", "!tlabeldef", tlbl->key + 100);
7864 break; // SSSSAAAA:BBBCCCCC
7866 case 6: // AABBBBBB:CCDDDDDD
7868 tlbl = newiTempLabel (NULL);
7869 emitcode ("mov", "c,acc.7");
7870 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7872 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7874 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7876 emitcode ("anl", "a,#!constbyte",
7877 SRMask[shCount]); // 000000AA:BBBBBBCC
7879 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7880 emitcode ("orl", "a,#!constbyte",
7881 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7883 emitcode ("", "!tlabeldef", tlbl->key + 100);
7885 case 7: // ABBBBBBB:CDDDDDDD
7887 tlbl = newiTempLabel (NULL);
7888 emitcode ("mov", "c,acc.7"); // c = A
7890 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7892 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7894 emitcode ("anl", "a,#!constbyte",
7895 SRMask[shCount]); // 0000000A:BBBBBBBC
7897 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7898 emitcode ("orl", "a,#!constbyte",
7899 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7901 emitcode ("", "!tlabeldef", tlbl->key + 100);
7909 #ifdef BETTER_LITERAL_SHIFT
7911 _loadLeftIntoAx(char **lsb,
7917 // Get the initial value from left into a pair of registers.
7918 // MSB must be in A, LSB can be any register.
7920 // If the result is held in registers, it is an optimization
7921 // if the LSB can be held in the register which will hold the,
7922 // result LSB since this saves us from having to copy it into
7923 // the result following AccAXLsh.
7925 // If the result is addressed indirectly, this is not a gain.
7926 if (AOP_NEEDSACC(result))
7930 _startLazyDPSEvaluation();
7931 if (AOP_TYPE(left) == AOP_DPTR2)
7934 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
7935 // get LSB in DP2_RESULT_REG.
7936 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
7937 assert(!strcmp(leftByte, DP2_RESULT_REG));
7941 // get LSB into DP2_RESULT_REG
7942 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
7943 if (strcmp(leftByte, DP2_RESULT_REG))
7946 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7949 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
7950 assert(strcmp(leftByte, DP2_RESULT_REG));
7953 _endLazyDPSEvaluation();
7954 *lsb = DP2_RESULT_REG;
7958 if (sameRegs (AOP (result), AOP (left)) &&
7959 ((offl + MSB16) == offr))
7961 /* don't crash result[offr] */
7962 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
7963 emitcode ("xch", "a,%s",
7964 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
7968 movLeft2Result (left, offl, result, offr, 0);
7969 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
7971 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
7972 assert(strcmp(*lsb,"a"));
7977 _storeAxResults(char *lsb,
7981 _startLazyDPSEvaluation();
7982 if (AOP_NEEDSACC(result))
7984 /* We have to explicitly update the result LSB.
7986 emitcode("xch","a,%s", lsb);
7987 aopPut(AOP(result), "a", offr);
7988 emitcode("mov","a,%s", lsb);
7990 if (getDataSize (result) > 1)
7992 aopPut (AOP (result), "a", offr + MSB16);
7994 _endLazyDPSEvaluation();
7997 /*-----------------------------------------------------------------*/
7998 /* shiftL2Left2Result - shift left two bytes from left to result */
7999 /*-----------------------------------------------------------------*/
8001 shiftL2Left2Result (operand * left, int offl,
8002 operand * result, int offr, int shCount)
8006 _loadLeftIntoAx(&lsb, left, result, offl, offr);
8008 AccAXLsh (lsb, shCount);
8010 _storeAxResults(lsb, result, offr);
8014 #ifdef BETTER_LITERAL_SHIFT
8015 /*-----------------------------------------------------------------*/
8016 /* shiftR2Left2Result - shift right two bytes from left to result */
8017 /*-----------------------------------------------------------------*/
8019 shiftR2Left2Result (operand * left, int offl,
8020 operand * result, int offr,
8021 int shCount, int sign)
8025 _loadLeftIntoAx(&lsb, left, result, offl, offr);
8027 /* a:x >> shCount (x = lsb(result)) */
8030 AccAXRshS(lsb, shCount);
8034 AccAXRsh(lsb, shCount);
8037 _storeAxResults(lsb, result, offr);
8041 /*-----------------------------------------------------------------*/
8042 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8043 /*-----------------------------------------------------------------*/
8045 shiftLLeftOrResult (operand * left, int offl,
8046 operand * result, int offr, int shCount)
8048 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8049 /* shift left accumulator */
8051 /* or with result */
8052 emitcode ("orl", "a,%s",
8053 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8054 /* back to result */
8055 aopPut (AOP (result), "a", offr);
8060 /*-----------------------------------------------------------------*/
8061 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8062 /*-----------------------------------------------------------------*/
8064 shiftRLeftOrResult (operand * left, int offl,
8065 operand * result, int offr, int shCount)
8067 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8068 /* shift right accumulator */
8070 /* or with result */
8071 emitcode ("orl", "a,%s",
8072 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8073 /* back to result */
8074 aopPut (AOP (result), "a", offr);
8078 #ifdef BETTER_LITERAL_SHIFT
8079 /*-----------------------------------------------------------------*/
8080 /* genlshOne - left shift a one byte quantity by known count */
8081 /*-----------------------------------------------------------------*/
8083 genlshOne (operand * result, operand * left, int shCount)
8085 D (emitcode (";", "genlshOne "););
8086 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8090 #ifdef BETTER_LITERAL_SHIFT
8091 /*-----------------------------------------------------------------*/
8092 /* genlshTwo - left shift two bytes by known amount != 0 */
8093 /*-----------------------------------------------------------------*/
8095 genlshTwo (operand * result, operand * left, int shCount)
8099 D (emitcode (";", "genlshTwo "););
8101 size = getDataSize (result);
8103 /* if shCount >= 8 */
8108 _startLazyDPSEvaluation();
8114 _endLazyDPSEvaluation();
8115 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8116 aopPut (AOP (result), zero, LSB);
8120 movLeft2Result (left, LSB, result, MSB16, 0);
8121 aopPut (AOP (result), zero, LSB);
8122 _endLazyDPSEvaluation();
8127 aopPut (AOP (result), zero, LSB);
8128 _endLazyDPSEvaluation();
8132 /* 1 <= shCount <= 7 */
8137 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8141 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8149 /*-----------------------------------------------------------------*/
8150 /* shiftLLong - shift left one long from left to result */
8151 /* offl = LSB or MSB16 */
8152 /*-----------------------------------------------------------------*/
8154 shiftLLong (operand * left, operand * result, int offr)
8157 int size = AOP_SIZE (result);
8159 if (size >= LSB + offr)
8161 l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8163 emitcode ("add", "a,acc");
8164 if (sameRegs (AOP (left), AOP (result)) &&
8165 size >= MSB16 + offr && offr != LSB)
8166 emitcode ("xch", "a,%s",
8167 aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8169 aopPut (AOP (result), "a", LSB + offr);
8172 if (size >= MSB16 + offr)
8174 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8176 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8178 emitcode ("rlc", "a");
8179 if (sameRegs (AOP (left), AOP (result)) &&
8180 size >= MSB24 + offr && offr != LSB)
8181 emitcode ("xch", "a,%s",
8182 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8184 aopPut (AOP (result), "a", MSB16 + offr);
8187 if (size >= MSB24 + offr)
8189 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8191 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8193 emitcode ("rlc", "a");
8194 if (sameRegs (AOP (left), AOP (result)) &&
8195 size >= MSB32 + offr && offr != LSB)
8196 emitcode ("xch", "a,%s",
8197 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8199 aopPut (AOP (result), "a", MSB24 + offr);
8202 if (size > MSB32 + offr)
8204 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8206 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8208 emitcode ("rlc", "a");
8209 aopPut (AOP (result), "a", MSB32 + offr);
8212 aopPut (AOP (result), zero, LSB);
8218 /*-----------------------------------------------------------------*/
8219 /* genlshFour - shift four byte by a known amount != 0 */
8220 /*-----------------------------------------------------------------*/
8222 genlshFour (operand * result, operand * left, int shCount)
8226 D (emitcode (";", "genlshFour ");
8229 size = AOP_SIZE (result);
8231 /* if shifting more that 3 bytes */
8236 /* lowest order of left goes to the highest
8237 order of the destination */
8238 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8240 movLeft2Result (left, LSB, result, MSB32, 0);
8241 aopPut (AOP (result), zero, LSB);
8242 aopPut (AOP (result), zero, MSB16);
8243 aopPut (AOP (result), zero, MSB24);
8247 /* more than two bytes */
8248 else if (shCount >= 16)
8250 /* lower order two bytes goes to higher order two bytes */
8252 /* if some more remaining */
8254 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8257 movLeft2Result (left, MSB16, result, MSB32, 0);
8258 movLeft2Result (left, LSB, result, MSB24, 0);
8260 aopPut (AOP (result), zero, MSB16);
8261 aopPut (AOP (result), zero, LSB);
8265 /* if more than 1 byte */
8266 else if (shCount >= 8)
8268 /* lower order three bytes goes to higher order three bytes */
8273 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8275 movLeft2Result (left, LSB, result, MSB16, 0);
8281 movLeft2Result (left, MSB24, result, MSB32, 0);
8282 movLeft2Result (left, MSB16, result, MSB24, 0);
8283 movLeft2Result (left, LSB, result, MSB16, 0);
8284 aopPut (AOP (result), zero, LSB);
8286 else if (shCount == 1)
8287 shiftLLong (left, result, MSB16);
8290 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8291 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8292 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8293 aopPut (AOP (result), zero, LSB);
8298 /* 1 <= shCount <= 7 */
8299 else if (shCount <= 2)
8301 shiftLLong (left, result, LSB);
8303 shiftLLong (result, result, LSB);
8305 /* 3 <= shCount <= 7, optimize */
8308 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8309 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8310 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8315 #ifdef BETTER_LITERAL_SHIFT
8316 /*-----------------------------------------------------------------*/
8317 /* genLeftShiftLiteral - left shifting by known count */
8318 /*-----------------------------------------------------------------*/
8320 genLeftShiftLiteral (operand * left,
8325 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8328 size = getSize (operandType (result));
8330 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8332 /* We only handle certain easy cases so far. */
8334 && (shCount < (size * 8))
8338 D(emitcode (";", "genLeftShiftLiteral wimping out"););
8342 freeAsmop (right, NULL, ic, TRUE);
8344 aopOp(left, ic, FALSE, FALSE);
8345 aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8348 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8350 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8351 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8353 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8356 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8358 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8359 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8361 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8367 emitcode ("; shift left ", "result %d, left %d", size,
8371 /* I suppose that the left size >= result size */
8374 _startLazyDPSEvaluation();
8377 movLeft2Result (left, size, result, size, 0);
8379 _endLazyDPSEvaluation();
8381 else if (shCount >= (size * 8))
8383 _startLazyDPSEvaluation();
8386 aopPut (AOP (result), zero, size);
8388 _endLazyDPSEvaluation();
8395 genlshOne (result, left, shCount);
8399 genlshTwo (result, left, shCount);
8403 genlshFour (result, left, shCount);
8407 fprintf(stderr, "*** ack! mystery literal shift!\n");
8411 freeAsmop (left, NULL, ic, TRUE);
8412 freeAsmop (result, NULL, ic, TRUE);
8417 /*-----------------------------------------------------------------*/
8418 /* genLeftShift - generates code for left shifting */
8419 /*-----------------------------------------------------------------*/
8421 genLeftShift (iCode * ic)
8423 operand *left, *right, *result;
8426 symbol *tlbl, *tlbl1;
8428 D (emitcode (";", "genLeftShift "););
8430 right = IC_RIGHT (ic);
8431 left = IC_LEFT (ic);
8432 result = IC_RESULT (ic);
8434 aopOp (right, ic, FALSE, FALSE);
8437 #ifdef BETTER_LITERAL_SHIFT
8438 /* if the shift count is known then do it
8439 as efficiently as possible */
8440 if (AOP_TYPE (right) == AOP_LIT)
8442 if (genLeftShiftLiteral (left, right, result, ic))
8449 /* shift count is unknown then we have to form
8450 a loop get the loop count in B : Note: we take
8451 only the lower order byte since shifting
8452 more that 32 bits make no sense anyway, ( the
8453 largest size of an object can be only 32 bits ) */
8455 if (AOP_TYPE (right) == AOP_LIT)
8457 /* Really should be handled by genLeftShiftLiteral,
8458 * but since I'm too lazy to fix that today, at least we can make
8459 * some small improvement.
8461 emitcode("mov", "b,#!constbyte",
8462 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8466 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8467 emitcode ("inc", "b");
8469 freeAsmop (right, NULL, ic, TRUE);
8470 aopOp (left, ic, FALSE, FALSE);
8471 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8473 /* now move the left to the result if they are not the
8475 if (!sameRegs (AOP (left), AOP (result)) &&
8476 AOP_SIZE (result) > 1)
8479 size = AOP_SIZE (result);
8481 _startLazyDPSEvaluation ();
8484 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8485 if (*l == '@' && (IS_AOP_PREG (result)))
8488 emitcode ("mov", "a,%s", l);
8489 aopPut (AOP (result), "a", offset);
8492 aopPut (AOP (result), l, offset);
8495 _endLazyDPSEvaluation ();
8498 tlbl = newiTempLabel (NULL);
8499 size = AOP_SIZE (result);
8501 tlbl1 = newiTempLabel (NULL);
8503 /* if it is only one byte then */
8506 symbol *tlbl1 = newiTempLabel (NULL);
8508 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8509 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8510 emitcode ("", "!tlabeldef", tlbl->key + 100);
8511 emitcode ("add", "a,acc");
8512 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8513 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8514 aopPut (AOP (result), "a", 0);
8518 reAdjustPreg (AOP (result));
8520 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8521 emitcode ("", "!tlabeldef", tlbl->key + 100);
8522 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8523 emitcode ("add", "a,acc");
8524 aopPut (AOP (result), "a", offset++);
8525 _startLazyDPSEvaluation ();
8528 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8529 emitcode ("rlc", "a");
8530 aopPut (AOP (result), "a", offset++);
8532 _endLazyDPSEvaluation ();
8533 reAdjustPreg (AOP (result));
8535 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8536 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8538 freeAsmop (left, NULL, ic, TRUE);
8539 freeAsmop (result, NULL, ic, TRUE);
8542 #ifdef BETTER_LITERAL_SHIFT
8543 /*-----------------------------------------------------------------*/
8544 /* genrshOne - right shift a one byte quantity by known count */
8545 /*-----------------------------------------------------------------*/
8547 genrshOne (operand * result, operand * left,
8548 int shCount, int sign)
8550 D (emitcode (";", "genrshOne"););
8551 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8555 #ifdef BETTER_LITERAL_SHIFT
8556 /*-----------------------------------------------------------------*/
8557 /* genrshTwo - right shift two bytes by known amount != 0 */
8558 /*-----------------------------------------------------------------*/
8560 genrshTwo (operand * result, operand * left,
8561 int shCount, int sign)
8563 D (emitcode (";", "genrshTwo"););
8565 /* if shCount >= 8 */
8569 _startLazyDPSEvaluation();
8572 shiftR1Left2Result (left, MSB16, result, LSB,
8577 movLeft2Result (left, MSB16, result, LSB, sign);
8579 addSign (result, MSB16, sign);
8580 _endLazyDPSEvaluation();
8583 /* 1 <= shCount <= 7 */
8586 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8591 /*-----------------------------------------------------------------*/
8592 /* shiftRLong - shift right one long from left to result */
8593 /* offl = LSB or MSB16 */
8594 /*-----------------------------------------------------------------*/
8596 shiftRLong (operand * left, int offl,
8597 operand * result, int sign)
8599 int isSameRegs=sameRegs(AOP(left),AOP(result));
8601 if (isSameRegs && offl>1) {
8602 // we are in big trouble, but this shouldn't happen
8603 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8606 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8611 emitcode ("rlc", "a");
8612 emitcode ("subb", "a,acc");
8613 emitcode ("xch", "a,%s",
8614 aopGet(AOP(left), MSB32, FALSE, FALSE, DP2_RESULT_REG));
8616 aopPut (AOP(result), zero, MSB32);
8621 emitcode ("clr", "c");
8623 emitcode ("mov", "c,acc.7");
8626 emitcode ("rrc", "a");
8628 if (isSameRegs && offl==MSB16) {
8630 "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE, DP2_RESULT_REG));
8632 aopPut (AOP (result), "a", MSB32);
8633 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8636 emitcode ("rrc", "a");
8637 if (isSameRegs && offl==1) {
8638 emitcode ("xch", "a,%s",
8639 aopGet (AOP (left), MSB16, FALSE, FALSE, DP2_RESULT_REG));
8641 aopPut (AOP (result), "a", MSB24);
8642 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, NULL));
8644 emitcode ("rrc", "a");
8645 aopPut (AOP (result), "a", MSB16 - offl);
8649 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, NULL));
8650 emitcode ("rrc", "a");
8651 aopPut (AOP (result), "a", LSB);
8655 /*-----------------------------------------------------------------*/
8656 /* genrshFour - shift four byte by a known amount != 0 */
8657 /*-----------------------------------------------------------------*/
8659 genrshFour (operand * result, operand * left,
8660 int shCount, int sign)
8662 D (emitcode (";", "genrshFour"););
8664 /* if shifting more that 3 bytes */
8668 _startLazyDPSEvaluation();
8670 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8672 movLeft2Result (left, MSB32, result, LSB, sign);
8673 addSign (result, MSB16, sign);
8674 _endLazyDPSEvaluation();
8676 else if (shCount >= 16)
8679 _startLazyDPSEvaluation();
8681 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8684 movLeft2Result (left, MSB24, result, LSB, 0);
8685 movLeft2Result (left, MSB32, result, MSB16, sign);
8687 addSign (result, MSB24, sign);
8688 _endLazyDPSEvaluation();
8690 else if (shCount >= 8)
8693 _startLazyDPSEvaluation();
8696 shiftRLong (left, MSB16, result, sign);
8698 else if (shCount == 0)
8700 movLeft2Result (left, MSB16, result, LSB, 0);
8701 movLeft2Result (left, MSB24, result, MSB16, 0);
8702 movLeft2Result (left, MSB32, result, MSB24, sign);
8703 addSign (result, MSB32, sign);
8707 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8708 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8709 /* the last shift is signed */
8710 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8711 addSign (result, MSB32, sign);
8713 _endLazyDPSEvaluation();
8717 /* 1 <= shCount <= 7 */
8720 shiftRLong (left, LSB, result, sign);
8722 shiftRLong (result, LSB, result, sign);
8726 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8727 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8728 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8733 #ifdef BETTER_LITERAL_SHIFT
8734 /*-----------------------------------------------------------------*/
8735 /* genRightShiftLiteral - right shifting by known count */
8736 /*-----------------------------------------------------------------*/
8738 genRightShiftLiteral (operand * left,
8744 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8747 size = getSize (operandType (result));
8749 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8751 /* We only handle certain easy cases so far. */
8753 && (shCount < (size * 8))
8758 D(emitcode (";", "genRightShiftLiteral wimping out"););
8762 freeAsmop (right, NULL, ic, TRUE);
8764 aopOp (left, ic, FALSE, FALSE);
8765 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8768 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8772 /* test the LEFT size !!! */
8774 /* I suppose that the left size >= result size */
8777 size = getDataSize (result);
8778 _startLazyDPSEvaluation();
8781 movLeft2Result (left, size, result, size, 0);
8783 _endLazyDPSEvaluation();
8785 else if (shCount >= (size * 8))
8789 /* get sign in acc.7 */
8790 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
8792 addSign (result, LSB, sign);
8799 genrshOne (result, left, shCount, sign);
8803 genrshTwo (result, left, shCount, sign);
8807 genrshFour (result, left, shCount, sign);
8814 freeAsmop (left, NULL, ic, TRUE);
8815 freeAsmop (result, NULL, ic, TRUE);
8821 /*-----------------------------------------------------------------*/
8822 /* genSignedRightShift - right shift of signed number */
8823 /*-----------------------------------------------------------------*/
8825 genSignedRightShift (iCode * ic)
8827 operand *right, *left, *result;
8830 symbol *tlbl, *tlbl1;
8832 D (emitcode (";", "genSignedRightShift "););
8834 /* we do it the hard way put the shift count in b
8835 and loop thru preserving the sign */
8837 right = IC_RIGHT (ic);
8838 left = IC_LEFT (ic);
8839 result = IC_RESULT (ic);
8841 aopOp (right, ic, FALSE, FALSE);
8843 #ifdef BETTER_LITERAL_SHIFT
8844 if (AOP_TYPE (right) == AOP_LIT)
8846 if (genRightShiftLiteral (left, right, result, ic, 1))
8852 /* shift count is unknown then we have to form
8853 a loop get the loop count in B : Note: we take
8854 only the lower order byte since shifting
8855 more that 32 bits make no sense anyway, ( the
8856 largest size of an object can be only 32 bits ) */
8858 if (AOP_TYPE (right) == AOP_LIT)
8860 /* Really should be handled by genRightShiftLiteral,
8861 * but since I'm too lazy to fix that today, at least we can make
8862 * some small improvement.
8864 emitcode("mov", "b,#!constbyte",
8865 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8869 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8870 emitcode ("inc", "b");
8872 freeAsmop (right, NULL, ic, TRUE);
8873 aopOp (left, ic, FALSE, FALSE);
8874 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8876 /* now move the left to the result if they are not the
8878 if (!sameRegs (AOP (left), AOP (result)) &&
8879 AOP_SIZE (result) > 1)
8882 size = AOP_SIZE (result);
8884 _startLazyDPSEvaluation ();
8887 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8888 if (*l == '@' && IS_AOP_PREG (result))
8891 emitcode ("mov", "a,%s", l);
8892 aopPut (AOP (result), "a", offset);
8895 aopPut (AOP (result), l, offset);
8898 _endLazyDPSEvaluation ();
8901 /* mov the highest order bit to OVR */
8902 tlbl = newiTempLabel (NULL);
8903 tlbl1 = newiTempLabel (NULL);
8905 size = AOP_SIZE (result);
8907 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
8908 emitcode ("rlc", "a");
8909 emitcode ("mov", "ov,c");
8910 /* if it is only one byte then */
8913 MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8914 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8915 emitcode ("", "!tlabeldef", tlbl->key + 100);
8916 emitcode ("mov", "c,ov");
8917 emitcode ("rrc", "a");
8918 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8919 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8920 aopPut (AOP (result), "a", 0);
8924 reAdjustPreg (AOP (result));
8925 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8926 emitcode ("", "!tlabeldef", tlbl->key + 100);
8927 emitcode ("mov", "c,ov");
8928 _startLazyDPSEvaluation ();
8931 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8932 emitcode ("rrc", "a");
8933 aopPut (AOP (result), "a", offset--);
8935 _endLazyDPSEvaluation ();
8936 reAdjustPreg (AOP (result));
8937 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8938 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8941 freeAsmop (left, NULL, ic, TRUE);
8942 freeAsmop (result, NULL, ic, TRUE);
8945 /*-----------------------------------------------------------------*/
8946 /* genRightShift - generate code for right shifting */
8947 /*-----------------------------------------------------------------*/
8949 genRightShift (iCode * ic)
8951 operand *right, *left, *result;
8955 symbol *tlbl, *tlbl1;
8957 D (emitcode (";", "genRightShift "););
8959 /* if signed then we do it the hard way preserve the
8960 sign bit moving it inwards */
8961 letype = getSpec (operandType (IC_LEFT (ic)));
8963 if (!SPEC_USIGN (letype))
8965 genSignedRightShift (ic);
8969 /* signed & unsigned types are treated the same : i.e. the
8970 signed is NOT propagated inwards : quoting from the
8971 ANSI - standard : "for E1 >> E2, is equivalent to division
8972 by 2**E2 if unsigned or if it has a non-negative value,
8973 otherwise the result is implementation defined ", MY definition
8974 is that the sign does not get propagated */
8976 right = IC_RIGHT (ic);
8977 left = IC_LEFT (ic);
8978 result = IC_RESULT (ic);
8980 aopOp (right, ic, FALSE, FALSE);
8982 #ifdef BETTER_LITERAL_SHIFT
8983 /* if the shift count is known then do it
8984 as efficiently as possible */
8985 if (AOP_TYPE (right) == AOP_LIT)
8987 if (genRightShiftLiteral (left, right, result, ic, 0))
8994 /* shift count is unknown then we have to form
8995 a loop get the loop count in B : Note: we take
8996 only the lower order byte since shifting
8997 more that 32 bits make no sense anyway, ( the
8998 largest size of an object can be only 32 bits ) */
9000 if (AOP_TYPE (right) == AOP_LIT)
9002 /* Really should be handled by genRightShiftLiteral,
9003 * but since I'm too lazy to fix that today, at least we can make
9004 * some small improvement.
9006 emitcode("mov", "b,#!constbyte",
9007 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9011 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
9012 emitcode ("inc", "b");
9014 freeAsmop (right, NULL, ic, TRUE);
9015 aopOp (left, ic, FALSE, FALSE);
9016 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9018 /* now move the left to the result if they are not the
9020 if (!sameRegs (AOP (left), AOP (result)) &&
9021 AOP_SIZE (result) > 1)
9024 size = AOP_SIZE (result);
9026 _startLazyDPSEvaluation ();
9029 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
9030 if (*l == '@' && IS_AOP_PREG (result))
9033 emitcode ("mov", "a,%s", l);
9034 aopPut (AOP (result), "a", offset);
9037 aopPut (AOP (result), l, offset);
9040 _endLazyDPSEvaluation ();
9043 tlbl = newiTempLabel (NULL);
9044 tlbl1 = newiTempLabel (NULL);
9045 size = AOP_SIZE (result);
9048 /* if it is only one byte then */
9051 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9052 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9053 emitcode ("", "!tlabeldef", tlbl->key + 100);
9055 emitcode ("rrc", "a");
9056 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9057 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9058 aopPut (AOP (result), "a", 0);
9062 reAdjustPreg (AOP (result));
9063 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9064 emitcode ("", "!tlabeldef", tlbl->key + 100);
9066 _startLazyDPSEvaluation ();
9069 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
9070 emitcode ("rrc", "a");
9071 aopPut (AOP (result), "a", offset--);
9073 _endLazyDPSEvaluation ();
9074 reAdjustPreg (AOP (result));
9076 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9077 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9080 freeAsmop (left, NULL, ic, TRUE);
9081 freeAsmop (result, NULL, ic, TRUE);
9085 /*-----------------------------------------------------------------*/
9086 /* emitPtrByteGet - emits code to get a byte into A through a */
9087 /* pointer register (R0, R1, or DPTR). The */
9088 /* original value of A can be preserved in B. */
9089 /*-----------------------------------------------------------------*/
9091 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9098 emitcode ("mov", "b,a");
9099 emitcode ("mov", "a,@%s", rname);
9104 emitcode ("mov", "b,a");
9105 emitcode ("movx", "a,@%s", rname);
9110 emitcode ("mov", "b,a");
9111 emitcode ("movx", "a,@dptr");
9116 emitcode ("mov", "b,a");
9117 emitcode ("clr", "a");
9118 emitcode ("movc", "a,@a+dptr");
9124 emitcode ("push", "b");
9125 emitcode ("push", "acc");
9127 emitcode ("lcall", "__gptrget");
9129 emitcode ("pop", "b");
9134 /*-----------------------------------------------------------------*/
9135 /* emitPtrByteSet - emits code to set a byte from src through a */
9136 /* pointer register (R0, R1, or DPTR). */
9137 /*-----------------------------------------------------------------*/
9139 emitPtrByteSet (char *rname, int p_type, char *src)
9148 emitcode ("mov", "@%s,a", rname);
9151 emitcode ("mov", "@%s,%s", rname, src);
9156 emitcode ("movx", "@%s,a", rname);
9161 emitcode ("movx", "@dptr,a");
9166 emitcode ("lcall", "__gptrput");
9171 /*-----------------------------------------------------------------*/
9172 /* genUnpackBits - generates code for unpacking bits */
9173 /*-----------------------------------------------------------------*/
9175 genUnpackBits (operand * result, char *rname, int ptype)
9177 int offset = 0; /* result byte offset */
9178 int rsize; /* result size */
9179 int rlen = 0; /* remaining bitfield length */
9180 sym_link *etype; /* bitfield type information */
9181 int blen; /* bitfield length */
9182 int bstr; /* bitfield starting bit within byte */
9184 D(emitcode ("; genUnpackBits",""));
9186 etype = getSpec (operandType (result));
9187 rsize = getSize (operandType (result));
9188 blen = SPEC_BLEN (etype);
9189 bstr = SPEC_BSTR (etype);
9191 /* If the bitfield length is less than a byte */
9194 emitPtrByteGet (rname, ptype, FALSE);
9196 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
9197 aopPut (AOP (result), "a", offset++);
9201 /* Bit field did not fit in a byte. Copy all
9202 but the partial byte at the end. */
9203 for (rlen=blen;rlen>=8;rlen-=8)
9205 emitPtrByteGet (rname, ptype, FALSE);
9206 aopPut (AOP (result), "a", offset++);
9208 emitcode ("inc", "%s", rname);
9211 /* Handle the partial byte at the end */
9214 emitPtrByteGet (rname, ptype, FALSE);
9215 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
9216 aopPut (AOP (result), "a", offset++);
9224 aopPut (AOP (result), zero, offset++);
9229 /*-----------------------------------------------------------------*/
9230 /* genDataPointerGet - generates code when ptr offset is known */
9231 /*-----------------------------------------------------------------*/
9233 genDataPointerGet (operand * left,
9239 int size, offset = 0;
9240 aopOp (result, ic, TRUE, FALSE);
9242 /* get the string representation of the name */
9243 l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9244 size = AOP_SIZE (result);
9245 _startLazyDPSEvaluation ();
9250 SNPRINTF (buff, sizeof(buff),
9251 "(%s + %d)", l + 1, offset);
9255 SNPRINTF (buff, sizeof(buff),
9258 aopPut (AOP (result), buff, offset++);
9260 _endLazyDPSEvaluation ();
9262 freeAsmop (left, NULL, ic, TRUE);
9263 freeAsmop (result, NULL, ic, TRUE);
9266 /*-----------------------------------------------------------------*/
9267 /* genNearPointerGet - emitcode for near pointer fetch */
9268 /*-----------------------------------------------------------------*/
9270 genNearPointerGet (operand * left,
9278 sym_link *rtype, *retype, *letype;
9279 sym_link *ltype = operandType (left);
9282 rtype = operandType (result);
9283 retype = getSpec (rtype);
9284 letype = getSpec (ltype);
9286 aopOp (left, ic, FALSE, FALSE);
9288 /* if left is rematerialisable and
9289 result is not bit variable type and
9290 the left is pointer to data space i.e
9291 lower 128 bytes of space */
9292 if (AOP_TYPE (left) == AOP_IMMD &&
9293 !IS_BITVAR (retype) &&
9294 !IS_BITVAR (letype) &&
9295 DCL_TYPE (ltype) == POINTER)
9297 genDataPointerGet (left, result, ic);
9301 /* if the value is already in a pointer register
9302 then don't need anything more */
9303 if (!AOP_INPREG (AOP (left)))
9305 /* otherwise get a free pointer register */
9307 preg = getFreePtr (ic, &aop, FALSE);
9308 emitcode ("mov", "%s,%s",
9310 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9314 rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9316 freeAsmop (left, NULL, ic, TRUE);
9317 aopOp (result, ic, FALSE, FALSE);
9319 /* if bitfield then unpack the bits */
9320 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9321 genUnpackBits (result, rname, POINTER);
9324 /* we have can just get the values */
9325 int size = AOP_SIZE (result);
9330 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9333 emitcode ("mov", "a,@%s", rname);
9334 aopPut (AOP (result), "a", offset);
9338 SNPRINTF (buff, sizeof(buff), "@%s", rname);
9339 aopPut (AOP (result), buff, offset);
9344 emitcode ("inc", "%s", rname);
9349 /* now some housekeeping stuff */
9352 /* we had to allocate for this iCode */
9353 if (pi) { /* post increment present */
9354 aopPut(AOP ( left ),rname,0);
9356 freeAsmop (NULL, aop, ic, TRUE);
9360 /* we did not allocate which means left
9361 already in a pointer register, then
9362 if size > 0 && this could be used again
9363 we have to point it back to where it
9365 if (AOP_SIZE (result) > 1 &&
9366 !OP_SYMBOL (left)->remat &&
9367 (OP_SYMBOL (left)->liveTo > ic->seq ||
9371 int size = AOP_SIZE (result) - 1;
9373 emitcode ("dec", "%s", rname);
9378 freeAsmop (result, NULL, ic, TRUE);
9379 if (pi) pi->generated = 1;
9382 /*-----------------------------------------------------------------*/
9383 /* genPagedPointerGet - emitcode for paged pointer fetch */
9384 /*-----------------------------------------------------------------*/
9386 genPagedPointerGet (operand * left,
9394 sym_link *rtype, *retype, *letype;
9396 rtype = operandType (result);
9397 retype = getSpec (rtype);
9398 letype = getSpec (operandType (left));
9399 aopOp (left, ic, FALSE, FALSE);
9401 /* if the value is already in a pointer register
9402 then don't need anything more */
9403 if (!AOP_INPREG (AOP (left)))
9405 /* otherwise get a free pointer register */
9407 preg = getFreePtr (ic, &aop, FALSE);
9408 emitcode ("mov", "%s,%s",
9410 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9414 rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9416 freeAsmop (left, NULL, ic, TRUE);
9417 aopOp (result, ic, FALSE, FALSE);
9419 /* if bitfield then unpack the bits */
9420 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9421 genUnpackBits (result, rname, PPOINTER);
9424 /* we have can just get the values */
9425 int size = AOP_SIZE (result);
9431 emitcode ("movx", "a,@%s", rname);
9432 aopPut (AOP (result), "a", offset);
9437 emitcode ("inc", "%s", rname);
9441 /* now some housekeeping stuff */
9444 /* we had to allocate for this iCode */
9445 if (pi) aopPut ( AOP (left), rname, 0);
9446 freeAsmop (NULL, aop, ic, TRUE);
9450 /* we did not allocate which means left
9451 already in a pointer register, then
9452 if size > 0 && this could be used again
9453 we have to point it back to where it
9455 if (AOP_SIZE (result) > 1 &&
9456 !OP_SYMBOL (left)->remat &&
9457 (OP_SYMBOL (left)->liveTo > ic->seq ||
9461 int size = AOP_SIZE (result) - 1;
9463 emitcode ("dec", "%s", rname);
9468 freeAsmop (result, NULL, ic, TRUE);
9469 if (pi) pi->generated = 1;
9472 /*-----------------------------------------------------------------*/
9473 /* genFarPointerGet - gget value from far space */
9474 /*-----------------------------------------------------------------*/
9476 genFarPointerGet (operand * left,
9477 operand * result, iCode * ic, iCode *pi)
9479 int size, offset, dopi=1;
9480 sym_link *retype = getSpec (operandType (result));
9481 sym_link *letype = getSpec (operandType (left));
9482 D (emitcode (";", "genFarPointerGet"););
9484 aopOp (left, ic, FALSE, FALSE);
9486 /* if the operand is already in dptr
9487 then we do nothing else we move the value to dptr */
9488 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9490 /* if this is remateriazable */
9491 if (AOP_TYPE (left) == AOP_IMMD)
9493 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9497 /* we need to get it byte by byte */
9498 _startLazyDPSEvaluation ();
9499 if (AOP_TYPE (left) != AOP_DPTR)
9501 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9502 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9503 if (options.model == MODEL_FLAT24)
9504 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9508 /* We need to generate a load to DPTR indirect through DPTR. */
9509 D (emitcode (";", "genFarPointerGet -- indirection special case."););
9510 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9511 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9512 if (options.model == MODEL_FLAT24)
9513 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9514 emitcode ("pop", "dph");
9515 emitcode ("pop", "dpl");
9518 _endLazyDPSEvaluation ();
9521 /* so dptr know contains the address */
9522 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9524 /* if bit then unpack */
9525 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9526 if (AOP_INDPTRn(left)) {
9527 genSetDPTR(AOP(left)->aopu.dptr);
9529 genUnpackBits (result, "dptr", FPOINTER);
9530 if (AOP_INDPTRn(left)) {
9535 size = AOP_SIZE (result);
9538 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9540 genSetDPTR(AOP(left)->aopu.dptr);
9541 emitcode ("movx", "a,@dptr");
9542 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9543 emitcode ("inc", "dptr");
9545 aopPut (AOP (result), "a", offset++);
9548 _startLazyDPSEvaluation ();
9550 if (AOP_INDPTRn(left)) {
9551 genSetDPTR(AOP(left)->aopu.dptr);
9557 emitcode ("movx", "a,@dptr");
9558 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9559 emitcode ("inc", "dptr");
9561 aopPut (AOP (result), "a", offset++);
9563 _endLazyDPSEvaluation ();
9566 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9567 if (!AOP_INDPTRn(left)) {
9568 _startLazyDPSEvaluation ();
9569 aopPut ( AOP (left), "dpl", 0);
9570 aopPut ( AOP (left), "dph", 1);
9571 if (options.model == MODEL_FLAT24)
9572 aopPut ( AOP (left), "dpx", 2);
9573 _endLazyDPSEvaluation ();
9576 } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) &&
9577 AOP_SIZE(result) > 1 &&
9579 (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
9581 size = AOP_SIZE (result) - 1;
9582 if (AOP_INDPTRn(left)) {
9583 genSetDPTR(AOP(left)->aopu.dptr);
9585 while (size--) emitcode ("lcall","__decdptr");
9586 if (AOP_INDPTRn(left)) {
9591 freeAsmop (left, NULL, ic, TRUE);
9592 freeAsmop (result, NULL, ic, TRUE);
9595 /*-----------------------------------------------------------------*/
9596 /* genCodePointerGet - get value from code space */
9597 /*-----------------------------------------------------------------*/
9599 genCodePointerGet (operand * left,
9600 operand * result, iCode * ic, iCode *pi)
9602 int size, offset, dopi=1;
9603 sym_link *retype = getSpec (operandType (result));
9605 aopOp (left, ic, FALSE, FALSE);
9607 /* if the operand is already in dptr
9608 then we do nothing else we move the value to dptr */
9609 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
9611 /* if this is remateriazable */
9612 if (AOP_TYPE (left) == AOP_IMMD)
9614 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9617 { /* we need to get it byte by byte */
9618 _startLazyDPSEvaluation ();
9619 if (AOP_TYPE (left) != AOP_DPTR)
9621 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9622 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9623 if (options.model == MODEL_FLAT24)
9624 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9628 /* We need to generate a load to DPTR indirect through DPTR. */
9629 D (emitcode (";", "gencodePointerGet -- indirection special case."););
9630 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9631 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9632 if (options.model == MODEL_FLAT24)
9633 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9634 emitcode ("pop", "dph");
9635 emitcode ("pop", "dpl");
9638 _endLazyDPSEvaluation ();
9641 /* so dptr know contains the address */
9642 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9644 /* if bit then unpack */
9645 if (IS_BITVAR (retype)) {
9646 if (AOP_INDPTRn(left)) {
9647 genSetDPTR(AOP(left)->aopu.dptr);
9649 genUnpackBits (result, "dptr", CPOINTER);
9650 if (AOP_INDPTRn(left)) {
9655 size = AOP_SIZE (result);
9657 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9659 genSetDPTR(AOP(left)->aopu.dptr);
9660 emitcode ("clr", "a");
9661 emitcode ("movc", "a,@a+dptr");
9662 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9663 emitcode ("inc", "dptr");
9665 aopPut (AOP (result), "a", offset++);
9668 _startLazyDPSEvaluation ();
9671 if (AOP_INDPTRn(left)) {
9672 genSetDPTR(AOP(left)->aopu.dptr);
9678 emitcode ("clr", "a");
9679 emitcode ("movc", "a,@a+dptr");
9680 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9681 emitcode ("inc", "dptr");
9682 aopPut (AOP (result), "a", offset++);
9684 _endLazyDPSEvaluation ();
9687 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9688 if (!AOP_INDPTRn(left)) {
9689 _startLazyDPSEvaluation ();
9691 aopPut ( AOP (left), "dpl", 0);
9692 aopPut ( AOP (left), "dph", 1);
9693 if (options.model == MODEL_FLAT24)
9694 aopPut ( AOP (left), "dpx", 2);
9696 _endLazyDPSEvaluation ();
9699 } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
9700 AOP_SIZE(result) > 1 &&
9701 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9703 size = AOP_SIZE (result) - 1;
9704 if (AOP_INDPTRn(left)) {
9705 genSetDPTR(AOP(left)->aopu.dptr);
9707 while (size--) emitcode ("lcall","__decdptr");
9708 if (AOP_INDPTRn(left)) {
9713 freeAsmop (left, NULL, ic, TRUE);
9714 freeAsmop (result, NULL, ic, TRUE);
9717 /*-----------------------------------------------------------------*/
9718 /* genGenPointerGet - gget value from generic pointer space */
9719 /*-----------------------------------------------------------------*/
9721 genGenPointerGet (operand * left,
9722 operand * result, iCode * ic, iCode * pi)
9725 sym_link *retype = getSpec (operandType (result));
9726 sym_link *letype = getSpec (operandType (left));
9728 D (emitcode (";", "genGenPointerGet "); );
9730 aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
9732 /* if the operand is already in dptr
9733 then we do nothing else we move the value to dptr */
9734 if (AOP_TYPE (left) != AOP_STR)
9736 /* if this is remateriazable */
9737 if (AOP_TYPE (left) == AOP_IMMD)
9739 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9740 if (AOP(left)->aopu.aop_immd.from_cast_remat)
9742 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
9746 emitcode ("mov", "b,#%d", pointerCode (retype));
9750 { /* we need to get it byte by byte */
9751 _startLazyDPSEvaluation ();
9752 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
9753 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
9754 if (options.model == MODEL_FLAT24) {
9755 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9756 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
9758 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9760 _endLazyDPSEvaluation ();
9764 /* so dptr-b now contains the address */
9766 aopOp (result, ic, FALSE, TRUE);
9769 /* if bit then unpack */
9770 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9772 genUnpackBits (result, "dptr", GPOINTER);
9776 size = AOP_SIZE (result);
9783 // Get two bytes at a time, results in _AP & A.
9784 // dptr will be incremented ONCE by __gptrgetWord.
9786 // Note: any change here must be coordinated
9787 // with the implementation of __gptrgetWord
9788 // in device/lib/_gptrget.c
9789 emitcode ("lcall", "__gptrgetWord");
9790 aopPut (AOP (result), DP2_RESULT_REG, offset++);
9791 aopPut (AOP (result), "a", offset++);
9796 // Only one byte to get.
9797 emitcode ("lcall", "__gptrget");
9798 aopPut (AOP (result), "a", offset++);
9801 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9803 emitcode ("inc", "dptr");
9808 if (pi && AOP_TYPE (left) != AOP_IMMD) {
9809 _startLazyDPSEvaluation ();
9811 aopPut ( AOP (left), "dpl", 0);
9812 aopPut ( AOP (left), "dph", 1);
9813 if (options.model == MODEL_FLAT24) {
9814 aopPut ( AOP (left), "dpx", 2);
9815 aopPut ( AOP (left), "b", 3);
9816 } else aopPut ( AOP (left), "b", 2);
9818 _endLazyDPSEvaluation ();
9821 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9822 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9824 size = AOP_SIZE (result) - 1;
9825 while (size--) emitcode ("lcall","__decdptr");
9828 freeAsmop (left, NULL, ic, TRUE);
9829 freeAsmop (result, NULL, ic, TRUE);
9832 /*-----------------------------------------------------------------*/
9833 /* genPointerGet - generate code for pointer get */
9834 /*-----------------------------------------------------------------*/
9836 genPointerGet (iCode * ic, iCode *pi)
9838 operand *left, *result;
9839 sym_link *type, *etype;
9842 D (emitcode (";", "genPointerGet ");
9845 left = IC_LEFT (ic);
9846 result = IC_RESULT (ic);
9848 /* depending on the type of pointer we need to
9849 move it to the correct pointer register */
9850 type = operandType (left);
9851 etype = getSpec (type);
9852 /* if left is of type of pointer then it is simple */
9853 if (IS_PTR (type) && !IS_FUNC (type->next))
9854 p_type = DCL_TYPE (type);
9857 /* we have to go by the storage class */
9858 p_type = PTR_TYPE (SPEC_OCLS (etype));
9860 /* special case when cast remat */
9861 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9862 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9863 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9864 type = operandType (left);
9865 p_type = DCL_TYPE (type);
9867 /* now that we have the pointer type we assign
9868 the pointer values */
9874 genNearPointerGet (left, result, ic, pi);
9878 genPagedPointerGet (left, result, ic, pi);
9882 genFarPointerGet (left, result, ic, pi);
9886 genCodePointerGet (left, result, ic, pi);
9890 genGenPointerGet (left, result, ic, pi);
9896 /*-----------------------------------------------------------------*/
9897 /* genPackBits - generates code for packed bit storage */
9898 /*-----------------------------------------------------------------*/
9900 genPackBits (sym_link * etype,
9902 char *rname, int p_type)
9904 int offset = 0; /* source byte offset */
9905 int rlen = 0; /* remaining bitfield length */
9906 int blen; /* bitfield length */
9907 int bstr; /* bitfield starting bit within byte */
9908 int litval; /* source literal value (if AOP_LIT) */
9909 unsigned char mask; /* bitmask within current byte */
9911 D(emitcode ("; genPackBits",""));
9913 blen = SPEC_BLEN (etype);
9914 bstr = SPEC_BSTR (etype);
9916 /* If the bitfield length is less than a byte */
9919 mask = ((unsigned char) (0xFF << (blen + bstr)) |
9920 (unsigned char) (0xFF >> (8 - bstr)));
9922 if (AOP_TYPE (right) == AOP_LIT)
9924 /* Case with a bitfield length <8 and literal source
9926 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9928 litval &= (~mask) & 0xff;
9929 emitPtrByteGet (rname, p_type, FALSE);
9930 if ((mask|litval)!=0xff)
9931 emitcode ("anl","a,#!constbyte", mask);
9933 emitcode ("orl","a,#!constbyte", litval);
9937 if ((blen==1) && (p_type!=GPOINTER))
9939 /* Case with a bitfield length == 1 and no generic pointer
9941 if (AOP_TYPE (right) == AOP_CRY)
9942 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9945 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
9946 emitcode ("rrc","a");
9948 emitPtrByteGet (rname, p_type, FALSE);
9949 emitcode ("mov","acc.%d,c",bstr);
9953 /* Case with a bitfield length < 8 and arbitrary source
9955 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
9956 /* shift and mask source value */
9958 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
9960 /* transfer A to B and get next byte */
9961 emitPtrByteGet (rname, p_type, TRUE);
9963 emitcode ("anl", "a,#!constbyte", mask);
9964 emitcode ("orl", "a,b");
9965 if (p_type == GPOINTER)
9966 emitcode ("pop", "b");
9970 emitPtrByteSet (rname, p_type, "a");
9974 /* Bit length is greater than 7 bits. In this case, copy */
9975 /* all except the partial byte at the end */
9976 for (rlen=blen;rlen>=8;rlen-=8)
9978 emitPtrByteSet (rname, p_type,
9979 aopGet (AOP (right), offset++, FALSE, TRUE, NULL) );
9981 emitcode ("inc", "%s", rname);
9984 /* If there was a partial byte at the end */
9987 mask = (((unsigned char) -1 << rlen) & 0xff);
9989 if (AOP_TYPE (right) == AOP_LIT)
9991 /* Case with partial byte and literal source
9993 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9994 litval >>= (blen-rlen);
9995 litval &= (~mask) & 0xff;
9996 emitPtrByteGet (rname, p_type, FALSE);
9997 if ((mask|litval)!=0xff)
9998 emitcode ("anl","a,#!constbyte", mask);
10000 emitcode ("orl","a,#!constbyte", litval);
10004 /* Case with partial byte and arbitrary source
10006 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10007 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10009 /* transfer A to B and get next byte */
10010 emitPtrByteGet (rname, p_type, TRUE);
10012 emitcode ("anl", "a,#!constbyte", mask);
10013 emitcode ("orl", "a,b");
10014 if (p_type == GPOINTER)
10015 emitcode ("pop", "b");
10017 emitPtrByteSet (rname, p_type, "a");
10023 /*-----------------------------------------------------------------*/
10024 /* genDataPointerSet - remat pointer to data space */
10025 /*-----------------------------------------------------------------*/
10027 genDataPointerSet (operand * right,
10031 int size, offset = 0;
10032 char *l, buff[256];
10034 aopOp (right, ic, FALSE, FALSE);
10036 l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
10037 size = AOP_SIZE (right);
10042 SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
10046 SNPRINTF (buff, sizeof(buff), "%s", l + 1);
10049 emitcode ("mov", "%s,%s", buff,
10050 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10053 freeAsmop (right, NULL, ic, TRUE);
10054 freeAsmop (result, NULL, ic, TRUE);
10057 /*-----------------------------------------------------------------*/
10058 /* genNearPointerSet - emitcode for near pointer put */
10059 /*-----------------------------------------------------------------*/
10061 genNearPointerSet (operand * right,
10068 sym_link *retype, *letype;
10069 sym_link *ptype = operandType (result);
10071 retype = getSpec (operandType (right));
10072 letype = getSpec (ptype);
10074 aopOp (result, ic, FALSE, FALSE);
10076 /* if the result is rematerializable &
10077 in data space & not a bit variable */
10078 if (AOP_TYPE (result) == AOP_IMMD &&
10079 DCL_TYPE (ptype) == POINTER &&
10080 !IS_BITVAR (retype) &&
10081 !IS_BITVAR (letype))
10083 genDataPointerSet (right, result, ic);
10087 /* if the value is already in a pointer register
10088 then don't need anything more */
10089 if (!AOP_INPREG (AOP (result)))
10091 /* otherwise get a free pointer register */
10094 aop = newAsmop (0);
10095 preg = getFreePtr (ic, &aop, FALSE);
10096 emitcode ("mov", "%s,%s",
10098 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10099 rname = preg->name;
10102 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10104 aopOp (right, ic, FALSE, FALSE);
10106 /* if bitfield then unpack the bits */
10107 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10108 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
10111 /* we have can just get the values */
10112 int size = AOP_SIZE (right);
10117 l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
10121 emitcode ("mov", "@%s,a", rname);
10124 emitcode ("mov", "@%s,%s", rname, l);
10126 emitcode ("inc", "%s", rname);
10131 /* now some housekeeping stuff */
10134 /* we had to allocate for this iCode */
10135 if (pi) aopPut (AOP (result),rname,0);
10136 freeAsmop (NULL, aop, ic, TRUE);
10140 /* we did not allocate which means left
10141 already in a pointer register, then
10142 if size > 0 && this could be used again
10143 we have to point it back to where it
10145 if (AOP_SIZE (right) > 1 &&
10146 !OP_SYMBOL (result)->remat &&
10147 (OP_SYMBOL (result)->liveTo > ic->seq ||
10151 int size = AOP_SIZE (right) - 1;
10153 emitcode ("dec", "%s", rname);
10158 if (pi) pi->generated = 1;
10159 freeAsmop (result, NULL, ic, TRUE);
10160 freeAsmop (right, NULL, ic, TRUE);
10165 /*-----------------------------------------------------------------*/
10166 /* genPagedPointerSet - emitcode for Paged pointer put */
10167 /*-----------------------------------------------------------------*/
10169 genPagedPointerSet (operand * right,
10176 sym_link *retype, *letype;
10178 retype = getSpec (operandType (right));
10179 letype = getSpec (operandType (result));
10181 aopOp (result, ic, FALSE, FALSE);
10183 /* if the value is already in a pointer register
10184 then don't need anything more */
10185 if (!AOP_INPREG (AOP (result)))
10187 /* otherwise get a free pointer register */
10190 aop = newAsmop (0);
10191 preg = getFreePtr (ic, &aop, FALSE);
10192 emitcode ("mov", "%s,%s",
10194 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10195 rname = preg->name;
10198 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10200 aopOp (right, ic, FALSE, FALSE);
10202 /* if bitfield then unpack the bits */
10203 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10204 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
10207 /* we have can just get the values */
10208 int size = AOP_SIZE (right);
10213 MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10215 emitcode ("movx", "@%s,a", rname);
10218 emitcode ("inc", "%s", rname);
10224 /* now some housekeeping stuff */
10227 if (pi) aopPut (AOP (result),rname,0);
10228 /* we had to allocate for this iCode */
10229 freeAsmop (NULL, aop, ic, TRUE);
10233 /* we did not allocate which means left
10234 already in a pointer register, then
10235 if size > 0 && this could be used again
10236 we have to point it back to where it
10238 if (AOP_SIZE (right) > 1 &&
10239 !OP_SYMBOL (result)->remat &&
10240 (OP_SYMBOL (result)->liveTo > ic->seq ||
10244 int size = AOP_SIZE (right) - 1;
10246 emitcode ("dec", "%s", rname);
10251 if (pi) pi->generated = 1;
10252 freeAsmop (result, NULL, ic, TRUE);
10253 freeAsmop (right, NULL, ic, TRUE);
10258 /*-----------------------------------------------------------------*/
10259 /* genFarPointerSet - set value from far space */
10260 /*-----------------------------------------------------------------*/
10262 genFarPointerSet (operand * right,
10263 operand * result, iCode * ic, iCode *pi)
10265 int size, offset, dopi=1;
10266 sym_link *retype = getSpec (operandType (right));
10267 sym_link *letype = getSpec (operandType (result));
10269 aopOp (result, ic, FALSE, FALSE);
10271 /* if the operand is already in dptr
10272 then we do nothing else we move the value to dptr */
10273 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10275 /* if this is remateriazable */
10276 if (AOP_TYPE (result) == AOP_IMMD)
10277 emitcode ("mov", "dptr,%s",
10278 aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10281 /* we need to get it byte by byte */
10282 _startLazyDPSEvaluation ();
10283 if (AOP_TYPE (result) != AOP_DPTR)
10285 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10286 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10287 if (options.model == MODEL_FLAT24)
10288 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10292 /* We need to generate a load to DPTR indirect through DPTR. */
10293 D (emitcode (";", "genFarPointerSet -- indirection special case."););
10295 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10296 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10297 if (options.model == MODEL_FLAT24)
10298 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10299 emitcode ("pop", "dph");
10300 emitcode ("pop", "dpl");
10303 _endLazyDPSEvaluation ();
10306 /* so dptr know contains the address */
10307 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10309 /* if bit then unpack */
10310 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
10311 if (AOP_INDPTRn(result)) {
10312 genSetDPTR(AOP(result)->aopu.dptr);
10314 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
10315 if (AOP_INDPTRn(result)) {
10319 size = AOP_SIZE (right);
10321 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10323 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10325 genSetDPTR(AOP(result)->aopu.dptr);
10326 emitcode ("movx", "@dptr,a");
10327 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10328 emitcode ("inc", "dptr");
10332 _startLazyDPSEvaluation ();
10334 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10336 if (AOP_INDPTRn(result)) {
10337 genSetDPTR(AOP(result)->aopu.dptr);
10343 emitcode ("movx", "@dptr,a");
10344 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10345 emitcode ("inc", "dptr");
10347 _endLazyDPSEvaluation ();
10351 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10352 if (!AOP_INDPTRn(result)) {
10353 _startLazyDPSEvaluation ();
10355 aopPut (AOP(result),"dpl",0);
10356 aopPut (AOP(result),"dph",1);
10357 if (options.model == MODEL_FLAT24)
10358 aopPut (AOP(result),"dpx",2);
10360 _endLazyDPSEvaluation ();
10363 } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
10364 AOP_SIZE(right) > 1 &&
10365 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10367 size = AOP_SIZE (right) - 1;
10368 if (AOP_INDPTRn(result)) {
10369 genSetDPTR(AOP(result)->aopu.dptr);
10371 while (size--) emitcode ("lcall","__decdptr");
10372 if (AOP_INDPTRn(result)) {
10376 freeAsmop (result, NULL, ic, TRUE);
10377 freeAsmop (right, NULL, ic, TRUE);
10380 /*-----------------------------------------------------------------*/
10381 /* genGenPointerSet - set value from generic pointer space */
10382 /*-----------------------------------------------------------------*/
10384 genGenPointerSet (operand * right,
10385 operand * result, iCode * ic, iCode *pi)
10388 sym_link *retype = getSpec (operandType (right));
10389 sym_link *letype = getSpec (operandType (result));
10391 aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10393 /* if the operand is already in dptr
10394 then we do nothing else we move the value to dptr */
10395 if (AOP_TYPE (result) != AOP_STR)
10397 _startLazyDPSEvaluation ();
10398 /* if this is remateriazable */
10399 if (AOP_TYPE (result) == AOP_IMMD)
10401 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10402 if (AOP(result)->aopu.aop_immd.from_cast_remat)
10404 MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10409 "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10413 { /* we need to get it byte by byte */
10414 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10415 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10416 if (options.model == MODEL_FLAT24) {
10417 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10418 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10420 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10423 _endLazyDPSEvaluation ();
10425 /* so dptr + b now contains the address */
10427 aopOp (right, ic, FALSE, TRUE);
10431 /* if bit then unpack */
10432 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10434 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
10438 size = AOP_SIZE (right);
10441 _startLazyDPSEvaluation ();
10446 // Set two bytes at a time, passed in _AP & A.
10447 // dptr will be incremented ONCE by __gptrputWord.
10449 // Note: any change here must be coordinated
10450 // with the implementation of __gptrputWord
10451 // in device/lib/_gptrput.c
10452 emitcode("mov", "_ap, %s",
10453 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10454 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10458 emitcode ("lcall", "__gptrputWord");
10463 // Only one byte to put.
10464 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10468 emitcode ("lcall", "__gptrput");
10471 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10473 emitcode ("inc", "dptr");
10476 _endLazyDPSEvaluation ();
10479 if (pi && AOP_TYPE (result) != AOP_IMMD) {
10480 _startLazyDPSEvaluation ();
10482 aopPut (AOP(result),"dpl",0);
10483 aopPut (AOP(result),"dph",1);
10484 if (options.model == MODEL_FLAT24) {
10485 aopPut (AOP(result),"dpx",2);
10486 aopPut (AOP(result),"b",3);
10488 aopPut (AOP(result),"b",2);
10490 _endLazyDPSEvaluation ();
10493 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10494 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10496 size = AOP_SIZE (right) - 1;
10497 while (size--) emitcode ("lcall","__decdptr");
10499 freeAsmop (result, NULL, ic, TRUE);
10500 freeAsmop (right, NULL, ic, TRUE);
10503 /*-----------------------------------------------------------------*/
10504 /* genPointerSet - stores the value into a pointer location */
10505 /*-----------------------------------------------------------------*/
10507 genPointerSet (iCode * ic, iCode *pi)
10509 operand *right, *result;
10510 sym_link *type, *etype;
10513 D (emitcode (";", "genPointerSet "););
10515 right = IC_RIGHT (ic);
10516 result = IC_RESULT (ic);
10518 /* depending on the type of pointer we need to
10519 move it to the correct pointer register */
10520 type = operandType (result);
10521 etype = getSpec (type);
10522 /* if left is of type of pointer then it is simple */
10523 if (IS_PTR (type) && !IS_FUNC (type->next))
10525 p_type = DCL_TYPE (type);
10529 /* we have to go by the storage class */
10530 p_type = PTR_TYPE (SPEC_OCLS (etype));
10532 /* special case when cast remat */
10533 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10534 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10535 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10536 type = operandType (result);
10537 p_type = DCL_TYPE (type);
10540 /* now that we have the pointer type we assign
10541 the pointer values */
10547 genNearPointerSet (right, result, ic, pi);
10551 genPagedPointerSet (right, result, ic, pi);
10555 genFarPointerSet (right, result, ic, pi);
10559 genGenPointerSet (right, result, ic, pi);
10563 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10564 "genPointerSet: illegal pointer type");
10569 /*-----------------------------------------------------------------*/
10570 /* genIfx - generate code for Ifx statement */
10571 /*-----------------------------------------------------------------*/
10573 genIfx (iCode * ic, iCode * popIc)
10575 operand *cond = IC_COND (ic);
10578 D (emitcode (";", "genIfx "););
10580 aopOp (cond, ic, FALSE, FALSE);
10582 /* get the value into acc */
10583 if (AOP_TYPE (cond) != AOP_CRY)
10592 /* the result is now in the accumulator */
10593 freeAsmop (cond, NULL, ic, TRUE);
10595 /* if there was something to be popped then do it */
10599 /* if the condition is a bit variable */
10600 if (isbit && IS_ITEMP (cond) &&
10603 genIfxJump (ic, SPIL_LOC (cond)->rname);
10605 else if (isbit && !IS_ITEMP (cond))
10607 genIfxJump (ic, OP_SYMBOL (cond)->rname);
10611 genIfxJump (ic, "a");
10617 /*-----------------------------------------------------------------*/
10618 /* genAddrOf - generates code for address of */
10619 /*-----------------------------------------------------------------*/
10621 genAddrOf (iCode * ic)
10623 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10626 D (emitcode (";", "genAddrOf ");
10629 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10631 /* if the operand is on the stack then we
10632 need to get the stack offset of this
10634 if (sym->onStack) {
10636 /* if 10 bit stack */
10637 if (options.stack10bit) {
10641 tsprintf(buff, sizeof(buff),
10642 "#!constbyte",(options.stack_loc >> 16) & 0xff);
10643 /* if it has an offset then we need to compute it */
10644 /* emitcode ("subb", "a,#!constbyte", */
10645 /* -((sym->stack < 0) ? */
10646 /* ((short) (sym->stack - _G.nRegsSaved)) : */
10647 /* ((short) sym->stack)) & 0xff); */
10648 /* emitcode ("mov","b,a"); */
10649 /* emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
10650 /* ((short) (sym->stack - _G.nRegsSaved)) : */
10651 /* ((short) sym->stack)) >> 8) & 0xff); */
10653 emitcode ("mov", "a,_bpx");
10654 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
10655 ((char) (sym->stack - _G.nRegsSaved)) :
10656 ((char) sym->stack )) & 0xff);
10657 emitcode ("mov", "b,a");
10658 emitcode ("mov", "a,_bpx+1");
10660 offset = (((sym->stack < 0) ?
10661 ((short) (sym->stack - _G.nRegsSaved)) :
10662 ((short) sym->stack )) >> 8) & 0xff;
10664 emitcode ("addc","a,#!constbyte", offset);
10666 aopPut (AOP (IC_RESULT (ic)), "b", 0);
10667 aopPut (AOP (IC_RESULT (ic)), "a", 1);
10668 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10670 /* we can just move _bp */
10671 aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10672 aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10673 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10676 /* if it has an offset then we need to compute it */
10678 emitcode ("mov", "a,_bp");
10679 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10680 aopPut (AOP (IC_RESULT (ic)), "a", 0);
10682 /* we can just move _bp */
10683 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10685 /* fill the result with zero */
10686 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10689 if (options.stack10bit && size < (FPTRSIZE - 1)) {
10691 "*** warning: pointer to stack var truncated.\n");
10696 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10702 /* object not on stack then we need the name */
10703 size = AOP_SIZE (IC_RESULT (ic));
10708 char s[SDCC_NAME_MAX];
10712 tsprintf(s, sizeof(s), "#!his",sym->rname);
10715 tsprintf(s, sizeof(s), "#!hihis",sym->rname);
10718 tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
10720 default: /* should not need this (just in case) */
10721 SNPRINTF (s, sizeof(s), "#(%s >> %d)",
10728 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10731 aopPut (AOP (IC_RESULT (ic)), s, offset++);
10735 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10739 #if 0 // obsolete, and buggy for != xdata
10740 /*-----------------------------------------------------------------*/
10741 /* genArrayInit - generates code for address of */
10742 /*-----------------------------------------------------------------*/
10744 genArrayInit (iCode * ic)
10746 literalList *iLoop;
10748 int elementSize = 0, eIndex;
10749 unsigned val, lastVal;
10751 operand *left=IC_LEFT(ic);
10753 D (emitcode (";", "genArrayInit "););
10755 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10757 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10759 // Load immediate value into DPTR.
10760 emitcode("mov", "dptr, %s",
10761 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
10763 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10766 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10767 "Unexpected operand to genArrayInit.\n");
10770 // a regression because of SDCCcse.c:1.52
10771 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10772 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10773 if (options.model == MODEL_FLAT24)
10774 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10778 type = operandType(IC_LEFT(ic));
10780 if (type && type->next)
10782 elementSize = getSize(type->next);
10786 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10787 "can't determine element size in genArrayInit.\n");
10791 iLoop = IC_ARRAYILIST(ic);
10796 bool firstpass = TRUE;
10798 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
10799 iLoop->count, (int)iLoop->literalValue, elementSize);
10805 symbol *tlbl = NULL;
10807 count = ix > 256 ? 256 : ix;
10811 tlbl = newiTempLabel (NULL);
10812 if (firstpass || (count & 0xff))
10814 emitcode("mov", "b, #!constbyte", count & 0xff);
10817 emitcode ("", "!tlabeldef", tlbl->key + 100);
10822 for (eIndex = 0; eIndex < elementSize; eIndex++)
10824 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10825 if (val != lastVal)
10827 emitcode("mov", "a, #!constbyte", val);
10831 emitcode("movx", "@dptr, a");
10832 emitcode("inc", "dptr");
10837 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10843 iLoop = iLoop->next;
10846 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10850 /*-----------------------------------------------------------------*/
10851 /* genFarFarAssign - assignment when both are in far space */
10852 /*-----------------------------------------------------------------*/
10854 genFarFarAssign (operand * result, operand * right, iCode * ic)
10856 int size = AOP_SIZE (right);
10858 symbol *rSym = NULL;
10862 /* quick & easy case. */
10863 D(emitcode(";","genFarFarAssign (1 byte case)"););
10864 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
10865 freeAsmop (right, NULL, ic, FALSE);
10866 /* now assign DPTR to result */
10868 aopOp(result, ic, FALSE, FALSE);
10870 aopPut(AOP(result), "a", 0);
10871 freeAsmop(result, NULL, ic, FALSE);
10875 /* See if we've got an underlying symbol to abuse. */
10876 if (IS_SYMOP(result) && OP_SYMBOL(result))
10878 if (IS_TRUE_SYMOP(result))
10880 rSym = OP_SYMBOL(result);
10882 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10884 rSym = OP_SYMBOL(result)->usl.spillLoc;
10888 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10890 /* We can use the '390 auto-toggle feature to good effect here. */
10892 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10893 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
10894 emitcode ("mov", "dptr,#%s", rSym->rname);
10895 /* DP2 = result, DP1 = right, DP1 is current. */
10898 emitcode("movx", "a,@dptr");
10899 emitcode("movx", "@dptr,a");
10902 emitcode("inc", "dptr");
10903 emitcode("inc", "dptr");
10906 emitcode("mov", "dps,#0");
10907 freeAsmop (right, NULL, ic, FALSE);
10909 some alternative code for processors without auto-toggle
10910 no time to test now, so later well put in...kpb
10911 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10912 emitcode("mov", "dps,#1"); /* Select DPTR2. */
10913 emitcode ("mov", "dptr,#%s", rSym->rname);
10914 /* DP2 = result, DP1 = right, DP1 is current. */
10918 emitcode("movx", "a,@dptr");
10920 emitcode("inc", "dptr");
10921 emitcode("inc", "dps");
10922 emitcode("movx", "@dptr,a");
10924 emitcode("inc", "dptr");
10925 emitcode("inc", "dps");
10927 emitcode("mov", "dps,#0");
10928 freeAsmop (right, NULL, ic, FALSE);
10933 D (emitcode (";", "genFarFarAssign"););
10934 aopOp (result, ic, TRUE, TRUE);
10936 _startLazyDPSEvaluation ();
10940 aopPut (AOP (result),
10941 aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
10944 _endLazyDPSEvaluation ();
10945 freeAsmop (result, NULL, ic, FALSE);
10946 freeAsmop (right, NULL, ic, FALSE);
10950 /*-----------------------------------------------------------------*/
10951 /* genAssign - generate code for assignment */
10952 /*-----------------------------------------------------------------*/
10954 genAssign (iCode * ic)
10956 operand *result, *right;
10958 unsigned long lit = 0L;
10960 D (emitcode (";", "genAssign ");
10963 result = IC_RESULT (ic);
10964 right = IC_RIGHT (ic);
10966 /* if they are the same */
10967 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10970 aopOp (right, ic, FALSE, FALSE);
10972 emitcode (";", "genAssign: resultIsFar = %s",
10973 isOperandInFarSpace (result) ?
10976 /* special case both in far space */
10977 if ((AOP_TYPE (right) == AOP_DPTR ||
10978 AOP_TYPE (right) == AOP_DPTR2) &&
10979 /* IS_TRUE_SYMOP(result) && */
10980 isOperandInFarSpace (result))
10982 genFarFarAssign (result, right, ic);
10986 aopOp (result, ic, TRUE, FALSE);
10988 /* if they are the same registers */
10989 if (sameRegs (AOP (right), AOP (result)))
10992 /* if the result is a bit */
10993 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10995 /* if the right size is a literal then
10996 we know what the value is */
10997 if (AOP_TYPE (right) == AOP_LIT)
10999 if (((int) operandLitValue (right)))
11000 aopPut (AOP (result), one, 0);
11002 aopPut (AOP (result), zero, 0);
11006 /* the right is also a bit variable */
11007 if (AOP_TYPE (right) == AOP_CRY)
11009 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11010 aopPut (AOP (result), "c", 0);
11014 /* we need to or */
11016 aopPut (AOP (result), "a", 0);
11020 /* bit variables done */
11022 size = AOP_SIZE (result);
11024 if (AOP_TYPE (right) == AOP_LIT)
11025 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11028 (AOP_TYPE (result) != AOP_REG) &&
11029 (AOP_TYPE (right) == AOP_LIT) &&
11030 !IS_FLOAT (operandType (right)))
11032 _startLazyDPSEvaluation ();
11033 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
11035 aopPut (AOP (result),
11036 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11041 /* And now fill the rest with zeros. */
11044 emitcode ("clr", "a");
11048 aopPut (AOP (result), "a", offset++);
11050 _endLazyDPSEvaluation ();
11054 _startLazyDPSEvaluation ();
11057 aopPut (AOP (result),
11058 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11062 _endLazyDPSEvaluation ();
11066 freeAsmop (right, NULL, ic, FALSE);
11067 freeAsmop (result, NULL, ic, TRUE);
11070 /*-----------------------------------------------------------------*/
11071 /* genJumpTab - generates code for jump table */
11072 /*-----------------------------------------------------------------*/
11074 genJumpTab (iCode * ic)
11079 D (emitcode (";", "genJumpTab ");
11082 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
11083 /* get the condition into accumulator */
11084 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
11086 /* multiply by four! */
11087 emitcode ("add", "a,acc");
11088 emitcode ("add", "a,acc");
11089 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11091 jtab = newiTempLabel (NULL);
11092 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
11093 emitcode ("jmp", "@a+dptr");
11094 emitcode ("", "!tlabeldef", jtab->key + 100);
11095 /* now generate the jump labels */
11096 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11097 jtab = setNextItem (IC_JTLABELS (ic)))
11098 emitcode ("ljmp", "!tlabel", jtab->key + 100);
11102 /*-----------------------------------------------------------------*/
11103 /* genCast - gen code for casting */
11104 /*-----------------------------------------------------------------*/
11106 genCast (iCode * ic)
11108 operand *result = IC_RESULT (ic);
11109 sym_link *ctype = operandType (IC_LEFT (ic));
11110 sym_link *rtype = operandType (IC_RIGHT (ic));
11111 operand *right = IC_RIGHT (ic);
11114 D (emitcode (";", "genCast "););
11116 /* if they are equivalent then do nothing */
11117 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11120 aopOp (right, ic, FALSE, FALSE);
11121 aopOp (result, ic, FALSE, (AOP_TYPE(right) == AOP_DPTR));
11123 /* if the result is a bit */
11124 if (IS_BITVAR (OP_SYMBOL (result)->type)
11125 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
11127 /* if the right size is a literal then
11128 we know what the value is */
11129 if (AOP_TYPE (right) == AOP_LIT)
11131 if (((int) operandLitValue (right)))
11132 aopPut (AOP (result), one, 0);
11134 aopPut (AOP (result), zero, 0);
11139 /* the right is also a bit variable */
11140 if (AOP_TYPE (right) == AOP_CRY)
11142 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11143 aopPut (AOP (result), "c", 0);
11147 /* we need to or */
11149 aopPut (AOP (result), "a", 0);
11153 /* if they are the same size : or less */
11154 if (AOP_SIZE (result) <= AOP_SIZE (right))
11157 /* if they are in the same place */
11158 if (sameRegs (AOP (right), AOP (result)))
11161 /* if they in different places then copy */
11162 size = AOP_SIZE (result);
11164 _startLazyDPSEvaluation ();
11167 aopPut (AOP (result),
11168 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11172 _endLazyDPSEvaluation ();
11177 /* if the result is of type pointer */
11178 if (IS_PTR (ctype))
11182 sym_link *type = operandType (right);
11184 /* pointer to generic pointer */
11185 if (IS_GENPTR (ctype))
11189 p_type = DCL_TYPE (type);
11193 #if OLD_CAST_BEHAVIOR
11194 /* KV: we are converting a non-pointer type to
11195 * a generic pointer. This (ifdef'd out) code
11196 * says that the resulting generic pointer
11197 * should have the same class as the storage
11198 * location of the non-pointer variable.
11200 * For example, converting an int (which happens
11201 * to be stored in DATA space) to a pointer results
11202 * in a DATA generic pointer; if the original int
11203 * in XDATA space, so will be the resulting pointer.
11205 * I don't like that behavior, and thus this change:
11206 * all such conversions will be forced to XDATA and
11207 * throw a warning. If you want some non-XDATA
11208 * type, or you want to suppress the warning, you
11209 * must go through an intermediate cast, like so:
11211 * char _generic *gp = (char _xdata *)(intVar);
11213 sym_link *etype = getSpec (type);
11215 /* we have to go by the storage class */
11216 if (SPEC_OCLS (etype) != generic)
11218 p_type = PTR_TYPE (SPEC_OCLS (etype));
11223 /* Converting unknown class (i.e. register variable)
11224 * to generic pointer. This is not good, but
11225 * we'll make a guess (and throw a warning).
11228 werror (W_INT_TO_GEN_PTR_CAST);
11232 /* the first two bytes are known */
11233 size = GPTRSIZE - 1;
11235 _startLazyDPSEvaluation ();
11238 aopPut (AOP (result),
11239 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11243 _endLazyDPSEvaluation ();
11245 /* the last byte depending on type */
11247 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11252 // pointerTypeToGPByte will have bitched.
11256 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11257 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11262 /* just copy the pointers */
11263 size = AOP_SIZE (result);
11265 _startLazyDPSEvaluation ();
11268 aopPut (AOP (result),
11269 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11273 _endLazyDPSEvaluation ();
11277 /* so we now know that the size of destination is greater
11278 than the size of the source */
11279 /* we move to result for the size of source */
11280 size = AOP_SIZE (right);
11282 _startLazyDPSEvaluation ();
11285 aopPut (AOP (result),
11286 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11290 _endLazyDPSEvaluation ();
11292 /* now depending on the sign of the source && destination */
11293 size = AOP_SIZE (result) - AOP_SIZE (right);
11294 /* if unsigned or not an integral type */
11295 /* also, if the source is a bit, we don't need to sign extend, because
11296 * it can't possibly have set the sign bit.
11298 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
11302 aopPut (AOP (result), zero, offset++);
11307 /* we need to extend the sign :{ */
11308 MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11309 FALSE, FALSE, NULL));
11310 emitcode ("rlc", "a");
11311 emitcode ("subb", "a,acc");
11313 aopPut (AOP (result), "a", offset++);
11316 /* we are done hurray !!!! */
11319 freeAsmop (right, NULL, ic, TRUE);
11320 freeAsmop (result, NULL, ic, TRUE);
11324 /*-----------------------------------------------------------------*/
11325 /* genDjnz - generate decrement & jump if not zero instrucion */
11326 /*-----------------------------------------------------------------*/
11328 genDjnz (iCode * ic, iCode * ifx)
11330 symbol *lbl, *lbl1;
11334 /* if the if condition has a false label
11335 then we cannot save */
11336 if (IC_FALSE (ifx))
11339 /* if the minus is not of the form
11341 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11342 !IS_OP_LITERAL (IC_RIGHT (ic)))
11345 if (operandLitValue (IC_RIGHT (ic)) != 1)
11348 /* if the size of this greater than one then no
11350 if (getSize (operandType (IC_RESULT (ic))) > 1)
11353 /* otherwise we can save BIG */
11354 D(emitcode(";", "genDjnz"););
11356 lbl = newiTempLabel (NULL);
11357 lbl1 = newiTempLabel (NULL);
11359 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11361 if (AOP_NEEDSACC(IC_RESULT(ic)))
11363 /* If the result is accessed indirectly via
11364 * the accumulator, we must explicitly write
11365 * it back after the decrement.
11367 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11369 if (strcmp(rByte, "a"))
11371 /* Something is hopelessly wrong */
11372 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11373 __FILE__, __LINE__);
11374 /* We can just give up; the generated code will be inefficient,
11375 * but what the hey.
11377 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11380 emitcode ("dec", "%s", rByte);
11381 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11382 emitcode ("jnz", "!tlabel", lbl->key + 100);
11384 else if (IS_AOP_PREG (IC_RESULT (ic)))
11386 emitcode ("dec", "%s",
11387 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11388 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11389 emitcode ("jnz", "!tlabel", lbl->key + 100);
11393 emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11396 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11397 emitcode ("", "!tlabeldef", lbl->key + 100);
11398 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11399 emitcode ("", "!tlabeldef", lbl1->key + 100);
11401 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11402 ifx->generated = 1;
11406 /*-----------------------------------------------------------------*/
11407 /* genReceive - generate code for a receive iCode */
11408 /*-----------------------------------------------------------------*/
11410 genReceive (iCode * ic)
11412 int size = getSize (operandType (IC_RESULT (ic)));
11416 D (emitcode (";", "genReceive "););
11418 if (ic->argreg == 1)
11420 /* first parameter */
11421 if (AOP_IS_STR(IC_RESULT(ic)))
11423 /* Nothing to do: it's already in the proper place. */
11430 useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11431 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11432 IS_TRUE_SYMOP (IC_RESULT (ic)));
11435 aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11438 /* Sanity checking... */
11439 if (AOP_USESDPTR(IC_RESULT(ic)))
11441 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11442 "genReceive got unexpected DPTR.");
11444 assignResultValue (IC_RESULT (ic));
11449 /* second receive onwards */
11450 /* this gets a little tricky since unused recevies will be
11451 eliminated, we have saved the reg in the type field . and
11452 we use that to figure out which register to use */
11453 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11454 rb1off = ic->argreg;
11457 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11460 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11463 /*-----------------------------------------------------------------*/
11464 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
11465 /*-----------------------------------------------------------------*/
11466 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11468 operand *from , *to , *count;
11473 /* we know it has to be 3 parameters */
11474 assert (nparms == 3);
11476 rsave = newBitVect(16);
11477 /* save DPTR if it needs to be saved */
11478 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11479 if (bitVectBitValue(ic->rMask,i))
11480 rsave = bitVectSetBit(rsave,i);
11482 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11483 ds390_rUmaskForOp (IC_RESULT(ic))));
11490 aopOp (from, ic->next, FALSE, FALSE);
11492 /* get from into DPTR1 */
11493 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11494 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11495 if (options.model == MODEL_FLAT24) {
11496 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11499 freeAsmop (from, NULL, ic, FALSE);
11500 aopOp (to, ic, FALSE, FALSE);
11501 /* get "to" into DPTR */
11502 /* if the operand is already in dptr
11503 then we do nothing else we move the value to dptr */
11504 if (AOP_TYPE (to) != AOP_STR) {
11505 /* if already in DPTR then we need to push */
11506 if (AOP_TYPE(to) == AOP_DPTR) {
11507 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11508 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11509 if (options.model == MODEL_FLAT24)
11510 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11511 emitcode ("pop", "dph");
11512 emitcode ("pop", "dpl");
11514 _startLazyDPSEvaluation ();
11515 /* if this is remateriazable */
11516 if (AOP_TYPE (to) == AOP_IMMD) {
11517 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11518 } else { /* we need to get it byte by byte */
11519 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11520 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11521 if (options.model == MODEL_FLAT24) {
11522 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11525 _endLazyDPSEvaluation ();
11528 freeAsmop (to, NULL, ic, FALSE);
11529 _G.dptrInUse = _G.dptr1InUse = 1;
11530 aopOp (count, ic->next->next, FALSE,FALSE);
11531 lbl =newiTempLabel(NULL);
11533 /* now for the actual copy */
11534 if (AOP_TYPE(count) == AOP_LIT &&
11535 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11536 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11538 emitcode ("lcall","__bi_memcpyc2x_s");
11540 emitcode ("lcall","__bi_memcpyx2x_s");
11542 freeAsmop (count, NULL, ic, FALSE);
11544 symbol *lbl1 = newiTempLabel(NULL);
11546 emitcode (";"," Auto increment but no djnz");
11547 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11548 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11549 freeAsmop (count, NULL, ic, FALSE);
11550 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11551 emitcode ("","!tlabeldef",lbl->key+100);
11553 emitcode ("clr","a");
11554 emitcode ("movc", "a,@a+dptr");
11556 emitcode ("movx", "a,@dptr");
11557 emitcode ("movx", "@dptr,a");
11558 emitcode ("inc", "dptr");
11559 emitcode ("inc", "dptr");
11560 emitcode ("mov","a,b");
11561 emitcode ("orl","a,_ap");
11562 emitcode ("jz","!tlabel",lbl1->key+100);
11563 emitcode ("mov","a,_ap");
11564 emitcode ("add","a,#!constbyte",0xFF);
11565 emitcode ("mov","_ap,a");
11566 emitcode ("mov","a,b");
11567 emitcode ("addc","a,#!constbyte",0xFF);
11568 emitcode ("mov","b,a");
11569 emitcode ("sjmp","!tlabel",lbl->key+100);
11570 emitcode ("","!tlabeldef",lbl1->key+100);
11572 emitcode ("mov", "dps,#0");
11573 _G.dptrInUse = _G.dptr1InUse = 0;
11574 unsavermask(rsave);
11578 /*-----------------------------------------------------------------*/
11579 /* genMemcmpX2X - gen code for memcmp xdata to xdata */
11580 /*-----------------------------------------------------------------*/
11581 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11583 operand *from , *to , *count;
11588 /* we know it has to be 3 parameters */
11589 assert (nparms == 3);
11591 rsave = newBitVect(16);
11592 /* save DPTR if it needs to be saved */
11593 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11594 if (bitVectBitValue(ic->rMask,i))
11595 rsave = bitVectSetBit(rsave,i);
11597 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11598 ds390_rUmaskForOp (IC_RESULT(ic))));
11605 aopOp (from, ic->next, FALSE, FALSE);
11607 /* get from into DPTR1 */
11608 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11609 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11610 if (options.model == MODEL_FLAT24) {
11611 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11614 freeAsmop (from, NULL, ic, FALSE);
11615 aopOp (to, ic, FALSE, FALSE);
11616 /* get "to" into DPTR */
11617 /* if the operand is already in dptr
11618 then we do nothing else we move the value to dptr */
11619 if (AOP_TYPE (to) != AOP_STR) {
11620 /* if already in DPTR then we need to push */
11621 if (AOP_TYPE(to) == AOP_DPTR) {
11622 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11623 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11624 if (options.model == MODEL_FLAT24)
11625 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11626 emitcode ("pop", "dph");
11627 emitcode ("pop", "dpl");
11629 _startLazyDPSEvaluation ();
11630 /* if this is remateriazable */
11631 if (AOP_TYPE (to) == AOP_IMMD) {
11632 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11633 } else { /* we need to get it byte by byte */
11634 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11635 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11636 if (options.model == MODEL_FLAT24) {
11637 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11640 _endLazyDPSEvaluation ();
11643 freeAsmop (to, NULL, ic, FALSE);
11644 _G.dptrInUse = _G.dptr1InUse = 1;
11645 aopOp (count, ic->next->next, FALSE,FALSE);
11646 lbl =newiTempLabel(NULL);
11647 lbl2 =newiTempLabel(NULL);
11649 /* now for the actual compare */
11650 if (AOP_TYPE(count) == AOP_LIT &&
11651 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11652 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11654 emitcode("lcall","__bi_memcmpc2x_s");
11656 emitcode("lcall","__bi_memcmpx2x_s");
11657 freeAsmop (count, NULL, ic, FALSE);
11658 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11659 aopPut(AOP(IC_RESULT(ic)),"a",0);
11660 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11662 symbol *lbl1 = newiTempLabel(NULL);
11664 emitcode("push","ar0");
11665 emitcode (";"," Auto increment but no djnz");
11666 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11667 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11668 freeAsmop (count, NULL, ic, FALSE);
11669 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11670 emitcode ("","!tlabeldef",lbl->key+100);
11672 emitcode ("clr","a");
11673 emitcode ("movc", "a,@a+dptr");
11675 emitcode ("movx", "a,@dptr");
11676 emitcode ("mov","r0,a");
11677 emitcode ("movx", "a,@dptr");
11678 emitcode ("clr","c");
11679 emitcode ("subb","a,r0");
11680 emitcode ("jnz","!tlabel",lbl2->key+100);
11681 emitcode ("inc", "dptr");
11682 emitcode ("inc", "dptr");
11683 emitcode ("mov","a,b");
11684 emitcode ("orl","a,_ap");
11685 emitcode ("jz","!tlabel",lbl1->key+100);
11686 emitcode ("mov","a,_ap");
11687 emitcode ("add","a,#!constbyte",0xFF);
11688 emitcode ("mov","_ap,a");
11689 emitcode ("mov","a,b");
11690 emitcode ("addc","a,#!constbyte",0xFF);
11691 emitcode ("mov","b,a");
11692 emitcode ("sjmp","!tlabel",lbl->key+100);
11693 emitcode ("","!tlabeldef",lbl1->key+100);
11694 emitcode ("clr","a");
11695 emitcode ("","!tlabeldef",lbl2->key+100);
11696 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11697 aopPut(AOP(IC_RESULT(ic)),"a",0);
11698 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11699 emitcode("pop","ar0");
11700 emitcode ("mov", "dps,#0");
11702 _G.dptrInUse = _G.dptr1InUse = 0;
11703 unsavermask(rsave);
11707 /*-----------------------------------------------------------------*/
11708 /* genInp - gen code for __builtin_inp read data from a mem mapped */
11709 /* port, first parameter output area second parameter pointer to */
11710 /* port third parameter count */
11711 /*-----------------------------------------------------------------*/
11712 static void genInp( iCode *ic, int nparms, operand **parms)
11714 operand *from , *to , *count;
11719 /* we know it has to be 3 parameters */
11720 assert (nparms == 3);
11722 rsave = newBitVect(16);
11723 /* save DPTR if it needs to be saved */
11724 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11725 if (bitVectBitValue(ic->rMask,i))
11726 rsave = bitVectSetBit(rsave,i);
11728 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11729 ds390_rUmaskForOp (IC_RESULT(ic))));
11736 aopOp (from, ic->next, FALSE, FALSE);
11738 /* get from into DPTR1 */
11739 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11740 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11741 if (options.model == MODEL_FLAT24) {
11742 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11745 freeAsmop (from, NULL, ic, FALSE);
11746 aopOp (to, ic, FALSE, FALSE);
11747 /* get "to" into DPTR */
11748 /* if the operand is already in dptr
11749 then we do nothing else we move the value to dptr */
11750 if (AOP_TYPE (to) != AOP_STR) {
11751 /* if already in DPTR then we need to push */
11752 if (AOP_TYPE(to) == AOP_DPTR) {
11753 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11754 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11755 if (options.model == MODEL_FLAT24)
11756 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11757 emitcode ("pop", "dph");
11758 emitcode ("pop", "dpl");
11760 _startLazyDPSEvaluation ();
11761 /* if this is remateriazable */
11762 if (AOP_TYPE (to) == AOP_IMMD) {
11763 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11764 } else { /* we need to get it byte by byte */
11765 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11766 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11767 if (options.model == MODEL_FLAT24) {
11768 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11771 _endLazyDPSEvaluation ();
11774 freeAsmop (to, NULL, ic, FALSE);
11776 _G.dptrInUse = _G.dptr1InUse = 1;
11777 aopOp (count, ic->next->next, FALSE,FALSE);
11778 lbl =newiTempLabel(NULL);
11780 /* now for the actual copy */
11781 if (AOP_TYPE(count) == AOP_LIT &&
11782 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11783 emitcode (";","OH JOY auto increment with djnz (very fast)");
11784 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11785 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11786 freeAsmop (count, NULL, ic, FALSE);
11787 emitcode ("","!tlabeldef",lbl->key+100);
11788 emitcode ("movx", "a,@dptr"); /* read data from port */
11789 emitcode ("dec","dps"); /* switch to DPTR */
11790 emitcode ("movx", "@dptr,a"); /* save into location */
11791 emitcode ("inc", "dptr"); /* point to next area */
11792 emitcode ("inc","dps"); /* switch to DPTR2 */
11793 emitcode ("djnz","b,!tlabel",lbl->key+100);
11795 symbol *lbl1 = newiTempLabel(NULL);
11797 emitcode (";"," Auto increment but no djnz");
11798 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11799 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11800 freeAsmop (count, NULL, ic, FALSE);
11801 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11802 emitcode ("","!tlabeldef",lbl->key+100);
11803 emitcode ("movx", "a,@dptr");
11804 emitcode ("dec","dps"); /* switch to DPTR */
11805 emitcode ("movx", "@dptr,a");
11806 emitcode ("inc", "dptr");
11807 emitcode ("inc","dps"); /* switch to DPTR2 */
11808 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
11809 /* emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
11810 emitcode ("mov","a,b");
11811 emitcode ("orl","a,_ap");
11812 emitcode ("jz","!tlabel",lbl1->key+100);
11813 emitcode ("mov","a,_ap");
11814 emitcode ("add","a,#!constbyte",0xFF);
11815 emitcode ("mov","_ap,a");
11816 emitcode ("mov","a,b");
11817 emitcode ("addc","a,#!constbyte",0xFF);
11818 emitcode ("mov","b,a");
11819 emitcode ("sjmp","!tlabel",lbl->key+100);
11820 emitcode ("","!tlabeldef",lbl1->key+100);
11822 emitcode ("mov", "dps,#0");
11823 _G.dptrInUse = _G.dptr1InUse = 0;
11824 unsavermask(rsave);
11828 /*-----------------------------------------------------------------*/
11829 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
11830 /* port, first parameter output area second parameter pointer to */
11831 /* port third parameter count */
11832 /*-----------------------------------------------------------------*/
11833 static void genOutp( iCode *ic, int nparms, operand **parms)
11835 operand *from , *to , *count;
11840 /* we know it has to be 3 parameters */
11841 assert (nparms == 3);
11843 rsave = newBitVect(16);
11844 /* save DPTR if it needs to be saved */
11845 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11846 if (bitVectBitValue(ic->rMask,i))
11847 rsave = bitVectSetBit(rsave,i);
11849 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11850 ds390_rUmaskForOp (IC_RESULT(ic))));
11857 aopOp (from, ic->next, FALSE, FALSE);
11859 /* get from into DPTR1 */
11860 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11861 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11862 if (options.model == MODEL_FLAT24) {
11863 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11866 freeAsmop (from, NULL, ic, FALSE);
11867 aopOp (to, ic, FALSE, FALSE);
11868 /* get "to" into DPTR */
11869 /* if the operand is already in dptr
11870 then we do nothing else we move the value to dptr */
11871 if (AOP_TYPE (to) != AOP_STR) {
11872 /* if already in DPTR then we need to push */
11873 if (AOP_TYPE(to) == AOP_DPTR) {
11874 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11875 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11876 if (options.model == MODEL_FLAT24)
11877 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11878 emitcode ("pop", "dph");
11879 emitcode ("pop", "dpl");
11881 _startLazyDPSEvaluation ();
11882 /* if this is remateriazable */
11883 if (AOP_TYPE (to) == AOP_IMMD) {
11884 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11885 } else { /* we need to get it byte by byte */
11886 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11887 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11888 if (options.model == MODEL_FLAT24) {
11889 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11892 _endLazyDPSEvaluation ();
11895 freeAsmop (to, NULL, ic, FALSE);
11897 _G.dptrInUse = _G.dptr1InUse = 1;
11898 aopOp (count, ic->next->next, FALSE,FALSE);
11899 lbl =newiTempLabel(NULL);
11901 /* now for the actual copy */
11902 if (AOP_TYPE(count) == AOP_LIT &&
11903 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11904 emitcode (";","OH JOY auto increment with djnz (very fast)");
11905 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
11906 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11907 emitcode ("","!tlabeldef",lbl->key+100);
11908 emitcode ("movx", "a,@dptr"); /* read data from port */
11909 emitcode ("inc","dps"); /* switch to DPTR2 */
11910 emitcode ("movx", "@dptr,a"); /* save into location */
11911 emitcode ("inc", "dptr"); /* point to next area */
11912 emitcode ("dec","dps"); /* switch to DPTR */
11913 emitcode ("djnz","b,!tlabel",lbl->key+100);
11914 freeAsmop (count, NULL, ic, FALSE);
11916 symbol *lbl1 = newiTempLabel(NULL);
11918 emitcode (";"," Auto increment but no djnz");
11919 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11920 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11921 freeAsmop (count, NULL, ic, FALSE);
11922 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
11923 emitcode ("","!tlabeldef",lbl->key+100);
11924 emitcode ("movx", "a,@dptr");
11925 emitcode ("inc", "dptr");
11926 emitcode ("inc","dps"); /* switch to DPTR2 */
11927 emitcode ("movx", "@dptr,a");
11928 emitcode ("dec","dps"); /* switch to DPTR */
11929 emitcode ("mov","a,b");
11930 emitcode ("orl","a,_ap");
11931 emitcode ("jz","!tlabel",lbl1->key+100);
11932 emitcode ("mov","a,_ap");
11933 emitcode ("add","a,#!constbyte",0xFF);
11934 emitcode ("mov","_ap,a");
11935 emitcode ("mov","a,b");
11936 emitcode ("addc","a,#!constbyte",0xFF);
11937 emitcode ("mov","b,a");
11938 emitcode ("sjmp","!tlabel",lbl->key+100);
11939 emitcode ("","!tlabeldef",lbl1->key+100);
11941 emitcode ("mov", "dps,#0");
11942 _G.dptrInUse = _G.dptr1InUse = 0;
11943 unsavermask(rsave);
11947 /*-----------------------------------------------------------------*/
11948 /* genSwapW - swap lower & high order bytes */
11949 /*-----------------------------------------------------------------*/
11950 static void genSwapW(iCode *ic, int nparms, operand **parms)
11954 assert (nparms==1);
11957 dest=IC_RESULT(ic);
11959 assert(getSize(operandType(src))==2);
11961 aopOp (src, ic, FALSE, FALSE);
11962 emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
11964 MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
11966 freeAsmop (src, NULL, ic, FALSE);
11968 aopOp (dest,ic, FALSE, FALSE);
11969 aopPut(AOP(dest),"b",0);
11970 aopPut(AOP(dest),"a",1);
11971 freeAsmop (dest, NULL, ic, FALSE);
11974 /*-----------------------------------------------------------------*/
11975 /* genMemsetX - gencode for memSetX data */
11976 /*-----------------------------------------------------------------*/
11977 static void genMemsetX(iCode *ic, int nparms, operand **parms)
11979 operand *to , *val , *count;
11985 /* we know it has to be 3 parameters */
11986 assert (nparms == 3);
11992 /* save DPTR if it needs to be saved */
11993 rsave = newBitVect(16);
11994 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11995 if (bitVectBitValue(ic->rMask,i))
11996 rsave = bitVectSetBit(rsave,i);
11998 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11999 ds390_rUmaskForOp (IC_RESULT(ic))));
12002 aopOp (to, ic, FALSE, FALSE);
12003 /* get "to" into DPTR */
12004 /* if the operand is already in dptr
12005 then we do nothing else we move the value to dptr */
12006 if (AOP_TYPE (to) != AOP_STR) {
12007 /* if already in DPTR then we need to push */
12008 if (AOP_TYPE(to) == AOP_DPTR) {
12009 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12010 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12011 if (options.model == MODEL_FLAT24)
12012 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12013 emitcode ("pop", "dph");
12014 emitcode ("pop", "dpl");
12016 _startLazyDPSEvaluation ();
12017 /* if this is remateriazable */
12018 if (AOP_TYPE (to) == AOP_IMMD) {
12019 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12020 } else { /* we need to get it byte by byte */
12021 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12022 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12023 if (options.model == MODEL_FLAT24) {
12024 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12027 _endLazyDPSEvaluation ();
12030 freeAsmop (to, NULL, ic, FALSE);
12032 aopOp (val, ic->next->next, FALSE,FALSE);
12033 aopOp (count, ic->next->next, FALSE,FALSE);
12034 lbl =newiTempLabel(NULL);
12035 /* now for the actual copy */
12036 if (AOP_TYPE(count) == AOP_LIT &&
12037 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12038 l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
12039 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12041 emitcode ("","!tlabeldef",lbl->key+100);
12042 emitcode ("movx", "@dptr,a");
12043 emitcode ("inc", "dptr");
12044 emitcode ("djnz","b,!tlabel",lbl->key+100);
12046 symbol *lbl1 = newiTempLabel(NULL);
12048 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12049 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12050 emitcode ("","!tlabeldef",lbl->key+100);
12051 MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
12052 emitcode ("movx", "@dptr,a");
12053 emitcode ("inc", "dptr");
12054 emitcode ("mov","a,b");
12055 emitcode ("orl","a,_ap");
12056 emitcode ("jz","!tlabel",lbl1->key+100);
12057 emitcode ("mov","a,_ap");
12058 emitcode ("add","a,#!constbyte",0xFF);
12059 emitcode ("mov","_ap,a");
12060 emitcode ("mov","a,b");
12061 emitcode ("addc","a,#!constbyte",0xFF);
12062 emitcode ("mov","b,a");
12063 emitcode ("sjmp","!tlabel",lbl->key+100);
12064 emitcode ("","!tlabeldef",lbl1->key+100);
12066 freeAsmop (count, NULL, ic, FALSE);
12067 unsavermask(rsave);
12070 /*-----------------------------------------------------------------*/
12071 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
12072 /*-----------------------------------------------------------------*/
12073 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
12076 operand *pnum, *result;
12079 assert (nparms==1);
12080 /* save registers that need to be saved */
12081 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12082 ds390_rUmaskForOp (IC_RESULT(ic))));
12085 aopOp (pnum, ic, FALSE, FALSE);
12086 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12087 freeAsmop (pnum, NULL, ic, FALSE);
12088 emitcode ("lcall","NatLib_LoadPrimitive");
12089 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12090 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
12091 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
12092 for (i = (size-1) ; i >= 0 ; i-- ) {
12093 emitcode ("push","a%s",javaRet[i]);
12095 for (i=0; i < size ; i++ ) {
12096 emitcode ("pop","a%s",
12097 aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
12100 for (i = 0 ; i < size ; i++ ) {
12101 aopPut(AOP(result),javaRet[i],i);
12104 freeAsmop (result, NULL, ic, FALSE);
12105 unsavermask(rsave);
12108 /*-----------------------------------------------------------------*/
12109 /* genNatLibLoadPointer - calls TINI api function to load pointer */
12110 /*-----------------------------------------------------------------*/
12111 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
12114 operand *pnum, *result;
12118 assert (nparms==1);
12119 /* save registers that need to be saved */
12120 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12121 ds390_rUmaskForOp (IC_RESULT(ic))));
12124 aopOp (pnum, ic, FALSE, FALSE);
12125 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12126 freeAsmop (pnum, NULL, ic, FALSE);
12127 emitcode ("lcall","NatLib_LoadPointer");
12128 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12129 if (AOP_TYPE(result)!=AOP_STR) {
12130 for (i = 0 ; i < size ; i++ ) {
12131 aopPut(AOP(result),fReturn[i],i);
12134 freeAsmop (result, NULL, ic, FALSE);
12135 unsavermask(rsave);
12138 /*-----------------------------------------------------------------*/
12139 /* genNatLibInstallStateBlock - */
12140 /*-----------------------------------------------------------------*/
12141 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
12142 operand **parms, const char *name)
12145 operand *psb, *handle;
12146 assert (nparms==2);
12148 /* save registers that need to be saved */
12149 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12150 ds390_rUmaskForOp (IC_RESULT(ic))));
12154 /* put pointer to state block into DPTR1 */
12155 aopOp (psb, ic, FALSE, FALSE);
12156 if (AOP_TYPE (psb) == AOP_IMMD) {
12157 emitcode ("mov","dps,#1");
12158 emitcode ("mov", "dptr,%s",
12159 aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12160 emitcode ("mov","dps,#0");
12162 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12163 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12164 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12166 freeAsmop (psb, NULL, ic, FALSE);
12168 /* put libraryID into DPTR */
12169 emitcode ("mov","dptr,#LibraryID");
12171 /* put handle into r3:r2 */
12172 aopOp (handle, ic, FALSE, FALSE);
12173 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12174 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12175 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12176 emitcode ("pop","ar3");
12177 emitcode ("pop","ar2");
12179 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12180 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12182 freeAsmop (psb, NULL, ic, FALSE);
12184 /* make the call */
12185 emitcode ("lcall","NatLib_Install%sStateBlock",name);
12187 /* put return value into place*/
12189 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12191 aopPut(AOP(IC_RESULT(ic)),"a",0);
12192 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12193 unsavermask(rsave);
12196 /*-----------------------------------------------------------------*/
12197 /* genNatLibRemoveStateBlock - */
12198 /*-----------------------------------------------------------------*/
12199 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12205 /* save registers that need to be saved */
12206 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12207 ds390_rUmaskForOp (IC_RESULT(ic))));
12209 /* put libraryID into DPTR */
12210 emitcode ("mov","dptr,#LibraryID");
12211 /* make the call */
12212 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12213 unsavermask(rsave);
12216 /*-----------------------------------------------------------------*/
12217 /* genNatLibGetStateBlock - */
12218 /*-----------------------------------------------------------------*/
12219 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12220 operand **parms,const char *name)
12223 symbol *lbl = newiTempLabel(NULL);
12226 /* save registers that need to be saved */
12227 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12228 ds390_rUmaskForOp (IC_RESULT(ic))));
12230 /* put libraryID into DPTR */
12231 emitcode ("mov","dptr,#LibraryID");
12232 /* make the call */
12233 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12234 emitcode ("jnz","!tlabel",lbl->key+100);
12236 /* put return value into place */
12237 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12238 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12239 emitcode ("push","ar3");
12240 emitcode ("push","ar2");
12241 emitcode ("pop","%s",
12242 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12243 emitcode ("pop","%s",
12244 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12246 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12247 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12249 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12250 emitcode ("","!tlabeldef",lbl->key+100);
12251 unsavermask(rsave);
12254 /*-----------------------------------------------------------------*/
12255 /* genMMMalloc - */
12256 /*-----------------------------------------------------------------*/
12257 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12258 int size, const char *name)
12263 symbol *lbl = newiTempLabel(NULL);
12265 assert (nparms == 1);
12266 /* save registers that need to be saved */
12267 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12268 ds390_rUmaskForOp (IC_RESULT(ic))));
12271 aopOp (bsize,ic,FALSE,FALSE);
12273 /* put the size in R4-R2 */
12274 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12275 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12276 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12278 emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12279 emitcode("pop","ar4");
12281 emitcode("pop","ar3");
12282 emitcode("pop","ar2");
12284 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12285 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12287 emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12290 freeAsmop (bsize, NULL, ic, FALSE);
12292 /* make the call */
12293 emitcode ("lcall","MM_%s",name);
12294 emitcode ("jz","!tlabel",lbl->key+100);
12295 emitcode ("mov","r2,#!constbyte",0xff);
12296 emitcode ("mov","r3,#!constbyte",0xff);
12297 emitcode ("","!tlabeldef",lbl->key+100);
12298 /* we don't care about the pointer : we just save the handle */
12299 rsym = OP_SYMBOL(IC_RESULT(ic));
12300 if (rsym->liveFrom != rsym->liveTo) {
12301 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12302 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12303 emitcode ("push","ar3");
12304 emitcode ("push","ar2");
12305 emitcode ("pop","%s",
12306 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12307 emitcode ("pop","%s",
12308 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12310 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12311 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12313 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12315 unsavermask(rsave);
12318 /*-----------------------------------------------------------------*/
12320 /*-----------------------------------------------------------------*/
12321 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12326 assert (nparms == 1);
12327 /* save registers that need to be saved */
12328 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12329 ds390_rUmaskForOp (IC_RESULT(ic))));
12332 aopOp (handle,ic,FALSE,FALSE);
12334 /* put the size in R4-R2 */
12335 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12336 emitcode("push","%s",
12337 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12338 emitcode("push","%s",
12339 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12340 emitcode("pop","ar3");
12341 emitcode("pop","ar2");
12343 emitcode ("mov","r2,%s",
12344 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12345 emitcode ("mov","r3,%s",
12346 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12348 freeAsmop (handle, NULL, ic, FALSE);
12350 /* make the call */
12351 emitcode ("lcall","MM_Deref");
12354 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12355 if (rsym->liveFrom != rsym->liveTo) {
12356 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12357 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12358 _startLazyDPSEvaluation ();
12360 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12361 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12362 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12364 _endLazyDPSEvaluation ();
12369 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12370 unsavermask(rsave);
12373 /*-----------------------------------------------------------------*/
12374 /* genMMUnrestrictedPersist - */
12375 /*-----------------------------------------------------------------*/
12376 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12381 assert (nparms == 1);
12382 /* save registers that need to be saved */
12383 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12384 ds390_rUmaskForOp (IC_RESULT(ic))));
12387 aopOp (handle,ic,FALSE,FALSE);
12389 /* put the size in R3-R2 */
12390 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12391 emitcode("push","%s",
12392 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12393 emitcode("push","%s",
12394 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12395 emitcode("pop","ar3");
12396 emitcode("pop","ar2");
12398 emitcode ("mov","r2,%s",
12399 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12400 emitcode ("mov","r3,%s",
12401 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12403 freeAsmop (handle, NULL, ic, FALSE);
12405 /* make the call */
12406 emitcode ("lcall","MM_UnrestrictedPersist");
12409 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12410 if (rsym->liveFrom != rsym->liveTo) {
12411 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12412 aopPut(AOP(IC_RESULT(ic)),"a",0);
12413 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12416 unsavermask(rsave);
12419 /*-----------------------------------------------------------------*/
12420 /* genSystemExecJavaProcess - */
12421 /*-----------------------------------------------------------------*/
12422 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12425 operand *handle, *pp;
12427 assert (nparms==2);
12428 /* save registers that need to be saved */
12429 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12430 ds390_rUmaskForOp (IC_RESULT(ic))));
12435 /* put the handle in R3-R2 */
12436 aopOp (handle,ic,FALSE,FALSE);
12437 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12438 emitcode("push","%s",
12439 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12440 emitcode("push","%s",
12441 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12442 emitcode("pop","ar3");
12443 emitcode("pop","ar2");
12445 emitcode ("mov","r2,%s",
12446 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12447 emitcode ("mov","r3,%s",
12448 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12450 freeAsmop (handle, NULL, ic, FALSE);
12452 /* put pointer in DPTR */
12453 aopOp (pp,ic,FALSE,FALSE);
12454 if (AOP_TYPE(pp) == AOP_IMMD) {
12455 emitcode ("mov", "dptr,%s",
12456 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12457 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12458 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12459 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12460 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12462 freeAsmop (handle, NULL, ic, FALSE);
12464 /* make the call */
12465 emitcode ("lcall","System_ExecJavaProcess");
12467 /* put result in place */
12469 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12470 if (rsym->liveFrom != rsym->liveTo) {
12471 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12472 aopPut(AOP(IC_RESULT(ic)),"a",0);
12473 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12477 unsavermask(rsave);
12480 /*-----------------------------------------------------------------*/
12481 /* genSystemRTCRegisters - */
12482 /*-----------------------------------------------------------------*/
12483 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12489 assert (nparms==1);
12490 /* save registers that need to be saved */
12491 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12492 ds390_rUmaskForOp (IC_RESULT(ic))));
12495 /* put pointer in DPTR */
12496 aopOp (pp,ic,FALSE,FALSE);
12497 if (AOP_TYPE (pp) == AOP_IMMD) {
12498 emitcode ("mov","dps,#1");
12499 emitcode ("mov", "dptr,%s",
12500 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12501 emitcode ("mov","dps,#0");
12503 emitcode ("mov","dpl1,%s",
12504 aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12505 emitcode ("mov","dph1,%s",
12506 aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12507 emitcode ("mov","dpx1,%s",
12508 aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12510 freeAsmop (pp, NULL, ic, FALSE);
12512 /* make the call */
12513 emitcode ("lcall","System_%sRTCRegisters",name);
12515 unsavermask(rsave);
12518 /*-----------------------------------------------------------------*/
12519 /* genSystemThreadSleep - */
12520 /*-----------------------------------------------------------------*/
12521 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12526 assert (nparms==1);
12527 /* save registers that need to be saved */
12528 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12529 ds390_rUmaskForOp (IC_RESULT(ic))));
12532 aopOp(to,ic,FALSE,FALSE);
12533 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12534 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12535 emitcode ("push","%s",
12536 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12537 emitcode ("push","%s",
12538 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12539 emitcode ("push","%s",
12540 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12541 emitcode ("push","%s",
12542 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12543 emitcode ("pop","ar3");
12544 emitcode ("pop","ar2");
12545 emitcode ("pop","ar1");
12546 emitcode ("pop","ar0");
12548 emitcode ("mov","r0,%s",
12549 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12550 emitcode ("mov","r1,%s",
12551 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12552 emitcode ("mov","r2,%s",
12553 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12554 emitcode ("mov","r3,%s",
12555 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12557 freeAsmop (to, NULL, ic, FALSE);
12559 /* suspend in acc */
12561 aopOp(s,ic,FALSE,FALSE);
12562 emitcode ("mov","a,%s",
12563 aopGet(AOP(s),0,FALSE,TRUE,NULL));
12564 freeAsmop (s, NULL, ic, FALSE);
12566 /* make the call */
12567 emitcode ("lcall","System_%s",name);
12569 unsavermask(rsave);
12572 /*-----------------------------------------------------------------*/
12573 /* genSystemThreadResume - */
12574 /*-----------------------------------------------------------------*/
12575 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12580 assert (nparms==2);
12581 /* save registers that need to be saved */
12582 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12583 ds390_rUmaskForOp (IC_RESULT(ic))));
12589 aopOp(pid,ic,FALSE,FALSE);
12590 emitcode ("mov","r0,%s",
12591 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12592 freeAsmop (pid, NULL, ic, FALSE);
12595 aopOp(tid,ic,FALSE,FALSE);
12596 emitcode ("mov","a,%s",
12597 aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
12598 freeAsmop (tid, NULL, ic, FALSE);
12600 emitcode ("lcall","System_ThreadResume");
12602 /* put result into place */
12604 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12605 if (rsym->liveFrom != rsym->liveTo) {
12606 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12607 aopPut(AOP(IC_RESULT(ic)),"a",0);
12608 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12611 unsavermask(rsave);
12614 /*-----------------------------------------------------------------*/
12615 /* genSystemProcessResume - */
12616 /*-----------------------------------------------------------------*/
12617 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
12622 assert (nparms==1);
12623 /* save registers that need to be saved */
12624 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12625 ds390_rUmaskForOp (IC_RESULT(ic))));
12630 aopOp(pid,ic,FALSE,FALSE);
12631 emitcode ("mov","a,%s",
12632 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12633 freeAsmop (pid, NULL, ic, FALSE);
12635 emitcode ("lcall","System_ProcessResume");
12637 unsavermask(rsave);
12640 /*-----------------------------------------------------------------*/
12642 /*-----------------------------------------------------------------*/
12643 static void genSystem (iCode *ic,int nparms,char *name)
12645 assert(nparms == 0);
12647 emitcode ("lcall","System_%s",name);
12650 /*-----------------------------------------------------------------*/
12651 /* genSystemPoll - */
12652 /*-----------------------------------------------------------------*/
12653 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
12658 assert (nparms==1);
12659 /* save registers that need to be saved */
12660 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12661 ds390_rUmaskForOp (IC_RESULT(ic))));
12664 aopOp (fp,ic,FALSE,FALSE);
12665 if (AOP_TYPE (fp) == AOP_IMMD) {
12666 emitcode ("mov", "dptr,%s",
12667 aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
12668 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
12669 emitcode ("mov","dpl,%s",
12670 aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
12671 emitcode ("mov","dph,%s",
12672 aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
12673 emitcode ("mov","dpx,%s",
12674 aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
12676 freeAsmop (fp, NULL, ic, FALSE);
12678 emitcode ("lcall","System_%sPoll",name);
12680 /* put result into place */
12682 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12683 if (rsym->liveFrom != rsym->liveTo) {
12684 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12685 aopPut(AOP(IC_RESULT(ic)),"a",0);
12686 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12689 unsavermask(rsave);
12692 /*-----------------------------------------------------------------*/
12693 /* genSystemGetCurrentID - */
12694 /*-----------------------------------------------------------------*/
12695 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
12697 assert (nparms==0);
12699 emitcode ("lcall","System_GetCurrent%sId",name);
12700 /* put result into place */
12702 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12703 if (rsym->liveFrom != rsym->liveTo) {
12704 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12705 aopPut(AOP(IC_RESULT(ic)),"a",0);
12706 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12711 /*-----------------------------------------------------------------*/
12712 /* genDummyRead - generate code for dummy read of volatiles */
12713 /*-----------------------------------------------------------------*/
12715 genDummyRead (iCode * ic)
12720 D(emitcode("; genDummyRead",""));
12722 op = IC_RIGHT (ic);
12723 if (op && IS_SYMOP (op))
12725 aopOp (op, ic, FALSE, FALSE);
12727 /* if the result is a bit */
12728 if (AOP_TYPE (op) == AOP_CRY)
12729 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
12732 /* bit variables done */
12734 size = AOP_SIZE (op);
12738 MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
12743 freeAsmop (op, NULL, ic, TRUE);
12747 if (op && IS_SYMOP (op))
12749 aopOp (op, ic, FALSE, FALSE);
12751 /* if the result is a bit */
12752 if (AOP_TYPE (op) == AOP_CRY)
12753 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
12756 /* bit variables done */
12758 size = AOP_SIZE (op);
12762 MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
12767 freeAsmop (op, NULL, ic, TRUE);
12772 /*-----------------------------------------------------------------*/
12773 /* genCritical - generate code for start of a critical sequence */
12774 /*-----------------------------------------------------------------*/
12776 genCritical (iCode *ic)
12778 symbol *tlbl = newiTempLabel (NULL);
12780 D(emitcode("; genCritical",""));
12782 if (IC_RESULT (ic))
12783 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
12785 emitcode ("setb", "c");
12786 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
12787 emitcode ("clr", "c");
12788 emitcode ("", "%05d$:", (tlbl->key + 100));
12790 if (IC_RESULT (ic))
12791 outBitC (IC_RESULT (ic)); /* save old ea in an operand */
12793 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
12795 if (IC_RESULT (ic))
12796 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
12799 /*-----------------------------------------------------------------*/
12800 /* genEndCritical - generate code for end of a critical sequence */
12801 /*-----------------------------------------------------------------*/
12803 genEndCritical (iCode *ic)
12805 D(emitcode("; genEndCritical",""));
12809 aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
12810 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
12812 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
12813 emitcode ("mov", "ea,c");
12817 MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE, FALSE));
12818 emitcode ("rrc", "a");
12819 emitcode ("mov", "ea,c");
12821 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
12825 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
12826 emitcode ("mov", "ea,c");
12832 /*-----------------------------------------------------------------*/
12833 /* genBuiltIn - calls the appropriate function to generating code */
12834 /* for a built in function */
12835 /*-----------------------------------------------------------------*/
12836 static void genBuiltIn (iCode *ic)
12838 operand *bi_parms[MAX_BUILTIN_ARGS];
12843 /* get all the arguments for a built in function */
12844 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
12846 /* which function is it */
12847 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
12848 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
12849 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
12850 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
12851 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
12852 } else if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
12853 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
12854 } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
12855 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
12856 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
12857 genMemsetX(bi_iCode,nbi_parms,bi_parms);
12858 } else if (strcmp(bif->name,"__builtin_inp")==0) {
12859 genInp(bi_iCode,nbi_parms,bi_parms);
12860 } else if (strcmp(bif->name,"__builtin_outp")==0) {
12861 genOutp(bi_iCode,nbi_parms,bi_parms);
12862 } else if (strcmp(bif->name,"__builtin_swapw")==0) {
12863 genSwapW(bi_iCode,nbi_parms,bi_parms);
12864 /* JavaNative builtIns */
12865 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
12866 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
12867 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
12868 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
12869 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
12870 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
12871 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
12872 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
12873 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
12874 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12875 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
12876 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12877 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
12878 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
12879 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
12880 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
12881 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
12882 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12883 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
12884 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12885 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
12886 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
12887 } else if (strcmp(bif->name,"MM_Malloc")==0) {
12888 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
12889 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
12890 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
12891 } else if (strcmp(bif->name,"MM_Free")==0) {
12892 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
12893 } else if (strcmp(bif->name,"MM_Deref")==0) {
12894 genMMDeref(bi_iCode,nbi_parms,bi_parms);
12895 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
12896 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
12897 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
12898 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
12899 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
12900 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
12901 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
12902 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
12903 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
12904 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
12905 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
12906 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
12907 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
12908 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
12909 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
12910 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
12911 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12912 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12913 } else if (strcmp(bif->name,"System_SaveThread")==0) {
12914 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12915 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12916 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12917 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
12918 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
12919 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
12920 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
12921 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
12922 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
12923 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
12924 genSystem(bi_iCode,nbi_parms,"ProcessYield");
12925 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
12926 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
12927 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
12928 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
12929 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
12930 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
12931 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
12932 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
12933 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
12934 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
12936 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
12942 /*-----------------------------------------------------------------*/
12943 /* gen390Code - generate code for Dallas 390 based controllers */
12944 /*-----------------------------------------------------------------*/
12946 gen390Code (iCode * lic)
12951 lineHead = lineCurr = NULL;
12952 dptrn[1][0] = "dpl1";
12953 dptrn[1][1] = "dph1";
12954 dptrn[1][2] = "dpx1";
12956 if (options.model == MODEL_FLAT24) {
12957 fReturnSizeDS390 = 5;
12958 fReturn = fReturn24;
12960 fReturnSizeDS390 = 4;
12961 fReturn = fReturn16;
12962 options.stack10bit=0;
12965 /* print the allocation information */
12966 if (allocInfo && currFunc)
12967 printAllocInfo (currFunc, codeOutFile);
12969 /* if debug information required */
12970 if (options.debug && currFunc)
12972 debugFile->writeFunction(currFunc);
12974 if (IS_STATIC (currFunc->etype))
12975 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
12977 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
12980 /* stack pointer name */
12981 if (options.useXstack)
12987 for (ic = lic; ic; ic = ic->next)
12990 if (ic->lineno && cln != ic->lineno)
12995 emitcode ("", "C$%s$%d$%d$%d ==.",
12996 FileBaseName (ic->filename), ic->lineno,
12997 ic->level, ic->block);
13000 if (!options.noCcodeInAsm) {
13001 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
13002 printCLine(ic->filename, ic->lineno));
13006 if (options.iCodeInAsm) {
13007 emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
13009 /* if the result is marked as
13010 spilt and rematerializable or code for
13011 this has already been generated then
13013 if (resultRemat (ic) || ic->generated)
13016 /* depending on the operation */
13036 /* IPOP happens only when trying to restore a
13037 spilt live range, if there is an ifx statement
13038 following this pop then the if statement might
13039 be using some of the registers being popped which
13040 would destory the contents of the register so
13041 we need to check for this condition and handle it */
13043 ic->next->op == IFX &&
13044 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
13045 genIfx (ic->next, ic);
13063 genEndFunction (ic);
13083 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
13100 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
13104 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
13111 /* note these two are xlated by algebraic equivalence
13112 during parsing SDCC.y */
13113 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
13114 "got '>=' or '<=' shouldn't have come here");
13118 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
13130 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
13134 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
13138 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
13162 genRightShift (ic);
13165 case GET_VALUE_AT_ADDRESS:
13166 genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
13170 if (POINTER_SET (ic))
13171 genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
13197 if (ic->builtinSEND) genBuiltIn(ic);
13198 else addSet (&_G.sendSet, ic);
13201 case DUMMY_READ_VOLATILE:
13210 genEndCritical (ic);
13217 #if 0 // obsolete, and buggy for != xdata
13229 /* now we are ready to call the
13230 peep hole optimizer */
13231 if (!options.nopeep)
13232 peepHole (&lineHead);
13234 /* now do the actual printing */
13235 printLine (lineHead, codeOutFile);