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);
6397 /* if left is same as result */
6398 if (sameRegs (AOP (result), AOP (left)))
6400 for (; size--; offset++)
6402 if (AOP_TYPE (right) == AOP_LIT)
6404 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6406 else if (bytelit == 0)
6407 aopPut (AOP (result), zero, offset);
6408 else if (IS_AOP_PREG (result))
6410 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6411 emitcode ("anl", "a,%s",
6412 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6413 aopPut (AOP (result), "a", offset);
6416 emitcode ("anl", "%s,%s",
6417 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6418 aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6422 if (AOP_TYPE (left) == AOP_ACC)
6423 emitcode ("anl", "a,%s",
6424 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6427 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6428 if (IS_AOP_PREG (result))
6430 emitcode ("anl", "a,%s",
6431 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6432 aopPut (AOP (result), "a", offset);
6435 emitcode ("anl", "%s,a",
6436 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6443 // left & result in different registers
6444 if (AOP_TYPE (result) == AOP_CRY)
6447 // if(size), result in bit
6448 // if(!size && ifx), conditional oper: if(left & right)
6449 symbol *tlbl = newiTempLabel (NULL);
6450 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6452 emitcode ("setb", "c");
6455 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6456 emitcode ("anl", "a,%s",
6457 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6459 if (AOP_TYPE(left)==AOP_ACC) {
6460 emitcode("mov", "b,a");
6461 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6462 emitcode("anl", "a,b");
6464 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6465 emitcode ("anl", "a,%s",
6466 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6469 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6475 emitcode ("", "!tlabeldef", tlbl->key + 100);
6479 jmpTrueOrFalse (ifx, tlbl);
6483 for (; (size--); offset++)
6486 // result = left & right
6487 if (AOP_TYPE (right) == AOP_LIT)
6489 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6491 aopPut (AOP (result),
6492 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6496 else if (bytelit == 0)
6498 aopPut (AOP (result), zero, offset);
6501 D (emitcode (";", "better literal AND."););
6502 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6503 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6504 FALSE, FALSE, DP2_RESULT_REG));
6509 // faster than result <- left, anl result,right
6510 // and better if result is SFR
6511 if (AOP_TYPE (left) == AOP_ACC)
6513 emitcode ("anl", "a,%s",
6514 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6518 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6519 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6521 emitcode("mov", "b,a");
6525 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6526 emitcode ("anl", "a,%s", rOp);
6529 aopPut (AOP (result), "a", offset);
6535 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6536 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6537 freeAsmop (result, NULL, ic, TRUE);
6541 /*-----------------------------------------------------------------*/
6542 /* genOr - code for or */
6543 /*-----------------------------------------------------------------*/
6545 genOr (iCode * ic, iCode * ifx)
6547 operand *left, *right, *result;
6548 int size, offset = 0;
6549 unsigned long lit = 0L;
6552 D (emitcode (";", "genOr "););
6554 AOP_OP_3_NOFATAL (ic, pushResult);
6555 AOP_SET_LOCALS (ic);
6559 genFarFarLogicOp(ic, "orl");
6565 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6567 AOP_TYPE (left), AOP_TYPE (right));
6568 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6570 AOP_SIZE (left), AOP_SIZE (right));
6573 /* if left is a literal & right is not then exchange them */
6574 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6575 #ifdef LOGIC_OPS_BROKEN
6576 || AOP_NEEDSACC (left) // I think this is a net loss now.
6580 operand *tmp = right;
6585 /* if result = right then exchange them */
6586 if (sameRegs (AOP (result), AOP (right)))
6588 operand *tmp = right;
6593 /* if right is bit then exchange them */
6594 if (AOP_TYPE (right) == AOP_CRY &&
6595 AOP_TYPE (left) != AOP_CRY)
6597 operand *tmp = right;
6601 if (AOP_TYPE (right) == AOP_LIT)
6602 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6604 size = AOP_SIZE (result);
6608 if (AOP_TYPE (left) == AOP_CRY)
6610 if (AOP_TYPE (right) == AOP_LIT)
6612 // c = bit & literal;
6615 // lit != 0 => result = 1
6616 if (AOP_TYPE (result) == AOP_CRY)
6619 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6621 continueIfTrue (ifx);
6624 emitcode ("setb", "c");
6628 // lit == 0 => result = left
6629 if (size && sameRegs (AOP (result), AOP (left)))
6631 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6636 if (AOP_TYPE (right) == AOP_CRY)
6639 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6640 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6645 symbol *tlbl = newiTempLabel (NULL);
6646 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6647 emitcode ("setb", "c");
6648 emitcode ("jb", "%s,!tlabel",
6649 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6651 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6652 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6654 jmpTrueOrFalse (ifx, tlbl);
6660 emitcode ("", "!tlabeldef", tlbl->key + 100);
6669 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6670 genIfxJump (ifx, "c");
6674 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6675 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6676 if ((AOP_TYPE (right) == AOP_LIT) &&
6677 (AOP_TYPE (result) == AOP_CRY) &&
6678 (AOP_TYPE (left) != AOP_CRY))
6684 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6686 continueIfTrue (ifx);
6691 // lit = 0, result = boolean(left)
6693 emitcode ("setb", "c");
6697 symbol *tlbl = newiTempLabel (NULL);
6698 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6700 emitcode ("", "!tlabeldef", tlbl->key + 100);
6704 genIfxJump (ifx, "a");
6712 /* if left is same as result */
6713 if (sameRegs (AOP (result), AOP (left)))
6715 for (; size--; offset++)
6717 if (AOP_TYPE (right) == AOP_LIT)
6719 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6725 if (IS_AOP_PREG (left))
6727 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6728 emitcode ("orl", "a,%s",
6729 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6730 aopPut (AOP (result), "a", offset);
6734 emitcode ("orl", "%s,%s",
6735 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6736 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6742 if (AOP_TYPE (left) == AOP_ACC)
6744 emitcode ("orl", "a,%s",
6745 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6749 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6750 if (IS_AOP_PREG (left))
6752 emitcode ("orl", "a,%s",
6753 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6754 aopPut (AOP (result), "a", offset);
6758 emitcode ("orl", "%s,a",
6759 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6767 // left & result in different registers
6768 if (AOP_TYPE (result) == AOP_CRY)
6771 // if(size), result in bit
6772 // if(!size && ifx), conditional oper: if(left | right)
6773 symbol *tlbl = newiTempLabel (NULL);
6774 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6776 emitcode ("setb", "c");
6779 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6780 emitcode ("orl", "a,%s",
6781 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6783 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6784 emitcode ("orl", "a,%s",
6785 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6787 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6793 emitcode ("", "!tlabeldef", tlbl->key + 100);
6797 jmpTrueOrFalse (ifx, tlbl);
6801 _startLazyDPSEvaluation();
6802 for (; (size--); offset++)
6805 // result = left & right
6806 if (AOP_TYPE (right) == AOP_LIT)
6808 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6810 aopPut (AOP (result),
6811 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6815 D (emitcode (";", "better literal OR."););
6816 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6817 emitcode ("orl", "a, %s",
6818 aopGet (AOP (right), offset,
6819 FALSE, FALSE, DP2_RESULT_REG));
6824 // faster than result <- left, anl result,right
6825 // and better if result is SFR
6826 if (AOP_TYPE (left) == AOP_ACC)
6828 emitcode ("orl", "a,%s",
6829 aopGet (AOP (right), offset,
6830 FALSE, FALSE, DP2_RESULT_REG));
6834 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6836 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6838 emitcode("mov", "b,a");
6842 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6843 emitcode ("orl", "a,%s", rOp);
6846 aopPut (AOP (result), "a", offset);
6848 _endLazyDPSEvaluation();
6853 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6854 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6855 freeAsmop (result, NULL, ic, TRUE);
6858 /*-----------------------------------------------------------------*/
6859 /* genXor - code for xclusive or */
6860 /*-----------------------------------------------------------------*/
6862 genXor (iCode * ic, iCode * ifx)
6864 operand *left, *right, *result;
6865 int size, offset = 0;
6866 unsigned long lit = 0L;
6869 D (emitcode (";", "genXor "););
6871 AOP_OP_3_NOFATAL (ic, pushResult);
6872 AOP_SET_LOCALS (ic);
6876 genFarFarLogicOp(ic, "xrl");
6881 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6883 AOP_TYPE (left), AOP_TYPE (right));
6884 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6886 AOP_SIZE (left), AOP_SIZE (right));
6889 /* if left is a literal & right is not ||
6890 if left needs acc & right does not */
6891 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6892 #ifdef LOGIC_OPS_BROKEN
6893 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6897 operand *tmp = right;
6902 /* if result = right then exchange them */
6903 if (sameRegs (AOP (result), AOP (right)))
6905 operand *tmp = right;
6910 /* if right is bit then exchange them */
6911 if (AOP_TYPE (right) == AOP_CRY &&
6912 AOP_TYPE (left) != AOP_CRY)
6914 operand *tmp = right;
6918 if (AOP_TYPE (right) == AOP_LIT)
6919 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6921 size = AOP_SIZE (result);
6925 if (AOP_TYPE (left) == AOP_CRY)
6927 if (AOP_TYPE (right) == AOP_LIT)
6929 // c = bit & literal;
6932 // lit>>1 != 0 => result = 1
6933 if (AOP_TYPE (result) == AOP_CRY)
6936 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6938 continueIfTrue (ifx);
6941 emitcode ("setb", "c");
6948 // lit == 0, result = left
6949 if (size && sameRegs (AOP (result), AOP (left)))
6951 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6955 // lit == 1, result = not(left)
6956 if (size && sameRegs (AOP (result), AOP (left)))
6958 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6963 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6964 emitcode ("cpl", "c");
6973 symbol *tlbl = newiTempLabel (NULL);
6974 if (AOP_TYPE (right) == AOP_CRY)
6977 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6981 int sizer = AOP_SIZE (right);
6983 // if val>>1 != 0, result = 1
6984 emitcode ("setb", "c");
6987 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
6989 // test the msb of the lsb
6990 emitcode ("anl", "a,#!constbyte",0xfe);
6991 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6995 emitcode ("rrc", "a");
6997 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6998 emitcode ("cpl", "c");
6999 emitcode ("", "!tlabeldef", (tlbl->key + 100));
7006 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7007 genIfxJump (ifx, "c");
7011 if (sameRegs (AOP (result), AOP (left)))
7013 /* if left is same as result */
7014 for (; size--; offset++)
7016 if (AOP_TYPE (right) == AOP_LIT)
7018 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7020 else if (IS_AOP_PREG (left))
7022 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7023 emitcode ("xrl", "a,%s",
7024 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7025 aopPut (AOP (result), "a", offset);
7028 emitcode ("xrl", "%s,%s",
7029 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
7030 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7034 if (AOP_TYPE (left) == AOP_ACC)
7035 emitcode ("xrl", "a,%s",
7036 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7039 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7040 if (IS_AOP_PREG (left))
7042 emitcode ("xrl", "a,%s",
7043 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7044 aopPut (AOP (result), "a", offset);
7047 emitcode ("xrl", "%s,a",
7048 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7055 // left & result in different registers
7056 if (AOP_TYPE (result) == AOP_CRY)
7059 // if(size), result in bit
7060 // if(!size && ifx), conditional oper: if(left ^ right)
7061 symbol *tlbl = newiTempLabel (NULL);
7062 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7065 emitcode ("setb", "c");
7068 if ((AOP_TYPE (right) == AOP_LIT) &&
7069 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7071 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7075 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7076 emitcode ("xrl", "a,%s",
7077 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7079 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7080 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7082 emitcode("mov", "b,a");
7086 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7087 emitcode ("xrl", "a,%s", rOp);
7090 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7096 emitcode ("", "!tlabeldef", tlbl->key + 100);
7100 jmpTrueOrFalse (ifx, tlbl);
7104 for (; (size--); offset++)
7107 // result = left & right
7108 if (AOP_TYPE (right) == AOP_LIT)
7110 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7112 aopPut (AOP (result),
7113 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7117 D (emitcode (";", "better literal XOR."););
7118 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7119 emitcode ("xrl", "a, %s",
7120 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7124 // faster than result <- left, anl result,right
7125 // and better if result is SFR
7126 if (AOP_TYPE (left) == AOP_ACC)
7128 emitcode ("xrl", "a,%s",
7129 aopGet (AOP (right), offset,
7130 FALSE, FALSE, DP2_RESULT_REG));
7134 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7135 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7137 emitcode("mov", "b,a");
7141 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7142 emitcode ("xrl", "a,%s", rOp);
7145 aopPut (AOP (result), "a", offset);
7152 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7153 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7154 freeAsmop (result, NULL, ic, TRUE);
7157 /*-----------------------------------------------------------------*/
7158 /* genInline - write the inline code out */
7159 /*-----------------------------------------------------------------*/
7161 genInline (iCode * ic)
7163 char *buffer, *bp, *bp1;
7165 D (emitcode (";", "genInline "); );
7167 _G.inLine += (!options.asmpeep);
7169 buffer = Safe_strdup(IC_INLINE(ic));
7173 /* emit each line as a code */
7198 /* emitcode("",buffer); */
7199 _G.inLine -= (!options.asmpeep);
7202 /*-----------------------------------------------------------------*/
7203 /* genRRC - rotate right with carry */
7204 /*-----------------------------------------------------------------*/
7208 operand *left, *result;
7211 D (emitcode (";", "genRRC "););
7213 /* rotate right with carry */
7214 left = IC_LEFT (ic);
7215 result = IC_RESULT (ic);
7216 aopOp (left, ic, FALSE, FALSE);
7217 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7219 /* move it to the result */
7220 size = AOP_SIZE (result);
7224 _startLazyDPSEvaluation ();
7227 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7228 emitcode ("rrc", "a");
7229 if (AOP_SIZE (result) > 1)
7230 aopPut (AOP (result), "a", offset--);
7232 _endLazyDPSEvaluation ();
7234 /* now we need to put the carry into the
7235 highest order byte of the result */
7236 if (AOP_SIZE (result) > 1)
7238 MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7240 emitcode ("mov", "acc.7,c");
7241 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7242 freeAsmop (left, NULL, ic, TRUE);
7243 freeAsmop (result, NULL, ic, TRUE);
7246 /*-----------------------------------------------------------------*/
7247 /* genRLC - generate code for rotate left with carry */
7248 /*-----------------------------------------------------------------*/
7252 operand *left, *result;
7256 D (emitcode (";", "genRLC "););
7258 /* rotate right with carry */
7259 left = IC_LEFT (ic);
7260 result = IC_RESULT (ic);
7261 aopOp (left, ic, FALSE, FALSE);
7262 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7264 /* move it to the result */
7265 size = AOP_SIZE (result);
7269 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7271 emitcode ("add", "a,acc");
7272 if (AOP_SIZE (result) > 1)
7274 aopPut (AOP (result), "a", offset++);
7277 _startLazyDPSEvaluation ();
7280 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7282 emitcode ("rlc", "a");
7283 if (AOP_SIZE (result) > 1)
7284 aopPut (AOP (result), "a", offset++);
7286 _endLazyDPSEvaluation ();
7288 /* now we need to put the carry into the
7289 highest order byte of the result */
7290 if (AOP_SIZE (result) > 1)
7292 l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7295 emitcode ("mov", "acc.0,c");
7296 aopPut (AOP (result), "a", 0);
7297 freeAsmop (left, NULL, ic, TRUE);
7298 freeAsmop (result, NULL, ic, TRUE);
7301 /*-----------------------------------------------------------------*/
7302 /* genGetHbit - generates code get highest order bit */
7303 /*-----------------------------------------------------------------*/
7305 genGetHbit (iCode * ic)
7307 operand *left, *result;
7308 left = IC_LEFT (ic);
7309 result = IC_RESULT (ic);
7310 aopOp (left, ic, FALSE, FALSE);
7311 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7313 D (emitcode (";", "genGetHbit "););
7315 /* get the highest order byte into a */
7316 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7317 if (AOP_TYPE (result) == AOP_CRY)
7319 emitcode ("rlc", "a");
7324 emitcode ("rl", "a");
7325 emitcode ("anl", "a,#1");
7330 freeAsmop (left, NULL, ic, TRUE);
7331 freeAsmop (result, NULL, ic, TRUE);
7334 /*-----------------------------------------------------------------*/
7335 /* genSwap - generates code to swap nibbles or bytes */
7336 /*-----------------------------------------------------------------*/
7338 genSwap (iCode * ic)
7340 operand *left, *result;
7342 D(emitcode ("; genSwap",""));
7344 left = IC_LEFT (ic);
7345 result = IC_RESULT (ic);
7346 aopOp (left, ic, FALSE, FALSE);
7347 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7349 _startLazyDPSEvaluation ();
7350 switch (AOP_SIZE (left))
7352 case 1: /* swap nibbles in byte */
7353 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7354 emitcode ("swap", "a");
7355 aopPut (AOP (result), "a", 0);
7357 case 2: /* swap bytes in word */
7358 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7360 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7361 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7362 aopPut (AOP (result), "a", 1);
7364 else if (operandsEqu (left, result))
7367 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7368 if (AOP_NEEDSACC (left) || AOP_NEEDSACC (result))
7370 emitcode ("mov", "b,a");
7374 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7375 aopPut (AOP (result), reg, 1);
7380 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7381 aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE, NULL), 1);
7385 wassertl(FALSE, "unsupported SWAP operand size");
7387 _endLazyDPSEvaluation ();
7389 freeAsmop (left, NULL, ic, TRUE);
7390 freeAsmop (result, NULL, ic, TRUE);
7393 /*-----------------------------------------------------------------*/
7394 /* AccRol - rotate left accumulator by known count */
7395 /*-----------------------------------------------------------------*/
7397 AccRol (int shCount)
7399 shCount &= 0x0007; // shCount : 0..7
7406 emitcode ("rl", "a");
7409 emitcode ("rl", "a");
7410 emitcode ("rl", "a");
7413 emitcode ("swap", "a");
7414 emitcode ("rr", "a");
7417 emitcode ("swap", "a");
7420 emitcode ("swap", "a");
7421 emitcode ("rl", "a");
7424 emitcode ("rr", "a");
7425 emitcode ("rr", "a");
7428 emitcode ("rr", "a");
7433 /*-----------------------------------------------------------------*/
7434 /* AccLsh - left shift accumulator by known count */
7435 /*-----------------------------------------------------------------*/
7437 AccLsh (int shCount)
7442 emitcode ("add", "a,acc");
7443 else if (shCount == 2)
7445 emitcode ("add", "a,acc");
7446 emitcode ("add", "a,acc");
7450 /* rotate left accumulator */
7452 /* and kill the lower order bits */
7453 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7458 /*-----------------------------------------------------------------*/
7459 /* AccRsh - right shift accumulator by known count */
7460 /*-----------------------------------------------------------------*/
7462 AccRsh (int shCount)
7469 emitcode ("rrc", "a");
7473 /* rotate right accumulator */
7474 AccRol (8 - shCount);
7475 /* and kill the higher order bits */
7476 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7481 #ifdef BETTER_LITERAL_SHIFT
7482 /*-----------------------------------------------------------------*/
7483 /* AccSRsh - signed right shift accumulator by known count */
7484 /*-----------------------------------------------------------------*/
7486 AccSRsh (int shCount)
7493 emitcode ("mov", "c,acc.7");
7494 emitcode ("rrc", "a");
7496 else if (shCount == 2)
7498 emitcode ("mov", "c,acc.7");
7499 emitcode ("rrc", "a");
7500 emitcode ("mov", "c,acc.7");
7501 emitcode ("rrc", "a");
7505 tlbl = newiTempLabel (NULL);
7506 /* rotate right accumulator */
7507 AccRol (8 - shCount);
7508 /* and kill the higher order bits */
7509 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7510 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7511 emitcode ("orl", "a,#!constbyte",
7512 (unsigned char) ~SRMask[shCount]);
7513 emitcode ("", "!tlabeldef", tlbl->key + 100);
7519 #ifdef BETTER_LITERAL_SHIFT
7520 /*-----------------------------------------------------------------*/
7521 /* shiftR1Left2Result - shift right one byte from left to result */
7522 /*-----------------------------------------------------------------*/
7524 shiftR1Left2Result (operand * left, int offl,
7525 operand * result, int offr,
7526 int shCount, int sign)
7528 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7529 /* shift right accumulator */
7534 aopPut (AOP (result), "a", offr);
7538 #ifdef BETTER_LITERAL_SHIFT
7539 /*-----------------------------------------------------------------*/
7540 /* shiftL1Left2Result - shift left one byte from left to result */
7541 /*-----------------------------------------------------------------*/
7543 shiftL1Left2Result (operand * left, int offl,
7544 operand * result, int offr, int shCount)
7546 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7547 /* shift left accumulator */
7549 aopPut (AOP (result), "a", offr);
7553 #ifdef BETTER_LITERAL_SHIFT
7554 /*-----------------------------------------------------------------*/
7555 /* movLeft2Result - move byte from left to result */
7556 /*-----------------------------------------------------------------*/
7558 movLeft2Result (operand * left, int offl,
7559 operand * result, int offr, int sign)
7562 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7564 l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
7566 if (*l == '@' && (IS_AOP_PREG (result)))
7568 emitcode ("mov", "a,%s", l);
7569 aopPut (AOP (result), "a", offr);
7575 aopPut (AOP (result), l, offr);
7579 /* MSB sign in acc.7 ! */
7580 if (getDataSize (left) == offl + 1)
7582 emitcode ("mov", "a,%s", l);
7583 aopPut (AOP (result), "a", offr);
7591 #ifdef BETTER_LITERAL_SHIFT
7592 /*-----------------------------------------------------------------*/
7593 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7594 /*-----------------------------------------------------------------*/
7598 emitcode ("rrc", "a");
7599 emitcode ("xch", "a,%s", x);
7600 emitcode ("rrc", "a");
7601 emitcode ("xch", "a,%s", x);
7605 #ifdef BETTER_LITERAL_SHIFT
7607 /*-----------------------------------------------------------------*/
7608 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7609 /*-----------------------------------------------------------------*/
7613 emitcode ("xch", "a,%s", x);
7614 emitcode ("rlc", "a");
7615 emitcode ("xch", "a,%s", x);
7616 emitcode ("rlc", "a");
7620 #ifdef BETTER_LITERAL_SHIFT
7621 /*-----------------------------------------------------------------*/
7622 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7623 /*-----------------------------------------------------------------*/
7627 emitcode ("xch", "a,%s", x);
7628 emitcode ("add", "a,acc");
7629 emitcode ("xch", "a,%s", x);
7630 emitcode ("rlc", "a");
7634 #ifdef BETTER_LITERAL_SHIFT
7635 /*-----------------------------------------------------------------*/
7636 /* AccAXLsh - left shift a:x by known count (0..7) */
7637 /*-----------------------------------------------------------------*/
7639 AccAXLsh (char *x, int shCount)
7654 case 5: // AAAAABBB:CCCCCDDD
7656 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7658 emitcode ("anl", "a,#!constbyte",
7659 SLMask[shCount]); // BBB00000:CCCCCDDD
7661 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7663 AccRol (shCount); // DDDCCCCC:BBB00000
7665 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7667 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7669 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7671 emitcode ("anl", "a,#!constbyte",
7672 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7674 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7676 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7679 case 6: // AAAAAABB:CCCCCCDD
7680 emitcode ("anl", "a,#!constbyte",
7681 SRMask[shCount]); // 000000BB:CCCCCCDD
7682 emitcode ("mov", "c,acc.0"); // c = B
7683 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7685 AccAXRrl1 (x); // BCCCCCCD:D000000B
7686 AccAXRrl1 (x); // BBCCCCCC:DD000000
7688 emitcode("rrc","a");
7689 emitcode("xch","a,%s", x);
7690 emitcode("rrc","a");
7691 emitcode("mov","c,acc.0"); //<< get correct bit
7692 emitcode("xch","a,%s", x);
7694 emitcode("rrc","a");
7695 emitcode("xch","a,%s", x);
7696 emitcode("rrc","a");
7697 emitcode("xch","a,%s", x);
7700 case 7: // a:x <<= 7
7702 emitcode ("anl", "a,#!constbyte",
7703 SRMask[shCount]); // 0000000B:CCCCCCCD
7705 emitcode ("mov", "c,acc.0"); // c = B
7707 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7709 AccAXRrl1 (x); // BCCCCCCC:D0000000
7718 #ifdef BETTER_LITERAL_SHIFT
7720 /*-----------------------------------------------------------------*/
7721 /* AccAXRsh - right shift a:x known count (0..7) */
7722 /*-----------------------------------------------------------------*/
7724 AccAXRsh (char *x, int shCount)
7732 AccAXRrl1 (x); // 0->a:x
7737 AccAXRrl1 (x); // 0->a:x
7740 AccAXRrl1 (x); // 0->a:x
7745 case 5: // AAAAABBB:CCCCCDDD = a:x
7747 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7749 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7751 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7753 emitcode ("anl", "a,#!constbyte",
7754 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7756 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7758 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7760 emitcode ("anl", "a,#!constbyte",
7761 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7763 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7765 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7767 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7770 case 6: // AABBBBBB:CCDDDDDD
7772 emitcode ("mov", "c,acc.7");
7773 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7775 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7777 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7779 emitcode ("anl", "a,#!constbyte",
7780 SRMask[shCount]); // 000000AA:BBBBBBCC
7783 case 7: // ABBBBBBB:CDDDDDDD
7785 emitcode ("mov", "c,acc.7"); // c = A
7787 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7789 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7791 emitcode ("anl", "a,#!constbyte",
7792 SRMask[shCount]); // 0000000A:BBBBBBBC
7801 #ifdef BETTER_LITERAL_SHIFT
7802 /*-----------------------------------------------------------------*/
7803 /* AccAXRshS - right shift signed a:x known count (0..7) */
7804 /*-----------------------------------------------------------------*/
7806 AccAXRshS (char *x, int shCount)
7814 emitcode ("mov", "c,acc.7");
7815 AccAXRrl1 (x); // s->a:x
7819 emitcode ("mov", "c,acc.7");
7820 AccAXRrl1 (x); // s->a:x
7822 emitcode ("mov", "c,acc.7");
7823 AccAXRrl1 (x); // s->a:x
7828 case 5: // AAAAABBB:CCCCCDDD = a:x
7830 tlbl = newiTempLabel (NULL);
7831 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7833 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7835 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7837 emitcode ("anl", "a,#!constbyte",
7838 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7840 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7842 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7844 emitcode ("anl", "a,#!constbyte",
7845 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7847 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7849 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7851 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7853 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7854 emitcode ("orl", "a,#!constbyte",
7855 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7857 emitcode ("", "!tlabeldef", tlbl->key + 100);
7858 break; // SSSSAAAA:BBBCCCCC
7860 case 6: // AABBBBBB:CCDDDDDD
7862 tlbl = newiTempLabel (NULL);
7863 emitcode ("mov", "c,acc.7");
7864 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7866 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7868 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7870 emitcode ("anl", "a,#!constbyte",
7871 SRMask[shCount]); // 000000AA:BBBBBBCC
7873 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7874 emitcode ("orl", "a,#!constbyte",
7875 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7877 emitcode ("", "!tlabeldef", tlbl->key + 100);
7879 case 7: // ABBBBBBB:CDDDDDDD
7881 tlbl = newiTempLabel (NULL);
7882 emitcode ("mov", "c,acc.7"); // c = A
7884 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7886 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7888 emitcode ("anl", "a,#!constbyte",
7889 SRMask[shCount]); // 0000000A:BBBBBBBC
7891 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7892 emitcode ("orl", "a,#!constbyte",
7893 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7895 emitcode ("", "!tlabeldef", tlbl->key + 100);
7903 #ifdef BETTER_LITERAL_SHIFT
7905 _loadLeftIntoAx(char **lsb,
7911 // Get the initial value from left into a pair of registers.
7912 // MSB must be in A, LSB can be any register.
7914 // If the result is held in registers, it is an optimization
7915 // if the LSB can be held in the register which will hold the,
7916 // result LSB since this saves us from having to copy it into
7917 // the result following AccAXLsh.
7919 // If the result is addressed indirectly, this is not a gain.
7920 if (AOP_NEEDSACC(result))
7924 _startLazyDPSEvaluation();
7925 if (AOP_TYPE(left) == AOP_DPTR2)
7928 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
7929 // get LSB in DP2_RESULT_REG.
7930 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
7931 assert(!strcmp(leftByte, DP2_RESULT_REG));
7935 // get LSB into DP2_RESULT_REG
7936 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
7937 if (strcmp(leftByte, DP2_RESULT_REG))
7940 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7943 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
7944 assert(strcmp(leftByte, DP2_RESULT_REG));
7947 _endLazyDPSEvaluation();
7948 *lsb = DP2_RESULT_REG;
7952 if (sameRegs (AOP (result), AOP (left)) &&
7953 ((offl + MSB16) == offr))
7955 /* don't crash result[offr] */
7956 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
7957 emitcode ("xch", "a,%s",
7958 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
7962 movLeft2Result (left, offl, result, offr, 0);
7963 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
7965 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
7966 assert(strcmp(*lsb,"a"));
7971 _storeAxResults(char *lsb,
7975 _startLazyDPSEvaluation();
7976 if (AOP_NEEDSACC(result))
7978 /* We have to explicitly update the result LSB.
7980 emitcode("xch","a,%s", lsb);
7981 aopPut(AOP(result), "a", offr);
7982 emitcode("mov","a,%s", lsb);
7984 if (getDataSize (result) > 1)
7986 aopPut (AOP (result), "a", offr + MSB16);
7988 _endLazyDPSEvaluation();
7991 /*-----------------------------------------------------------------*/
7992 /* shiftL2Left2Result - shift left two bytes from left to result */
7993 /*-----------------------------------------------------------------*/
7995 shiftL2Left2Result (operand * left, int offl,
7996 operand * result, int offr, int shCount)
8000 _loadLeftIntoAx(&lsb, left, result, offl, offr);
8002 AccAXLsh (lsb, shCount);
8004 _storeAxResults(lsb, result, offr);
8008 #ifdef BETTER_LITERAL_SHIFT
8009 /*-----------------------------------------------------------------*/
8010 /* shiftR2Left2Result - shift right two bytes from left to result */
8011 /*-----------------------------------------------------------------*/
8013 shiftR2Left2Result (operand * left, int offl,
8014 operand * result, int offr,
8015 int shCount, int sign)
8019 _loadLeftIntoAx(&lsb, left, result, offl, offr);
8021 /* a:x >> shCount (x = lsb(result)) */
8024 AccAXRshS(lsb, shCount);
8028 AccAXRsh(lsb, shCount);
8031 _storeAxResults(lsb, result, offr);
8035 /*-----------------------------------------------------------------*/
8036 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8037 /*-----------------------------------------------------------------*/
8039 shiftLLeftOrResult (operand * left, int offl,
8040 operand * result, int offr, int shCount)
8042 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8043 /* shift left accumulator */
8045 /* or with result */
8046 emitcode ("orl", "a,%s",
8047 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8048 /* back to result */
8049 aopPut (AOP (result), "a", offr);
8054 /*-----------------------------------------------------------------*/
8055 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8056 /*-----------------------------------------------------------------*/
8058 shiftRLeftOrResult (operand * left, int offl,
8059 operand * result, int offr, int shCount)
8061 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8062 /* shift right accumulator */
8064 /* or with result */
8065 emitcode ("orl", "a,%s",
8066 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8067 /* back to result */
8068 aopPut (AOP (result), "a", offr);
8072 #ifdef BETTER_LITERAL_SHIFT
8073 /*-----------------------------------------------------------------*/
8074 /* genlshOne - left shift a one byte quantity by known count */
8075 /*-----------------------------------------------------------------*/
8077 genlshOne (operand * result, operand * left, int shCount)
8079 D (emitcode (";", "genlshOne "););
8080 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8084 #ifdef BETTER_LITERAL_SHIFT
8085 /*-----------------------------------------------------------------*/
8086 /* genlshTwo - left shift two bytes by known amount != 0 */
8087 /*-----------------------------------------------------------------*/
8089 genlshTwo (operand * result, operand * left, int shCount)
8093 D (emitcode (";", "genlshTwo "););
8095 size = getDataSize (result);
8097 /* if shCount >= 8 */
8102 _startLazyDPSEvaluation();
8108 _endLazyDPSEvaluation();
8109 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8110 aopPut (AOP (result), zero, LSB);
8114 movLeft2Result (left, LSB, result, MSB16, 0);
8115 aopPut (AOP (result), zero, LSB);
8116 _endLazyDPSEvaluation();
8121 aopPut (AOP (result), zero, LSB);
8122 _endLazyDPSEvaluation();
8126 /* 1 <= shCount <= 7 */
8131 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8135 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8143 /*-----------------------------------------------------------------*/
8144 /* shiftLLong - shift left one long from left to result */
8145 /* offl = LSB or MSB16 */
8146 /*-----------------------------------------------------------------*/
8148 shiftLLong (operand * left, operand * result, int offr)
8151 int size = AOP_SIZE (result);
8153 if (size >= LSB + offr)
8155 l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8157 emitcode ("add", "a,acc");
8158 if (sameRegs (AOP (left), AOP (result)) &&
8159 size >= MSB16 + offr && offr != LSB)
8160 emitcode ("xch", "a,%s",
8161 aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8163 aopPut (AOP (result), "a", LSB + offr);
8166 if (size >= MSB16 + offr)
8168 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8170 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8172 emitcode ("rlc", "a");
8173 if (sameRegs (AOP (left), AOP (result)) &&
8174 size >= MSB24 + offr && offr != LSB)
8175 emitcode ("xch", "a,%s",
8176 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8178 aopPut (AOP (result), "a", MSB16 + offr);
8181 if (size >= MSB24 + offr)
8183 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8185 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8187 emitcode ("rlc", "a");
8188 if (sameRegs (AOP (left), AOP (result)) &&
8189 size >= MSB32 + offr && offr != LSB)
8190 emitcode ("xch", "a,%s",
8191 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8193 aopPut (AOP (result), "a", MSB24 + offr);
8196 if (size > MSB32 + offr)
8198 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8200 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8202 emitcode ("rlc", "a");
8203 aopPut (AOP (result), "a", MSB32 + offr);
8206 aopPut (AOP (result), zero, LSB);
8212 /*-----------------------------------------------------------------*/
8213 /* genlshFour - shift four byte by a known amount != 0 */
8214 /*-----------------------------------------------------------------*/
8216 genlshFour (operand * result, operand * left, int shCount)
8220 D (emitcode (";", "genlshFour ");
8223 size = AOP_SIZE (result);
8225 /* if shifting more that 3 bytes */
8230 /* lowest order of left goes to the highest
8231 order of the destination */
8232 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8234 movLeft2Result (left, LSB, result, MSB32, 0);
8235 aopPut (AOP (result), zero, LSB);
8236 aopPut (AOP (result), zero, MSB16);
8237 aopPut (AOP (result), zero, MSB24);
8241 /* more than two bytes */
8242 else if (shCount >= 16)
8244 /* lower order two bytes goes to higher order two bytes */
8246 /* if some more remaining */
8248 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8251 movLeft2Result (left, MSB16, result, MSB32, 0);
8252 movLeft2Result (left, LSB, result, MSB24, 0);
8254 aopPut (AOP (result), zero, MSB16);
8255 aopPut (AOP (result), zero, LSB);
8259 /* if more than 1 byte */
8260 else if (shCount >= 8)
8262 /* lower order three bytes goes to higher order three bytes */
8267 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8269 movLeft2Result (left, LSB, result, MSB16, 0);
8275 movLeft2Result (left, MSB24, result, MSB32, 0);
8276 movLeft2Result (left, MSB16, result, MSB24, 0);
8277 movLeft2Result (left, LSB, result, MSB16, 0);
8278 aopPut (AOP (result), zero, LSB);
8280 else if (shCount == 1)
8281 shiftLLong (left, result, MSB16);
8284 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8285 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8286 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8287 aopPut (AOP (result), zero, LSB);
8292 /* 1 <= shCount <= 7 */
8293 else if (shCount <= 2)
8295 shiftLLong (left, result, LSB);
8297 shiftLLong (result, result, LSB);
8299 /* 3 <= shCount <= 7, optimize */
8302 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8303 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8304 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8309 #ifdef BETTER_LITERAL_SHIFT
8310 /*-----------------------------------------------------------------*/
8311 /* genLeftShiftLiteral - left shifting by known count */
8312 /*-----------------------------------------------------------------*/
8314 genLeftShiftLiteral (operand * left,
8319 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8322 size = getSize (operandType (result));
8324 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8326 /* We only handle certain easy cases so far. */
8328 && (shCount < (size * 8))
8332 D(emitcode (";", "genLeftShiftLiteral wimping out"););
8336 freeAsmop (right, NULL, ic, TRUE);
8338 aopOp(left, ic, FALSE, FALSE);
8339 aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8342 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8344 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8345 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8347 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8350 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8352 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8353 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8355 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8361 emitcode ("; shift left ", "result %d, left %d", size,
8365 /* I suppose that the left size >= result size */
8368 _startLazyDPSEvaluation();
8371 movLeft2Result (left, size, result, size, 0);
8373 _endLazyDPSEvaluation();
8375 else if (shCount >= (size * 8))
8377 _startLazyDPSEvaluation();
8380 aopPut (AOP (result), zero, size);
8382 _endLazyDPSEvaluation();
8389 genlshOne (result, left, shCount);
8393 genlshTwo (result, left, shCount);
8397 genlshFour (result, left, shCount);
8401 fprintf(stderr, "*** ack! mystery literal shift!\n");
8405 freeAsmop (left, NULL, ic, TRUE);
8406 freeAsmop (result, NULL, ic, TRUE);
8411 /*-----------------------------------------------------------------*/
8412 /* genLeftShift - generates code for left shifting */
8413 /*-----------------------------------------------------------------*/
8415 genLeftShift (iCode * ic)
8417 operand *left, *right, *result;
8420 symbol *tlbl, *tlbl1;
8422 D (emitcode (";", "genLeftShift "););
8424 right = IC_RIGHT (ic);
8425 left = IC_LEFT (ic);
8426 result = IC_RESULT (ic);
8428 aopOp (right, ic, FALSE, FALSE);
8431 #ifdef BETTER_LITERAL_SHIFT
8432 /* if the shift count is known then do it
8433 as efficiently as possible */
8434 if (AOP_TYPE (right) == AOP_LIT)
8436 if (genLeftShiftLiteral (left, right, result, ic))
8443 /* shift count is unknown then we have to form
8444 a loop get the loop count in B : Note: we take
8445 only the lower order byte since shifting
8446 more that 32 bits make no sense anyway, ( the
8447 largest size of an object can be only 32 bits ) */
8449 if (AOP_TYPE (right) == AOP_LIT)
8451 /* Really should be handled by genLeftShiftLiteral,
8452 * but since I'm too lazy to fix that today, at least we can make
8453 * some small improvement.
8455 emitcode("mov", "b,#!constbyte",
8456 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8460 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8461 emitcode ("inc", "b");
8463 freeAsmop (right, NULL, ic, TRUE);
8464 aopOp (left, ic, FALSE, FALSE);
8465 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8467 /* now move the left to the result if they are not the
8469 if (!sameRegs (AOP (left), AOP (result)) &&
8470 AOP_SIZE (result) > 1)
8473 size = AOP_SIZE (result);
8475 _startLazyDPSEvaluation ();
8478 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8479 if (*l == '@' && (IS_AOP_PREG (result)))
8482 emitcode ("mov", "a,%s", l);
8483 aopPut (AOP (result), "a", offset);
8486 aopPut (AOP (result), l, offset);
8489 _endLazyDPSEvaluation ();
8492 tlbl = newiTempLabel (NULL);
8493 size = AOP_SIZE (result);
8495 tlbl1 = newiTempLabel (NULL);
8497 /* if it is only one byte then */
8500 symbol *tlbl1 = newiTempLabel (NULL);
8502 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8503 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8504 emitcode ("", "!tlabeldef", tlbl->key + 100);
8505 emitcode ("add", "a,acc");
8506 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8507 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8508 aopPut (AOP (result), "a", 0);
8512 reAdjustPreg (AOP (result));
8514 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8515 emitcode ("", "!tlabeldef", tlbl->key + 100);
8516 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8517 emitcode ("add", "a,acc");
8518 aopPut (AOP (result), "a", offset++);
8519 _startLazyDPSEvaluation ();
8522 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8523 emitcode ("rlc", "a");
8524 aopPut (AOP (result), "a", offset++);
8526 _endLazyDPSEvaluation ();
8527 reAdjustPreg (AOP (result));
8529 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8530 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8532 freeAsmop (left, NULL, ic, TRUE);
8533 freeAsmop (result, NULL, ic, TRUE);
8536 #ifdef BETTER_LITERAL_SHIFT
8537 /*-----------------------------------------------------------------*/
8538 /* genrshOne - right shift a one byte quantity by known count */
8539 /*-----------------------------------------------------------------*/
8541 genrshOne (operand * result, operand * left,
8542 int shCount, int sign)
8544 D (emitcode (";", "genrshOne"););
8545 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8549 #ifdef BETTER_LITERAL_SHIFT
8550 /*-----------------------------------------------------------------*/
8551 /* genrshTwo - right shift two bytes by known amount != 0 */
8552 /*-----------------------------------------------------------------*/
8554 genrshTwo (operand * result, operand * left,
8555 int shCount, int sign)
8557 D (emitcode (";", "genrshTwo"););
8559 /* if shCount >= 8 */
8563 _startLazyDPSEvaluation();
8566 shiftR1Left2Result (left, MSB16, result, LSB,
8571 movLeft2Result (left, MSB16, result, LSB, sign);
8573 addSign (result, MSB16, sign);
8574 _endLazyDPSEvaluation();
8577 /* 1 <= shCount <= 7 */
8580 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8585 /*-----------------------------------------------------------------*/
8586 /* shiftRLong - shift right one long from left to result */
8587 /* offl = LSB or MSB16 */
8588 /*-----------------------------------------------------------------*/
8590 shiftRLong (operand * left, int offl,
8591 operand * result, int sign)
8593 int isSameRegs=sameRegs(AOP(left),AOP(result));
8595 if (isSameRegs && offl>1) {
8596 // we are in big trouble, but this shouldn't happen
8597 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8600 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8605 emitcode ("rlc", "a");
8606 emitcode ("subb", "a,acc");
8607 emitcode ("xch", "a,%s",
8608 aopGet(AOP(left), MSB32, FALSE, FALSE, DP2_RESULT_REG));
8610 aopPut (AOP(result), zero, MSB32);
8615 emitcode ("clr", "c");
8617 emitcode ("mov", "c,acc.7");
8620 emitcode ("rrc", "a");
8622 if (isSameRegs && offl==MSB16) {
8624 "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE, DP2_RESULT_REG));
8626 aopPut (AOP (result), "a", MSB32);
8627 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8630 emitcode ("rrc", "a");
8631 if (isSameRegs && offl==1) {
8632 emitcode ("xch", "a,%s",
8633 aopGet (AOP (left), MSB16, FALSE, FALSE, DP2_RESULT_REG));
8635 aopPut (AOP (result), "a", MSB24);
8636 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, NULL));
8638 emitcode ("rrc", "a");
8639 aopPut (AOP (result), "a", MSB16 - offl);
8643 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, NULL));
8644 emitcode ("rrc", "a");
8645 aopPut (AOP (result), "a", LSB);
8649 /*-----------------------------------------------------------------*/
8650 /* genrshFour - shift four byte by a known amount != 0 */
8651 /*-----------------------------------------------------------------*/
8653 genrshFour (operand * result, operand * left,
8654 int shCount, int sign)
8656 D (emitcode (";", "genrshFour"););
8658 /* if shifting more that 3 bytes */
8662 _startLazyDPSEvaluation();
8664 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8666 movLeft2Result (left, MSB32, result, LSB, sign);
8667 addSign (result, MSB16, sign);
8668 _endLazyDPSEvaluation();
8670 else if (shCount >= 16)
8673 _startLazyDPSEvaluation();
8675 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8678 movLeft2Result (left, MSB24, result, LSB, 0);
8679 movLeft2Result (left, MSB32, result, MSB16, sign);
8681 addSign (result, MSB24, sign);
8682 _endLazyDPSEvaluation();
8684 else if (shCount >= 8)
8687 _startLazyDPSEvaluation();
8690 shiftRLong (left, MSB16, result, sign);
8692 else if (shCount == 0)
8694 movLeft2Result (left, MSB16, result, LSB, 0);
8695 movLeft2Result (left, MSB24, result, MSB16, 0);
8696 movLeft2Result (left, MSB32, result, MSB24, sign);
8697 addSign (result, MSB32, sign);
8701 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8702 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8703 /* the last shift is signed */
8704 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8705 addSign (result, MSB32, sign);
8707 _endLazyDPSEvaluation();
8711 /* 1 <= shCount <= 7 */
8714 shiftRLong (left, LSB, result, sign);
8716 shiftRLong (result, LSB, result, sign);
8720 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8721 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8722 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8727 #ifdef BETTER_LITERAL_SHIFT
8728 /*-----------------------------------------------------------------*/
8729 /* genRightShiftLiteral - right shifting by known count */
8730 /*-----------------------------------------------------------------*/
8732 genRightShiftLiteral (operand * left,
8738 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8741 size = getSize (operandType (result));
8743 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8745 /* We only handle certain easy cases so far. */
8747 && (shCount < (size * 8))
8752 D(emitcode (";", "genRightShiftLiteral wimping out"););
8756 freeAsmop (right, NULL, ic, TRUE);
8758 aopOp (left, ic, FALSE, FALSE);
8759 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8762 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8766 /* test the LEFT size !!! */
8768 /* I suppose that the left size >= result size */
8771 size = getDataSize (result);
8772 _startLazyDPSEvaluation();
8775 movLeft2Result (left, size, result, size, 0);
8777 _endLazyDPSEvaluation();
8779 else if (shCount >= (size * 8))
8783 /* get sign in acc.7 */
8784 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
8786 addSign (result, LSB, sign);
8793 genrshOne (result, left, shCount, sign);
8797 genrshTwo (result, left, shCount, sign);
8801 genrshFour (result, left, shCount, sign);
8808 freeAsmop (left, NULL, ic, TRUE);
8809 freeAsmop (result, NULL, ic, TRUE);
8815 /*-----------------------------------------------------------------*/
8816 /* genSignedRightShift - right shift of signed number */
8817 /*-----------------------------------------------------------------*/
8819 genSignedRightShift (iCode * ic)
8821 operand *right, *left, *result;
8824 symbol *tlbl, *tlbl1;
8826 D (emitcode (";", "genSignedRightShift "););
8828 /* we do it the hard way put the shift count in b
8829 and loop thru preserving the sign */
8831 right = IC_RIGHT (ic);
8832 left = IC_LEFT (ic);
8833 result = IC_RESULT (ic);
8835 aopOp (right, ic, FALSE, FALSE);
8837 #ifdef BETTER_LITERAL_SHIFT
8838 if (AOP_TYPE (right) == AOP_LIT)
8840 if (genRightShiftLiteral (left, right, result, ic, 1))
8846 /* shift count is unknown then we have to form
8847 a loop get the loop count in B : Note: we take
8848 only the lower order byte since shifting
8849 more that 32 bits make no sense anyway, ( the
8850 largest size of an object can be only 32 bits ) */
8852 if (AOP_TYPE (right) == AOP_LIT)
8854 /* Really should be handled by genRightShiftLiteral,
8855 * but since I'm too lazy to fix that today, at least we can make
8856 * some small improvement.
8858 emitcode("mov", "b,#!constbyte",
8859 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8863 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8864 emitcode ("inc", "b");
8866 freeAsmop (right, NULL, ic, TRUE);
8867 aopOp (left, ic, FALSE, FALSE);
8868 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8870 /* now move the left to the result if they are not the
8872 if (!sameRegs (AOP (left), AOP (result)) &&
8873 AOP_SIZE (result) > 1)
8876 size = AOP_SIZE (result);
8878 _startLazyDPSEvaluation ();
8881 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8882 if (*l == '@' && IS_AOP_PREG (result))
8885 emitcode ("mov", "a,%s", l);
8886 aopPut (AOP (result), "a", offset);
8889 aopPut (AOP (result), l, offset);
8892 _endLazyDPSEvaluation ();
8895 /* mov the highest order bit to OVR */
8896 tlbl = newiTempLabel (NULL);
8897 tlbl1 = newiTempLabel (NULL);
8899 size = AOP_SIZE (result);
8901 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
8902 emitcode ("rlc", "a");
8903 emitcode ("mov", "ov,c");
8904 /* if it is only one byte then */
8907 MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8908 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8909 emitcode ("", "!tlabeldef", tlbl->key + 100);
8910 emitcode ("mov", "c,ov");
8911 emitcode ("rrc", "a");
8912 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8913 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8914 aopPut (AOP (result), "a", 0);
8918 reAdjustPreg (AOP (result));
8919 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8920 emitcode ("", "!tlabeldef", tlbl->key + 100);
8921 emitcode ("mov", "c,ov");
8922 _startLazyDPSEvaluation ();
8925 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8926 emitcode ("rrc", "a");
8927 aopPut (AOP (result), "a", offset--);
8929 _endLazyDPSEvaluation ();
8930 reAdjustPreg (AOP (result));
8931 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8932 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8935 freeAsmop (left, NULL, ic, TRUE);
8936 freeAsmop (result, NULL, ic, TRUE);
8939 /*-----------------------------------------------------------------*/
8940 /* genRightShift - generate code for right shifting */
8941 /*-----------------------------------------------------------------*/
8943 genRightShift (iCode * ic)
8945 operand *right, *left, *result;
8949 symbol *tlbl, *tlbl1;
8951 D (emitcode (";", "genRightShift "););
8953 /* if signed then we do it the hard way preserve the
8954 sign bit moving it inwards */
8955 retype = getSpec (operandType (IC_RESULT (ic)));
8957 if (!SPEC_USIGN (retype))
8959 genSignedRightShift (ic);
8963 /* signed & unsigned types are treated the same : i.e. the
8964 signed is NOT propagated inwards : quoting from the
8965 ANSI - standard : "for E1 >> E2, is equivalent to division
8966 by 2**E2 if unsigned or if it has a non-negative value,
8967 otherwise the result is implementation defined ", MY definition
8968 is that the sign does not get propagated */
8970 right = IC_RIGHT (ic);
8971 left = IC_LEFT (ic);
8972 result = IC_RESULT (ic);
8974 aopOp (right, ic, FALSE, FALSE);
8976 #ifdef BETTER_LITERAL_SHIFT
8977 /* if the shift count is known then do it
8978 as efficiently as possible */
8979 if (AOP_TYPE (right) == AOP_LIT)
8981 if (genRightShiftLiteral (left, right, result, ic, 0))
8988 /* shift count is unknown then we have to form
8989 a loop get the loop count in B : Note: we take
8990 only the lower order byte since shifting
8991 more that 32 bits make no sense anyway, ( the
8992 largest size of an object can be only 32 bits ) */
8994 if (AOP_TYPE (right) == AOP_LIT)
8996 /* Really should be handled by genRightShiftLiteral,
8997 * but since I'm too lazy to fix that today, at least we can make
8998 * some small improvement.
9000 emitcode("mov", "b,#!constbyte",
9001 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9005 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
9006 emitcode ("inc", "b");
9008 freeAsmop (right, NULL, ic, TRUE);
9009 aopOp (left, ic, FALSE, FALSE);
9010 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9012 /* now move the left to the result if they are not the
9014 if (!sameRegs (AOP (left), AOP (result)) &&
9015 AOP_SIZE (result) > 1)
9018 size = AOP_SIZE (result);
9020 _startLazyDPSEvaluation ();
9023 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
9024 if (*l == '@' && IS_AOP_PREG (result))
9027 emitcode ("mov", "a,%s", l);
9028 aopPut (AOP (result), "a", offset);
9031 aopPut (AOP (result), l, offset);
9034 _endLazyDPSEvaluation ();
9037 tlbl = newiTempLabel (NULL);
9038 tlbl1 = newiTempLabel (NULL);
9039 size = AOP_SIZE (result);
9042 /* if it is only one byte then */
9045 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9046 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9047 emitcode ("", "!tlabeldef", tlbl->key + 100);
9049 emitcode ("rrc", "a");
9050 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9051 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9052 aopPut (AOP (result), "a", 0);
9056 reAdjustPreg (AOP (result));
9057 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9058 emitcode ("", "!tlabeldef", tlbl->key + 100);
9060 _startLazyDPSEvaluation ();
9063 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
9064 emitcode ("rrc", "a");
9065 aopPut (AOP (result), "a", offset--);
9067 _endLazyDPSEvaluation ();
9068 reAdjustPreg (AOP (result));
9070 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9071 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9074 freeAsmop (left, NULL, ic, TRUE);
9075 freeAsmop (result, NULL, ic, TRUE);
9079 /*-----------------------------------------------------------------*/
9080 /* emitPtrByteGet - emits code to get a byte into A through a */
9081 /* pointer register (R0, R1, or DPTR). The */
9082 /* original value of A can be preserved in B. */
9083 /*-----------------------------------------------------------------*/
9085 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9092 emitcode ("mov", "b,a");
9093 emitcode ("mov", "a,@%s", rname);
9098 emitcode ("mov", "b,a");
9099 emitcode ("movx", "a,@%s", rname);
9104 emitcode ("mov", "b,a");
9105 emitcode ("movx", "a,@dptr");
9110 emitcode ("mov", "b,a");
9111 emitcode ("clr", "a");
9112 emitcode ("movc", "a,@a+dptr");
9118 emitcode ("push", "b");
9119 emitcode ("push", "acc");
9121 emitcode ("lcall", "__gptrget");
9123 emitcode ("pop", "b");
9128 /*-----------------------------------------------------------------*/
9129 /* emitPtrByteSet - emits code to set a byte from src through a */
9130 /* pointer register (R0, R1, or DPTR). */
9131 /*-----------------------------------------------------------------*/
9133 emitPtrByteSet (char *rname, int p_type, char *src)
9142 emitcode ("mov", "@%s,a", rname);
9145 emitcode ("mov", "@%s,%s", rname, src);
9150 emitcode ("movx", "@%s,a", rname);
9155 emitcode ("movx", "@dptr,a");
9160 emitcode ("lcall", "__gptrput");
9165 /*-----------------------------------------------------------------*/
9166 /* genUnpackBits - generates code for unpacking bits */
9167 /*-----------------------------------------------------------------*/
9169 genUnpackBits (operand * result, char *rname, int ptype)
9171 int offset = 0; /* result byte offset */
9172 int rsize; /* result size */
9173 int rlen = 0; /* remaining bitfield length */
9174 sym_link *etype; /* bitfield type information */
9175 int blen; /* bitfield length */
9176 int bstr; /* bitfield starting bit within byte */
9178 D(emitcode ("; genUnpackBits",""));
9180 etype = getSpec (operandType (result));
9181 rsize = getSize (operandType (result));
9182 blen = SPEC_BLEN (etype);
9183 bstr = SPEC_BSTR (etype);
9185 /* If the bitfield length is less than a byte */
9188 emitPtrByteGet (rname, ptype, FALSE);
9190 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
9191 aopPut (AOP (result), "a", offset++);
9195 /* Bit field did not fit in a byte. Copy all
9196 but the partial byte at the end. */
9197 for (rlen=blen;rlen>=8;rlen-=8)
9199 emitPtrByteGet (rname, ptype, FALSE);
9200 aopPut (AOP (result), "a", offset++);
9202 emitcode ("inc", "%s", rname);
9205 /* Handle the partial byte at the end */
9208 emitPtrByteGet (rname, ptype, FALSE);
9209 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
9210 aopPut (AOP (result), "a", offset++);
9218 aopPut (AOP (result), zero, offset++);
9223 /*-----------------------------------------------------------------*/
9224 /* genDataPointerGet - generates code when ptr offset is known */
9225 /*-----------------------------------------------------------------*/
9227 genDataPointerGet (operand * left,
9233 int size, offset = 0;
9234 aopOp (result, ic, TRUE, FALSE);
9236 /* get the string representation of the name */
9237 l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9238 size = AOP_SIZE (result);
9239 _startLazyDPSEvaluation ();
9244 SNPRINTF (buff, sizeof(buff),
9245 "(%s + %d)", l + 1, offset);
9249 SNPRINTF (buff, sizeof(buff),
9252 aopPut (AOP (result), buff, offset++);
9254 _endLazyDPSEvaluation ();
9256 freeAsmop (left, NULL, ic, TRUE);
9257 freeAsmop (result, NULL, ic, TRUE);
9260 /*-----------------------------------------------------------------*/
9261 /* genNearPointerGet - emitcode for near pointer fetch */
9262 /*-----------------------------------------------------------------*/
9264 genNearPointerGet (operand * left,
9272 sym_link *rtype, *retype, *letype;
9273 sym_link *ltype = operandType (left);
9276 rtype = operandType (result);
9277 retype = getSpec (rtype);
9278 letype = getSpec (ltype);
9280 aopOp (left, ic, FALSE, FALSE);
9282 /* if left is rematerialisable and
9283 result is not bit variable type and
9284 the left is pointer to data space i.e
9285 lower 128 bytes of space */
9286 if (AOP_TYPE (left) == AOP_IMMD &&
9287 !IS_BITVAR (retype) &&
9288 !IS_BITVAR (letype) &&
9289 DCL_TYPE (ltype) == POINTER)
9291 genDataPointerGet (left, result, ic);
9295 /* if the value is already in a pointer register
9296 then don't need anything more */
9297 if (!AOP_INPREG (AOP (left)))
9299 /* otherwise get a free pointer register */
9301 preg = getFreePtr (ic, &aop, FALSE);
9302 emitcode ("mov", "%s,%s",
9304 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9308 rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9310 freeAsmop (left, NULL, ic, TRUE);
9311 aopOp (result, ic, FALSE, FALSE);
9313 /* if bitfield then unpack the bits */
9314 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9315 genUnpackBits (result, rname, POINTER);
9318 /* we have can just get the values */
9319 int size = AOP_SIZE (result);
9324 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9327 emitcode ("mov", "a,@%s", rname);
9328 aopPut (AOP (result), "a", offset);
9332 SNPRINTF (buff, sizeof(buff), "@%s", rname);
9333 aopPut (AOP (result), buff, offset);
9338 emitcode ("inc", "%s", rname);
9343 /* now some housekeeping stuff */
9346 /* we had to allocate for this iCode */
9347 if (pi) { /* post increment present */
9348 aopPut(AOP ( left ),rname,0);
9350 freeAsmop (NULL, aop, ic, TRUE);
9354 /* we did not allocate which means left
9355 already in a pointer register, then
9356 if size > 0 && this could be used again
9357 we have to point it back to where it
9359 if (AOP_SIZE (result) > 1 &&
9360 !OP_SYMBOL (left)->remat &&
9361 (OP_SYMBOL (left)->liveTo > ic->seq ||
9365 int size = AOP_SIZE (result) - 1;
9367 emitcode ("dec", "%s", rname);
9372 freeAsmop (result, NULL, ic, TRUE);
9373 if (pi) pi->generated = 1;
9376 /*-----------------------------------------------------------------*/
9377 /* genPagedPointerGet - emitcode for paged pointer fetch */
9378 /*-----------------------------------------------------------------*/
9380 genPagedPointerGet (operand * left,
9388 sym_link *rtype, *retype, *letype;
9390 rtype = operandType (result);
9391 retype = getSpec (rtype);
9392 letype = getSpec (operandType (left));
9393 aopOp (left, ic, FALSE, FALSE);
9395 /* if the value is already in a pointer register
9396 then don't need anything more */
9397 if (!AOP_INPREG (AOP (left)))
9399 /* otherwise get a free pointer register */
9401 preg = getFreePtr (ic, &aop, FALSE);
9402 emitcode ("mov", "%s,%s",
9404 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9408 rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9410 freeAsmop (left, NULL, ic, TRUE);
9411 aopOp (result, ic, FALSE, FALSE);
9413 /* if bitfield then unpack the bits */
9414 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9415 genUnpackBits (result, rname, PPOINTER);
9418 /* we have can just get the values */
9419 int size = AOP_SIZE (result);
9425 emitcode ("movx", "a,@%s", rname);
9426 aopPut (AOP (result), "a", offset);
9431 emitcode ("inc", "%s", rname);
9435 /* now some housekeeping stuff */
9438 /* we had to allocate for this iCode */
9439 if (pi) aopPut ( AOP (left), rname, 0);
9440 freeAsmop (NULL, aop, ic, TRUE);
9444 /* we did not allocate which means left
9445 already in a pointer register, then
9446 if size > 0 && this could be used again
9447 we have to point it back to where it
9449 if (AOP_SIZE (result) > 1 &&
9450 !OP_SYMBOL (left)->remat &&
9451 (OP_SYMBOL (left)->liveTo > ic->seq ||
9455 int size = AOP_SIZE (result) - 1;
9457 emitcode ("dec", "%s", rname);
9462 freeAsmop (result, NULL, ic, TRUE);
9463 if (pi) pi->generated = 1;
9466 /*-----------------------------------------------------------------*/
9467 /* genFarPointerGet - gget value from far space */
9468 /*-----------------------------------------------------------------*/
9470 genFarPointerGet (operand * left,
9471 operand * result, iCode * ic, iCode *pi)
9473 int size, offset, dopi=1;
9474 sym_link *retype = getSpec (operandType (result));
9475 sym_link *letype = getSpec (operandType (left));
9476 D (emitcode (";", "genFarPointerGet"););
9478 aopOp (left, ic, FALSE, FALSE);
9480 /* if the operand is already in dptr
9481 then we do nothing else we move the value to dptr */
9482 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9484 /* if this is remateriazable */
9485 if (AOP_TYPE (left) == AOP_IMMD)
9487 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9491 /* we need to get it byte by byte */
9492 _startLazyDPSEvaluation ();
9493 if (AOP_TYPE (left) != AOP_DPTR)
9495 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9496 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9497 if (options.model == MODEL_FLAT24)
9498 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9502 /* We need to generate a load to DPTR indirect through DPTR. */
9503 D (emitcode (";", "genFarPointerGet -- indirection special case."););
9504 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9505 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9506 if (options.model == MODEL_FLAT24)
9507 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9508 emitcode ("pop", "dph");
9509 emitcode ("pop", "dpl");
9512 _endLazyDPSEvaluation ();
9515 /* so dptr know contains the address */
9516 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9518 /* if bit then unpack */
9519 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9520 if (AOP_INDPTRn(left)) {
9521 genSetDPTR(AOP(left)->aopu.dptr);
9523 genUnpackBits (result, "dptr", FPOINTER);
9524 if (AOP_INDPTRn(left)) {
9529 size = AOP_SIZE (result);
9532 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9534 genSetDPTR(AOP(left)->aopu.dptr);
9535 emitcode ("movx", "a,@dptr");
9536 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9537 emitcode ("inc", "dptr");
9539 aopPut (AOP (result), "a", offset++);
9542 _startLazyDPSEvaluation ();
9544 if (AOP_INDPTRn(left)) {
9545 genSetDPTR(AOP(left)->aopu.dptr);
9551 emitcode ("movx", "a,@dptr");
9552 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9553 emitcode ("inc", "dptr");
9555 aopPut (AOP (result), "a", offset++);
9557 _endLazyDPSEvaluation ();
9560 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9561 if (!AOP_INDPTRn(left)) {
9562 _startLazyDPSEvaluation ();
9563 aopPut ( AOP (left), "dpl", 0);
9564 aopPut ( AOP (left), "dph", 1);
9565 if (options.model == MODEL_FLAT24)
9566 aopPut ( AOP (left), "dpx", 2);
9567 _endLazyDPSEvaluation ();
9570 } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) &&
9571 AOP_SIZE(result) > 1 &&
9573 (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
9575 size = AOP_SIZE (result) - 1;
9576 if (AOP_INDPTRn(left)) {
9577 genSetDPTR(AOP(left)->aopu.dptr);
9579 while (size--) emitcode ("lcall","__decdptr");
9580 if (AOP_INDPTRn(left)) {
9585 freeAsmop (left, NULL, ic, TRUE);
9586 freeAsmop (result, NULL, ic, TRUE);
9589 /*-----------------------------------------------------------------*/
9590 /* genCodePointerGet - get value from code space */
9591 /*-----------------------------------------------------------------*/
9593 genCodePointerGet (operand * left,
9594 operand * result, iCode * ic, iCode *pi)
9596 int size, offset, dopi=1;
9597 sym_link *retype = getSpec (operandType (result));
9599 aopOp (left, ic, FALSE, FALSE);
9601 /* if the operand is already in dptr
9602 then we do nothing else we move the value to dptr */
9603 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
9605 /* if this is remateriazable */
9606 if (AOP_TYPE (left) == AOP_IMMD)
9608 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9611 { /* we need to get it byte by byte */
9612 _startLazyDPSEvaluation ();
9613 if (AOP_TYPE (left) != AOP_DPTR)
9615 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9616 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9617 if (options.model == MODEL_FLAT24)
9618 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9622 /* We need to generate a load to DPTR indirect through DPTR. */
9623 D (emitcode (";", "gencodePointerGet -- indirection special case."););
9624 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9625 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9626 if (options.model == MODEL_FLAT24)
9627 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9628 emitcode ("pop", "dph");
9629 emitcode ("pop", "dpl");
9632 _endLazyDPSEvaluation ();
9635 /* so dptr know contains the address */
9636 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9638 /* if bit then unpack */
9639 if (IS_BITVAR (retype)) {
9640 if (AOP_INDPTRn(left)) {
9641 genSetDPTR(AOP(left)->aopu.dptr);
9643 genUnpackBits (result, "dptr", CPOINTER);
9644 if (AOP_INDPTRn(left)) {
9649 size = AOP_SIZE (result);
9651 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9653 genSetDPTR(AOP(left)->aopu.dptr);
9654 emitcode ("clr", "a");
9655 emitcode ("movc", "a,@a+dptr");
9656 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9657 emitcode ("inc", "dptr");
9659 aopPut (AOP (result), "a", offset++);
9662 _startLazyDPSEvaluation ();
9665 if (AOP_INDPTRn(left)) {
9666 genSetDPTR(AOP(left)->aopu.dptr);
9672 emitcode ("clr", "a");
9673 emitcode ("movc", "a,@a+dptr");
9674 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9675 emitcode ("inc", "dptr");
9676 aopPut (AOP (result), "a", offset++);
9678 _endLazyDPSEvaluation ();
9681 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9682 if (!AOP_INDPTRn(left)) {
9683 _startLazyDPSEvaluation ();
9685 aopPut ( AOP (left), "dpl", 0);
9686 aopPut ( AOP (left), "dph", 1);
9687 if (options.model == MODEL_FLAT24)
9688 aopPut ( AOP (left), "dpx", 2);
9690 _endLazyDPSEvaluation ();
9693 } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
9694 AOP_SIZE(result) > 1 &&
9695 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9697 size = AOP_SIZE (result) - 1;
9698 if (AOP_INDPTRn(left)) {
9699 genSetDPTR(AOP(left)->aopu.dptr);
9701 while (size--) emitcode ("lcall","__decdptr");
9702 if (AOP_INDPTRn(left)) {
9707 freeAsmop (left, NULL, ic, TRUE);
9708 freeAsmop (result, NULL, ic, TRUE);
9711 /*-----------------------------------------------------------------*/
9712 /* genGenPointerGet - gget value from generic pointer space */
9713 /*-----------------------------------------------------------------*/
9715 genGenPointerGet (operand * left,
9716 operand * result, iCode * ic, iCode * pi)
9719 sym_link *retype = getSpec (operandType (result));
9720 sym_link *letype = getSpec (operandType (left));
9722 D (emitcode (";", "genGenPointerGet "); );
9724 aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
9726 /* if the operand is already in dptr
9727 then we do nothing else we move the value to dptr */
9728 if (AOP_TYPE (left) != AOP_STR)
9730 /* if this is remateriazable */
9731 if (AOP_TYPE (left) == AOP_IMMD)
9733 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9734 if (AOP(left)->aopu.aop_immd.from_cast_remat)
9736 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
9740 emitcode ("mov", "b,#%d", pointerCode (retype));
9744 { /* we need to get it byte by byte */
9745 _startLazyDPSEvaluation ();
9746 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
9747 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
9748 if (options.model == MODEL_FLAT24) {
9749 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9750 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
9752 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9754 _endLazyDPSEvaluation ();
9758 /* so dptr-b now contains the address */
9760 aopOp (result, ic, FALSE, TRUE);
9763 /* if bit then unpack */
9764 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9766 genUnpackBits (result, "dptr", GPOINTER);
9770 size = AOP_SIZE (result);
9777 // Get two bytes at a time, results in _AP & A.
9778 // dptr will be incremented ONCE by __gptrgetWord.
9780 // Note: any change here must be coordinated
9781 // with the implementation of __gptrgetWord
9782 // in device/lib/_gptrget.c
9783 emitcode ("lcall", "__gptrgetWord");
9784 aopPut (AOP (result), DP2_RESULT_REG, offset++);
9785 aopPut (AOP (result), "a", offset++);
9790 // Only one byte to get.
9791 emitcode ("lcall", "__gptrget");
9792 aopPut (AOP (result), "a", offset++);
9795 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9797 emitcode ("inc", "dptr");
9802 if (pi && AOP_TYPE (left) != AOP_IMMD) {
9803 _startLazyDPSEvaluation ();
9805 aopPut ( AOP (left), "dpl", 0);
9806 aopPut ( AOP (left), "dph", 1);
9807 if (options.model == MODEL_FLAT24) {
9808 aopPut ( AOP (left), "dpx", 2);
9809 aopPut ( AOP (left), "b", 3);
9810 } else aopPut ( AOP (left), "b", 2);
9812 _endLazyDPSEvaluation ();
9815 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9816 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9818 size = AOP_SIZE (result) - 1;
9819 while (size--) emitcode ("lcall","__decdptr");
9822 freeAsmop (left, NULL, ic, TRUE);
9823 freeAsmop (result, NULL, ic, TRUE);
9826 /*-----------------------------------------------------------------*/
9827 /* genPointerGet - generate code for pointer get */
9828 /*-----------------------------------------------------------------*/
9830 genPointerGet (iCode * ic, iCode *pi)
9832 operand *left, *result;
9833 sym_link *type, *etype;
9836 D (emitcode (";", "genPointerGet ");
9839 left = IC_LEFT (ic);
9840 result = IC_RESULT (ic);
9842 /* depending on the type of pointer we need to
9843 move it to the correct pointer register */
9844 type = operandType (left);
9845 etype = getSpec (type);
9846 /* if left is of type of pointer then it is simple */
9847 if (IS_PTR (type) && !IS_FUNC (type->next))
9848 p_type = DCL_TYPE (type);
9851 /* we have to go by the storage class */
9852 p_type = PTR_TYPE (SPEC_OCLS (etype));
9854 /* special case when cast remat */
9855 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9856 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9857 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9858 type = operandType (left);
9859 p_type = DCL_TYPE (type);
9861 /* now that we have the pointer type we assign
9862 the pointer values */
9868 genNearPointerGet (left, result, ic, pi);
9872 genPagedPointerGet (left, result, ic, pi);
9876 genFarPointerGet (left, result, ic, pi);
9880 genCodePointerGet (left, result, ic, pi);
9884 genGenPointerGet (left, result, ic, pi);
9890 /*-----------------------------------------------------------------*/
9891 /* genPackBits - generates code for packed bit storage */
9892 /*-----------------------------------------------------------------*/
9894 genPackBits (sym_link * etype,
9896 char *rname, int p_type)
9898 int offset = 0; /* source byte offset */
9899 int rlen = 0; /* remaining bitfield length */
9900 int blen; /* bitfield length */
9901 int bstr; /* bitfield starting bit within byte */
9902 int litval; /* source literal value (if AOP_LIT) */
9903 unsigned char mask; /* bitmask within current byte */
9905 D(emitcode ("; genPackBits",""));
9907 blen = SPEC_BLEN (etype);
9908 bstr = SPEC_BSTR (etype);
9910 /* If the bitfield length is less than a byte */
9913 mask = ((unsigned char) (0xFF << (blen + bstr)) |
9914 (unsigned char) (0xFF >> (8 - bstr)));
9916 if (AOP_TYPE (right) == AOP_LIT)
9918 /* Case with a bitfield length <8 and literal source
9920 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9922 litval &= (~mask) & 0xff;
9923 emitPtrByteGet (rname, p_type, FALSE);
9924 if ((mask|litval)!=0xff)
9925 emitcode ("anl","a,#!constbyte", mask);
9927 emitcode ("orl","a,#!constbyte", litval);
9931 if ((blen==1) && (p_type!=GPOINTER))
9933 /* Case with a bitfield length == 1 and no generic pointer
9935 if (AOP_TYPE (right) == AOP_CRY)
9936 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9939 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
9940 emitcode ("rrc","a");
9942 emitPtrByteGet (rname, p_type, FALSE);
9943 emitcode ("mov","acc.%d,c",bstr);
9947 /* Case with a bitfield length < 8 and arbitrary source
9949 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
9950 /* shift and mask source value */
9952 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
9954 /* transfer A to B and get next byte */
9955 emitPtrByteGet (rname, p_type, TRUE);
9957 emitcode ("anl", "a,#!constbyte", mask);
9958 emitcode ("orl", "a,b");
9959 if (p_type == GPOINTER)
9960 emitcode ("pop", "b");
9964 emitPtrByteSet (rname, p_type, "a");
9968 /* Bit length is greater than 7 bits. In this case, copy */
9969 /* all except the partial byte at the end */
9970 for (rlen=blen;rlen>=8;rlen-=8)
9972 emitPtrByteSet (rname, p_type,
9973 aopGet (AOP (right), offset++, FALSE, TRUE, NULL) );
9975 emitcode ("inc", "%s", rname);
9978 /* If there was a partial byte at the end */
9981 mask = (((unsigned char) -1 << rlen) & 0xff);
9983 if (AOP_TYPE (right) == AOP_LIT)
9985 /* Case with partial byte and literal source
9987 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9988 litval >>= (blen-rlen);
9989 litval &= (~mask) & 0xff;
9990 emitPtrByteGet (rname, p_type, FALSE);
9991 if ((mask|litval)!=0xff)
9992 emitcode ("anl","a,#!constbyte", mask);
9994 emitcode ("orl","a,#!constbyte", litval);
9998 /* Case with partial byte and arbitrary source
10000 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10001 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10003 /* transfer A to B and get next byte */
10004 emitPtrByteGet (rname, p_type, TRUE);
10006 emitcode ("anl", "a,#!constbyte", mask);
10007 emitcode ("orl", "a,b");
10008 if (p_type == GPOINTER)
10009 emitcode ("pop", "b");
10011 emitPtrByteSet (rname, p_type, "a");
10017 /*-----------------------------------------------------------------*/
10018 /* genDataPointerSet - remat pointer to data space */
10019 /*-----------------------------------------------------------------*/
10021 genDataPointerSet (operand * right,
10025 int size, offset = 0;
10026 char *l, buff[256];
10028 aopOp (right, ic, FALSE, FALSE);
10030 l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
10031 size = AOP_SIZE (right);
10036 SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
10040 SNPRINTF (buff, sizeof(buff), "%s", l + 1);
10043 emitcode ("mov", "%s,%s", buff,
10044 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10047 freeAsmop (right, NULL, ic, TRUE);
10048 freeAsmop (result, NULL, ic, TRUE);
10051 /*-----------------------------------------------------------------*/
10052 /* genNearPointerSet - emitcode for near pointer put */
10053 /*-----------------------------------------------------------------*/
10055 genNearPointerSet (operand * right,
10062 sym_link *retype, *letype;
10063 sym_link *ptype = operandType (result);
10065 retype = getSpec (operandType (right));
10066 letype = getSpec (ptype);
10068 aopOp (result, ic, FALSE, FALSE);
10070 /* if the result is rematerializable &
10071 in data space & not a bit variable */
10072 if (AOP_TYPE (result) == AOP_IMMD &&
10073 DCL_TYPE (ptype) == POINTER &&
10074 !IS_BITVAR (retype) &&
10075 !IS_BITVAR (letype))
10077 genDataPointerSet (right, result, ic);
10081 /* if the value is already in a pointer register
10082 then don't need anything more */
10083 if (!AOP_INPREG (AOP (result)))
10085 /* otherwise get a free pointer register */
10088 aop = newAsmop (0);
10089 preg = getFreePtr (ic, &aop, FALSE);
10090 emitcode ("mov", "%s,%s",
10092 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10093 rname = preg->name;
10096 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10098 aopOp (right, ic, FALSE, FALSE);
10100 /* if bitfield then unpack the bits */
10101 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10102 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
10105 /* we have can just get the values */
10106 int size = AOP_SIZE (right);
10111 l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
10115 emitcode ("mov", "@%s,a", rname);
10118 emitcode ("mov", "@%s,%s", rname, l);
10120 emitcode ("inc", "%s", rname);
10125 /* now some housekeeping stuff */
10128 /* we had to allocate for this iCode */
10129 if (pi) aopPut (AOP (result),rname,0);
10130 freeAsmop (NULL, aop, ic, TRUE);
10134 /* we did not allocate which means left
10135 already in a pointer register, then
10136 if size > 0 && this could be used again
10137 we have to point it back to where it
10139 if (AOP_SIZE (right) > 1 &&
10140 !OP_SYMBOL (result)->remat &&
10141 (OP_SYMBOL (result)->liveTo > ic->seq ||
10145 int size = AOP_SIZE (right) - 1;
10147 emitcode ("dec", "%s", rname);
10152 if (pi) pi->generated = 1;
10153 freeAsmop (result, NULL, ic, TRUE);
10154 freeAsmop (right, NULL, ic, TRUE);
10159 /*-----------------------------------------------------------------*/
10160 /* genPagedPointerSet - emitcode for Paged pointer put */
10161 /*-----------------------------------------------------------------*/
10163 genPagedPointerSet (operand * right,
10170 sym_link *retype, *letype;
10172 retype = getSpec (operandType (right));
10173 letype = getSpec (operandType (result));
10175 aopOp (result, ic, FALSE, FALSE);
10177 /* if the value is already in a pointer register
10178 then don't need anything more */
10179 if (!AOP_INPREG (AOP (result)))
10181 /* otherwise get a free pointer register */
10184 aop = newAsmop (0);
10185 preg = getFreePtr (ic, &aop, FALSE);
10186 emitcode ("mov", "%s,%s",
10188 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10189 rname = preg->name;
10192 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10194 aopOp (right, ic, FALSE, FALSE);
10196 /* if bitfield then unpack the bits */
10197 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10198 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
10201 /* we have can just get the values */
10202 int size = AOP_SIZE (right);
10207 MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10209 emitcode ("movx", "@%s,a", rname);
10212 emitcode ("inc", "%s", rname);
10218 /* now some housekeeping stuff */
10221 if (pi) aopPut (AOP (result),rname,0);
10222 /* we had to allocate for this iCode */
10223 freeAsmop (NULL, aop, ic, TRUE);
10227 /* we did not allocate which means left
10228 already in a pointer register, then
10229 if size > 0 && this could be used again
10230 we have to point it back to where it
10232 if (AOP_SIZE (right) > 1 &&
10233 !OP_SYMBOL (result)->remat &&
10234 (OP_SYMBOL (result)->liveTo > ic->seq ||
10238 int size = AOP_SIZE (right) - 1;
10240 emitcode ("dec", "%s", rname);
10245 if (pi) pi->generated = 1;
10246 freeAsmop (result, NULL, ic, TRUE);
10247 freeAsmop (right, NULL, ic, TRUE);
10252 /*-----------------------------------------------------------------*/
10253 /* genFarPointerSet - set value from far space */
10254 /*-----------------------------------------------------------------*/
10256 genFarPointerSet (operand * right,
10257 operand * result, iCode * ic, iCode *pi)
10259 int size, offset, dopi=1;
10260 sym_link *retype = getSpec (operandType (right));
10261 sym_link *letype = getSpec (operandType (result));
10263 aopOp (result, ic, FALSE, FALSE);
10265 /* if the operand is already in dptr
10266 then we do nothing else we move the value to dptr */
10267 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10269 /* if this is remateriazable */
10270 if (AOP_TYPE (result) == AOP_IMMD)
10271 emitcode ("mov", "dptr,%s",
10272 aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10275 /* we need to get it byte by byte */
10276 _startLazyDPSEvaluation ();
10277 if (AOP_TYPE (result) != AOP_DPTR)
10279 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10280 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10281 if (options.model == MODEL_FLAT24)
10282 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10286 /* We need to generate a load to DPTR indirect through DPTR. */
10287 D (emitcode (";", "genFarPointerSet -- indirection special case."););
10289 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10290 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10291 if (options.model == MODEL_FLAT24)
10292 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10293 emitcode ("pop", "dph");
10294 emitcode ("pop", "dpl");
10297 _endLazyDPSEvaluation ();
10300 /* so dptr know contains the address */
10301 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10303 /* if bit then unpack */
10304 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
10305 if (AOP_INDPTRn(result)) {
10306 genSetDPTR(AOP(result)->aopu.dptr);
10308 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
10309 if (AOP_INDPTRn(result)) {
10313 size = AOP_SIZE (right);
10315 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10317 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10319 genSetDPTR(AOP(result)->aopu.dptr);
10320 emitcode ("movx", "@dptr,a");
10321 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10322 emitcode ("inc", "dptr");
10326 _startLazyDPSEvaluation ();
10328 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10330 if (AOP_INDPTRn(result)) {
10331 genSetDPTR(AOP(result)->aopu.dptr);
10337 emitcode ("movx", "@dptr,a");
10338 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10339 emitcode ("inc", "dptr");
10341 _endLazyDPSEvaluation ();
10345 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10346 if (!AOP_INDPTRn(result)) {
10347 _startLazyDPSEvaluation ();
10349 aopPut (AOP(result),"dpl",0);
10350 aopPut (AOP(result),"dph",1);
10351 if (options.model == MODEL_FLAT24)
10352 aopPut (AOP(result),"dpx",2);
10354 _endLazyDPSEvaluation ();
10357 } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
10358 AOP_SIZE(right) > 1 &&
10359 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10361 size = AOP_SIZE (right) - 1;
10362 if (AOP_INDPTRn(result)) {
10363 genSetDPTR(AOP(result)->aopu.dptr);
10365 while (size--) emitcode ("lcall","__decdptr");
10366 if (AOP_INDPTRn(result)) {
10370 freeAsmop (result, NULL, ic, TRUE);
10371 freeAsmop (right, NULL, ic, TRUE);
10374 /*-----------------------------------------------------------------*/
10375 /* genGenPointerSet - set value from generic pointer space */
10376 /*-----------------------------------------------------------------*/
10378 genGenPointerSet (operand * right,
10379 operand * result, iCode * ic, iCode *pi)
10382 sym_link *retype = getSpec (operandType (right));
10383 sym_link *letype = getSpec (operandType (result));
10385 aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10387 /* if the operand is already in dptr
10388 then we do nothing else we move the value to dptr */
10389 if (AOP_TYPE (result) != AOP_STR)
10391 _startLazyDPSEvaluation ();
10392 /* if this is remateriazable */
10393 if (AOP_TYPE (result) == AOP_IMMD)
10395 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10396 if (AOP(result)->aopu.aop_immd.from_cast_remat)
10398 MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10403 "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10407 { /* we need to get it byte by byte */
10408 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10409 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10410 if (options.model == MODEL_FLAT24) {
10411 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10412 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10414 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10417 _endLazyDPSEvaluation ();
10419 /* so dptr + b now contains the address */
10421 aopOp (right, ic, FALSE, TRUE);
10425 /* if bit then unpack */
10426 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10428 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
10432 size = AOP_SIZE (right);
10435 _startLazyDPSEvaluation ();
10440 // Set two bytes at a time, passed in _AP & A.
10441 // dptr will be incremented ONCE by __gptrputWord.
10443 // Note: any change here must be coordinated
10444 // with the implementation of __gptrputWord
10445 // in device/lib/_gptrput.c
10446 emitcode("mov", "_ap, %s",
10447 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10448 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10452 emitcode ("lcall", "__gptrputWord");
10457 // Only one byte to put.
10458 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10462 emitcode ("lcall", "__gptrput");
10465 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10467 emitcode ("inc", "dptr");
10470 _endLazyDPSEvaluation ();
10473 if (pi && AOP_TYPE (result) != AOP_IMMD) {
10474 _startLazyDPSEvaluation ();
10476 aopPut (AOP(result),"dpl",0);
10477 aopPut (AOP(result),"dph",1);
10478 if (options.model == MODEL_FLAT24) {
10479 aopPut (AOP(result),"dpx",2);
10480 aopPut (AOP(result),"b",3);
10482 aopPut (AOP(result),"b",2);
10484 _endLazyDPSEvaluation ();
10487 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10488 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10490 size = AOP_SIZE (right) - 1;
10491 while (size--) emitcode ("lcall","__decdptr");
10493 freeAsmop (result, NULL, ic, TRUE);
10494 freeAsmop (right, NULL, ic, TRUE);
10497 /*-----------------------------------------------------------------*/
10498 /* genPointerSet - stores the value into a pointer location */
10499 /*-----------------------------------------------------------------*/
10501 genPointerSet (iCode * ic, iCode *pi)
10503 operand *right, *result;
10504 sym_link *type, *etype;
10507 D (emitcode (";", "genPointerSet "););
10509 right = IC_RIGHT (ic);
10510 result = IC_RESULT (ic);
10512 /* depending on the type of pointer we need to
10513 move it to the correct pointer register */
10514 type = operandType (result);
10515 etype = getSpec (type);
10516 /* if left is of type of pointer then it is simple */
10517 if (IS_PTR (type) && !IS_FUNC (type->next))
10519 p_type = DCL_TYPE (type);
10523 /* we have to go by the storage class */
10524 p_type = PTR_TYPE (SPEC_OCLS (etype));
10526 /* special case when cast remat */
10527 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10528 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10529 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10530 type = operandType (result);
10531 p_type = DCL_TYPE (type);
10534 /* now that we have the pointer type we assign
10535 the pointer values */
10541 genNearPointerSet (right, result, ic, pi);
10545 genPagedPointerSet (right, result, ic, pi);
10549 genFarPointerSet (right, result, ic, pi);
10553 genGenPointerSet (right, result, ic, pi);
10557 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10558 "genPointerSet: illegal pointer type");
10563 /*-----------------------------------------------------------------*/
10564 /* genIfx - generate code for Ifx statement */
10565 /*-----------------------------------------------------------------*/
10567 genIfx (iCode * ic, iCode * popIc)
10569 operand *cond = IC_COND (ic);
10572 D (emitcode (";", "genIfx "););
10574 aopOp (cond, ic, FALSE, FALSE);
10576 /* get the value into acc */
10577 if (AOP_TYPE (cond) != AOP_CRY)
10586 /* the result is now in the accumulator */
10587 freeAsmop (cond, NULL, ic, TRUE);
10589 /* if there was something to be popped then do it */
10593 /* if the condition is a bit variable */
10594 if (isbit && IS_ITEMP (cond) &&
10597 genIfxJump (ic, SPIL_LOC (cond)->rname);
10599 else if (isbit && !IS_ITEMP (cond))
10601 genIfxJump (ic, OP_SYMBOL (cond)->rname);
10605 genIfxJump (ic, "a");
10611 /*-----------------------------------------------------------------*/
10612 /* genAddrOf - generates code for address of */
10613 /*-----------------------------------------------------------------*/
10615 genAddrOf (iCode * ic)
10617 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10620 D (emitcode (";", "genAddrOf ");
10623 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10625 /* if the operand is on the stack then we
10626 need to get the stack offset of this
10628 if (sym->onStack) {
10630 /* if 10 bit stack */
10631 if (options.stack10bit) {
10635 tsprintf(buff, sizeof(buff),
10636 "#!constbyte",(options.stack_loc >> 16) & 0xff);
10637 /* if it has an offset then we need to compute it */
10638 /* emitcode ("subb", "a,#!constbyte", */
10639 /* -((sym->stack < 0) ? */
10640 /* ((short) (sym->stack - _G.nRegsSaved)) : */
10641 /* ((short) sym->stack)) & 0xff); */
10642 /* emitcode ("mov","b,a"); */
10643 /* emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
10644 /* ((short) (sym->stack - _G.nRegsSaved)) : */
10645 /* ((short) sym->stack)) >> 8) & 0xff); */
10647 emitcode ("mov", "a,_bpx");
10648 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
10649 ((char) (sym->stack - _G.nRegsSaved)) :
10650 ((char) sym->stack )) & 0xff);
10651 emitcode ("mov", "b,a");
10652 emitcode ("mov", "a,_bpx+1");
10654 offset = (((sym->stack < 0) ?
10655 ((short) (sym->stack - _G.nRegsSaved)) :
10656 ((short) sym->stack )) >> 8) & 0xff;
10658 emitcode ("addc","a,#!constbyte", offset);
10660 aopPut (AOP (IC_RESULT (ic)), "b", 0);
10661 aopPut (AOP (IC_RESULT (ic)), "a", 1);
10662 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10664 /* we can just move _bp */
10665 aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10666 aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10667 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10670 /* if it has an offset then we need to compute it */
10672 emitcode ("mov", "a,_bp");
10673 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10674 aopPut (AOP (IC_RESULT (ic)), "a", 0);
10676 /* we can just move _bp */
10677 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10679 /* fill the result with zero */
10680 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10683 if (options.stack10bit && size < (FPTRSIZE - 1)) {
10685 "*** warning: pointer to stack var truncated.\n");
10690 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10696 /* object not on stack then we need the name */
10697 size = AOP_SIZE (IC_RESULT (ic));
10702 char s[SDCC_NAME_MAX];
10706 tsprintf(s, sizeof(s), "#!his",sym->rname);
10709 tsprintf(s, sizeof(s), "#!hihis",sym->rname);
10712 tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
10714 default: /* should not need this (just in case) */
10715 SNPRINTF (s, sizeof(s), "#(%s >> %d)",
10722 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10725 aopPut (AOP (IC_RESULT (ic)), s, offset++);
10729 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10733 #if 0 // obsolete, and buggy for != xdata
10734 /*-----------------------------------------------------------------*/
10735 /* genArrayInit - generates code for address of */
10736 /*-----------------------------------------------------------------*/
10738 genArrayInit (iCode * ic)
10740 literalList *iLoop;
10742 int elementSize = 0, eIndex;
10743 unsigned val, lastVal;
10745 operand *left=IC_LEFT(ic);
10747 D (emitcode (";", "genArrayInit "););
10749 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10751 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10753 // Load immediate value into DPTR.
10754 emitcode("mov", "dptr, %s",
10755 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
10757 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10760 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10761 "Unexpected operand to genArrayInit.\n");
10764 // a regression because of SDCCcse.c:1.52
10765 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10766 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10767 if (options.model == MODEL_FLAT24)
10768 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10772 type = operandType(IC_LEFT(ic));
10774 if (type && type->next)
10776 elementSize = getSize(type->next);
10780 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10781 "can't determine element size in genArrayInit.\n");
10785 iLoop = IC_ARRAYILIST(ic);
10790 bool firstpass = TRUE;
10792 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
10793 iLoop->count, (int)iLoop->literalValue, elementSize);
10799 symbol *tlbl = NULL;
10801 count = ix > 256 ? 256 : ix;
10805 tlbl = newiTempLabel (NULL);
10806 if (firstpass || (count & 0xff))
10808 emitcode("mov", "b, #!constbyte", count & 0xff);
10811 emitcode ("", "!tlabeldef", tlbl->key + 100);
10816 for (eIndex = 0; eIndex < elementSize; eIndex++)
10818 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10819 if (val != lastVal)
10821 emitcode("mov", "a, #!constbyte", val);
10825 emitcode("movx", "@dptr, a");
10826 emitcode("inc", "dptr");
10831 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10837 iLoop = iLoop->next;
10840 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10844 /*-----------------------------------------------------------------*/
10845 /* genFarFarAssign - assignment when both are in far space */
10846 /*-----------------------------------------------------------------*/
10848 genFarFarAssign (operand * result, operand * right, iCode * ic)
10850 int size = AOP_SIZE (right);
10852 symbol *rSym = NULL;
10856 /* quick & easy case. */
10857 D(emitcode(";","genFarFarAssign (1 byte case)"););
10858 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
10859 freeAsmop (right, NULL, ic, FALSE);
10860 /* now assign DPTR to result */
10862 aopOp(result, ic, FALSE, FALSE);
10864 aopPut(AOP(result), "a", 0);
10865 freeAsmop(result, NULL, ic, FALSE);
10869 /* See if we've got an underlying symbol to abuse. */
10870 if (IS_SYMOP(result) && OP_SYMBOL(result))
10872 if (IS_TRUE_SYMOP(result))
10874 rSym = OP_SYMBOL(result);
10876 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10878 rSym = OP_SYMBOL(result)->usl.spillLoc;
10882 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10884 /* We can use the '390 auto-toggle feature to good effect here. */
10886 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10887 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
10888 emitcode ("mov", "dptr,#%s", rSym->rname);
10889 /* DP2 = result, DP1 = right, DP1 is current. */
10892 emitcode("movx", "a,@dptr");
10893 emitcode("movx", "@dptr,a");
10896 emitcode("inc", "dptr");
10897 emitcode("inc", "dptr");
10900 emitcode("mov", "dps,#0");
10901 freeAsmop (right, NULL, ic, FALSE);
10903 some alternative code for processors without auto-toggle
10904 no time to test now, so later well put in...kpb
10905 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10906 emitcode("mov", "dps,#1"); /* Select DPTR2. */
10907 emitcode ("mov", "dptr,#%s", rSym->rname);
10908 /* DP2 = result, DP1 = right, DP1 is current. */
10912 emitcode("movx", "a,@dptr");
10914 emitcode("inc", "dptr");
10915 emitcode("inc", "dps");
10916 emitcode("movx", "@dptr,a");
10918 emitcode("inc", "dptr");
10919 emitcode("inc", "dps");
10921 emitcode("mov", "dps,#0");
10922 freeAsmop (right, NULL, ic, FALSE);
10927 D (emitcode (";", "genFarFarAssign"););
10928 aopOp (result, ic, TRUE, TRUE);
10930 _startLazyDPSEvaluation ();
10934 aopPut (AOP (result),
10935 aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
10938 _endLazyDPSEvaluation ();
10939 freeAsmop (result, NULL, ic, FALSE);
10940 freeAsmop (right, NULL, ic, FALSE);
10944 /*-----------------------------------------------------------------*/
10945 /* genAssign - generate code for assignment */
10946 /*-----------------------------------------------------------------*/
10948 genAssign (iCode * ic)
10950 operand *result, *right;
10952 unsigned long lit = 0L;
10954 D (emitcode (";", "genAssign ");
10957 result = IC_RESULT (ic);
10958 right = IC_RIGHT (ic);
10960 /* if they are the same */
10961 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10964 aopOp (right, ic, FALSE, FALSE);
10966 emitcode (";", "genAssign: resultIsFar = %s",
10967 isOperandInFarSpace (result) ?
10970 /* special case both in far space */
10971 if ((AOP_TYPE (right) == AOP_DPTR ||
10972 AOP_TYPE (right) == AOP_DPTR2) &&
10973 /* IS_TRUE_SYMOP(result) && */
10974 isOperandInFarSpace (result))
10976 genFarFarAssign (result, right, ic);
10980 aopOp (result, ic, TRUE, FALSE);
10982 /* if they are the same registers */
10983 if (sameRegs (AOP (right), AOP (result)))
10986 /* if the result is a bit */
10987 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10989 /* if the right size is a literal then
10990 we know what the value is */
10991 if (AOP_TYPE (right) == AOP_LIT)
10993 if (((int) operandLitValue (right)))
10994 aopPut (AOP (result), one, 0);
10996 aopPut (AOP (result), zero, 0);
11000 /* the right is also a bit variable */
11001 if (AOP_TYPE (right) == AOP_CRY)
11003 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11004 aopPut (AOP (result), "c", 0);
11008 /* we need to or */
11010 aopPut (AOP (result), "a", 0);
11014 /* bit variables done */
11016 size = AOP_SIZE (result);
11018 if (AOP_TYPE (right) == AOP_LIT)
11019 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11022 (AOP_TYPE (result) != AOP_REG) &&
11023 (AOP_TYPE (right) == AOP_LIT) &&
11024 !IS_FLOAT (operandType (right)))
11026 _startLazyDPSEvaluation ();
11027 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
11029 aopPut (AOP (result),
11030 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11035 /* And now fill the rest with zeros. */
11038 emitcode ("clr", "a");
11042 aopPut (AOP (result), "a", offset++);
11044 _endLazyDPSEvaluation ();
11048 _startLazyDPSEvaluation ();
11051 aopPut (AOP (result),
11052 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11056 _endLazyDPSEvaluation ();
11060 freeAsmop (right, NULL, ic, FALSE);
11061 freeAsmop (result, NULL, ic, TRUE);
11064 /*-----------------------------------------------------------------*/
11065 /* genJumpTab - generates code for jump table */
11066 /*-----------------------------------------------------------------*/
11068 genJumpTab (iCode * ic)
11073 D (emitcode (";", "genJumpTab ");
11076 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
11077 /* get the condition into accumulator */
11078 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
11080 /* multiply by four! */
11081 emitcode ("add", "a,acc");
11082 emitcode ("add", "a,acc");
11083 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11085 jtab = newiTempLabel (NULL);
11086 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
11087 emitcode ("jmp", "@a+dptr");
11088 emitcode ("", "!tlabeldef", jtab->key + 100);
11089 /* now generate the jump labels */
11090 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11091 jtab = setNextItem (IC_JTLABELS (ic)))
11092 emitcode ("ljmp", "!tlabel", jtab->key + 100);
11096 /*-----------------------------------------------------------------*/
11097 /* genCast - gen code for casting */
11098 /*-----------------------------------------------------------------*/
11100 genCast (iCode * ic)
11102 operand *result = IC_RESULT (ic);
11103 sym_link *ctype = operandType (IC_LEFT (ic));
11104 sym_link *rtype = operandType (IC_RIGHT (ic));
11105 operand *right = IC_RIGHT (ic);
11108 D (emitcode (";", "genCast "););
11110 /* if they are equivalent then do nothing */
11111 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11114 aopOp (right, ic, FALSE, FALSE);
11115 aopOp (result, ic, FALSE, (AOP_TYPE(right) == AOP_DPTR));
11117 /* if the result is a bit */
11118 if (IS_BITVAR (OP_SYMBOL (result)->type)
11119 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
11121 /* if the right size is a literal then
11122 we know what the value is */
11123 if (AOP_TYPE (right) == AOP_LIT)
11125 if (((int) operandLitValue (right)))
11126 aopPut (AOP (result), one, 0);
11128 aopPut (AOP (result), zero, 0);
11133 /* the right is also a bit variable */
11134 if (AOP_TYPE (right) == AOP_CRY)
11136 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11137 aopPut (AOP (result), "c", 0);
11141 /* we need to or */
11143 aopPut (AOP (result), "a", 0);
11147 /* if they are the same size : or less */
11148 if (AOP_SIZE (result) <= AOP_SIZE (right))
11151 /* if they are in the same place */
11152 if (sameRegs (AOP (right), AOP (result)))
11155 /* if they in different places then copy */
11156 size = AOP_SIZE (result);
11158 _startLazyDPSEvaluation ();
11161 aopPut (AOP (result),
11162 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11166 _endLazyDPSEvaluation ();
11171 /* if the result is of type pointer */
11172 if (IS_PTR (ctype))
11176 sym_link *type = operandType (right);
11178 /* pointer to generic pointer */
11179 if (IS_GENPTR (ctype))
11183 p_type = DCL_TYPE (type);
11187 #if OLD_CAST_BEHAVIOR
11188 /* KV: we are converting a non-pointer type to
11189 * a generic pointer. This (ifdef'd out) code
11190 * says that the resulting generic pointer
11191 * should have the same class as the storage
11192 * location of the non-pointer variable.
11194 * For example, converting an int (which happens
11195 * to be stored in DATA space) to a pointer results
11196 * in a DATA generic pointer; if the original int
11197 * in XDATA space, so will be the resulting pointer.
11199 * I don't like that behavior, and thus this change:
11200 * all such conversions will be forced to XDATA and
11201 * throw a warning. If you want some non-XDATA
11202 * type, or you want to suppress the warning, you
11203 * must go through an intermediate cast, like so:
11205 * char _generic *gp = (char _xdata *)(intVar);
11207 sym_link *etype = getSpec (type);
11209 /* we have to go by the storage class */
11210 if (SPEC_OCLS (etype) != generic)
11212 p_type = PTR_TYPE (SPEC_OCLS (etype));
11217 /* Converting unknown class (i.e. register variable)
11218 * to generic pointer. This is not good, but
11219 * we'll make a guess (and throw a warning).
11222 werror (W_INT_TO_GEN_PTR_CAST);
11226 /* the first two bytes are known */
11227 size = GPTRSIZE - 1;
11229 _startLazyDPSEvaluation ();
11232 aopPut (AOP (result),
11233 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11237 _endLazyDPSEvaluation ();
11239 /* the last byte depending on type */
11241 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11246 // pointerTypeToGPByte will have bitched.
11250 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11251 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11256 /* just copy the pointers */
11257 size = AOP_SIZE (result);
11259 _startLazyDPSEvaluation ();
11262 aopPut (AOP (result),
11263 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11267 _endLazyDPSEvaluation ();
11271 /* so we now know that the size of destination is greater
11272 than the size of the source */
11273 /* we move to result for the size of source */
11274 size = AOP_SIZE (right);
11276 _startLazyDPSEvaluation ();
11279 aopPut (AOP (result),
11280 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11284 _endLazyDPSEvaluation ();
11286 /* now depending on the sign of the source && destination */
11287 size = AOP_SIZE (result) - AOP_SIZE (right);
11288 /* if unsigned or not an integral type */
11289 /* also, if the source is a bit, we don't need to sign extend, because
11290 * it can't possibly have set the sign bit.
11292 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
11296 aopPut (AOP (result), zero, offset++);
11301 /* we need to extend the sign :{ */
11302 MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11303 FALSE, FALSE, NULL));
11304 emitcode ("rlc", "a");
11305 emitcode ("subb", "a,acc");
11307 aopPut (AOP (result), "a", offset++);
11310 /* we are done hurray !!!! */
11313 freeAsmop (right, NULL, ic, TRUE);
11314 freeAsmop (result, NULL, ic, TRUE);
11318 /*-----------------------------------------------------------------*/
11319 /* genDjnz - generate decrement & jump if not zero instrucion */
11320 /*-----------------------------------------------------------------*/
11322 genDjnz (iCode * ic, iCode * ifx)
11324 symbol *lbl, *lbl1;
11328 /* if the if condition has a false label
11329 then we cannot save */
11330 if (IC_FALSE (ifx))
11333 /* if the minus is not of the form
11335 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11336 !IS_OP_LITERAL (IC_RIGHT (ic)))
11339 if (operandLitValue (IC_RIGHT (ic)) != 1)
11342 /* if the size of this greater than one then no
11344 if (getSize (operandType (IC_RESULT (ic))) > 1)
11347 /* otherwise we can save BIG */
11348 D(emitcode(";", "genDjnz"););
11350 lbl = newiTempLabel (NULL);
11351 lbl1 = newiTempLabel (NULL);
11353 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11355 if (AOP_NEEDSACC(IC_RESULT(ic)))
11357 /* If the result is accessed indirectly via
11358 * the accumulator, we must explicitly write
11359 * it back after the decrement.
11361 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11363 if (strcmp(rByte, "a"))
11365 /* Something is hopelessly wrong */
11366 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11367 __FILE__, __LINE__);
11368 /* We can just give up; the generated code will be inefficient,
11369 * but what the hey.
11371 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11374 emitcode ("dec", "%s", rByte);
11375 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11376 emitcode ("jnz", "!tlabel", lbl->key + 100);
11378 else if (IS_AOP_PREG (IC_RESULT (ic)))
11380 emitcode ("dec", "%s",
11381 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11382 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11383 emitcode ("jnz", "!tlabel", lbl->key + 100);
11387 emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11390 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11391 emitcode ("", "!tlabeldef", lbl->key + 100);
11392 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11393 emitcode ("", "!tlabeldef", lbl1->key + 100);
11395 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11396 ifx->generated = 1;
11400 /*-----------------------------------------------------------------*/
11401 /* genReceive - generate code for a receive iCode */
11402 /*-----------------------------------------------------------------*/
11404 genReceive (iCode * ic)
11406 int size = getSize (operandType (IC_RESULT (ic)));
11410 D (emitcode (";", "genReceive "););
11412 if (ic->argreg == 1)
11414 /* first parameter */
11415 if (AOP_IS_STR(IC_RESULT(ic)))
11417 /* Nothing to do: it's already in the proper place. */
11424 useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11425 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11426 IS_TRUE_SYMOP (IC_RESULT (ic)));
11429 aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11432 /* Sanity checking... */
11433 if (AOP_USESDPTR(IC_RESULT(ic)))
11435 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11436 "genReceive got unexpected DPTR.");
11438 assignResultValue (IC_RESULT (ic));
11443 /* second receive onwards */
11444 /* this gets a little tricky since unused recevies will be
11445 eliminated, we have saved the reg in the type field . and
11446 we use that to figure out which register to use */
11447 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11448 rb1off = ic->argreg;
11451 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11454 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11457 /*-----------------------------------------------------------------*/
11458 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
11459 /*-----------------------------------------------------------------*/
11460 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11462 operand *from , *to , *count;
11467 /* we know it has to be 3 parameters */
11468 assert (nparms == 3);
11470 rsave = newBitVect(16);
11471 /* save DPTR if it needs to be saved */
11472 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11473 if (bitVectBitValue(ic->rMask,i))
11474 rsave = bitVectSetBit(rsave,i);
11476 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11477 ds390_rUmaskForOp (IC_RESULT(ic))));
11484 aopOp (from, ic->next, FALSE, FALSE);
11486 /* get from into DPTR1 */
11487 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11488 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11489 if (options.model == MODEL_FLAT24) {
11490 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11493 freeAsmop (from, NULL, ic, FALSE);
11494 aopOp (to, ic, FALSE, FALSE);
11495 /* get "to" into DPTR */
11496 /* if the operand is already in dptr
11497 then we do nothing else we move the value to dptr */
11498 if (AOP_TYPE (to) != AOP_STR) {
11499 /* if already in DPTR then we need to push */
11500 if (AOP_TYPE(to) == AOP_DPTR) {
11501 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11502 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11503 if (options.model == MODEL_FLAT24)
11504 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11505 emitcode ("pop", "dph");
11506 emitcode ("pop", "dpl");
11508 _startLazyDPSEvaluation ();
11509 /* if this is remateriazable */
11510 if (AOP_TYPE (to) == AOP_IMMD) {
11511 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11512 } else { /* we need to get it byte by byte */
11513 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11514 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11515 if (options.model == MODEL_FLAT24) {
11516 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11519 _endLazyDPSEvaluation ();
11522 freeAsmop (to, NULL, ic, FALSE);
11523 _G.dptrInUse = _G.dptr1InUse = 1;
11524 aopOp (count, ic->next->next, FALSE,FALSE);
11525 lbl =newiTempLabel(NULL);
11527 /* now for the actual copy */
11528 if (AOP_TYPE(count) == AOP_LIT &&
11529 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11530 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11532 emitcode ("lcall","__bi_memcpyc2x_s");
11534 emitcode ("lcall","__bi_memcpyx2x_s");
11536 freeAsmop (count, NULL, ic, FALSE);
11538 symbol *lbl1 = newiTempLabel(NULL);
11540 emitcode (";"," Auto increment but no djnz");
11541 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11542 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11543 freeAsmop (count, NULL, ic, FALSE);
11544 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11545 emitcode ("","!tlabeldef",lbl->key+100);
11547 emitcode ("clr","a");
11548 emitcode ("movc", "a,@a+dptr");
11550 emitcode ("movx", "a,@dptr");
11551 emitcode ("movx", "@dptr,a");
11552 emitcode ("inc", "dptr");
11553 emitcode ("inc", "dptr");
11554 emitcode ("mov","a,b");
11555 emitcode ("orl","a,_ap");
11556 emitcode ("jz","!tlabel",lbl1->key+100);
11557 emitcode ("mov","a,_ap");
11558 emitcode ("add","a,#!constbyte",0xFF);
11559 emitcode ("mov","_ap,a");
11560 emitcode ("mov","a,b");
11561 emitcode ("addc","a,#!constbyte",0xFF);
11562 emitcode ("mov","b,a");
11563 emitcode ("sjmp","!tlabel",lbl->key+100);
11564 emitcode ("","!tlabeldef",lbl1->key+100);
11566 emitcode ("mov", "dps,#0");
11567 _G.dptrInUse = _G.dptr1InUse = 0;
11568 unsavermask(rsave);
11572 /*-----------------------------------------------------------------*/
11573 /* genMemcmpX2X - gen code for memcmp xdata to xdata */
11574 /*-----------------------------------------------------------------*/
11575 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11577 operand *from , *to , *count;
11582 /* we know it has to be 3 parameters */
11583 assert (nparms == 3);
11585 rsave = newBitVect(16);
11586 /* save DPTR if it needs to be saved */
11587 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11588 if (bitVectBitValue(ic->rMask,i))
11589 rsave = bitVectSetBit(rsave,i);
11591 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11592 ds390_rUmaskForOp (IC_RESULT(ic))));
11599 aopOp (from, ic->next, FALSE, FALSE);
11601 /* get from into DPTR1 */
11602 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11603 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11604 if (options.model == MODEL_FLAT24) {
11605 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11608 freeAsmop (from, NULL, ic, FALSE);
11609 aopOp (to, ic, FALSE, FALSE);
11610 /* get "to" into DPTR */
11611 /* if the operand is already in dptr
11612 then we do nothing else we move the value to dptr */
11613 if (AOP_TYPE (to) != AOP_STR) {
11614 /* if already in DPTR then we need to push */
11615 if (AOP_TYPE(to) == AOP_DPTR) {
11616 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11617 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11618 if (options.model == MODEL_FLAT24)
11619 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11620 emitcode ("pop", "dph");
11621 emitcode ("pop", "dpl");
11623 _startLazyDPSEvaluation ();
11624 /* if this is remateriazable */
11625 if (AOP_TYPE (to) == AOP_IMMD) {
11626 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11627 } else { /* we need to get it byte by byte */
11628 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11629 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11630 if (options.model == MODEL_FLAT24) {
11631 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11634 _endLazyDPSEvaluation ();
11637 freeAsmop (to, NULL, ic, FALSE);
11638 _G.dptrInUse = _G.dptr1InUse = 1;
11639 aopOp (count, ic->next->next, FALSE,FALSE);
11640 lbl =newiTempLabel(NULL);
11641 lbl2 =newiTempLabel(NULL);
11643 /* now for the actual compare */
11644 if (AOP_TYPE(count) == AOP_LIT &&
11645 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11646 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11648 emitcode("lcall","__bi_memcmpc2x_s");
11650 emitcode("lcall","__bi_memcmpx2x_s");
11651 freeAsmop (count, NULL, ic, FALSE);
11652 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11653 aopPut(AOP(IC_RESULT(ic)),"a",0);
11654 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11656 symbol *lbl1 = newiTempLabel(NULL);
11658 emitcode("push","ar0");
11659 emitcode (";"," Auto increment but no djnz");
11660 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11661 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11662 freeAsmop (count, NULL, ic, FALSE);
11663 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11664 emitcode ("","!tlabeldef",lbl->key+100);
11666 emitcode ("clr","a");
11667 emitcode ("movc", "a,@a+dptr");
11669 emitcode ("movx", "a,@dptr");
11670 emitcode ("mov","r0,a");
11671 emitcode ("movx", "a,@dptr");
11672 emitcode ("clr","c");
11673 emitcode ("subb","a,r0");
11674 emitcode ("jnz","!tlabel",lbl2->key+100);
11675 emitcode ("inc", "dptr");
11676 emitcode ("inc", "dptr");
11677 emitcode ("mov","a,b");
11678 emitcode ("orl","a,_ap");
11679 emitcode ("jz","!tlabel",lbl1->key+100);
11680 emitcode ("mov","a,_ap");
11681 emitcode ("add","a,#!constbyte",0xFF);
11682 emitcode ("mov","_ap,a");
11683 emitcode ("mov","a,b");
11684 emitcode ("addc","a,#!constbyte",0xFF);
11685 emitcode ("mov","b,a");
11686 emitcode ("sjmp","!tlabel",lbl->key+100);
11687 emitcode ("","!tlabeldef",lbl1->key+100);
11688 emitcode ("clr","a");
11689 emitcode ("","!tlabeldef",lbl2->key+100);
11690 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11691 aopPut(AOP(IC_RESULT(ic)),"a",0);
11692 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11693 emitcode("pop","ar0");
11694 emitcode ("mov", "dps,#0");
11696 _G.dptrInUse = _G.dptr1InUse = 0;
11697 unsavermask(rsave);
11701 /*-----------------------------------------------------------------*/
11702 /* genInp - gen code for __builtin_inp read data from a mem mapped */
11703 /* port, first parameter output area second parameter pointer to */
11704 /* port third parameter count */
11705 /*-----------------------------------------------------------------*/
11706 static void genInp( iCode *ic, int nparms, operand **parms)
11708 operand *from , *to , *count;
11713 /* we know it has to be 3 parameters */
11714 assert (nparms == 3);
11716 rsave = newBitVect(16);
11717 /* save DPTR if it needs to be saved */
11718 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11719 if (bitVectBitValue(ic->rMask,i))
11720 rsave = bitVectSetBit(rsave,i);
11722 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11723 ds390_rUmaskForOp (IC_RESULT(ic))));
11730 aopOp (from, ic->next, FALSE, FALSE);
11732 /* get from into DPTR1 */
11733 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11734 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11735 if (options.model == MODEL_FLAT24) {
11736 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11739 freeAsmop (from, NULL, ic, FALSE);
11740 aopOp (to, ic, FALSE, FALSE);
11741 /* get "to" into DPTR */
11742 /* if the operand is already in dptr
11743 then we do nothing else we move the value to dptr */
11744 if (AOP_TYPE (to) != AOP_STR) {
11745 /* if already in DPTR then we need to push */
11746 if (AOP_TYPE(to) == AOP_DPTR) {
11747 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11748 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11749 if (options.model == MODEL_FLAT24)
11750 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11751 emitcode ("pop", "dph");
11752 emitcode ("pop", "dpl");
11754 _startLazyDPSEvaluation ();
11755 /* if this is remateriazable */
11756 if (AOP_TYPE (to) == AOP_IMMD) {
11757 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11758 } else { /* we need to get it byte by byte */
11759 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11760 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11761 if (options.model == MODEL_FLAT24) {
11762 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11765 _endLazyDPSEvaluation ();
11768 freeAsmop (to, NULL, ic, FALSE);
11770 _G.dptrInUse = _G.dptr1InUse = 1;
11771 aopOp (count, ic->next->next, FALSE,FALSE);
11772 lbl =newiTempLabel(NULL);
11774 /* now for the actual copy */
11775 if (AOP_TYPE(count) == AOP_LIT &&
11776 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11777 emitcode (";","OH JOY auto increment with djnz (very fast)");
11778 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11779 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11780 freeAsmop (count, NULL, ic, FALSE);
11781 emitcode ("","!tlabeldef",lbl->key+100);
11782 emitcode ("movx", "a,@dptr"); /* read data from port */
11783 emitcode ("dec","dps"); /* switch to DPTR */
11784 emitcode ("movx", "@dptr,a"); /* save into location */
11785 emitcode ("inc", "dptr"); /* point to next area */
11786 emitcode ("inc","dps"); /* switch to DPTR2 */
11787 emitcode ("djnz","b,!tlabel",lbl->key+100);
11789 symbol *lbl1 = newiTempLabel(NULL);
11791 emitcode (";"," Auto increment but no djnz");
11792 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11793 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11794 freeAsmop (count, NULL, ic, FALSE);
11795 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11796 emitcode ("","!tlabeldef",lbl->key+100);
11797 emitcode ("movx", "a,@dptr");
11798 emitcode ("dec","dps"); /* switch to DPTR */
11799 emitcode ("movx", "@dptr,a");
11800 emitcode ("inc", "dptr");
11801 emitcode ("inc","dps"); /* switch to DPTR2 */
11802 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
11803 /* emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
11804 emitcode ("mov","a,b");
11805 emitcode ("orl","a,_ap");
11806 emitcode ("jz","!tlabel",lbl1->key+100);
11807 emitcode ("mov","a,_ap");
11808 emitcode ("add","a,#!constbyte",0xFF);
11809 emitcode ("mov","_ap,a");
11810 emitcode ("mov","a,b");
11811 emitcode ("addc","a,#!constbyte",0xFF);
11812 emitcode ("mov","b,a");
11813 emitcode ("sjmp","!tlabel",lbl->key+100);
11814 emitcode ("","!tlabeldef",lbl1->key+100);
11816 emitcode ("mov", "dps,#0");
11817 _G.dptrInUse = _G.dptr1InUse = 0;
11818 unsavermask(rsave);
11822 /*-----------------------------------------------------------------*/
11823 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
11824 /* port, first parameter output area second parameter pointer to */
11825 /* port third parameter count */
11826 /*-----------------------------------------------------------------*/
11827 static void genOutp( iCode *ic, int nparms, operand **parms)
11829 operand *from , *to , *count;
11834 /* we know it has to be 3 parameters */
11835 assert (nparms == 3);
11837 rsave = newBitVect(16);
11838 /* save DPTR if it needs to be saved */
11839 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11840 if (bitVectBitValue(ic->rMask,i))
11841 rsave = bitVectSetBit(rsave,i);
11843 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11844 ds390_rUmaskForOp (IC_RESULT(ic))));
11851 aopOp (from, ic->next, FALSE, FALSE);
11853 /* get from into DPTR1 */
11854 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11855 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11856 if (options.model == MODEL_FLAT24) {
11857 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11860 freeAsmop (from, NULL, ic, FALSE);
11861 aopOp (to, ic, FALSE, FALSE);
11862 /* get "to" into DPTR */
11863 /* if the operand is already in dptr
11864 then we do nothing else we move the value to dptr */
11865 if (AOP_TYPE (to) != AOP_STR) {
11866 /* if already in DPTR then we need to push */
11867 if (AOP_TYPE(to) == AOP_DPTR) {
11868 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11869 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11870 if (options.model == MODEL_FLAT24)
11871 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11872 emitcode ("pop", "dph");
11873 emitcode ("pop", "dpl");
11875 _startLazyDPSEvaluation ();
11876 /* if this is remateriazable */
11877 if (AOP_TYPE (to) == AOP_IMMD) {
11878 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11879 } else { /* we need to get it byte by byte */
11880 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11881 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11882 if (options.model == MODEL_FLAT24) {
11883 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11886 _endLazyDPSEvaluation ();
11889 freeAsmop (to, NULL, ic, FALSE);
11891 _G.dptrInUse = _G.dptr1InUse = 1;
11892 aopOp (count, ic->next->next, FALSE,FALSE);
11893 lbl =newiTempLabel(NULL);
11895 /* now for the actual copy */
11896 if (AOP_TYPE(count) == AOP_LIT &&
11897 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11898 emitcode (";","OH JOY auto increment with djnz (very fast)");
11899 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
11900 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11901 emitcode ("","!tlabeldef",lbl->key+100);
11902 emitcode ("movx", "a,@dptr"); /* read data from port */
11903 emitcode ("inc","dps"); /* switch to DPTR2 */
11904 emitcode ("movx", "@dptr,a"); /* save into location */
11905 emitcode ("inc", "dptr"); /* point to next area */
11906 emitcode ("dec","dps"); /* switch to DPTR */
11907 emitcode ("djnz","b,!tlabel",lbl->key+100);
11908 freeAsmop (count, NULL, ic, FALSE);
11910 symbol *lbl1 = newiTempLabel(NULL);
11912 emitcode (";"," Auto increment but no djnz");
11913 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11914 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11915 freeAsmop (count, NULL, ic, FALSE);
11916 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
11917 emitcode ("","!tlabeldef",lbl->key+100);
11918 emitcode ("movx", "a,@dptr");
11919 emitcode ("inc", "dptr");
11920 emitcode ("inc","dps"); /* switch to DPTR2 */
11921 emitcode ("movx", "@dptr,a");
11922 emitcode ("dec","dps"); /* switch to DPTR */
11923 emitcode ("mov","a,b");
11924 emitcode ("orl","a,_ap");
11925 emitcode ("jz","!tlabel",lbl1->key+100);
11926 emitcode ("mov","a,_ap");
11927 emitcode ("add","a,#!constbyte",0xFF);
11928 emitcode ("mov","_ap,a");
11929 emitcode ("mov","a,b");
11930 emitcode ("addc","a,#!constbyte",0xFF);
11931 emitcode ("mov","b,a");
11932 emitcode ("sjmp","!tlabel",lbl->key+100);
11933 emitcode ("","!tlabeldef",lbl1->key+100);
11935 emitcode ("mov", "dps,#0");
11936 _G.dptrInUse = _G.dptr1InUse = 0;
11937 unsavermask(rsave);
11941 /*-----------------------------------------------------------------*/
11942 /* genSwapW - swap lower & high order bytes */
11943 /*-----------------------------------------------------------------*/
11944 static void genSwapW(iCode *ic, int nparms, operand **parms)
11948 assert (nparms==1);
11951 dest=IC_RESULT(ic);
11953 assert(getSize(operandType(src))==2);
11955 aopOp (src, ic, FALSE, FALSE);
11956 emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
11958 MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
11960 freeAsmop (src, NULL, ic, FALSE);
11962 aopOp (dest,ic, FALSE, FALSE);
11963 aopPut(AOP(dest),"b",0);
11964 aopPut(AOP(dest),"a",1);
11965 freeAsmop (dest, NULL, ic, FALSE);
11968 /*-----------------------------------------------------------------*/
11969 /* genMemsetX - gencode for memSetX data */
11970 /*-----------------------------------------------------------------*/
11971 static void genMemsetX(iCode *ic, int nparms, operand **parms)
11973 operand *to , *val , *count;
11979 /* we know it has to be 3 parameters */
11980 assert (nparms == 3);
11986 /* save DPTR if it needs to be saved */
11987 rsave = newBitVect(16);
11988 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11989 if (bitVectBitValue(ic->rMask,i))
11990 rsave = bitVectSetBit(rsave,i);
11992 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11993 ds390_rUmaskForOp (IC_RESULT(ic))));
11996 aopOp (to, ic, FALSE, FALSE);
11997 /* get "to" into DPTR */
11998 /* if the operand is already in dptr
11999 then we do nothing else we move the value to dptr */
12000 if (AOP_TYPE (to) != AOP_STR) {
12001 /* if already in DPTR then we need to push */
12002 if (AOP_TYPE(to) == AOP_DPTR) {
12003 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12004 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12005 if (options.model == MODEL_FLAT24)
12006 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12007 emitcode ("pop", "dph");
12008 emitcode ("pop", "dpl");
12010 _startLazyDPSEvaluation ();
12011 /* if this is remateriazable */
12012 if (AOP_TYPE (to) == AOP_IMMD) {
12013 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12014 } else { /* we need to get it byte by byte */
12015 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12016 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12017 if (options.model == MODEL_FLAT24) {
12018 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12021 _endLazyDPSEvaluation ();
12024 freeAsmop (to, NULL, ic, FALSE);
12026 aopOp (val, ic->next->next, FALSE,FALSE);
12027 aopOp (count, ic->next->next, FALSE,FALSE);
12028 lbl =newiTempLabel(NULL);
12029 /* now for the actual copy */
12030 if (AOP_TYPE(count) == AOP_LIT &&
12031 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12032 l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
12033 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12035 emitcode ("","!tlabeldef",lbl->key+100);
12036 emitcode ("movx", "@dptr,a");
12037 emitcode ("inc", "dptr");
12038 emitcode ("djnz","b,!tlabel",lbl->key+100);
12040 symbol *lbl1 = newiTempLabel(NULL);
12042 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12043 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12044 emitcode ("","!tlabeldef",lbl->key+100);
12045 MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
12046 emitcode ("movx", "@dptr,a");
12047 emitcode ("inc", "dptr");
12048 emitcode ("mov","a,b");
12049 emitcode ("orl","a,_ap");
12050 emitcode ("jz","!tlabel",lbl1->key+100);
12051 emitcode ("mov","a,_ap");
12052 emitcode ("add","a,#!constbyte",0xFF);
12053 emitcode ("mov","_ap,a");
12054 emitcode ("mov","a,b");
12055 emitcode ("addc","a,#!constbyte",0xFF);
12056 emitcode ("mov","b,a");
12057 emitcode ("sjmp","!tlabel",lbl->key+100);
12058 emitcode ("","!tlabeldef",lbl1->key+100);
12060 freeAsmop (count, NULL, ic, FALSE);
12061 unsavermask(rsave);
12064 /*-----------------------------------------------------------------*/
12065 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
12066 /*-----------------------------------------------------------------*/
12067 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
12070 operand *pnum, *result;
12073 assert (nparms==1);
12074 /* save registers that need to be saved */
12075 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12076 ds390_rUmaskForOp (IC_RESULT(ic))));
12079 aopOp (pnum, ic, FALSE, FALSE);
12080 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12081 freeAsmop (pnum, NULL, ic, FALSE);
12082 emitcode ("lcall","NatLib_LoadPrimitive");
12083 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12084 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
12085 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
12086 for (i = (size-1) ; i >= 0 ; i-- ) {
12087 emitcode ("push","a%s",javaRet[i]);
12089 for (i=0; i < size ; i++ ) {
12090 emitcode ("pop","a%s",
12091 aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
12094 for (i = 0 ; i < size ; i++ ) {
12095 aopPut(AOP(result),javaRet[i],i);
12098 freeAsmop (result, NULL, ic, FALSE);
12099 unsavermask(rsave);
12102 /*-----------------------------------------------------------------*/
12103 /* genNatLibLoadPointer - calls TINI api function to load pointer */
12104 /*-----------------------------------------------------------------*/
12105 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
12108 operand *pnum, *result;
12112 assert (nparms==1);
12113 /* save registers that need to be saved */
12114 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12115 ds390_rUmaskForOp (IC_RESULT(ic))));
12118 aopOp (pnum, ic, FALSE, FALSE);
12119 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12120 freeAsmop (pnum, NULL, ic, FALSE);
12121 emitcode ("lcall","NatLib_LoadPointer");
12122 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12123 if (AOP_TYPE(result)!=AOP_STR) {
12124 for (i = 0 ; i < size ; i++ ) {
12125 aopPut(AOP(result),fReturn[i],i);
12128 freeAsmop (result, NULL, ic, FALSE);
12129 unsavermask(rsave);
12132 /*-----------------------------------------------------------------*/
12133 /* genNatLibInstallStateBlock - */
12134 /*-----------------------------------------------------------------*/
12135 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
12136 operand **parms, const char *name)
12139 operand *psb, *handle;
12140 assert (nparms==2);
12142 /* save registers that need to be saved */
12143 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12144 ds390_rUmaskForOp (IC_RESULT(ic))));
12148 /* put pointer to state block into DPTR1 */
12149 aopOp (psb, ic, FALSE, FALSE);
12150 if (AOP_TYPE (psb) == AOP_IMMD) {
12151 emitcode ("mov","dps,#1");
12152 emitcode ("mov", "dptr,%s",
12153 aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12154 emitcode ("mov","dps,#0");
12156 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12157 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12158 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12160 freeAsmop (psb, NULL, ic, FALSE);
12162 /* put libraryID into DPTR */
12163 emitcode ("mov","dptr,#LibraryID");
12165 /* put handle into r3:r2 */
12166 aopOp (handle, ic, FALSE, FALSE);
12167 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12168 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12169 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12170 emitcode ("pop","ar3");
12171 emitcode ("pop","ar2");
12173 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12174 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12176 freeAsmop (psb, NULL, ic, FALSE);
12178 /* make the call */
12179 emitcode ("lcall","NatLib_Install%sStateBlock",name);
12181 /* put return value into place*/
12183 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12185 aopPut(AOP(IC_RESULT(ic)),"a",0);
12186 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12187 unsavermask(rsave);
12190 /*-----------------------------------------------------------------*/
12191 /* genNatLibRemoveStateBlock - */
12192 /*-----------------------------------------------------------------*/
12193 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12199 /* save registers that need to be saved */
12200 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12201 ds390_rUmaskForOp (IC_RESULT(ic))));
12203 /* put libraryID into DPTR */
12204 emitcode ("mov","dptr,#LibraryID");
12205 /* make the call */
12206 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12207 unsavermask(rsave);
12210 /*-----------------------------------------------------------------*/
12211 /* genNatLibGetStateBlock - */
12212 /*-----------------------------------------------------------------*/
12213 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12214 operand **parms,const char *name)
12217 symbol *lbl = newiTempLabel(NULL);
12220 /* save registers that need to be saved */
12221 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12222 ds390_rUmaskForOp (IC_RESULT(ic))));
12224 /* put libraryID into DPTR */
12225 emitcode ("mov","dptr,#LibraryID");
12226 /* make the call */
12227 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12228 emitcode ("jnz","!tlabel",lbl->key+100);
12230 /* put return value into place */
12231 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12232 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12233 emitcode ("push","ar3");
12234 emitcode ("push","ar2");
12235 emitcode ("pop","%s",
12236 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12237 emitcode ("pop","%s",
12238 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12240 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12241 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12243 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12244 emitcode ("","!tlabeldef",lbl->key+100);
12245 unsavermask(rsave);
12248 /*-----------------------------------------------------------------*/
12249 /* genMMMalloc - */
12250 /*-----------------------------------------------------------------*/
12251 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12252 int size, const char *name)
12257 symbol *lbl = newiTempLabel(NULL);
12259 assert (nparms == 1);
12260 /* save registers that need to be saved */
12261 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12262 ds390_rUmaskForOp (IC_RESULT(ic))));
12265 aopOp (bsize,ic,FALSE,FALSE);
12267 /* put the size in R4-R2 */
12268 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12269 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12270 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12272 emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12273 emitcode("pop","ar4");
12275 emitcode("pop","ar3");
12276 emitcode("pop","ar2");
12278 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12279 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12281 emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12284 freeAsmop (bsize, NULL, ic, FALSE);
12286 /* make the call */
12287 emitcode ("lcall","MM_%s",name);
12288 emitcode ("jz","!tlabel",lbl->key+100);
12289 emitcode ("mov","r2,#!constbyte",0xff);
12290 emitcode ("mov","r3,#!constbyte",0xff);
12291 emitcode ("","!tlabeldef",lbl->key+100);
12292 /* we don't care about the pointer : we just save the handle */
12293 rsym = OP_SYMBOL(IC_RESULT(ic));
12294 if (rsym->liveFrom != rsym->liveTo) {
12295 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12296 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12297 emitcode ("push","ar3");
12298 emitcode ("push","ar2");
12299 emitcode ("pop","%s",
12300 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12301 emitcode ("pop","%s",
12302 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12304 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12305 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12307 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12309 unsavermask(rsave);
12312 /*-----------------------------------------------------------------*/
12314 /*-----------------------------------------------------------------*/
12315 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12320 assert (nparms == 1);
12321 /* save registers that need to be saved */
12322 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12323 ds390_rUmaskForOp (IC_RESULT(ic))));
12326 aopOp (handle,ic,FALSE,FALSE);
12328 /* put the size in R4-R2 */
12329 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12330 emitcode("push","%s",
12331 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12332 emitcode("push","%s",
12333 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12334 emitcode("pop","ar3");
12335 emitcode("pop","ar2");
12337 emitcode ("mov","r2,%s",
12338 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12339 emitcode ("mov","r3,%s",
12340 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12342 freeAsmop (handle, NULL, ic, FALSE);
12344 /* make the call */
12345 emitcode ("lcall","MM_Deref");
12348 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12349 if (rsym->liveFrom != rsym->liveTo) {
12350 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12351 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12352 _startLazyDPSEvaluation ();
12354 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12355 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12356 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12358 _endLazyDPSEvaluation ();
12363 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12364 unsavermask(rsave);
12367 /*-----------------------------------------------------------------*/
12368 /* genMMUnrestrictedPersist - */
12369 /*-----------------------------------------------------------------*/
12370 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12375 assert (nparms == 1);
12376 /* save registers that need to be saved */
12377 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12378 ds390_rUmaskForOp (IC_RESULT(ic))));
12381 aopOp (handle,ic,FALSE,FALSE);
12383 /* put the size in R3-R2 */
12384 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12385 emitcode("push","%s",
12386 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12387 emitcode("push","%s",
12388 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12389 emitcode("pop","ar3");
12390 emitcode("pop","ar2");
12392 emitcode ("mov","r2,%s",
12393 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12394 emitcode ("mov","r3,%s",
12395 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12397 freeAsmop (handle, NULL, ic, FALSE);
12399 /* make the call */
12400 emitcode ("lcall","MM_UnrestrictedPersist");
12403 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12404 if (rsym->liveFrom != rsym->liveTo) {
12405 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12406 aopPut(AOP(IC_RESULT(ic)),"a",0);
12407 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12410 unsavermask(rsave);
12413 /*-----------------------------------------------------------------*/
12414 /* genSystemExecJavaProcess - */
12415 /*-----------------------------------------------------------------*/
12416 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12419 operand *handle, *pp;
12421 assert (nparms==2);
12422 /* save registers that need to be saved */
12423 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12424 ds390_rUmaskForOp (IC_RESULT(ic))));
12429 /* put the handle in R3-R2 */
12430 aopOp (handle,ic,FALSE,FALSE);
12431 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12432 emitcode("push","%s",
12433 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12434 emitcode("push","%s",
12435 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12436 emitcode("pop","ar3");
12437 emitcode("pop","ar2");
12439 emitcode ("mov","r2,%s",
12440 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12441 emitcode ("mov","r3,%s",
12442 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12444 freeAsmop (handle, NULL, ic, FALSE);
12446 /* put pointer in DPTR */
12447 aopOp (pp,ic,FALSE,FALSE);
12448 if (AOP_TYPE(pp) == AOP_IMMD) {
12449 emitcode ("mov", "dptr,%s",
12450 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12451 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12452 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12453 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12454 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12456 freeAsmop (handle, NULL, ic, FALSE);
12458 /* make the call */
12459 emitcode ("lcall","System_ExecJavaProcess");
12461 /* put result in place */
12463 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12464 if (rsym->liveFrom != rsym->liveTo) {
12465 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12466 aopPut(AOP(IC_RESULT(ic)),"a",0);
12467 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12471 unsavermask(rsave);
12474 /*-----------------------------------------------------------------*/
12475 /* genSystemRTCRegisters - */
12476 /*-----------------------------------------------------------------*/
12477 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12483 assert (nparms==1);
12484 /* save registers that need to be saved */
12485 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12486 ds390_rUmaskForOp (IC_RESULT(ic))));
12489 /* put pointer in DPTR */
12490 aopOp (pp,ic,FALSE,FALSE);
12491 if (AOP_TYPE (pp) == AOP_IMMD) {
12492 emitcode ("mov","dps,#1");
12493 emitcode ("mov", "dptr,%s",
12494 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12495 emitcode ("mov","dps,#0");
12497 emitcode ("mov","dpl1,%s",
12498 aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12499 emitcode ("mov","dph1,%s",
12500 aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12501 emitcode ("mov","dpx1,%s",
12502 aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12504 freeAsmop (pp, NULL, ic, FALSE);
12506 /* make the call */
12507 emitcode ("lcall","System_%sRTCRegisters",name);
12509 unsavermask(rsave);
12512 /*-----------------------------------------------------------------*/
12513 /* genSystemThreadSleep - */
12514 /*-----------------------------------------------------------------*/
12515 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12520 assert (nparms==1);
12521 /* save registers that need to be saved */
12522 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12523 ds390_rUmaskForOp (IC_RESULT(ic))));
12526 aopOp(to,ic,FALSE,FALSE);
12527 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12528 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12529 emitcode ("push","%s",
12530 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12531 emitcode ("push","%s",
12532 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12533 emitcode ("push","%s",
12534 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12535 emitcode ("push","%s",
12536 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12537 emitcode ("pop","ar3");
12538 emitcode ("pop","ar2");
12539 emitcode ("pop","ar1");
12540 emitcode ("pop","ar0");
12542 emitcode ("mov","r0,%s",
12543 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12544 emitcode ("mov","r1,%s",
12545 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12546 emitcode ("mov","r2,%s",
12547 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12548 emitcode ("mov","r3,%s",
12549 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12551 freeAsmop (to, NULL, ic, FALSE);
12553 /* suspend in acc */
12555 aopOp(s,ic,FALSE,FALSE);
12556 emitcode ("mov","a,%s",
12557 aopGet(AOP(s),0,FALSE,TRUE,NULL));
12558 freeAsmop (s, NULL, ic, FALSE);
12560 /* make the call */
12561 emitcode ("lcall","System_%s",name);
12563 unsavermask(rsave);
12566 /*-----------------------------------------------------------------*/
12567 /* genSystemThreadResume - */
12568 /*-----------------------------------------------------------------*/
12569 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12574 assert (nparms==2);
12575 /* save registers that need to be saved */
12576 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12577 ds390_rUmaskForOp (IC_RESULT(ic))));
12583 aopOp(pid,ic,FALSE,FALSE);
12584 emitcode ("mov","r0,%s",
12585 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12586 freeAsmop (pid, NULL, ic, FALSE);
12589 aopOp(tid,ic,FALSE,FALSE);
12590 emitcode ("mov","a,%s",
12591 aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
12592 freeAsmop (tid, NULL, ic, FALSE);
12594 emitcode ("lcall","System_ThreadResume");
12596 /* put result into place */
12598 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12599 if (rsym->liveFrom != rsym->liveTo) {
12600 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12601 aopPut(AOP(IC_RESULT(ic)),"a",0);
12602 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12605 unsavermask(rsave);
12608 /*-----------------------------------------------------------------*/
12609 /* genSystemProcessResume - */
12610 /*-----------------------------------------------------------------*/
12611 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
12616 assert (nparms==1);
12617 /* save registers that need to be saved */
12618 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12619 ds390_rUmaskForOp (IC_RESULT(ic))));
12624 aopOp(pid,ic,FALSE,FALSE);
12625 emitcode ("mov","a,%s",
12626 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12627 freeAsmop (pid, NULL, ic, FALSE);
12629 emitcode ("lcall","System_ProcessResume");
12631 unsavermask(rsave);
12634 /*-----------------------------------------------------------------*/
12636 /*-----------------------------------------------------------------*/
12637 static void genSystem (iCode *ic,int nparms,char *name)
12639 assert(nparms == 0);
12641 emitcode ("lcall","System_%s",name);
12644 /*-----------------------------------------------------------------*/
12645 /* genSystemPoll - */
12646 /*-----------------------------------------------------------------*/
12647 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
12652 assert (nparms==1);
12653 /* save registers that need to be saved */
12654 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12655 ds390_rUmaskForOp (IC_RESULT(ic))));
12658 aopOp (fp,ic,FALSE,FALSE);
12659 if (AOP_TYPE (fp) == AOP_IMMD) {
12660 emitcode ("mov", "dptr,%s",
12661 aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
12662 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
12663 emitcode ("mov","dpl,%s",
12664 aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
12665 emitcode ("mov","dph,%s",
12666 aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
12667 emitcode ("mov","dpx,%s",
12668 aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
12670 freeAsmop (fp, NULL, ic, FALSE);
12672 emitcode ("lcall","System_%sPoll",name);
12674 /* put result into place */
12676 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12677 if (rsym->liveFrom != rsym->liveTo) {
12678 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12679 aopPut(AOP(IC_RESULT(ic)),"a",0);
12680 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12683 unsavermask(rsave);
12686 /*-----------------------------------------------------------------*/
12687 /* genSystemGetCurrentID - */
12688 /*-----------------------------------------------------------------*/
12689 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
12691 assert (nparms==0);
12693 emitcode ("lcall","System_GetCurrent%sId",name);
12694 /* put result into place */
12696 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12697 if (rsym->liveFrom != rsym->liveTo) {
12698 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12699 aopPut(AOP(IC_RESULT(ic)),"a",0);
12700 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12705 /*-----------------------------------------------------------------*/
12706 /* genDummyRead - generate code for dummy read of volatiles */
12707 /*-----------------------------------------------------------------*/
12709 genDummyRead (iCode * ic)
12714 D(emitcode("; genDummyRead",""));
12716 right = IC_RIGHT (ic);
12718 aopOp (right, ic, FALSE, FALSE);
12720 /* if the result is a bit */
12721 if (AOP_TYPE (right) == AOP_CRY)
12723 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
12727 /* bit variables done */
12729 size = AOP_SIZE (right);
12733 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
12738 freeAsmop (right, NULL, ic, TRUE);
12741 /*-----------------------------------------------------------------*/
12742 /* genCritical - generate code for start of a critical sequence */
12743 /*-----------------------------------------------------------------*/
12745 genCritical (iCode *ic)
12747 symbol *tlbl = newiTempLabel (NULL);
12749 D(emitcode("; genCritical",""));
12751 if (IC_RESULT (ic))
12752 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
12754 emitcode ("setb", "c");
12755 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
12756 emitcode ("clr", "c");
12757 emitcode ("", "%05d$:", (tlbl->key + 100));
12759 if (IC_RESULT (ic))
12760 outBitC (IC_RESULT (ic)); /* save old ea in an operand */
12762 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
12764 if (IC_RESULT (ic))
12765 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
12768 /*-----------------------------------------------------------------*/
12769 /* genEndCritical - generate code for end of a critical sequence */
12770 /*-----------------------------------------------------------------*/
12772 genEndCritical (iCode *ic)
12774 D(emitcode("; genEndCritical",""));
12778 aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
12779 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
12781 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
12782 emitcode ("mov", "ea,c");
12786 MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE, FALSE));
12787 emitcode ("rrc", "a");
12788 emitcode ("mov", "ea,c");
12790 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
12794 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
12795 emitcode ("mov", "ea,c");
12801 /*-----------------------------------------------------------------*/
12802 /* genBuiltIn - calls the appropriate function to generating code */
12803 /* for a built in function */
12804 /*-----------------------------------------------------------------*/
12805 static void genBuiltIn (iCode *ic)
12807 operand *bi_parms[MAX_BUILTIN_ARGS];
12812 /* get all the arguments for a built in function */
12813 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
12815 /* which function is it */
12816 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
12817 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
12818 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
12819 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
12820 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
12821 } else if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
12822 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
12823 } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
12824 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
12825 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
12826 genMemsetX(bi_iCode,nbi_parms,bi_parms);
12827 } else if (strcmp(bif->name,"__builtin_inp")==0) {
12828 genInp(bi_iCode,nbi_parms,bi_parms);
12829 } else if (strcmp(bif->name,"__builtin_outp")==0) {
12830 genOutp(bi_iCode,nbi_parms,bi_parms);
12831 } else if (strcmp(bif->name,"__builtin_swapw")==0) {
12832 genSwapW(bi_iCode,nbi_parms,bi_parms);
12833 /* JavaNative builtIns */
12834 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
12835 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
12836 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
12837 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
12838 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
12839 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
12840 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
12841 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
12842 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
12843 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12844 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
12845 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12846 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
12847 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
12848 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
12849 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
12850 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
12851 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12852 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
12853 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12854 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
12855 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
12856 } else if (strcmp(bif->name,"MM_Malloc")==0) {
12857 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
12858 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
12859 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
12860 } else if (strcmp(bif->name,"MM_Free")==0) {
12861 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
12862 } else if (strcmp(bif->name,"MM_Deref")==0) {
12863 genMMDeref(bi_iCode,nbi_parms,bi_parms);
12864 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
12865 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
12866 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
12867 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
12868 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
12869 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
12870 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
12871 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
12872 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
12873 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
12874 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
12875 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
12876 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
12877 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
12878 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
12879 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
12880 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12881 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12882 } else if (strcmp(bif->name,"System_SaveThread")==0) {
12883 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12884 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12885 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12886 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
12887 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
12888 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
12889 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
12890 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
12891 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
12892 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
12893 genSystem(bi_iCode,nbi_parms,"ProcessYield");
12894 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
12895 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
12896 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
12897 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
12898 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
12899 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
12900 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
12901 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
12902 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
12903 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
12905 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
12911 /*-----------------------------------------------------------------*/
12912 /* gen390Code - generate code for Dallas 390 based controllers */
12913 /*-----------------------------------------------------------------*/
12915 gen390Code (iCode * lic)
12920 lineHead = lineCurr = NULL;
12921 dptrn[1][0] = "dpl1";
12922 dptrn[1][1] = "dph1";
12923 dptrn[1][2] = "dpx1";
12925 if (options.model == MODEL_FLAT24) {
12926 fReturnSizeDS390 = 5;
12927 fReturn = fReturn24;
12929 fReturnSizeDS390 = 4;
12930 fReturn = fReturn16;
12931 options.stack10bit=0;
12934 /* print the allocation information */
12935 if (allocInfo && currFunc)
12936 printAllocInfo (currFunc, codeOutFile);
12938 /* if debug information required */
12939 if (options.debug && currFunc)
12941 debugFile->writeFunction(currFunc);
12943 if (IS_STATIC (currFunc->etype))
12944 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
12946 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
12949 /* stack pointer name */
12950 if (options.useXstack)
12956 for (ic = lic; ic; ic = ic->next)
12959 if (ic->lineno && cln != ic->lineno)
12964 emitcode ("", "C$%s$%d$%d$%d ==.",
12965 FileBaseName (ic->filename), ic->lineno,
12966 ic->level, ic->block);
12969 if (!options.noCcodeInAsm) {
12970 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
12971 printCLine(ic->filename, ic->lineno));
12975 if (options.iCodeInAsm) {
12976 emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
12978 /* if the result is marked as
12979 spilt and rematerializable or code for
12980 this has already been generated then
12982 if (resultRemat (ic) || ic->generated)
12985 /* depending on the operation */
13005 /* IPOP happens only when trying to restore a
13006 spilt live range, if there is an ifx statement
13007 following this pop then the if statement might
13008 be using some of the registers being popped which
13009 would destory the contents of the register so
13010 we need to check for this condition and handle it */
13012 ic->next->op == IFX &&
13013 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
13014 genIfx (ic->next, ic);
13032 genEndFunction (ic);
13052 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
13069 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
13073 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
13080 /* note these two are xlated by algebraic equivalence
13081 during parsing SDCC.y */
13082 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
13083 "got '>=' or '<=' shouldn't have come here");
13087 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
13099 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
13103 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
13107 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
13131 genRightShift (ic);
13134 case GET_VALUE_AT_ADDRESS:
13135 genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
13139 if (POINTER_SET (ic))
13140 genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
13166 if (ic->builtinSEND) genBuiltIn(ic);
13167 else addSet (&_G.sendSet, ic);
13170 case DUMMY_READ_VOLATILE:
13179 genEndCritical (ic);
13186 #if 0 // obsolete, and buggy for != xdata
13198 /* now we are ready to call the
13199 peep hole optimizer */
13200 if (!options.nopeep)
13201 peepHole (&lineHead);
13203 /* now do the actual printing */
13204 printLine (lineHead, codeOutFile);