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 /* aopForSym - for a true symbol */
443 /*-----------------------------------------------------------------*/
445 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
448 memmap *space = SPEC_OCLS (sym->etype);
450 /* if already has one */
454 /* assign depending on the storage class */
455 /* if it is on the stack or indirectly addressable */
456 /* space we need to assign either r0 or r1 to it */
457 if ((sym->onStack && !options.stack10bit) || sym->iaccess)
459 sym->aop = aop = newAsmop (0);
460 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
461 aop->size = getSize (sym->type);
463 /* now assign the address of the variable to
464 the pointer register */
465 if (aop->type != AOP_STK)
471 emitcode ("push", "acc");
474 emitcode ("push", "b");
476 emitcode ("mov", "a,_bp");
477 emitcode ("add", "a,#!constbyte",
479 ((char) (sym->stack - _G.nRegsSaved)) :
480 ((char) sym->stack)) & 0xff);
481 emitcode ("mov", "%s,a",
482 aop->aopu.aop_ptr->name);
485 emitcode ("pop", "b");
488 emitcode ("pop", "acc");
491 emitcode ("mov", "%s,#%s",
492 aop->aopu.aop_ptr->name,
494 aop->paged = space->paged;
497 aop->aopu.aop_stk = sym->stack;
501 if (sym->onStack && options.stack10bit)
503 short stack_val = -((sym->stack < 0) ?
504 ((short) (sym->stack - _G.nRegsSaved)) :
505 ((short) sym->stack)) ;
506 if (useDP2 && _G.dptr1InUse) {
507 emitcode ("push","dpl1");
508 emitcode ("push","dph1");
509 emitcode ("push","dpx1");
510 } else if (_G.dptrInUse ) {
511 emitcode ("push","dpl");
512 emitcode ("push","dph");
513 emitcode ("push","dpx");
515 /* It's on the 10 bit stack, which is located in
518 if (stack_val < 0 && stack_val > -5) { /* between -5 & -1 */
520 if (options.model == MODEL_FLAT24)
521 emitcode ("mov", "dpx1,#!constbyte", (options.stack_loc >> 16) & 0xff);
523 emitcode ("mov", "dph1,_bpx+1");
524 emitcode ("mov", "dpl1,_bpx");
525 emitcode ("mov","dps,#1");
527 if (options.model == MODEL_FLAT24)
528 emitcode ("mov", "dpx,#!constbyte", (options.stack_loc >> 16) & 0xff);
529 emitcode ("mov", "dph,_bpx+1");
530 emitcode ("mov", "dpl,_bpx");
532 stack_val = -stack_val;
533 while (stack_val--) {
534 emitcode ("inc","dptr");
537 emitcode("mov","dps,#0");
541 emitcode ("push", "acc");
544 emitcode ("push", "b");
546 emitcode ("mov", "a,_bpx");
547 emitcode ("clr","c");
548 emitcode ("subb", "a,#!constbyte", stack_val & 0xff);
549 emitcode ("mov","b,a");
550 emitcode ("mov","a,_bpx+1");
551 emitcode ("subb","a,#!constbyte",(stack_val >> 8) & 0xff);
553 if (options.model == MODEL_FLAT24)
554 emitcode ("mov", "dpx1,#!constbyte", (options.stack_loc >> 16) & 0xff);
556 emitcode ("mov", "dph1,a");
557 emitcode ("mov", "dpl1,b");
559 if (options.model == MODEL_FLAT24)
560 emitcode ("mov", "dpx,#!constbyte", (options.stack_loc >> 16) & 0xff);
561 emitcode ("mov", "dph,a");
562 emitcode ("mov", "dpl,b");
566 emitcode ("pop", "b");
569 emitcode ("pop", "acc");
571 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
572 aop->size = getSize (sym->type);
576 /* if in bit space */
577 if (IN_BITSPACE (space))
579 sym->aop = aop = newAsmop (AOP_CRY);
580 aop->aopu.aop_dir = sym->rname;
581 aop->size = getSize (sym->type);
584 /* if it is in direct space */
585 if (IN_DIRSPACE (space))
587 sym->aop = aop = newAsmop (AOP_DIR);
588 aop->aopu.aop_dir = sym->rname;
589 aop->size = getSize (sym->type);
593 /* special case for a function */
594 if (IS_FUNC (sym->type))
596 sym->aop = aop = newAsmop (AOP_IMMD);
597 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
598 aop->size = FPTRSIZE;
602 /* only remaining is far space */
603 /* in which case DPTR gets the address */
604 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
609 emitcode ("mov", "dptr,#%s", sym->rname);
614 emitcode ("mov", "dptr,#%s", sym->rname);
616 aop->size = getSize (sym->type);
618 /* if it is in code space */
619 if (IN_CODESPACE (space))
625 /*-----------------------------------------------------------------*/
626 /* aopForRemat - rematerialzes an object */
627 /*-----------------------------------------------------------------*/
629 aopForRemat (symbol * sym)
631 iCode *ic = sym->rematiCode;
632 asmop *aop = newAsmop (AOP_IMMD);
639 val += (int) operandLitValue (IC_RIGHT (ic));
640 else if (ic->op == '-')
641 val -= (int) operandLitValue (IC_RIGHT (ic));
642 else if (IS_CAST_ICODE(ic)) {
643 sym_link *from_type = operandType(IC_RIGHT(ic));
644 aop->aopu.aop_immd.from_cast_remat = 1;
645 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
646 ptr_type = DCL_TYPE(from_type);
647 if (ptr_type == IPOINTER) {
654 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
659 SNPRINTF (buffer, sizeof(buffer),
661 OP_SYMBOL (IC_LEFT (ic))->rname,
662 val >= 0 ? '+' : '-',
663 abs (val) & 0xffffff);
667 if (IS_ASSIGN_ICODE(ic) && isOperandLiteral(IC_RIGHT(ic)))
669 SNPRINTF(buffer, sizeof(buffer),
670 "0x%x",(int) operandLitValue (IC_RIGHT (ic)));
674 strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
678 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);
679 /* set immd2 field if required */
680 if (aop->aopu.aop_immd.from_cast_remat)
682 tsprintf(buffer, sizeof(buffer), "#!constbyte",ptr_type);
683 aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
689 /*-----------------------------------------------------------------*/
690 /* aopHasRegs - returns true if aop has regs between from-to */
691 /*-----------------------------------------------------------------*/
692 static int aopHasRegs(asmop *aop, int from, int to)
696 if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
698 for (; size < aop->size ; size++) {
700 for (reg = from ; reg <= to ; reg++)
701 if (aop->aopu.aop_reg[size] == ds390_regWithIdx(reg)) return 1;
706 /*-----------------------------------------------------------------*/
707 /* regsInCommon - two operands have some registers in common */
708 /*-----------------------------------------------------------------*/
710 regsInCommon (operand * op1, operand * op2)
715 /* if they have registers in common */
716 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
719 sym1 = OP_SYMBOL (op1);
720 sym2 = OP_SYMBOL (op2);
722 if (sym1->nRegs == 0 || sym2->nRegs == 0)
725 for (i = 0; i < sym1->nRegs; i++)
731 for (j = 0; j < sym2->nRegs; j++)
736 if (sym2->regs[j] == sym1->regs[i])
744 /*-----------------------------------------------------------------*/
745 /* operandsEqu - equivalent */
746 /*-----------------------------------------------------------------*/
748 operandsEqu (operand * op1, operand * op2)
752 /* if they not symbols */
753 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
756 sym1 = OP_SYMBOL (op1);
757 sym2 = OP_SYMBOL (op2);
759 /* if both are itemps & one is spilt
760 and the other is not then false */
761 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
762 sym1->isspilt != sym2->isspilt)
765 /* if they are the same */
769 if (strcmp (sym1->rname, sym2->rname) == 0)
773 /* if left is a tmp & right is not */
774 if (IS_ITEMP (op1) &&
777 (sym1->usl.spillLoc == sym2))
780 if (IS_ITEMP (op2) &&
784 (sym2->usl.spillLoc == sym1))
790 /*-----------------------------------------------------------------*/
791 /* sameRegs - two asmops have the same registers */
792 /*-----------------------------------------------------------------*/
794 sameRegs (asmop * aop1, asmop * aop2)
800 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
807 if (aop1->type != AOP_REG ||
808 aop2->type != AOP_REG)
811 if (aop1->size != aop2->size)
814 for (i = 0; i < aop1->size; i++)
815 if (aop1->aopu.aop_reg[i] !=
816 aop2->aopu.aop_reg[i])
822 /*-----------------------------------------------------------------*/
823 /* aopOp - allocates an asmop for an operand : */
824 /*-----------------------------------------------------------------*/
826 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
835 /* if this a literal */
836 if (IS_OP_LITERAL (op))
838 op->aop = aop = newAsmop (AOP_LIT);
839 aop->aopu.aop_lit = op->operand.valOperand;
840 aop->size = getSize (operandType (op));
844 /* if already has a asmop then continue */
848 /* if the underlying symbol has a aop */
849 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
851 op->aop = OP_SYMBOL (op)->aop;
855 /* if this is a true symbol */
856 if (IS_TRUE_SYMOP (op))
858 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
862 /* this is a temporary : this has
868 e) can be a return use only */
870 sym = OP_SYMBOL (op);
873 /* if the type is a conditional */
874 if (sym->regType == REG_CND)
876 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
881 /* if it is spilt then two situations
883 b) has a spill location */
884 if (sym->isspilt || sym->nRegs == 0)
887 /* rematerialize it NOW */
890 sym->aop = op->aop = aop =
892 aop->size = getSize (sym->type);
899 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
900 aop->size = getSize (sym->type);
901 for (i = 0; i < 2; i++)
902 aop->aopu.aop_str[i] = accUse[i];
912 /* a AOP_STR uses DPTR, but DPTR is already in use;
915 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"AOP_STR with DPTR in use!");
918 aop = op->aop = sym->aop = newAsmop (AOP_STR);
919 aop->size = getSize (sym->type);
920 for (i = 0; i < (int) fReturnSizeDS390; i++)
921 aop->aopu.aop_str[i] = fReturn[i];
925 if (sym->dptr) { /* has been allocated to a DPTRn */
926 aop = op->aop = sym->aop = newAsmop (AOP_DPTRn);
927 aop->size = getSize (sym->type);
928 aop->aopu.dptr = sym->dptr;
931 /* else spill location */
932 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
933 /* force a new aop if sizes differ */
934 sym->usl.spillLoc->aop = NULL;
936 sym->aop = op->aop = aop =
937 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
938 aop->size = getSize (sym->type);
942 /* must be in a register */
943 sym->aop = op->aop = aop = newAsmop (AOP_REG);
944 aop->size = sym->nRegs;
945 for (i = 0; i < sym->nRegs; i++)
946 aop->aopu.aop_reg[i] = sym->regs[i];
949 /*-----------------------------------------------------------------*/
950 /* freeAsmop - free up the asmop given to an operand */
951 /*----------------------------------------------------------------*/
953 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
970 /* depending on the asmop type only three cases need work AOP_RO
971 , AOP_R1 && AOP_STK */
979 emitcode ("pop", "ar0");
983 bitVectUnSetBit (ic->rUsed, R0_IDX);
991 emitcode ("pop", "ar1");
995 bitVectUnSetBit (ic->rUsed, R1_IDX);
1001 int stk = aop->aopu.aop_stk + aop->size;
1002 bitVectUnSetBit (ic->rUsed, R0_IDX);
1003 bitVectUnSetBit (ic->rUsed, R1_IDX);
1005 getFreePtr (ic, &aop, FALSE);
1007 if (options.stack10bit)
1009 /* I'm not sure what to do here yet... */
1012 "*** Warning: probably generating bad code for "
1013 "10 bit stack mode.\n");
1018 emitcode ("mov", "a,_bp");
1019 emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
1020 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1024 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1029 emitcode ("pop", "acc");
1030 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1033 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1036 freeAsmop (op, NULL, ic, TRUE);
1039 emitcode ("pop", "ar0");
1045 emitcode ("pop", "ar1");
1050 if (_G.dptr1InUse) {
1051 emitcode ("pop","dpx1");
1052 emitcode ("pop","dph1");
1053 emitcode ("pop","dpl1");
1058 emitcode ("pop","dpx");
1059 emitcode ("pop","dph");
1060 emitcode ("pop","dpl");
1065 /* all other cases just dealloc */
1071 OP_SYMBOL (op)->aop = NULL;
1072 /* if the symbol has a spill */
1074 SPIL_LOC (op)->aop = NULL;
1079 #define DEFAULT_ACC_WARNING 0
1080 static int saveAccWarn = DEFAULT_ACC_WARNING;
1082 /*-------------------------------------------------------------------*/
1083 /* aopGet - for fetching value of the aop */
1085 /* Set saveAcc to NULL if you are sure it is OK to clobber the value */
1086 /* in the accumulator. Set it to the name of a free register */
1087 /* if acc must be preserved; the register will be used to preserve */
1088 /* acc temporarily and to return the result byte. */
1089 /*-------------------------------------------------------------------*/
1098 /* offset is greater than
1100 if (offset > (aop->size - 1) &&
1101 aop->type != AOP_LIT)
1104 /* depending on type */
1110 /* if we need to increment it */
1111 while (offset > aop->coff)
1113 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1117 while (offset < aop->coff)
1119 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1126 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1127 return (dname ? "acc" : "a");
1129 SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1130 return Safe_strdup(buffer);
1133 assert(offset <= 3);
1134 return dptrn[aop->aopu.dptr][offset];
1139 if (aop->type == AOP_DPTR2)
1147 // if (aop->type != AOP_DPTR2)
1149 // if (saveAccWarn) { fprintf(stderr, "saveAcc for DPTR...\n"); }
1150 // emitcode(";", "spanky: saveAcc for DPTR");
1153 emitcode ("xch", "a, %s", saveAcc);
1158 while (offset > aop->coff)
1160 emitcode ("inc", "dptr");
1164 while (offset < aop->coff)
1166 emitcode ("lcall", "__decdptr");
1173 emitcode ("clr", "a");
1174 emitcode ("movc", "a,@a+dptr");
1178 emitcode ("movx", "a,@dptr");
1181 if (aop->type == AOP_DPTR2)
1189 emitcode ("xch", "a, %s", saveAcc);
1190 // if (strcmp(saveAcc, "_ap"))
1192 // emitcode(";", "spiffy: non _ap return from aopGet.");
1197 return (dname ? "acc" : "a");
1200 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1202 SNPRINTF(buffer, sizeof(buffer),
1203 "%s",aop->aopu.aop_immd.aop_immd2);
1207 SNPRINTF(buffer, sizeof(buffer),
1208 "#%s", aop->aopu.aop_immd.aop_immd1);
1214 tsprintf(buffer, sizeof(buffer),
1215 "#!his",aop->aopu.aop_immd.aop_immd1);
1218 tsprintf(buffer, sizeof(buffer),
1219 "#!hihis",aop->aopu.aop_immd.aop_immd1);
1222 tsprintf(buffer, sizeof(buffer),
1223 "#!hihihis",aop->aopu.aop_immd.aop_immd1);
1225 default: /* should not need this (just in case) */
1226 SNPRINTF (buffer, sizeof(buffer),
1228 aop->aopu.aop_immd.aop_immd1,
1234 SNPRINTF (buffer, sizeof(buffer),
1235 "#%s", aop->aopu.aop_immd.aop_immd1);
1237 return Safe_strdup(buffer);
1242 SNPRINTF (buffer, sizeof(buffer),
1249 SNPRINTF(buffer, sizeof(buffer),
1250 "%s", aop->aopu.aop_dir);
1253 return Safe_strdup(buffer);
1257 return aop->aopu.aop_reg[offset]->dname;
1259 return aop->aopu.aop_reg[offset]->name;
1262 emitcode ("clr", "a");
1263 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1264 emitcode ("rlc", "a");
1265 return (dname ? "acc" : "a");
1268 if (!offset && dname)
1270 return aop->aopu.aop_str[offset];
1273 return aopLiteral (aop->aopu.aop_lit, offset);
1277 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1281 return aop->aopu.aop_str[offset];
1285 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1286 "aopget got unsupported aop->type");
1289 return NULL; // not reached, but makes compiler happy.
1291 /*-----------------------------------------------------------------*/
1292 /* aopPut - puts a string for a aop */
1293 /*-----------------------------------------------------------------*/
1295 aopPut (asmop * aop, char *s, int offset)
1297 if (aop->size && offset > (aop->size - 1))
1299 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1300 "aopPut got offset > aop->size");
1304 /* will assign value to value */
1305 /* depending on where it is ofcourse */
1311 SNPRINTF (buffer, sizeof(buffer),
1313 aop->aopu.aop_dir, offset);
1317 SNPRINTF (buffer, sizeof(buffer),
1318 "%s", aop->aopu.aop_dir);
1322 if (strcmp (buffer, s))
1324 emitcode ("mov", "%s,%s", buffer, s);
1329 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1330 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1333 strcmp (s, "r0") == 0 ||
1334 strcmp (s, "r1") == 0 ||
1335 strcmp (s, "r2") == 0 ||
1336 strcmp (s, "r3") == 0 ||
1337 strcmp (s, "r4") == 0 ||
1338 strcmp (s, "r5") == 0 ||
1339 strcmp (s, "r6") == 0 ||
1340 strcmp (s, "r7") == 0)
1342 emitcode ("mov", "%s,%s",
1343 aop->aopu.aop_reg[offset]->dname, s);
1347 emitcode ("mov", "%s,%s",
1348 aop->aopu.aop_reg[offset]->name, s);
1354 emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1360 if (aop->type == AOP_DPTR2)
1368 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1369 "aopPut writting to code space");
1373 while (offset > aop->coff)
1376 emitcode ("inc", "dptr");
1379 while (offset < aop->coff)
1382 emitcode ("lcall", "__decdptr");
1387 /* if not in accumulater */
1390 emitcode ("movx", "@dptr,a");
1392 if (aop->type == AOP_DPTR2)
1400 while (offset > aop->coff)
1403 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1405 while (offset < aop->coff)
1408 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1415 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1421 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1423 else if (strcmp (s, "r0") == 0 ||
1424 strcmp (s, "r1") == 0 ||
1425 strcmp (s, "r2") == 0 ||
1426 strcmp (s, "r3") == 0 ||
1427 strcmp (s, "r4") == 0 ||
1428 strcmp (s, "r5") == 0 ||
1429 strcmp (s, "r6") == 0 ||
1430 strcmp (s, "r7") == 0)
1433 SNPRINTF(buff, sizeof(buff),
1435 emitcode ("mov", "@%s,%s",
1436 aop->aopu.aop_ptr->name, buff);
1440 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1445 if (strcmp (s, "a") == 0)
1446 emitcode ("push", "acc");
1450 emitcode ("push", "acc");
1452 emitcode ("push", s);
1458 /* if bit variable */
1459 if (!aop->aopu.aop_dir)
1461 emitcode ("clr", "a");
1462 emitcode ("rlc", "a");
1467 emitcode ("clr", "%s", aop->aopu.aop_dir);
1469 emitcode ("setb", "%s", aop->aopu.aop_dir);
1470 else if (!strcmp (s, "c"))
1471 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1474 if (strcmp (s, "a"))
1479 /* set C, if a >= 1 */
1480 emitcode ("add", "a,#!constbyte",0xff);
1481 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1489 if (strcmp (aop->aopu.aop_str[offset], s))
1490 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1495 if (!offset && (strcmp (s, "acc") == 0))
1498 if (strcmp (aop->aopu.aop_str[offset], s))
1499 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1503 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1504 "aopPut got unsupported aop->type");
1511 /*--------------------------------------------------------------------*/
1512 /* reAdjustPreg - points a register back to where it should (coff==0) */
1513 /*--------------------------------------------------------------------*/
1515 reAdjustPreg (asmop * aop)
1517 if ((aop->coff==0) || (aop->size <= 1)) {
1526 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1530 if (aop->type == AOP_DPTR2)
1537 emitcode ("lcall", "__decdptr");
1540 if (aop->type == AOP_DPTR2)
1550 #define AOP(op) op->aop
1551 #define AOP_TYPE(op) AOP(op)->type
1552 #define AOP_SIZE(op) AOP(op)->size
1553 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1554 AOP_TYPE(x) == AOP_R0))
1556 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1557 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1560 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1561 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1562 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1563 #define AOP_INDPTRn(x) (AOP_TYPE(x) == AOP_DPTRn)
1564 #define AOP_USESDPTR(x) ((AOP_TYPE(x) == AOP_DPTR) || (AOP_TYPE(x) == AOP_STR))
1565 #define AOP_USESDPTR2(x) ((AOP_TYPE(x) == AOP_DPTR2) || (AOP_TYPE(x) == AOP_DPTRn))
1567 // The following two macros can be used even if the aop has not yet been aopOp'd.
1568 #define AOP_IS_STR(x) (IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
1569 #define AOP_IS_DPTRn(x) (IS_SYMOP(x) && OP_SYMBOL(x)->dptr)
1571 /* Workaround for DS80C390 bug: div ab may return bogus results
1572 * if A is accessed in instruction immediately before the div.
1574 * Will be fixed in B4 rev of processor, Dallas claims.
1577 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1578 if (!AOP_NEEDSACC(RIGHT)) \
1580 /* We can load A first, then B, since \
1581 * B (the RIGHT operand) won't clobber A, \
1582 * thus avoiding touching A right before the div. \
1584 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1585 L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL); \
1587 L = aopGet(AOP(RIGHT),0,FALSE,FALSE,"b"); \
1592 /* Just stuff in a nop after loading A. */ \
1593 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,NULL));\
1594 L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL); \
1596 emitcode("nop", "; workaround for DS80C390 div bug."); \
1599 /*-----------------------------------------------------------------*/
1600 /* genNotFloat - generates not for float operations */
1601 /*-----------------------------------------------------------------*/
1603 genNotFloat (operand * op, operand * res)
1608 D (emitcode (";", "genNotFloat "););
1610 /* we will put 127 in the first byte of
1612 aopPut (AOP (res), "#127", 0);
1613 size = AOP_SIZE (op) - 1;
1616 _startLazyDPSEvaluation ();
1617 MOVA(aopGet(op->aop, offset++, FALSE, FALSE, NULL));
1621 emitcode ("orl", "a,%s",
1623 offset++, FALSE, FALSE,
1626 _endLazyDPSEvaluation ();
1628 tlbl = newiTempLabel (NULL);
1629 aopPut (res->aop, one, 1);
1630 emitcode ("jz", "!tlabel", (tlbl->key + 100));
1631 aopPut (res->aop, zero, 1);
1632 emitcode ("", "!tlabeldef", (tlbl->key + 100));
1634 size = res->aop->size - 2;
1636 /* put zeros in the rest */
1638 aopPut (res->aop, zero, offset++);
1641 /*-----------------------------------------------------------------*/
1642 /* opIsGptr: returns non-zero if the passed operand is */
1643 /* a generic pointer type. */
1644 /*-----------------------------------------------------------------*/
1646 opIsGptr (operand * op)
1648 sym_link *type = operandType (op);
1650 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1657 /*-----------------------------------------------------------------*/
1658 /* getDataSize - get the operand data size */
1659 /*-----------------------------------------------------------------*/
1661 getDataSize (operand * op)
1664 size = AOP_SIZE (op);
1665 if (size == GPTRSIZE)
1667 sym_link *type = operandType (op);
1668 if (IS_GENPTR (type))
1670 /* generic pointer; arithmetic operations
1671 * should ignore the high byte (pointer type).
1679 /*-----------------------------------------------------------------*/
1680 /* outAcc - output Acc */
1681 /*-----------------------------------------------------------------*/
1683 outAcc (operand * result)
1686 size = getDataSize (result);
1689 aopPut (AOP (result), "a", 0);
1692 /* unsigned or positive */
1695 aopPut (AOP (result), zero, offset++);
1700 /*-----------------------------------------------------------------*/
1701 /* outBitC - output a bit C */
1702 /*-----------------------------------------------------------------*/
1704 outBitC (operand * result)
1706 /* if the result is bit */
1707 if (AOP_TYPE (result) == AOP_CRY)
1709 aopPut (AOP (result), "c", 0);
1713 emitcode ("clr", "a");
1714 emitcode ("rlc", "a");
1719 /*-----------------------------------------------------------------*/
1720 /* toBoolean - emit code for orl a,operator(sizeop) */
1721 /*-----------------------------------------------------------------*/
1723 toBoolean (operand * oper)
1725 int size = AOP_SIZE (oper) - 1;
1729 /* The generic part of a generic pointer should
1730 * not participate in it's truth value.
1732 * i.e. 0x10000000 is zero.
1734 if (opIsGptr (oper))
1736 D (emitcode (";", "toBoolean: generic ptr special case."););
1740 _startLazyDPSEvaluation ();
1741 if (AOP_NEEDSACC (oper) && size)
1746 emitcode ("push", "b");
1748 MOVB (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1752 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1759 emitcode ("orl", "b,%s",
1760 aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1764 emitcode ("orl", "a,%s",
1765 aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1768 _endLazyDPSEvaluation ();
1772 emitcode ("mov", "a,b");
1775 emitcode ("pop", "b");
1782 /*-----------------------------------------------------------------*/
1783 /* genNot - generate code for ! operation */
1784 /*-----------------------------------------------------------------*/
1789 sym_link *optype = operandType (IC_LEFT (ic));
1791 D (emitcode (";", "genNot "););
1793 /* assign asmOps to operand & result */
1794 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1795 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1797 /* if in bit space then a special case */
1798 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1800 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1801 emitcode ("cpl", "c");
1802 outBitC (IC_RESULT (ic));
1806 /* if type float then do float */
1807 if (IS_FLOAT (optype))
1809 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1813 toBoolean (IC_LEFT (ic));
1815 tlbl = newiTempLabel (NULL);
1816 emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1817 emitcode ("", "!tlabeldef", tlbl->key + 100);
1818 outBitC (IC_RESULT (ic));
1821 /* release the aops */
1822 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1823 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1827 /*-----------------------------------------------------------------*/
1828 /* genCpl - generate code for complement */
1829 /*-----------------------------------------------------------------*/
1837 D (emitcode (";", "genCpl "););
1840 /* assign asmOps to operand & result */
1841 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1842 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1844 /* special case if in bit space */
1845 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1846 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1847 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1848 emitcode ("cpl", "c");
1849 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1852 tlbl=newiTempLabel(NULL);
1853 emitcode ("cjne", "%s,#0x01,%05d$",
1854 aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE,NULL), tlbl->key+100);
1855 emitcode ("", "%05d$:", tlbl->key+100);
1856 outBitC (IC_RESULT(ic));
1860 size = AOP_SIZE (IC_RESULT (ic));
1861 _startLazyDPSEvaluation ();
1864 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
1865 emitcode ("cpl", "a");
1866 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1868 _endLazyDPSEvaluation ();
1872 /* release the aops */
1873 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1874 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1877 /*-----------------------------------------------------------------*/
1878 /* genUminusFloat - unary minus for floating points */
1879 /*-----------------------------------------------------------------*/
1881 genUminusFloat (operand * op, operand * result)
1883 int size, offset = 0;
1885 D(emitcode (";", "genUminusFloat"););
1887 /* for this we just copy and then flip the bit */
1889 _startLazyDPSEvaluation ();
1890 size = AOP_SIZE (op) - 1;
1894 aopPut (AOP (result),
1895 aopGet (AOP (op), offset, FALSE, FALSE, NULL),
1900 MOVA(aopGet (AOP (op), offset, FALSE, FALSE, NULL));
1902 emitcode ("cpl", "acc.7");
1903 aopPut (AOP (result), "a", offset);
1904 _endLazyDPSEvaluation ();
1907 /*-----------------------------------------------------------------*/
1908 /* genUminus - unary minus code generation */
1909 /*-----------------------------------------------------------------*/
1911 genUminus (iCode * ic)
1916 D (emitcode (";", "genUminus "););
1919 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1920 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1922 /* if both in bit space then special
1924 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1925 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1928 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1929 emitcode ("cpl", "c");
1930 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1934 optype = operandType (IC_LEFT (ic));
1936 /* if float then do float stuff */
1937 if (IS_FLOAT (optype))
1939 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1943 /* otherwise subtract from zero */
1944 size = AOP_SIZE (IC_LEFT (ic));
1946 _startLazyDPSEvaluation ();
1949 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL);
1950 if (!strcmp (l, "a"))
1954 emitcode ("cpl", "a");
1955 emitcode ("addc", "a,#0");
1961 emitcode ("clr", "a");
1962 emitcode ("subb", "a,%s", l);
1964 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1966 _endLazyDPSEvaluation ();
1968 /* if any remaining bytes in the result */
1969 /* we just need to propagate the sign */
1970 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic)))) != 0)
1972 emitcode ("rlc", "a");
1973 emitcode ("subb", "a,acc");
1975 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1979 /* release the aops */
1980 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1981 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1984 /*-----------------------------------------------------------------*/
1985 /* savermask - saves registers in the mask */
1986 /*-----------------------------------------------------------------*/
1987 static void savermask(bitVect *rs_mask)
1990 if (options.useXstack) {
1991 if (bitVectBitValue (rs_mask, R0_IDX))
1992 emitcode ("mov", "b,r0");
1993 emitcode ("mov", "r0,%s", spname);
1994 for (i = 0; i < ds390_nRegs; i++) {
1995 if (bitVectBitValue (rs_mask, i)) {
1997 emitcode ("mov", "a,b");
1999 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
2000 emitcode ("movx", "@r0,a");
2001 emitcode ("inc", "r0");
2004 emitcode ("mov", "%s,r0", spname);
2005 if (bitVectBitValue (rs_mask, R0_IDX))
2006 emitcode ("mov", "r0,b");
2008 for (i = 0; i < ds390_nRegs; i++) {
2009 if (bitVectBitValue (rs_mask, i))
2010 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2015 /*-----------------------------------------------------------------*/
2016 /* saveRegisters - will look for a call and save the registers */
2017 /*-----------------------------------------------------------------*/
2019 saveRegisters (iCode * lic)
2025 for (ic = lic; ic; ic = ic->next)
2026 if (ic->op == CALL || ic->op == PCALL)
2031 fprintf (stderr, "found parameter push with no function call\n");
2035 /* if the registers have been saved already then
2037 if (ic->regsSaved ||
2038 (IS_SYMOP(IC_LEFT(ic)) && IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic)))))
2041 /* special case if DPTR alive across a function call then must save it
2042 even though callee saves */
2043 if (IS_SYMOP(IC_LEFT(ic)) &&
2044 IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2046 rsave = newBitVect(ic->rMask->size);
2047 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2048 if (bitVectBitValue(ic->rMask,i))
2049 rsave = bitVectSetBit(rsave,i);
2051 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2053 /* safe the registers in use at this time but skip the
2054 ones for the result */
2055 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2056 ds390_rUmaskForOp (IC_RESULT(ic)));
2062 /*-----------------------------------------------------------------*/
2063 /* usavermask - restore registers with mask */
2064 /*-----------------------------------------------------------------*/
2065 static void unsavermask(bitVect *rs_mask)
2068 if (options.useXstack) {
2069 emitcode ("mov", "r0,%s", spname);
2070 for (i = ds390_nRegs; i >= 0; i--) {
2071 if (bitVectBitValue (rs_mask, i)) {
2072 emitcode ("dec", "r0");
2073 emitcode ("movx", "a,@r0");
2075 emitcode ("mov", "b,a");
2077 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
2080 emitcode ("mov", "%s,r0", spname);
2081 if (bitVectBitValue (rs_mask, R0_IDX))
2082 emitcode ("mov", "r0,b");
2084 for (i = ds390_nRegs; i >= 0; i--) {
2085 if (bitVectBitValue (rs_mask, i))
2086 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2091 /*-----------------------------------------------------------------*/
2092 /* unsaveRegisters - pop the pushed registers */
2093 /*-----------------------------------------------------------------*/
2095 unsaveRegisters (iCode * ic)
2099 if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2101 rsave = newBitVect(ic->rMask->size);
2102 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2103 if (bitVectBitValue(ic->rMask,i))
2104 rsave = bitVectSetBit(rsave,i);
2106 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2108 /* restore the registers in use at this time but skip the
2109 ones for the result */
2110 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2111 ds390_rUmaskForOp (IC_RESULT(ic)));
2117 /*-----------------------------------------------------------------*/
2119 /*-----------------------------------------------------------------*/
2121 pushSide (operand * oper, int size)
2124 _startLazyDPSEvaluation ();
2127 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, NULL);
2128 if (AOP_TYPE (oper) != AOP_REG &&
2129 AOP_TYPE (oper) != AOP_DIR &&
2132 emitcode ("mov", "a,%s", l);
2133 emitcode ("push", "acc");
2136 emitcode ("push", "%s", l);
2138 _endLazyDPSEvaluation ();
2141 /*-----------------------------------------------------------------*/
2142 /* assignResultValue - */
2143 /*-----------------------------------------------------------------*/
2145 assignResultValue (operand * oper)
2148 int size = AOP_SIZE (oper);
2149 bool pushedAcc = FALSE;
2151 if (size == fReturnSizeDS390)
2153 /* I don't think this case can ever happen... */
2154 /* ACC is the last part of this. If writing the result
2155 * uses AC, we must preserve it.
2157 if (AOP_NEEDSACC(oper))
2159 emitcode(";", "assignResultValue special case for ACC.");
2160 emitcode("push", "acc");
2167 _startLazyDPSEvaluation ();
2170 aopPut (AOP (oper), fReturn[offset], offset);
2173 _endLazyDPSEvaluation ();
2177 emitcode("pop", "acc");
2178 aopPut(AOP(oper), "a", offset);
2183 /*-----------------------------------------------------------------*/
2184 /* genXpush - pushes onto the external stack */
2185 /*-----------------------------------------------------------------*/
2187 genXpush (iCode * ic)
2189 asmop *aop = newAsmop (0);
2191 int size, offset = 0;
2193 D (emitcode (";", "genXpush ");
2196 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2197 r = getFreePtr (ic, &aop, FALSE);
2200 emitcode ("mov", "%s,_spx", r->name);
2202 size = AOP_SIZE (IC_LEFT (ic));
2203 _startLazyDPSEvaluation ();
2207 MOVA (aopGet (AOP (IC_LEFT (ic)),
2208 offset++, FALSE, FALSE, NULL));
2209 emitcode ("movx", "@%s,a", r->name);
2210 emitcode ("inc", "%s", r->name);
2213 _endLazyDPSEvaluation ();
2216 emitcode ("mov", "_spx,%s", r->name);
2218 freeAsmop (NULL, aop, ic, TRUE);
2219 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2222 /*-----------------------------------------------------------------*/
2223 /* genIpush - generate code for pushing this gets a little complex */
2224 /*-----------------------------------------------------------------*/
2226 genIpush (iCode * ic)
2228 int size, offset = 0;
2231 D (emitcode (";", "genIpush ");
2234 /* if this is not a parm push : ie. it is spill push
2235 and spill push is always done on the local stack */
2239 /* and the item is spilt then do nothing */
2240 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2243 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2244 size = AOP_SIZE (IC_LEFT (ic));
2245 /* push it on the stack */
2246 _startLazyDPSEvaluation ();
2249 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2255 emitcode ("push", "%s", l);
2257 _endLazyDPSEvaluation ();
2261 /* this is a paramter push: in this case we call
2262 the routine to find the call and save those
2263 registers that need to be saved */
2266 /* if use external stack then call the external
2267 stack pushing routine */
2268 if (options.useXstack)
2274 /* then do the push */
2275 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2277 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2278 size = AOP_SIZE (IC_LEFT (ic));
2280 _startLazyDPSEvaluation ();
2283 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2284 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2285 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2288 emitcode ("mov", "a,%s", l);
2289 emitcode ("push", "acc");
2293 emitcode ("push", "%s", l);
2296 _endLazyDPSEvaluation ();
2298 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2301 /*-----------------------------------------------------------------*/
2302 /* genIpop - recover the registers: can happen only for spilling */
2303 /*-----------------------------------------------------------------*/
2305 genIpop (iCode * ic)
2309 D (emitcode (";", "genIpop ");
2313 /* if the temp was not pushed then */
2314 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2317 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2318 size = AOP_SIZE (IC_LEFT (ic));
2319 offset = (size - 1);
2320 _startLazyDPSEvaluation ();
2323 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2324 FALSE, TRUE, NULL));
2326 _endLazyDPSEvaluation ();
2328 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2331 /*-----------------------------------------------------------------*/
2332 /* unsaveRBank - restores the resgister bank from stack */
2333 /*-----------------------------------------------------------------*/
2335 unsaveRBank (int bank, iCode * ic, bool popPsw)
2341 if (options.useXstack)
2345 /* Assume r0 is available for use. */
2346 r = ds390_regWithIdx (R0_IDX);;
2351 r = getFreePtr (ic, &aop, FALSE);
2353 emitcode ("mov", "%s,_spx", r->name);
2358 if (options.useXstack)
2360 emitcode ("movx", "a,@%s", r->name);
2361 emitcode ("mov", "psw,a");
2362 emitcode ("dec", "%s", r->name);
2366 emitcode ("pop", "psw");
2370 for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2372 if (options.useXstack)
2374 emitcode ("movx", "a,@%s", r->name);
2375 emitcode ("mov", "(%s+%d),a",
2376 regs390[i].base, 8 * bank + regs390[i].offset);
2377 emitcode ("dec", "%s", r->name);
2381 emitcode ("pop", "(%s+%d)",
2382 regs390[i].base, 8 * bank + regs390[i].offset);
2385 if (options.useXstack)
2387 emitcode ("mov", "_spx,%s", r->name);
2392 freeAsmop (NULL, aop, ic, TRUE);
2396 /*-----------------------------------------------------------------*/
2397 /* saveRBank - saves an entire register bank on the stack */
2398 /*-----------------------------------------------------------------*/
2400 saveRBank (int bank, iCode * ic, bool pushPsw)
2406 if (options.useXstack)
2410 /* Assume r0 is available for use. */
2411 r = ds390_regWithIdx (R0_IDX);;
2416 r = getFreePtr (ic, &aop, FALSE);
2418 emitcode ("mov", "%s,_spx", r->name);
2421 for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2423 if (options.useXstack)
2425 emitcode ("inc", "%s", r->name);
2426 emitcode ("mov", "a,(%s+%d)",
2427 regs390[i].base, 8 * bank + regs390[i].offset);
2428 emitcode ("movx", "@%s,a", r->name);
2431 emitcode ("push", "(%s+%d)",
2432 regs390[i].base, 8 * bank + regs390[i].offset);
2437 if (options.useXstack)
2439 emitcode ("mov", "a,psw");
2440 emitcode ("movx", "@%s,a", r->name);
2441 emitcode ("inc", "%s", r->name);
2442 emitcode ("mov", "_spx,%s", r->name);
2446 emitcode ("push", "psw");
2449 emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2454 freeAsmop (NULL, aop, ic, TRUE);
2463 /*-----------------------------------------------------------------*/
2464 /* genSend - gen code for SEND */
2465 /*-----------------------------------------------------------------*/
2466 static void genSend(set *sendSet)
2470 static int rb1_count = 0;
2472 for (sic = setFirstItem (sendSet); sic;
2473 sic = setNextItem (sendSet)) {
2474 int size, offset = 0;
2476 size=getSize(operandType(IC_LEFT(sic)));
2477 D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2478 if (sendCount == 0) { /* first parameter */
2479 // we know that dpl(hxb) is the result, so
2481 _startLazyDPSEvaluation ();
2483 aopOp (IC_LEFT (sic), sic, FALSE,
2484 (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2486 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2489 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2490 FALSE, FALSE, NULL);
2491 if (strcmp (l, fReturn[offset])) {
2492 emitcode ("mov", "%s,%s",
2498 _endLazyDPSEvaluation ();
2499 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2501 } else { /* if more parameter in registers */
2502 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2504 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
2505 FALSE, FALSE, NULL));
2507 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2513 /*-----------------------------------------------------------------*/
2514 /* genCall - generates a call statement */
2515 /*-----------------------------------------------------------------*/
2517 genCall (iCode * ic)
2520 bool restoreBank = FALSE;
2521 bool swapBanks = FALSE;
2523 D (emitcode (";", "genCall "););
2525 /* if we are calling a not _naked function that is not using
2526 the same register bank then we need to save the
2527 destination registers on the stack */
2528 dtype = operandType (IC_LEFT (ic));
2529 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2530 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2531 IFFUNC_ISISR (currFunc->type))
2535 /* This is unexpected; the bank should have been saved in
2538 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2544 /* if caller saves & we have not saved then */
2548 /* if send set is not empty the assign */
2549 /* We've saved all the registers we care about;
2550 * therefore, we may clobber any register not used
2551 * in the calling convention (i.e. anything not in
2556 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2557 genSend(reverseSet(_G.sendSet));
2559 genSend(_G.sendSet);
2566 emitcode ("mov", "psw,#!constbyte",
2567 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2571 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2572 OP_SYMBOL (IC_LEFT (ic))->rname :
2573 OP_SYMBOL (IC_LEFT (ic))->name));
2577 emitcode ("mov", "psw,#!constbyte",
2578 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2581 /* if we need assign a result value */
2582 if ((IS_ITEMP (IC_RESULT (ic)) &&
2583 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2584 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2585 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2586 IS_TRUE_SYMOP (IC_RESULT (ic)))
2588 if (isOperandInFarSpace (IC_RESULT (ic))
2589 && getSize (operandType (IC_RESULT (ic))) <= 2)
2591 int size = getSize (operandType (IC_RESULT (ic)));
2593 /* Special case for 1 or 2 byte return in far space. */
2597 emitcode ("mov", "b,%s", fReturn[1]);
2600 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2601 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2605 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2607 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2612 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2615 assignResultValue (IC_RESULT (ic));
2617 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2621 /* adjust the stack for parameters if
2623 if (ic->parmBytes) {
2625 if (options.stack10bit) {
2626 if (ic->parmBytes <= 10) {
2627 emitcode(";","stack adjustment for parms");
2628 for (i=0; i < ic->parmBytes ; i++) {
2629 emitcode("pop","acc");
2633 emitcode ("clr","c");
2634 emitcode ("mov","a,sp");
2635 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2636 emitcode ("mov","sp,a");
2637 emitcode ("mov","a,esp");
2638 emitcode ("anl","a,#3");
2639 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2640 emitcode ("mov","esp,a");
2644 if (ic->parmBytes > 3) {
2645 emitcode ("mov", "a,%s", spname);
2646 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2647 emitcode ("mov", "%s,a", spname);
2649 for (i = 0; i < ic->parmBytes; i++)
2650 emitcode ("dec", "%s", spname);
2654 /* if we hade saved some registers then unsave them */
2656 unsaveRegisters (ic);
2658 /* if register bank was saved then pop them */
2660 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2663 /*-----------------------------------------------------------------*/
2664 /* genPcall - generates a call by pointer statement */
2665 /*-----------------------------------------------------------------*/
2667 genPcall (iCode * ic)
2670 symbol *rlbl = newiTempLabel (NULL);
2671 bool restoreBank=FALSE;
2673 D (emitcode (";", "genPcall ");
2677 /* if caller saves & we have not saved then */
2681 /* if we are calling a function that is not using
2682 the same register bank then we need to save the
2683 destination registers on the stack */
2684 dtype = operandType (IC_LEFT (ic));
2685 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2686 IFFUNC_ISISR (currFunc->type) &&
2687 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2688 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2692 /* push the return address on to the stack */
2693 emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2694 emitcode ("push", "acc");
2695 emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2696 emitcode ("push", "acc");
2698 if (options.model == MODEL_FLAT24)
2700 emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2701 emitcode ("push", "acc");
2704 /* now push the calling address */
2705 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2707 pushSide (IC_LEFT (ic), FPTRSIZE);
2709 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2711 /* if send set is not empty the assign */
2714 genSend(reverseSet(_G.sendSet));
2718 emitcode ("ret", "");
2719 emitcode ("", "!tlabeldef", (rlbl->key + 100));
2722 /* if we need assign a result value */
2723 if ((IS_ITEMP (IC_RESULT (ic)) &&
2724 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2725 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2726 IS_TRUE_SYMOP (IC_RESULT (ic)))
2730 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2733 assignResultValue (IC_RESULT (ic));
2735 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2738 /* adjust the stack for parameters if
2743 if (options.stack10bit) {
2744 if (ic->parmBytes <= 10) {
2745 emitcode(";","stack adjustment for parms");
2746 for (i=0; i < ic->parmBytes ; i++) {
2747 emitcode("pop","acc");
2751 emitcode ("clr","c");
2752 emitcode ("mov","a,sp");
2753 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2754 emitcode ("mov","sp,a");
2755 emitcode ("mov","a,esp");
2756 emitcode ("anl","a,#3");
2757 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2758 emitcode ("mov","esp,a");
2762 if (ic->parmBytes > 3) {
2763 emitcode ("mov", "a,%s", spname);
2764 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2765 emitcode ("mov", "%s,a", spname);
2768 for (i = 0; i < ic->parmBytes; i++)
2769 emitcode ("dec", "%s", spname);
2773 /* if register bank was saved then unsave them */
2775 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2777 /* if we hade saved some registers then
2780 unsaveRegisters (ic);
2784 /*-----------------------------------------------------------------*/
2785 /* resultRemat - result is rematerializable */
2786 /*-----------------------------------------------------------------*/
2788 resultRemat (iCode * ic)
2790 if (SKIP_IC (ic) || ic->op == IFX)
2793 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2795 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2796 if (sym->remat && !POINTER_SET (ic))
2803 #if defined(__BORLANDC__) || defined(_MSC_VER)
2804 #define STRCASECMP stricmp
2806 #define STRCASECMP strcasecmp
2809 /*-----------------------------------------------------------------*/
2810 /* inExcludeList - return 1 if the string is in exclude Reg list */
2811 /*-----------------------------------------------------------------*/
2813 inExcludeList (char *s)
2817 if (options.excludeRegs[i] &&
2818 STRCASECMP (options.excludeRegs[i], "none") == 0)
2821 for (i = 0; options.excludeRegs[i]; i++)
2823 if (options.excludeRegs[i] &&
2824 STRCASECMP (s, options.excludeRegs[i]) == 0)
2830 /*-----------------------------------------------------------------*/
2831 /* genFunction - generated code for function entry */
2832 /*-----------------------------------------------------------------*/
2834 genFunction (iCode * ic)
2838 bool switchedPSW = FALSE;
2840 D (emitcode (";", "genFunction "););
2843 /* create the function header */
2844 emitcode (";", "-----------------------------------------");
2845 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2846 emitcode (";", "-----------------------------------------");
2848 emitcode ("", "%s:", sym->rname);
2849 ftype = operandType (IC_LEFT (ic));
2851 if (IFFUNC_ISNAKED(ftype))
2853 emitcode(";", "naked function: no prologue.");
2857 if (options.stack_probe)
2858 emitcode ("lcall","__stack_probe");
2859 /* if critical function then turn interrupts off */
2860 if (IFFUNC_ISCRITICAL (ftype))
2861 emitcode ("clr", "ea");
2863 /* here we need to generate the equates for the
2864 register bank if required */
2865 if (FUNC_REGBANK (ftype) != rbank)
2869 rbank = FUNC_REGBANK (ftype);
2870 for (i = 0; i < ds390_nRegs; i++)
2872 if (regs390[i].print) {
2873 if (strcmp (regs390[i].base, "0") == 0)
2874 emitcode ("", "%s !equ !constbyte",
2876 8 * rbank + regs390[i].offset);
2878 emitcode ("", "%s !equ %s + !constbyte",
2881 8 * rbank + regs390[i].offset);
2886 /* if this is an interrupt service routine then
2887 save acc, b, dpl, dph */
2888 if (IFFUNC_ISISR (sym->type))
2890 if (!inExcludeList ("acc"))
2891 emitcode ("push", "acc");
2892 if (!inExcludeList ("b"))
2893 emitcode ("push", "b");
2894 if (!inExcludeList ("dpl"))
2895 emitcode ("push", "dpl");
2896 if (!inExcludeList ("dph"))
2897 emitcode ("push", "dph");
2898 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2900 emitcode ("push", "dpx");
2901 /* Make sure we're using standard DPTR */
2902 emitcode ("push", "dps");
2903 emitcode ("mov", "dps,#0");
2904 if (options.stack10bit)
2906 /* This ISR could conceivably use DPTR2. Better save it. */
2907 emitcode ("push", "dpl1");
2908 emitcode ("push", "dph1");
2909 emitcode ("push", "dpx1");
2910 emitcode ("push", DP2_RESULT_REG);
2913 /* if this isr has no bank i.e. is going to
2914 run with bank 0 , then we need to save more
2916 if (!FUNC_REGBANK (sym->type))
2920 /* if this function does not call any other
2921 function then we can be economical and
2922 save only those registers that are used */
2923 if (!IFFUNC_HASFCALL(sym->type))
2926 /* if any registers used */
2929 /* save the registers used */
2930 for (i = 0; i < sym->regsUsed->size; i++)
2932 if (bitVectBitValue (sym->regsUsed, i) ||
2933 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2934 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2941 /* this function has a function call cannot
2942 determines register usage so we will have to push the
2944 saveRBank (0, ic, FALSE);
2945 if (options.parms_in_bank1) {
2946 for (i=0; i < 8 ; i++ ) {
2947 emitcode ("push","%s",rb1regs[i]);
2954 /* This ISR uses a non-zero bank.
2956 * We assume that the bank is available for our
2959 * However, if this ISR calls a function which uses some
2960 * other bank, we must save that bank entirely.
2962 unsigned long banksToSave = 0;
2964 if (IFFUNC_HASFCALL(sym->type))
2967 #define MAX_REGISTER_BANKS 4
2972 for (i = ic; i; i = i->next)
2974 if (i->op == ENDFUNCTION)
2976 /* we got to the end OK. */
2984 dtype = operandType (IC_LEFT(i));
2986 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2988 /* Mark this bank for saving. */
2989 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2991 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2995 banksToSave |= (1 << FUNC_REGBANK(dtype));
2998 /* And note that we don't need to do it in
3006 /* This is a mess; we have no idea what
3007 * register bank the called function might
3010 * The only thing I can think of to do is
3011 * throw a warning and hope.
3013 werror(W_FUNCPTR_IN_USING_ISR);
3017 if (banksToSave && options.useXstack)
3019 /* Since we aren't passing it an ic,
3020 * saveRBank will assume r0 is available to abuse.
3022 * So switch to our (trashable) bank now, so
3023 * the caller's R0 isn't trashed.
3025 emitcode ("push", "psw");
3026 emitcode ("mov", "psw,#!constbyte",
3027 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3031 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3033 if (banksToSave & (1 << ix))
3035 saveRBank(ix, NULL, FALSE);
3039 // TODO: this needs a closer look
3040 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3045 /* if callee-save to be used for this function
3046 then save the registers being used in this function */
3047 if (IFFUNC_CALLEESAVES(sym->type))
3051 /* if any registers used */
3054 /* save the registers used */
3055 for (i = 0; i < sym->regsUsed->size; i++)
3057 if (bitVectBitValue (sym->regsUsed, i) ||
3058 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3060 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3068 /* set the register bank to the desired value */
3069 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3072 emitcode ("push", "psw");
3073 emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3076 if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3077 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3078 if (options.stack10bit) {
3079 emitcode ("push","_bpx");
3080 emitcode ("push","_bpx+1");
3081 emitcode ("mov","_bpx,%s",spname);
3082 emitcode ("mov","_bpx+1,esp");
3083 emitcode ("anl","_bpx+1,#3");
3085 if (options.useXstack) {
3086 emitcode ("mov", "r0,%s", spname);
3087 emitcode ("mov", "a,_bp");
3088 emitcode ("movx", "@r0,a");
3089 emitcode ("inc", "%s", spname);
3091 /* set up the stack */
3092 emitcode ("push", "_bp"); /* save the callers stack */
3094 emitcode ("mov", "_bp,%s", spname);
3098 /* adjust the stack for the function */
3101 if (options.stack10bit) {
3102 if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
3103 assert (sym->recvSize <= 4);
3104 if (sym->stack <= 8) {
3105 while (i--) emitcode ("push","acc");
3108 emitcode ("mov","a,sp");
3109 emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3110 emitcode ("mov","sp,a");
3111 emitcode ("mov","a,esp");
3112 emitcode ("anl","a,#3");
3113 emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3114 emitcode ("mov","esp,a");
3119 werror (W_STACK_OVERFLOW, sym->name);
3121 if (i > 3 && sym->recvSize < 4) {
3123 emitcode ("mov", "a,sp");
3124 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3125 emitcode ("mov", "sp,a");
3129 emitcode ("inc", "sp");
3136 emitcode ("mov", "a,_spx");
3137 emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3138 emitcode ("mov", "_spx,a");
3143 /*-----------------------------------------------------------------*/
3144 /* genEndFunction - generates epilogue for functions */
3145 /*-----------------------------------------------------------------*/
3147 genEndFunction (iCode * ic)
3149 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3151 D (emitcode (";", "genEndFunction "););
3153 if (IFFUNC_ISNAKED(sym->type))
3155 emitcode(";", "naked function: no epilogue.");
3159 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3160 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3162 if (options.stack10bit) {
3164 emitcode ("mov", "sp,_bpx", spname);
3165 emitcode ("mov", "esp,_bpx+1", spname);
3168 emitcode ("mov", "%s,_bp", spname);
3172 /* if use external stack but some variables were
3173 added to the local stack then decrement the
3175 if (options.useXstack && sym->stack) {
3176 emitcode ("mov", "a,sp");
3177 emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3178 emitcode ("mov", "sp,a");
3182 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3183 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3185 if (options.useXstack) {
3186 emitcode ("mov", "r0,%s", spname);
3187 emitcode ("movx", "a,@r0");
3188 emitcode ("mov", "_bp,a");
3189 emitcode ("dec", "%s", spname);
3191 if (options.stack10bit) {
3192 emitcode ("pop", "_bpx+1");
3193 emitcode ("pop", "_bpx");
3195 emitcode ("pop", "_bp");
3200 /* restore the register bank */
3201 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3203 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3204 || !options.useXstack)
3206 /* Special case of ISR using non-zero bank with useXstack
3209 emitcode ("pop", "psw");
3213 if (IFFUNC_ISISR (sym->type))
3216 /* now we need to restore the registers */
3217 /* if this isr has no bank i.e. is going to
3218 run with bank 0 , then we need to save more
3220 if (!FUNC_REGBANK (sym->type))
3223 /* if this function does not call any other
3224 function then we can be economical and
3225 save only those registers that are used */
3226 if (!IFFUNC_HASFCALL(sym->type))
3229 /* if any registers used */
3232 /* save the registers used */
3233 for (i = sym->regsUsed->size; i >= 0; i--)
3235 if (bitVectBitValue (sym->regsUsed, i) ||
3236 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3237 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3244 /* this function has a function call cannot
3245 determines register usage so we will have to pop the
3247 if (options.parms_in_bank1) {
3248 for (i = 7 ; i >= 0 ; i-- ) {
3249 emitcode ("pop","%s",rb1regs[i]);
3252 unsaveRBank (0, ic, FALSE);
3257 /* This ISR uses a non-zero bank.
3259 * Restore any register banks saved by genFunction
3262 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3265 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3267 if (savedBanks & (1 << ix))
3269 unsaveRBank(ix, NULL, FALSE);
3273 if (options.useXstack)
3275 /* Restore bank AFTER calling unsaveRBank,
3276 * since it can trash r0.
3278 emitcode ("pop", "psw");
3282 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3284 if (options.stack10bit)
3286 emitcode ("pop", DP2_RESULT_REG);
3287 emitcode ("pop", "dpx1");
3288 emitcode ("pop", "dph1");
3289 emitcode ("pop", "dpl1");
3291 emitcode ("pop", "dps");
3292 emitcode ("pop", "dpx");
3294 if (!inExcludeList ("dph"))
3295 emitcode ("pop", "dph");
3296 if (!inExcludeList ("dpl"))
3297 emitcode ("pop", "dpl");
3298 if (!inExcludeList ("b"))
3299 emitcode ("pop", "b");
3300 if (!inExcludeList ("acc"))
3301 emitcode ("pop", "acc");
3303 if (IFFUNC_ISCRITICAL (sym->type))
3304 emitcode ("setb", "ea");
3306 /* if debug then send end of function */
3307 if (options.debug && currFunc) {
3309 emitcode ("", "C$%s$%d$%d$%d ==.",
3310 FileBaseName (ic->filename), currFunc->lastLine,
3311 ic->level, ic->block);
3312 if (IS_STATIC (currFunc->etype))
3313 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3315 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3319 emitcode ("reti", "");
3323 if (IFFUNC_ISCRITICAL (sym->type))
3324 emitcode ("setb", "ea");
3326 if (IFFUNC_CALLEESAVES(sym->type))
3330 /* if any registers used */
3333 /* save the registers used */
3334 for (i = sym->regsUsed->size; i >= 0; i--)
3336 if (bitVectBitValue (sym->regsUsed, i) ||
3337 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3338 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3344 /* if debug then send end of function */
3345 if (options.debug && currFunc)
3348 emitcode ("", "C$%s$%d$%d$%d ==.",
3349 FileBaseName (ic->filename), currFunc->lastLine,
3350 ic->level, ic->block);
3351 if (IS_STATIC (currFunc->etype))
3352 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3354 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3358 emitcode ("ret", "");
3363 /*-----------------------------------------------------------------*/
3364 /* genJavaNativeRet - generate code for return JavaNative */
3365 /*-----------------------------------------------------------------*/
3366 static void genJavaNativeRet(iCode *ic)
3370 aopOp (IC_LEFT (ic), ic, FALSE,
3371 AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
3372 size = AOP_SIZE (IC_LEFT (ic));
3376 /* it is assigned to GPR0-R3 then push them */
3377 if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3378 aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3379 for (i = 0 ; i < size ; i++ ) {
3380 emitcode ("push","%s",
3381 aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3383 for (i = (size-1) ; i >= 0 ; i--) {
3384 emitcode ("pop","a%s",javaRet[i]);
3387 for (i = 0 ; i < size ; i++)
3388 emitcode ("mov","%s,%s",javaRet[i],
3389 aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3391 for (i = size ; i < 4 ; i++ )
3392 emitcode ("mov","%s,#0",javaRet[i]);
3396 /*-----------------------------------------------------------------*/
3397 /* genRet - generate code for return statement */
3398 /*-----------------------------------------------------------------*/
3402 int size, offset = 0, pushed = 0;
3404 D (emitcode (";", "genRet "););
3406 /* if we have no return value then
3407 just generate the "ret" */
3411 /* if this is a JavaNative function then return
3412 value in different register */
3413 if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3414 genJavaNativeRet(ic);
3417 /* we have something to return then
3418 move the return value into place */
3419 aopOp (IC_LEFT (ic), ic, FALSE,
3420 (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
3421 size = AOP_SIZE (IC_LEFT (ic));
3423 _startLazyDPSEvaluation ();
3427 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3429 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3431 emitcode ("push", "%s", l);
3436 /* Since A is the last element of fReturn,
3437 * is is OK to clobber it in the aopGet.
3439 l = aopGet (AOP (IC_LEFT (ic)), offset,
3440 FALSE, FALSE, NULL);
3441 if (strcmp (fReturn[offset], l))
3442 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3445 _endLazyDPSEvaluation ();
3452 if (strcmp (fReturn[pushed], "a"))
3453 emitcode ("pop", fReturn[pushed]);
3455 emitcode ("pop", "acc");
3458 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3461 /* generate a jump to the return label
3462 if the next is not the return statement */
3463 if (!(ic->next && ic->next->op == LABEL &&
3464 IC_LABEL (ic->next) == returnLabel))
3466 emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3470 /*-----------------------------------------------------------------*/
3471 /* genLabel - generates a label */
3472 /*-----------------------------------------------------------------*/
3474 genLabel (iCode * ic)
3476 /* special case never generate */
3477 if (IC_LABEL (ic) == entryLabel)
3480 D (emitcode (";", "genLabel ");
3483 emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3486 /*-----------------------------------------------------------------*/
3487 /* genGoto - generates a ljmp */
3488 /*-----------------------------------------------------------------*/
3490 genGoto (iCode * ic)
3492 D (emitcode (";", "genGoto ");
3494 emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3497 /*-----------------------------------------------------------------*/
3498 /* findLabelBackwards: walks back through the iCode chain looking */
3499 /* for the given label. Returns number of iCode instructions */
3500 /* between that label and given ic. */
3501 /* Returns zero if label not found. */
3502 /*-----------------------------------------------------------------*/
3504 findLabelBackwards (iCode * ic, int key)
3513 /* If we have any pushes or pops, we cannot predict the distance.
3514 I don't like this at all, this should be dealt with in the
3516 if (ic->op == IPUSH || ic->op == IPOP) {
3520 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3522 /* printf("findLabelBackwards = %d\n", count); */
3530 /*-----------------------------------------------------------------*/
3531 /* genPlusIncr :- does addition with increment if possible */
3532 /*-----------------------------------------------------------------*/
3534 genPlusIncr (iCode * ic)
3536 unsigned int icount;
3537 unsigned int size = getDataSize (IC_RESULT (ic));
3539 /* will try to generate an increment */
3540 /* if the right side is not a literal
3542 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3545 /* if the literal value of the right hand side
3546 is greater than 4 then it is not worth it */
3547 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3550 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3551 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3553 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
3557 /* if increment 16 bits in register */
3559 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3560 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3561 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3570 /* If the next instruction is a goto and the goto target
3571 * is <= 5 instructions previous to this, we can generate
3572 * jumps straight to that target.
3574 if (ic->next && ic->next->op == GOTO
3575 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3578 D(emitcode (";", "tail increment optimized (range %d)", labelRange););
3579 tlbl = IC_LABEL (ic->next);
3584 tlbl = newiTempLabel (NULL);
3588 l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
3589 emitcode ("inc", "%s", l);
3591 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3592 IS_AOP_PREG (IC_RESULT (ic)))
3594 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3598 emitcode ("clr", "a");
3599 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3602 l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
3603 emitcode ("inc", "%s", l);
3606 if (!strcmp(l, "acc"))
3608 emitcode("jnz", "!tlabel", tlbl->key + 100);
3610 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3611 IS_AOP_PREG (IC_RESULT (ic)))
3613 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3617 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3620 l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
3621 emitcode ("inc", "%s", l);
3625 if (!strcmp(l, "acc"))
3627 emitcode("jnz", "!tlabel", tlbl->key + 100);
3629 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3630 IS_AOP_PREG (IC_RESULT (ic)))
3632 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3636 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3639 l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
3640 emitcode ("inc", "%s", l); }
3644 emitcode ("", "!tlabeldef", tlbl->key + 100);
3649 if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3650 !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 &&
3651 options.model == MODEL_FLAT24 ) {
3655 emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, NULL));
3657 emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, NULL));
3659 emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3662 while (icount--) emitcode ("inc","dptr");
3666 if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3667 AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3669 emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3670 while (icount--) emitcode ("inc","dptr");
3671 emitcode ("mov","dps,#0");
3675 /* if the sizes are greater than 1 then we cannot */
3676 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3677 AOP_SIZE (IC_LEFT (ic)) > 1)
3680 /* we can if the aops of the left & result match or
3681 if they are in registers and the registers are the
3684 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3685 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3686 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3691 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3692 emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3693 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3698 _startLazyDPSEvaluation ();
3701 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3703 _endLazyDPSEvaluation ();
3712 /*-----------------------------------------------------------------*/
3713 /* outBitAcc - output a bit in acc */
3714 /*-----------------------------------------------------------------*/
3716 outBitAcc (operand * result)
3718 symbol *tlbl = newiTempLabel (NULL);
3719 /* if the result is a bit */
3720 if (AOP_TYPE (result) == AOP_CRY)
3722 aopPut (AOP (result), "a", 0);
3726 emitcode ("jz", "!tlabel", tlbl->key + 100);
3727 emitcode ("mov", "a,%s", one);
3728 emitcode ("", "!tlabeldef", tlbl->key + 100);
3733 /*-----------------------------------------------------------------*/
3734 /* genPlusBits - generates code for addition of two bits */
3735 /*-----------------------------------------------------------------*/
3737 genPlusBits (iCode * ic)
3739 D (emitcode (";", "genPlusBits "););
3741 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3743 symbol *lbl = newiTempLabel (NULL);
3744 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3745 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3746 emitcode ("cpl", "c");
3747 emitcode ("", "!tlabeldef", (lbl->key + 100));
3748 outBitC (IC_RESULT (ic));
3752 emitcode ("clr", "a");
3753 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3754 emitcode ("rlc", "a");
3755 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3756 emitcode ("addc", "a,#0");
3757 outAcc (IC_RESULT (ic));
3762 adjustArithmeticResult (iCode * ic)
3764 if (opIsGptr (IC_RESULT (ic)) &&
3765 opIsGptr (IC_LEFT (ic)) &&
3766 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3768 aopPut (AOP (IC_RESULT (ic)),
3769 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3773 if (opIsGptr (IC_RESULT (ic)) &&
3774 opIsGptr (IC_RIGHT (ic)) &&
3775 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3777 aopPut (AOP (IC_RESULT (ic)),
3778 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3782 if (opIsGptr (IC_RESULT (ic)) &&
3783 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3784 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3785 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3786 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3789 SNPRINTF (buff, sizeof(buff),
3790 "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3791 aopPut (AOP (IC_RESULT (ic)), buff, GPTRSIZE - 1);
3795 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
3796 // generates the result if possible. If result is generated, returns TRUE; otherwise
3797 // returns false and caller must deal with fact that result isn't aopOp'd.
3798 bool aopOp3(iCode * ic)
3800 bool dp1InUse, dp2InUse;
3803 // First, generate the right opcode. DPTR may be used if neither left nor result are
3806 // D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
3807 // AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
3808 // AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
3809 // AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
3811 // D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
3812 // AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
3813 // AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
3814 // AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
3817 // Right uses DPTR unless left or result is an AOP_STR; however,
3818 // if right is an AOP_STR, it must use DPTR regardless.
3819 if ((AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)))
3820 && !AOP_IS_STR(IC_RIGHT(ic)))
3829 aopOp (IC_RIGHT(ic),ic,FALSE, useDp2);
3831 // if the right used DPTR, left MUST use DPTR2.
3832 // if the right used DPTR2, left MUST use DPTR.
3833 // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
3834 // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
3835 // enabling us to assign DPTR to result.
3837 if (AOP_USESDPTR(IC_RIGHT(ic)))
3841 else if (AOP_USESDPTR2(IC_RIGHT(ic)))
3847 if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
3857 aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
3859 // We've op'd the left & right. So, if left or right are the same operand as result,
3860 // we know aopOp will succeed, and we can just do it & bail.
3861 if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)) ||
3862 isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
3864 // D(emitcode(";", "aopOp3: (left | right) & result equal"););
3865 aopOp(IC_RESULT(ic),ic,TRUE, FALSE);
3869 // Note which dptrs are currently in use.
3870 dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
3871 dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
3873 // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot
3875 if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
3880 // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
3881 if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
3886 // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck
3887 if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
3892 aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
3894 // Some sanity checking...
3895 if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
3898 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
3899 __FILE__, __LINE__, ic->filename, ic->lineno);
3900 emitcode(";", ">>> unexpected DPTR here.");
3903 if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
3906 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
3907 __FILE__, __LINE__, ic->filename, ic->lineno);
3908 emitcode(";", ">>> unexpected DPTR2 here.");
3914 // Macro to aopOp all three operands of an ic. If this cannot be done,
3915 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3916 // will be set TRUE. The caller must then handle the case specially, noting
3917 // that the IC_RESULT operand is not aopOp'd.
3919 #define AOP_OP_3_NOFATAL(ic, rc) \
3920 do { rc = !aopOp3(ic); } while (0)
3922 // aopOp the left & right operands of an ic.
3923 #define AOP_OP_2(ic) \
3924 aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
3925 aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
3927 // convienience macro.
3928 #define AOP_SET_LOCALS(ic) \
3929 left = IC_LEFT(ic); \
3930 right = IC_RIGHT(ic); \
3931 result = IC_RESULT(ic);
3934 // Given an integer value of pushedSize bytes on the stack,
3935 // adjust it to be resultSize bytes, either by discarding
3936 // the most significant bytes or by zero-padding.
3938 // On exit from this macro, pushedSize will have been adjusted to
3939 // equal resultSize, and ACC may be trashed.
3940 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3941 /* If the pushed data is bigger than the result, \
3942 * simply discard unused bytes. Icky, but works. \
3944 while (pushedSize > resultSize) \
3946 D (emitcode (";", "discarding unused result byte."););\
3947 emitcode ("pop", "acc"); \
3950 if (pushedSize < resultSize) \
3952 emitcode ("clr", "a"); \
3953 /* Conversly, we haven't pushed enough here. \
3954 * just zero-pad, and all is well. \
3956 while (pushedSize < resultSize) \
3958 emitcode("push", "acc"); \
3962 assert(pushedSize == resultSize);
3964 /*-----------------------------------------------------------------*/
3965 /* genPlus - generates code for addition */
3966 /*-----------------------------------------------------------------*/
3968 genPlus (iCode * ic)
3970 int size, offset = 0;
3974 D (emitcode (";", "genPlus "););
3976 /* special cases :- */
3977 if ( AOP_IS_STR(IC_LEFT(ic)) &&
3978 isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
3979 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
3980 size = floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
3982 while (size--) emitcode ("inc","dptr");
3984 emitcode ("mov","a,dpl");
3985 emitcode ("add","a,#!constbyte",size & 0xff);
3986 emitcode ("mov","dpl,a");
3987 emitcode ("mov","a,dph");
3988 emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
3989 emitcode ("mov","dph,a");
3990 emitcode ("mov","a,dpx");
3991 emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
3992 emitcode ("mov","dpx,a");
3994 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
3997 if ( IS_SYMOP(IC_LEFT(ic)) &&
3998 OP_SYMBOL(IC_LEFT(ic))->remat &&
3999 isOperandInFarSpace(IC_RIGHT(ic))) {
4000 operand *op = IC_RIGHT(ic);
4001 IC_RIGHT(ic) = IC_LEFT(ic);
4005 AOP_OP_3_NOFATAL (ic, pushResult);
4009 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
4014 /* if literal, literal on the right or
4015 if left requires ACC or right is already
4017 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4018 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
4019 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4021 operand *t = IC_RIGHT (ic);
4022 IC_RIGHT (ic) = IC_LEFT (ic);
4024 emitcode (";", "Swapped plus args.");
4027 /* if both left & right are in bit
4029 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4030 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4036 /* if left in bit space & right literal */
4037 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4038 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4040 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4041 /* if result in bit space */
4042 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4044 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4045 emitcode ("cpl", "c");
4046 outBitC (IC_RESULT (ic));
4050 size = getDataSize (IC_RESULT (ic));
4051 _startLazyDPSEvaluation ();
4054 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4055 emitcode ("addc", "a,#0");
4056 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4058 _endLazyDPSEvaluation ();
4063 /* if I can do an increment instead
4064 of add then GOOD for ME */
4065 if (genPlusIncr (ic) == TRUE)
4067 emitcode (";", "did genPlusIncr");
4072 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4074 _startLazyDPSEvaluation ();
4077 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4079 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4081 emitcode ("add", "a,%s",
4082 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4084 emitcode ("addc", "a,%s",
4085 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4089 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4091 /* right is going to use ACC or we would have taken the
4094 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4096 D(emitcode(";", "+ AOP_ACC special case."););
4097 emitcode("xch", "a, %s", DP2_RESULT_REG);
4099 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4102 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4105 emitcode("add", "a, %s", DP2_RESULT_REG);
4109 emitcode ("add", "a,%s",
4110 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE,
4116 emitcode ("addc", "a,%s",
4117 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE,
4123 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4127 emitcode ("push", "acc");
4131 _endLazyDPSEvaluation ();
4135 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4137 size = getDataSize (IC_LEFT (ic));
4138 rSize = getDataSize (IC_RESULT (ic));
4140 ADJUST_PUSHED_RESULT(size, rSize);
4142 _startLazyDPSEvaluation ();
4145 emitcode ("pop", "acc");
4146 aopPut (AOP (IC_RESULT (ic)), "a", size);
4148 _endLazyDPSEvaluation ();
4151 adjustArithmeticResult (ic);
4154 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4155 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4156 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4159 /*-----------------------------------------------------------------*/
4160 /* genMinusDec :- does subtraction with deccrement if possible */
4161 /*-----------------------------------------------------------------*/
4163 genMinusDec (iCode * ic)
4165 unsigned int icount;
4166 unsigned int size = getDataSize (IC_RESULT (ic));
4168 /* will try to generate an increment */
4169 /* if the right side is not a literal
4171 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4174 /* if the literal value of the right hand side
4175 is greater than 4 then it is not worth it */
4176 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4179 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4180 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4182 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
4186 /* if decrement 16 bits in register */
4187 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4188 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4189 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4198 /* If the next instruction is a goto and the goto target
4199 * is <= 5 instructions previous to this, we can generate
4200 * jumps straight to that target.
4202 if (ic->next && ic->next->op == GOTO
4203 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4206 emitcode (";", "tail decrement optimized (range %d)", labelRange);
4207 tlbl = IC_LABEL (ic->next);
4212 tlbl = newiTempLabel (NULL);
4216 l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
4217 emitcode ("dec", "%s", l);
4219 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4220 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4221 IS_AOP_PREG (IC_RESULT (ic)))
4223 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4227 emitcode ("mov", "a,#!constbyte",0xff);
4228 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4230 l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
4231 emitcode ("dec", "%s", l);
4234 if (!strcmp(l, "acc"))
4236 emitcode("jnz", "!tlabel", tlbl->key + 100);
4238 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4239 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4240 IS_AOP_PREG (IC_RESULT (ic)))
4242 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4246 emitcode ("mov", "a,#!constbyte",0xff);
4247 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4249 l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
4250 emitcode ("dec", "%s", l);
4254 if (!strcmp(l, "acc"))
4256 emitcode("jnz", "!tlabel", tlbl->key + 100);
4258 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4259 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4260 IS_AOP_PREG (IC_RESULT (ic)))
4262 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4266 emitcode ("mov", "a,#!constbyte",0xff);
4267 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4269 l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
4270 emitcode ("dec", "%s", l);
4274 emitcode ("", "!tlabeldef", tlbl->key + 100);
4279 /* if the sizes are greater than 1 then we cannot */
4280 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4281 AOP_SIZE (IC_LEFT (ic)) > 1)
4284 /* we can if the aops of the left & result match or
4285 if they are in registers and the registers are the
4288 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4289 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4290 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4293 _startLazyDPSEvaluation ();
4296 emitcode ("dec", "%s",
4297 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
4299 _endLazyDPSEvaluation ();
4307 /*-----------------------------------------------------------------*/
4308 /* addSign - complete with sign */
4309 /*-----------------------------------------------------------------*/
4311 addSign (operand * result, int offset, int sign)
4313 int size = (getDataSize (result) - offset);
4316 _startLazyDPSEvaluation();
4319 emitcode ("rlc", "a");
4320 emitcode ("subb", "a,acc");
4323 aopPut (AOP (result), "a", offset++);
4330 aopPut (AOP (result), zero, offset++);
4333 _endLazyDPSEvaluation();
4337 /*-----------------------------------------------------------------*/
4338 /* genMinusBits - generates code for subtraction of two bits */
4339 /*-----------------------------------------------------------------*/
4341 genMinusBits (iCode * ic)
4343 symbol *lbl = newiTempLabel (NULL);
4345 D (emitcode (";", "genMinusBits "););
4347 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4349 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4350 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4351 emitcode ("cpl", "c");
4352 emitcode ("", "!tlabeldef", (lbl->key + 100));
4353 outBitC (IC_RESULT (ic));
4357 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4358 emitcode ("subb", "a,acc");
4359 emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4360 emitcode ("inc", "a");
4361 emitcode ("", "!tlabeldef", (lbl->key + 100));
4362 aopPut (AOP (IC_RESULT (ic)), "a", 0);
4363 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4367 /*-----------------------------------------------------------------*/
4368 /* genMinus - generates code for subtraction */
4369 /*-----------------------------------------------------------------*/
4371 genMinus (iCode * ic)
4373 int size, offset = 0;
4378 D (emitcode (";", "genMinus "););
4380 AOP_OP_3_NOFATAL(ic, pushResult);
4384 /* special cases :- */
4385 /* if both left & right are in bit space */
4386 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4387 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4393 /* if I can do an decrement instead
4394 of subtract then GOOD for ME */
4395 if (genMinusDec (ic) == TRUE)
4400 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4402 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4408 lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4413 /* if literal, add a,#-lit, else normal subb */
4414 _startLazyDPSEvaluation ();
4416 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4417 if (AOP_USESDPTR(IC_RIGHT(ic))) {
4418 emitcode ("mov","b,%s",
4419 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4420 MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4421 emitcode ("subb","a,b");
4423 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4424 emitcode ("subb", "a,%s",
4425 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE,
4429 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4430 /* first add without previous c */
4432 if (!size && lit==-1) {
4433 emitcode ("dec", "a");
4435 emitcode ("add", "a,#!constbyte",
4436 (unsigned int) (lit & 0x0FFL));
4439 emitcode ("addc", "a,#!constbyte",
4440 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4445 emitcode ("push", "acc");
4447 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4451 _endLazyDPSEvaluation ();
4455 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4457 size = getDataSize (IC_LEFT (ic));
4458 rSize = getDataSize (IC_RESULT (ic));
4460 ADJUST_PUSHED_RESULT(size, rSize);
4462 _startLazyDPSEvaluation ();
4465 emitcode ("pop", "acc");
4466 aopPut (AOP (IC_RESULT (ic)), "a", size);
4468 _endLazyDPSEvaluation ();
4471 adjustArithmeticResult (ic);
4474 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4475 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4476 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4480 /*-----------------------------------------------------------------*/
4481 /* genMultbits :- multiplication of bits */
4482 /*-----------------------------------------------------------------*/
4484 genMultbits (operand * left,
4489 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4490 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4491 aopOp(result, ic, TRUE, FALSE);
4496 /*-----------------------------------------------------------------*/
4497 /* genMultOneByte : 8*8=8/16 bit multiplication */
4498 /*-----------------------------------------------------------------*/
4500 genMultOneByte (operand * left,
4505 sym_link *opetype = operandType (result);
4509 /* (if two literals: the value is computed before) */
4510 /* if one literal, literal on the right */
4511 if (AOP_TYPE (left) == AOP_LIT)
4516 emitcode (";", "swapped left and right");
4519 if (SPEC_USIGN(opetype)
4520 // ignore the sign of left and right, what else can we do?
4521 || (SPEC_USIGN(operandType(left)) &&
4522 SPEC_USIGN(operandType(right)))) {
4523 // just an unsigned 8*8=8/16 multiply
4524 //emitcode (";","unsigned");
4525 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4526 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4527 emitcode ("mul", "ab");
4529 _G.accInUse++; _G.bInUse++;
4530 aopOp(result, ic, TRUE, FALSE);
4532 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4534 // this should never happen
4535 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4536 AOP_SIZE(result), __FILE__, lineno);
4540 aopPut (AOP (result), "a", 0);
4541 _G.accInUse--; _G.bInUse--;
4542 if (AOP_SIZE(result)==2)
4544 aopPut (AOP (result), "b", 1);
4549 // we have to do a signed multiply
4551 emitcode (";", "signed");
4552 emitcode ("clr", "F0"); // reset sign flag
4553 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4555 lbl=newiTempLabel(NULL);
4556 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4557 // left side is negative, 8-bit two's complement, this fails for -128
4558 emitcode ("setb", "F0"); // set sign flag
4559 emitcode ("cpl", "a");
4560 emitcode ("inc", "a");
4562 emitcode ("", "!tlabeldef", lbl->key+100);
4565 if (AOP_TYPE(right)==AOP_LIT) {
4566 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4567 /* AND literal negative */
4568 if ((int) val < 0) {
4569 emitcode ("cpl", "F0"); // complement sign flag
4570 emitcode ("mov", "b,#!constbyte", -val);
4572 emitcode ("mov", "b,#!constbyte", val);
4575 lbl=newiTempLabel(NULL);
4576 emitcode ("mov", "b,a");
4577 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4578 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4579 // right side is negative, 8-bit two's complement
4580 emitcode ("cpl", "F0"); // complement sign flag
4581 emitcode ("cpl", "a");
4582 emitcode ("inc", "a");
4583 emitcode ("", "!tlabeldef", lbl->key+100);
4585 emitcode ("mul", "ab");
4587 _G.accInUse++;_G.bInUse++;
4588 aopOp(result, ic, TRUE, FALSE);
4590 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4592 // this should never happen
4593 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4594 AOP_SIZE(result), __FILE__, lineno);
4598 lbl=newiTempLabel(NULL);
4599 emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4600 // only ONE op was negative, we have to do a 8/16-bit two's complement
4601 emitcode ("cpl", "a"); // lsb
4602 if (AOP_SIZE(result)==1) {
4603 emitcode ("inc", "a");
4605 emitcode ("add", "a,#1");
4606 emitcode ("xch", "a,b");
4607 emitcode ("cpl", "a"); // msb
4608 emitcode ("addc", "a,#0");
4609 emitcode ("xch", "a,b");
4612 emitcode ("", "!tlabeldef", lbl->key+100);
4613 aopPut (AOP (result), "a", 0);
4614 _G.accInUse--;_G.bInUse--;
4615 if (AOP_SIZE(result)==2) {
4616 aopPut (AOP (result), "b", 1);
4620 /*-----------------------------------------------------------------*/
4621 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
4622 /*-----------------------------------------------------------------*/
4623 static void genMultTwoByte (operand *left, operand *right,
4624 operand *result, iCode *ic)
4626 sym_link *retype = getSpec(operandType(right));
4627 sym_link *letype = getSpec(operandType(left));
4628 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4631 if (AOP_TYPE (left) == AOP_LIT) {
4636 /* save EA bit in F1 */
4637 lbl = newiTempLabel(NULL);
4638 emitcode ("setb","F1");
4639 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4640 emitcode ("clr","F1");
4641 emitcode("","!tlabeldef",lbl->key+100);
4643 /* load up MB with right */
4645 emitcode("clr","F0");
4646 if (AOP_TYPE(right) == AOP_LIT) {
4647 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4649 emitcode("setb","F0");
4652 emitcode ("mov","mb,#!constbyte",val & 0xff);
4653 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4655 lbl = newiTempLabel(NULL);
4656 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4657 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4658 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4659 emitcode ("xch", "a,b");
4660 emitcode ("cpl","a");
4661 emitcode ("add", "a,#1");
4662 emitcode ("xch", "a,b");
4663 emitcode ("cpl", "a"); // msb
4664 emitcode ("addc", "a,#0");
4665 emitcode ("setb","F0");
4666 emitcode ("","!tlabeldef",lbl->key+100);
4667 emitcode ("mov","mb,b");
4668 emitcode ("mov","mb,a");
4671 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4672 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4674 /* load up MA with left */
4676 lbl = newiTempLabel(NULL);
4677 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4678 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4679 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4680 emitcode ("xch", "a,b");
4681 emitcode ("cpl","a");
4682 emitcode ("add", "a,#1");
4683 emitcode ("xch", "a,b");
4684 emitcode ("cpl", "a"); // msb
4685 emitcode ("addc","a,#0");
4686 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4687 emitcode ("setb","F0");
4688 emitcode ("","!tlabeldef",lbl->key+100);
4689 emitcode ("mov","ma,b");
4690 emitcode ("mov","ma,a");
4692 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4693 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4695 /* wait for multiplication to finish */
4696 lbl = newiTempLabel(NULL);
4697 emitcode("","!tlabeldef", lbl->key+100);
4698 emitcode("mov","a,mcnt1");
4699 emitcode("anl","a,#!constbyte",0x80);
4700 emitcode("jnz","!tlabel",lbl->key+100);
4702 freeAsmop (left, NULL, ic, TRUE);
4703 freeAsmop (right, NULL, ic,TRUE);
4704 aopOp(result, ic, TRUE, FALSE);
4706 /* if unsigned then simple */
4708 emitcode ("mov","a,ma");
4709 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4710 emitcode ("mov","a,ma");
4711 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4712 aopPut(AOP(result),"ma",1);
4713 aopPut(AOP(result),"ma",0);
4715 emitcode("push","ma");
4716 emitcode("push","ma");
4717 emitcode("push","ma");
4719 /* negate result if needed */
4720 lbl = newiTempLabel(NULL);
4721 emitcode("jnb","F0,!tlabel",lbl->key+100);
4722 emitcode("cpl","a");
4723 emitcode("add","a,#1");
4724 emitcode("","!tlabeldef", lbl->key+100);
4725 if (AOP_TYPE(result) == AOP_ACC)
4727 D(emitcode(";", "ACC special case."););
4728 /* We know result is the only live aop, and
4729 * it's obviously not a DPTR2, so AP is available.
4731 emitcode("mov", "%s,acc", DP2_RESULT_REG);
4735 aopPut(AOP(result),"a",0);
4738 emitcode("pop","acc");
4739 lbl = newiTempLabel(NULL);
4740 emitcode("jnb","F0,!tlabel",lbl->key+100);
4741 emitcode("cpl","a");
4742 emitcode("addc","a,#0");
4743 emitcode("","!tlabeldef", lbl->key+100);
4744 aopPut(AOP(result),"a",1);
4745 emitcode("pop","acc");
4746 if (AOP_SIZE(result) >= 3) {
4747 lbl = newiTempLabel(NULL);
4748 emitcode("jnb","F0,!tlabel",lbl->key+100);
4749 emitcode("cpl","a");
4750 emitcode("addc","a,#0");
4751 emitcode("","!tlabeldef", lbl->key+100);
4752 aopPut(AOP(result),"a",2);
4754 emitcode("pop","acc");
4755 if (AOP_SIZE(result) >= 4) {
4756 lbl = newiTempLabel(NULL);
4757 emitcode("jnb","F0,!tlabel",lbl->key+100);
4758 emitcode("cpl","a");
4759 emitcode("addc","a,#0");
4760 emitcode("","!tlabeldef", lbl->key+100);
4761 aopPut(AOP(result),"a",3);
4763 if (AOP_TYPE(result) == AOP_ACC)
4765 /* We stashed the result away above. */
4766 emitcode("mov", "acc,%s", DP2_RESULT_REG);
4770 freeAsmop (result, NULL, ic, TRUE);
4772 /* restore EA bit in F1 */
4773 lbl = newiTempLabel(NULL);
4774 emitcode ("jnb","F1,!tlabel",lbl->key+100);
4775 emitcode ("setb","EA");
4776 emitcode("","!tlabeldef",lbl->key+100);
4780 /*-----------------------------------------------------------------*/
4781 /* genMult - generates code for multiplication */
4782 /*-----------------------------------------------------------------*/
4784 genMult (iCode * ic)
4786 operand *left = IC_LEFT (ic);
4787 operand *right = IC_RIGHT (ic);
4788 operand *result = IC_RESULT (ic);
4790 D (emitcode (";", "genMult "););
4792 /* assign the amsops */
4795 /* special cases first */
4797 if (AOP_TYPE (left) == AOP_CRY &&
4798 AOP_TYPE (right) == AOP_CRY)
4800 genMultbits (left, right, result, ic);
4804 /* if both are of size == 1 */
4805 if (AOP_SIZE (left) == 1 &&
4806 AOP_SIZE (right) == 1)
4808 genMultOneByte (left, right, result, ic);
4812 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4813 /* use the ds390 ARITHMETIC accel UNIT */
4814 genMultTwoByte (left, right, result, ic);
4817 /* should have been converted to function call */
4821 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4822 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4823 freeAsmop (result, NULL, ic, TRUE);
4826 /*-----------------------------------------------------------------*/
4827 /* genDivbits :- division of bits */
4828 /*-----------------------------------------------------------------*/
4830 genDivbits (operand * left,
4838 /* the result must be bit */
4839 LOAD_AB_FOR_DIV (left, right, l);
4840 emitcode ("div", "ab");
4841 emitcode ("rrc", "a");
4842 aopOp(result, ic, TRUE, FALSE);
4844 aopPut (AOP (result), "c", 0);
4847 /*-----------------------------------------------------------------*/
4848 /* genDivOneByte : 8 bit division */
4849 /*-----------------------------------------------------------------*/
4851 genDivOneByte (operand * left,
4856 sym_link *opetype = operandType (result);
4862 /* signed or unsigned */
4863 if (SPEC_USIGN (opetype))
4865 /* unsigned is easy */
4866 LOAD_AB_FOR_DIV (left, right, l);
4867 emitcode ("div", "ab");
4870 aopOp(result, ic, TRUE, FALSE);
4871 aopPut (AOP (result), "a", 0);
4874 size = AOP_SIZE (result) - 1;
4878 aopPut (AOP (result), zero, offset++);
4883 /* signed is a little bit more difficult */
4885 /* save the signs of the operands */
4886 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4887 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4888 emitcode ("push", "acc"); /* save it on the stack */
4890 /* now sign adjust for both left & right */
4891 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4892 lbl = newiTempLabel (NULL);
4893 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4894 emitcode ("cpl", "a");
4895 emitcode ("inc", "a");
4896 emitcode ("", "!tlabeldef", (lbl->key + 100));
4897 emitcode ("mov", "b,a");
4899 /* sign adjust left side */
4900 MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4902 lbl = newiTempLabel (NULL);
4903 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4904 emitcode ("cpl", "a");
4905 emitcode ("inc", "a");
4906 emitcode ("", "!tlabeldef", (lbl->key + 100));
4908 /* now the division */
4909 emitcode ("nop", "; workaround for DS80C390 div bug.");
4910 emitcode ("div", "ab");
4911 /* we are interested in the lower order
4913 emitcode ("mov", "b,a");
4914 lbl = newiTempLabel (NULL);
4915 emitcode ("pop", "acc");
4916 /* if there was an over flow we don't
4917 adjust the sign of the result */
4918 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4919 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4921 emitcode ("clr", "a");
4922 emitcode ("subb", "a,b");
4923 emitcode ("mov", "b,a");
4924 emitcode ("", "!tlabeldef", (lbl->key + 100));
4926 /* now we are done */
4927 _G.accInUse++; _G.bInUse++;
4928 aopOp(result, ic, TRUE, FALSE);
4930 aopPut (AOP (result), "b", 0);
4932 size = AOP_SIZE (result) - 1;
4936 emitcode ("mov", "c,b.7");
4937 emitcode ("subb", "a,acc");
4941 aopPut (AOP (result), "a", offset++);
4943 _G.accInUse--; _G.bInUse--;
4947 /*-----------------------------------------------------------------*/
4948 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
4949 /*-----------------------------------------------------------------*/
4950 static void genDivTwoByte (operand *left, operand *right,
4951 operand *result, iCode *ic)
4953 sym_link *retype = getSpec(operandType(right));
4954 sym_link *letype = getSpec(operandType(left));
4955 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4958 /* save EA bit in F1 */
4959 lbl = newiTempLabel(NULL);
4960 emitcode ("setb","F1");
4961 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4962 emitcode ("clr","F1");
4963 emitcode("","!tlabeldef",lbl->key+100);
4965 /* load up MA with left */
4967 emitcode("clr","F0");
4968 lbl = newiTempLabel(NULL);
4969 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4970 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4971 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4972 emitcode ("xch", "a,b");
4973 emitcode ("cpl","a");
4974 emitcode ("add", "a,#1");
4975 emitcode ("xch", "a,b");
4976 emitcode ("cpl", "a"); // msb
4977 emitcode ("addc","a,#0");
4978 emitcode ("setb","F0");
4979 emitcode ("","!tlabeldef",lbl->key+100);
4980 emitcode ("mov","ma,b");
4981 emitcode ("mov","ma,a");
4983 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4984 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4987 /* load up MB with right */
4989 if (AOP_TYPE(right) == AOP_LIT) {
4990 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4992 lbl = newiTempLabel(NULL);
4993 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4994 emitcode("setb","F0");
4995 emitcode ("","!tlabeldef",lbl->key+100);
4998 emitcode ("mov","mb,#!constbyte",val & 0xff);
4999 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5001 lbl = newiTempLabel(NULL);
5002 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5003 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5004 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5005 emitcode ("xch", "a,b");
5006 emitcode ("cpl","a");
5007 emitcode ("add", "a,#1");
5008 emitcode ("xch", "a,b");
5009 emitcode ("cpl", "a"); // msb
5010 emitcode ("addc", "a,#0");
5011 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5012 emitcode ("setb","F0");
5013 emitcode ("","!tlabeldef",lbl->key+100);
5014 emitcode ("mov","mb,b");
5015 emitcode ("mov","mb,a");
5018 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5019 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5022 /* wait for multiplication to finish */
5023 lbl = newiTempLabel(NULL);
5024 emitcode("","!tlabeldef", lbl->key+100);
5025 emitcode("mov","a,mcnt1");
5026 emitcode("anl","a,#!constbyte",0x80);
5027 emitcode("jnz","!tlabel",lbl->key+100);
5029 freeAsmop (left, NULL, ic, TRUE);
5030 freeAsmop (right, NULL, ic,TRUE);
5031 aopOp(result, ic, TRUE, FALSE);
5033 /* if unsigned then simple */
5035 aopPut(AOP(result),"ma",1);
5036 aopPut(AOP(result),"ma",0);
5038 emitcode("push","ma");
5040 /* negate result if needed */
5041 lbl = newiTempLabel(NULL);
5042 emitcode("jnb","F0,!tlabel",lbl->key+100);
5043 emitcode("cpl","a");
5044 emitcode("add","a,#1");
5045 emitcode("","!tlabeldef", lbl->key+100);
5046 aopPut(AOP(result),"a",0);
5047 emitcode("pop","acc");
5048 lbl = newiTempLabel(NULL);
5049 emitcode("jnb","F0,!tlabel",lbl->key+100);
5050 emitcode("cpl","a");
5051 emitcode("addc","a,#0");
5052 emitcode("","!tlabeldef", lbl->key+100);
5053 aopPut(AOP(result),"a",1);
5055 freeAsmop (result, NULL, ic, TRUE);
5056 /* restore EA bit in F1 */
5057 lbl = newiTempLabel(NULL);
5058 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5059 emitcode ("setb","EA");
5060 emitcode("","!tlabeldef",lbl->key+100);
5064 /*-----------------------------------------------------------------*/
5065 /* genDiv - generates code for division */
5066 /*-----------------------------------------------------------------*/
5070 operand *left = IC_LEFT (ic);
5071 operand *right = IC_RIGHT (ic);
5072 operand *result = IC_RESULT (ic);
5074 D (emitcode (";", "genDiv "););
5076 /* assign the amsops */
5079 /* special cases first */
5081 if (AOP_TYPE (left) == AOP_CRY &&
5082 AOP_TYPE (right) == AOP_CRY)
5084 genDivbits (left, right, result, ic);
5088 /* if both are of size == 1 */
5089 if (AOP_SIZE (left) == 1 &&
5090 AOP_SIZE (right) == 1)
5092 genDivOneByte (left, right, result, ic);
5096 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5097 /* use the ds390 ARITHMETIC accel UNIT */
5098 genDivTwoByte (left, right, result, ic);
5101 /* should have been converted to function call */
5104 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5105 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5106 freeAsmop (result, NULL, ic, TRUE);
5109 /*-----------------------------------------------------------------*/
5110 /* genModbits :- modulus of bits */
5111 /*-----------------------------------------------------------------*/
5113 genModbits (operand * left,
5121 /* the result must be bit */
5122 LOAD_AB_FOR_DIV (left, right, l);
5123 emitcode ("div", "ab");
5124 emitcode ("mov", "a,b");
5125 emitcode ("rrc", "a");
5126 aopOp(result, ic, TRUE, FALSE);
5127 aopPut (AOP (result), "c", 0);
5130 /*-----------------------------------------------------------------*/
5131 /* genModOneByte : 8 bit modulus */
5132 /*-----------------------------------------------------------------*/
5134 genModOneByte (operand * left,
5139 sym_link *opetype = operandType (result);
5143 /* signed or unsigned */
5144 if (SPEC_USIGN (opetype))
5146 /* unsigned is easy */
5147 LOAD_AB_FOR_DIV (left, right, l);
5148 emitcode ("div", "ab");
5149 aopOp(result, ic, TRUE, FALSE);
5150 aopPut (AOP (result), "b", 0);
5154 /* signed is a little bit more difficult */
5156 /* save the signs of the operands */
5157 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5159 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
5160 emitcode ("push", "acc"); /* save it on the stack */
5162 /* now sign adjust for both left & right */
5163 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5165 lbl = newiTempLabel (NULL);
5166 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5167 emitcode ("cpl", "a");
5168 emitcode ("inc", "a");
5169 emitcode ("", "!tlabeldef", (lbl->key + 100));
5170 emitcode ("mov", "b,a");
5172 /* sign adjust left side */
5173 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5175 lbl = newiTempLabel (NULL);
5176 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5177 emitcode ("cpl", "a");
5178 emitcode ("inc", "a");
5179 emitcode ("", "!tlabeldef", (lbl->key + 100));
5181 /* now the multiplication */
5182 emitcode ("nop", "; workaround for DS80C390 div bug.");
5183 emitcode ("div", "ab");
5184 /* we are interested in the lower order
5186 lbl = newiTempLabel (NULL);
5187 emitcode ("pop", "acc");
5188 /* if there was an over flow we don't
5189 adjust the sign of the result */
5190 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
5191 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5193 emitcode ("clr", "a");
5194 emitcode ("subb", "a,b");
5195 emitcode ("mov", "b,a");
5196 emitcode ("", "!tlabeldef", (lbl->key + 100));
5199 /* now we are done */
5200 aopOp(result, ic, TRUE, FALSE);
5201 aopPut (AOP (result), "b", 0);
5206 /*-----------------------------------------------------------------*/
5207 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
5208 /*-----------------------------------------------------------------*/
5209 static void genModTwoByte (operand *left, operand *right,
5210 operand *result, iCode *ic)
5212 sym_link *retype = getSpec(operandType(right));
5213 sym_link *letype = getSpec(operandType(left));
5214 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5217 /* load up MA with left */
5218 /* save EA bit in F1 */
5219 lbl = newiTempLabel(NULL);
5220 emitcode ("setb","F1");
5221 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5222 emitcode ("clr","F1");
5223 emitcode("","!tlabeldef",lbl->key+100);
5226 lbl = newiTempLabel(NULL);
5227 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5228 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5229 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5230 emitcode ("xch", "a,b");
5231 emitcode ("cpl","a");
5232 emitcode ("add", "a,#1");
5233 emitcode ("xch", "a,b");
5234 emitcode ("cpl", "a"); // msb
5235 emitcode ("addc","a,#0");
5236 emitcode ("","!tlabeldef",lbl->key+100);
5237 emitcode ("mov","ma,b");
5238 emitcode ("mov","ma,a");
5240 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5241 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5244 /* load up MB with right */
5246 if (AOP_TYPE(right) == AOP_LIT) {
5247 int val=floatFromVal (AOP (right)->aopu.aop_lit);
5251 emitcode ("mov","mb,#!constbyte",val & 0xff);
5252 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5254 lbl = newiTempLabel(NULL);
5255 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5256 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5257 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5258 emitcode ("xch", "a,b");
5259 emitcode ("cpl","a");
5260 emitcode ("add", "a,#1");
5261 emitcode ("xch", "a,b");
5262 emitcode ("cpl", "a"); // msb
5263 emitcode ("addc", "a,#0");
5264 emitcode ("","!tlabeldef",lbl->key+100);
5265 emitcode ("mov","mb,b");
5266 emitcode ("mov","mb,a");
5269 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5270 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5273 /* wait for multiplication to finish */
5274 lbl = newiTempLabel(NULL);
5275 emitcode("","!tlabeldef", lbl->key+100);
5276 emitcode("mov","a,mcnt1");
5277 emitcode("anl","a,#!constbyte",0x80);
5278 emitcode("jnz","!tlabel",lbl->key+100);
5280 freeAsmop (left, NULL, ic, TRUE);
5281 freeAsmop (right, NULL, ic,TRUE);
5282 aopOp(result, ic, TRUE, FALSE);
5284 aopPut(AOP(result),"mb",1);
5285 aopPut(AOP(result),"mb",0);
5286 freeAsmop (result, NULL, ic, TRUE);
5288 /* restore EA bit in F1 */
5289 lbl = newiTempLabel(NULL);
5290 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5291 emitcode ("setb","EA");
5292 emitcode("","!tlabeldef",lbl->key+100);
5296 /*-----------------------------------------------------------------*/
5297 /* genMod - generates code for division */
5298 /*-----------------------------------------------------------------*/
5302 operand *left = IC_LEFT (ic);
5303 operand *right = IC_RIGHT (ic);
5304 operand *result = IC_RESULT (ic);
5306 D (emitcode (";", "genMod "); );
5308 /* assign the amsops */
5311 /* special cases first */
5313 if (AOP_TYPE (left) == AOP_CRY &&
5314 AOP_TYPE (right) == AOP_CRY)
5316 genModbits (left, right, result, ic);
5320 /* if both are of size == 1 */
5321 if (AOP_SIZE (left) == 1 &&
5322 AOP_SIZE (right) == 1)
5324 genModOneByte (left, right, result, ic);
5328 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5329 /* use the ds390 ARITHMETIC accel UNIT */
5330 genModTwoByte (left, right, result, ic);
5334 /* should have been converted to function call */
5338 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5339 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5340 freeAsmop (result, NULL, ic, TRUE);
5343 /*-----------------------------------------------------------------*/
5344 /* genIfxJump :- will create a jump depending on the ifx */
5345 /*-----------------------------------------------------------------*/
5347 genIfxJump (iCode * ic, char *jval)
5350 symbol *tlbl = newiTempLabel (NULL);
5353 D (emitcode (";", "genIfxJump"););
5355 /* if true label then we jump if condition
5359 jlbl = IC_TRUE (ic);
5360 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5361 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5365 /* false label is present */
5366 jlbl = IC_FALSE (ic);
5367 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5368 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5370 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5371 emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5373 emitcode (inst, "!tlabel", tlbl->key + 100);
5374 emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5375 emitcode ("", "!tlabeldef", tlbl->key + 100);
5377 /* mark the icode as generated */
5381 /*-----------------------------------------------------------------*/
5382 /* genCmp :- greater or less than comparison */
5383 /*-----------------------------------------------------------------*/
5385 genCmp (operand * left, operand * right,
5386 iCode * ic, iCode * ifx, int sign)
5388 int size, offset = 0;
5389 unsigned long lit = 0L;
5392 D (emitcode (";", "genCmp"););
5394 result = IC_RESULT (ic);
5396 /* if left & right are bit variables */
5397 if (AOP_TYPE (left) == AOP_CRY &&
5398 AOP_TYPE (right) == AOP_CRY)
5400 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5401 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5405 /* subtract right from left if at the
5406 end the carry flag is set then we know that
5407 left is greater than right */
5408 size = max (AOP_SIZE (left), AOP_SIZE (right));
5410 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5411 if ((size == 1) && !sign
5412 && (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5414 symbol *lbl = newiTempLabel (NULL);
5415 emitcode ("cjne", "%s,%s,!tlabel",
5416 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
5417 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5419 emitcode ("", "!tlabeldef", lbl->key + 100);
5423 if (AOP_TYPE (right) == AOP_LIT)
5425 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5426 /* optimize if(x < 0) or if(x >= 0) */
5435 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
5437 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5438 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5440 aopOp (result, ic, FALSE, FALSE);
5442 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5444 freeAsmop (result, NULL, ic, TRUE);
5445 genIfxJump (ifx, "acc.7");
5450 emitcode ("rlc", "a");
5452 goto release_freedLR;
5460 // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5461 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5462 // emitcode (";", "genCmp #2");
5463 if (sign && (size == 0))
5465 // emitcode (";", "genCmp #3");
5466 emitcode ("xrl", "a,#!constbyte",0x80);
5467 if (AOP_TYPE (right) == AOP_LIT)
5469 unsigned long lit = (unsigned long)
5470 floatFromVal (AOP (right)->aopu.aop_lit);
5471 // emitcode (";", "genCmp #3.1");
5472 emitcode ("subb", "a,#!constbyte",
5473 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5477 // emitcode (";", "genCmp #3.2");
5479 MOVB(aopGet (AOP (right), offset++, FALSE, FALSE, "b"));
5480 saveAccWarn = DEFAULT_ACC_WARNING;
5481 emitcode ("xrl", "b,#!constbyte",0x80);
5482 emitcode ("subb", "a,b");
5489 // emitcode (";", "genCmp #4");
5491 s = aopGet (AOP (right), offset++, FALSE, FALSE, "b");
5492 saveAccWarn = DEFAULT_ACC_WARNING;
5494 emitcode ("subb", "a,%s", s);
5501 /* Don't need the left & right operands any more; do need the result. */
5502 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5503 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5505 aopOp (result, ic, FALSE, FALSE);
5509 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5515 /* if the result is used in the next
5516 ifx conditional branch then generate
5517 code a little differently */
5520 genIfxJump (ifx, "c");
5526 /* leave the result in acc */
5528 freeAsmop (result, NULL, ic, TRUE);
5531 /*-----------------------------------------------------------------*/
5532 /* genCmpGt :- greater than comparison */
5533 /*-----------------------------------------------------------------*/
5535 genCmpGt (iCode * ic, iCode * ifx)
5537 operand *left, *right;
5538 sym_link *letype, *retype;
5541 D (emitcode (";", "genCmpGt ");
5544 left = IC_LEFT (ic);
5545 right = IC_RIGHT (ic);
5547 letype = getSpec (operandType (left));
5548 retype = getSpec (operandType (right));
5549 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5551 /* assign the left & right amsops */
5554 genCmp (right, left, ic, ifx, sign);
5557 /*-----------------------------------------------------------------*/
5558 /* genCmpLt - less than comparisons */
5559 /*-----------------------------------------------------------------*/
5561 genCmpLt (iCode * ic, iCode * ifx)
5563 operand *left, *right;
5564 sym_link *letype, *retype;
5567 D (emitcode (";", "genCmpLt "););
5569 left = IC_LEFT (ic);
5570 right = IC_RIGHT (ic);
5572 letype = getSpec (operandType (left));
5573 retype = getSpec (operandType (right));
5574 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5576 /* assign the left & right amsops */
5579 genCmp (left, right, ic, ifx, sign);
5582 /*-----------------------------------------------------------------*/
5583 /* gencjneshort - compare and jump if not equal */
5584 /*-----------------------------------------------------------------*/
5586 gencjneshort (operand * left, operand * right, symbol * lbl)
5588 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5590 unsigned long lit = 0L;
5592 D (emitcode (";", "gencjneshort");
5595 /* if the left side is a literal or
5596 if the right is in a pointer register and left
5598 if ((AOP_TYPE (left) == AOP_LIT) ||
5599 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5606 if (AOP_TYPE (right) == AOP_LIT)
5607 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5609 if (opIsGptr (left) || opIsGptr (right))
5611 /* We are comparing a generic pointer to something.
5612 * Exclude the generic type byte from the comparison.
5615 D (emitcode (";", "cjneshort: generic ptr special case."););
5619 /* if the right side is a literal then anything goes */
5620 if (AOP_TYPE (right) == AOP_LIT &&
5621 AOP_TYPE (left) != AOP_DIR)
5625 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5626 emitcode ("cjne", "a,%s,!tlabel",
5627 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5633 /* if the right side is in a register or in direct space or
5634 if the left is a pointer register & right is not */
5635 else if (AOP_TYPE (right) == AOP_REG ||
5636 AOP_TYPE (right) == AOP_DIR ||
5637 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5638 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5642 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5643 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5644 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5645 emitcode ("jnz", "!tlabel", lbl->key + 100);
5647 emitcode ("cjne", "a,%s,!tlabel",
5648 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
5655 /* right is a pointer reg need both a & b */
5658 MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5659 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
5660 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5666 /*-----------------------------------------------------------------*/
5667 /* gencjne - compare and jump if not equal */
5668 /*-----------------------------------------------------------------*/
5670 gencjne (operand * left, operand * right, symbol * lbl)
5672 symbol *tlbl = newiTempLabel (NULL);
5674 D (emitcode (";", "gencjne");
5677 gencjneshort (left, right, lbl);
5679 emitcode ("mov", "a,%s", one);
5680 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5681 emitcode ("", "!tlabeldef", lbl->key + 100);
5682 emitcode ("clr", "a");
5683 emitcode ("", "!tlabeldef", tlbl->key + 100);
5686 /*-----------------------------------------------------------------*/
5687 /* genCmpEq - generates code for equal to */
5688 /*-----------------------------------------------------------------*/
5690 genCmpEq (iCode * ic, iCode * ifx)
5692 operand *left, *right, *result;
5694 D (emitcode (";", "genCmpEq ");
5698 AOP_SET_LOCALS (ic);
5700 /* if literal, literal on the right or
5701 if the right is in a pointer register and left
5703 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5704 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5706 operand *t = IC_RIGHT (ic);
5707 IC_RIGHT (ic) = IC_LEFT (ic);
5711 if (ifx && /* !AOP_SIZE(result) */
5712 OP_SYMBOL (result) &&
5713 OP_SYMBOL (result)->regType == REG_CND)
5716 /* if they are both bit variables */
5717 if (AOP_TYPE (left) == AOP_CRY &&
5718 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5720 if (AOP_TYPE (right) == AOP_LIT)
5722 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5725 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5726 emitcode ("cpl", "c");
5730 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5734 emitcode ("clr", "c");
5736 /* AOP_TYPE(right) == AOP_CRY */
5740 symbol *lbl = newiTempLabel (NULL);
5741 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5742 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5743 emitcode ("cpl", "c");
5744 emitcode ("", "!tlabeldef", (lbl->key + 100));
5746 /* if true label then we jump if condition
5748 tlbl = newiTempLabel (NULL);
5751 emitcode ("jnc", "!tlabel", tlbl->key + 100);
5752 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5756 emitcode ("jc", "!tlabel", tlbl->key + 100);
5757 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5759 emitcode ("", "!tlabeldef", tlbl->key + 100);
5763 tlbl = newiTempLabel (NULL);
5764 gencjneshort (left, right, tlbl);
5767 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5768 emitcode ("", "!tlabeldef", tlbl->key + 100);
5772 symbol *lbl = newiTempLabel (NULL);
5773 emitcode ("sjmp", "!tlabel", lbl->key + 100);
5774 emitcode ("", "!tlabeldef", tlbl->key + 100);
5775 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5776 emitcode ("", "!tlabeldef", lbl->key + 100);
5779 /* mark the icode as generated */
5782 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5783 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5787 /* if they are both bit variables */
5788 if (AOP_TYPE (left) == AOP_CRY &&
5789 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5791 if (AOP_TYPE (right) == AOP_LIT)
5793 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5796 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5797 emitcode ("cpl", "c");
5801 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5805 emitcode ("clr", "c");
5807 /* AOP_TYPE(right) == AOP_CRY */
5811 symbol *lbl = newiTempLabel (NULL);
5812 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5813 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5814 emitcode ("cpl", "c");
5815 emitcode ("", "!tlabeldef", (lbl->key + 100));
5818 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5819 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5821 aopOp (result, ic, TRUE, FALSE);
5824 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5831 genIfxJump (ifx, "c");
5834 /* if the result is used in an arithmetic operation
5835 then put the result in place */
5840 gencjne (left, right, newiTempLabel (NULL));
5842 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5843 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5845 aopOp (result, ic, TRUE, FALSE);
5847 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5849 aopPut (AOP (result), "a", 0);
5854 genIfxJump (ifx, "a");
5857 /* if the result is used in an arithmetic operation
5858 then put the result in place */
5859 if (AOP_TYPE (result) != AOP_CRY)
5861 /* leave the result in acc */
5865 freeAsmop (result, NULL, ic, TRUE);
5868 /*-----------------------------------------------------------------*/
5869 /* ifxForOp - returns the icode containing the ifx for operand */
5870 /*-----------------------------------------------------------------*/
5872 ifxForOp (operand * op, iCode * ic)
5874 /* if true symbol then needs to be assigned */
5875 if (IS_TRUE_SYMOP (op))
5878 /* if this has register type condition and
5879 the next instruction is ifx with the same operand
5880 and live to of the operand is upto the ifx only then */
5882 ic->next->op == IFX &&
5883 IC_COND (ic->next)->key == op->key &&
5884 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5889 /*-----------------------------------------------------------------*/
5890 /* hasInc - operand is incremented before any other use */
5891 /*-----------------------------------------------------------------*/
5893 hasInc (operand *op, iCode *ic, int osize)
5895 sym_link *type = operandType(op);
5896 sym_link *retype = getSpec (type);
5897 iCode *lic = ic->next;
5900 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5901 if (!IS_SYMOP(op)) return NULL;
5903 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5904 if (IS_AGGREGATE(type->next)) return NULL;
5905 if (osize != (isize = getSize(type->next))) return NULL;
5908 /* if operand of the form op = op + <sizeof *op> */
5909 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5910 isOperandEqual(IC_RESULT(lic),op) &&
5911 isOperandLiteral(IC_RIGHT(lic)) &&
5912 operandLitValue(IC_RIGHT(lic)) == isize) {
5915 /* if the operand used or deffed */
5916 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5919 /* if GOTO or IFX */
5920 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5926 /*-----------------------------------------------------------------*/
5927 /* genAndOp - for && operation */
5928 /*-----------------------------------------------------------------*/
5930 genAndOp (iCode * ic)
5932 operand *left, *right, *result;
5935 D (emitcode (";", "genAndOp "););
5937 /* note here that && operations that are in an
5938 if statement are taken away by backPatchLabels
5939 only those used in arthmetic operations remain */
5941 AOP_SET_LOCALS (ic);
5943 /* if both are bit variables */
5944 if (AOP_TYPE (left) == AOP_CRY &&
5945 AOP_TYPE (right) == AOP_CRY)
5947 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5948 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5949 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5950 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5952 aopOp (result,ic,FALSE, FALSE);
5957 tlbl = newiTempLabel (NULL);
5959 emitcode ("jz", "!tlabel", tlbl->key + 100);
5961 emitcode ("", "!tlabeldef", tlbl->key + 100);
5962 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5963 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5965 aopOp (result,ic,FALSE, FALSE);
5968 freeAsmop (result, NULL, ic, TRUE);
5972 /*-----------------------------------------------------------------*/
5973 /* genOrOp - for || operation */
5974 /*-----------------------------------------------------------------*/
5976 genOrOp (iCode * ic)
5978 operand *left, *right, *result;
5981 D (emitcode (";", "genOrOp "););
5983 /* note here that || operations that are in an
5984 if statement are taken away by backPatchLabels
5985 only those used in arthmetic operations remain */
5987 AOP_SET_LOCALS (ic);
5989 /* if both are bit variables */
5990 if (AOP_TYPE (left) == AOP_CRY &&
5991 AOP_TYPE (right) == AOP_CRY)
5993 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5994 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5995 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5996 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5998 aopOp (result,ic,FALSE, FALSE);
6004 tlbl = newiTempLabel (NULL);
6006 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6008 emitcode ("", "!tlabeldef", tlbl->key + 100);
6009 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6010 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6012 aopOp (result,ic,FALSE, FALSE);
6017 freeAsmop (result, NULL, ic, TRUE);
6020 /*-----------------------------------------------------------------*/
6021 /* isLiteralBit - test if lit == 2^n */
6022 /*-----------------------------------------------------------------*/
6024 isLiteralBit (unsigned long lit)
6026 unsigned long pw[32] =
6027 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6028 0x100L, 0x200L, 0x400L, 0x800L,
6029 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6030 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6031 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6032 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6033 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6036 for (idx = 0; idx < 32; idx++)
6042 /*-----------------------------------------------------------------*/
6043 /* continueIfTrue - */
6044 /*-----------------------------------------------------------------*/
6046 continueIfTrue (iCode * ic)
6049 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6053 /*-----------------------------------------------------------------*/
6055 /*-----------------------------------------------------------------*/
6057 jumpIfTrue (iCode * ic)
6060 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6064 /*-----------------------------------------------------------------*/
6065 /* jmpTrueOrFalse - */
6066 /*-----------------------------------------------------------------*/
6068 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6070 // ugly but optimized by peephole
6073 symbol *nlbl = newiTempLabel (NULL);
6074 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6075 emitcode ("", "!tlabeldef", tlbl->key + 100);
6076 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6077 emitcode ("", "!tlabeldef", nlbl->key + 100);
6081 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6082 emitcode ("", "!tlabeldef", tlbl->key + 100);
6087 // Generate code to perform a bit-wise logic operation
6088 // on two operands in far space (assumed to already have been
6089 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6090 // in far space. This requires pushing the result on the stack
6091 // then popping it into the result.
6093 genFarFarLogicOp(iCode *ic, char *logicOp)
6095 int size, resultSize, compSize;
6099 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6100 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
6101 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6103 _startLazyDPSEvaluation();
6104 for (size = compSize; (size--); offset++)
6106 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6107 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6108 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6110 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6111 emitcode ("push", "acc");
6113 _endLazyDPSEvaluation();
6115 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6116 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6117 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6119 resultSize = AOP_SIZE(IC_RESULT(ic));
6121 ADJUST_PUSHED_RESULT(compSize, resultSize);
6123 _startLazyDPSEvaluation();
6126 emitcode ("pop", "acc");
6127 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6129 _endLazyDPSEvaluation();
6130 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6134 /*-----------------------------------------------------------------*/
6135 /* genAnd - code for and */
6136 /*-----------------------------------------------------------------*/
6138 genAnd (iCode * ic, iCode * ifx)
6140 operand *left, *right, *result;
6141 int size, offset = 0;
6142 unsigned long lit = 0L;
6147 D (emitcode (";", "genAnd "););
6149 AOP_OP_3_NOFATAL (ic, pushResult);
6150 AOP_SET_LOCALS (ic);
6154 genFarFarLogicOp(ic, "anl");
6159 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6161 AOP_TYPE (left), AOP_TYPE (right));
6162 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6164 AOP_SIZE (left), AOP_SIZE (right));
6167 /* if left is a literal & right is not then exchange them */
6168 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6169 #ifdef LOGIC_OPS_BROKEN
6170 || AOP_NEEDSACC (left)
6174 operand *tmp = right;
6179 /* if result = right then exchange them */
6180 if (sameRegs (AOP (result), AOP (right)))
6182 operand *tmp = right;
6187 /* if right is bit then exchange them */
6188 if (AOP_TYPE (right) == AOP_CRY &&
6189 AOP_TYPE (left) != AOP_CRY)
6191 operand *tmp = right;
6195 if (AOP_TYPE (right) == AOP_LIT)
6196 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6198 size = AOP_SIZE (result);
6201 // result = bit & yy;
6202 if (AOP_TYPE (left) == AOP_CRY)
6204 // c = bit & literal;
6205 if (AOP_TYPE (right) == AOP_LIT)
6209 if (size && sameRegs (AOP (result), AOP (left)))
6212 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6217 if (size && (AOP_TYPE (result) == AOP_CRY))
6219 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6222 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6227 emitcode ("clr", "c");
6232 if (AOP_TYPE (right) == AOP_CRY)
6235 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6236 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6241 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6243 emitcode ("rrc", "a");
6244 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6252 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6253 genIfxJump (ifx, "c");
6257 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6258 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6259 if ((AOP_TYPE (right) == AOP_LIT) &&
6260 (AOP_TYPE (result) == AOP_CRY) &&
6261 (AOP_TYPE (left) != AOP_CRY))
6263 int posbit = isLiteralBit (lit);
6268 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6271 emitcode ("mov", "c,acc.%d", posbit & 0x07);
6277 SNPRINTF (buff, sizeof(buff),
6278 "acc.%d", posbit & 0x07);
6279 genIfxJump (ifx, buff);
6283 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6290 symbol *tlbl = newiTempLabel (NULL);
6291 int sizel = AOP_SIZE (left);
6293 emitcode ("setb", "c");
6296 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6298 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6300 if ((posbit = isLiteralBit (bytelit)) != 0)
6301 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6304 if (bytelit != 0x0FFL)
6305 emitcode ("anl", "a,%s",
6306 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6307 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6312 // bit = left & literal
6315 emitcode ("clr", "c");
6316 emitcode ("", "!tlabeldef", tlbl->key + 100);
6318 // if(left & literal)
6322 jmpTrueOrFalse (ifx, tlbl);
6330 /* if left is same as result */
6331 if (sameRegs (AOP (result), AOP (left)))
6333 for (; size--; offset++)
6335 if (AOP_TYPE (right) == AOP_LIT)
6337 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6339 else if (bytelit == 0)
6340 aopPut (AOP (result), zero, offset);
6341 else if (IS_AOP_PREG (result))
6343 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6344 emitcode ("anl", "a,%s",
6345 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6346 aopPut (AOP (result), "a", offset);
6349 emitcode ("anl", "%s,%s",
6350 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6351 aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6355 if (AOP_TYPE (left) == AOP_ACC)
6356 emitcode ("anl", "a,%s",
6357 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6360 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6361 if (IS_AOP_PREG (result))
6363 emitcode ("anl", "a,%s",
6364 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6365 aopPut (AOP (result), "a", offset);
6368 emitcode ("anl", "%s,a",
6369 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6376 // left & result in different registers
6377 if (AOP_TYPE (result) == AOP_CRY)
6380 // if(size), result in bit
6381 // if(!size && ifx), conditional oper: if(left & right)
6382 symbol *tlbl = newiTempLabel (NULL);
6383 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6385 emitcode ("setb", "c");
6388 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6389 emitcode ("anl", "a,%s",
6390 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6392 if (AOP_TYPE(left)==AOP_ACC) {
6393 emitcode("mov", "b,a");
6394 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6395 emitcode("anl", "a,b");
6397 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6398 emitcode ("anl", "a,%s",
6399 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6402 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6408 emitcode ("", "!tlabeldef", tlbl->key + 100);
6412 jmpTrueOrFalse (ifx, tlbl);
6416 for (; (size--); offset++)
6419 // result = left & right
6420 if (AOP_TYPE (right) == AOP_LIT)
6422 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6424 aopPut (AOP (result),
6425 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6429 else if (bytelit == 0)
6431 aopPut (AOP (result), zero, offset);
6434 D (emitcode (";", "better literal AND."););
6435 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6436 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6437 FALSE, FALSE, DP2_RESULT_REG));
6442 // faster than result <- left, anl result,right
6443 // and better if result is SFR
6444 if (AOP_TYPE (left) == AOP_ACC)
6446 emitcode ("anl", "a,%s",
6447 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6451 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6452 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6454 emitcode("mov", "b,a");
6458 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6459 emitcode ("anl", "a,%s", rOp);
6462 aopPut (AOP (result), "a", offset);
6468 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6469 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6470 freeAsmop (result, NULL, ic, TRUE);
6474 /*-----------------------------------------------------------------*/
6475 /* genOr - code for or */
6476 /*-----------------------------------------------------------------*/
6478 genOr (iCode * ic, iCode * ifx)
6480 operand *left, *right, *result;
6481 int size, offset = 0;
6482 unsigned long lit = 0L;
6485 D (emitcode (";", "genOr "););
6487 AOP_OP_3_NOFATAL (ic, pushResult);
6488 AOP_SET_LOCALS (ic);
6492 genFarFarLogicOp(ic, "orl");
6498 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6500 AOP_TYPE (left), AOP_TYPE (right));
6501 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6503 AOP_SIZE (left), AOP_SIZE (right));
6506 /* if left is a literal & right is not then exchange them */
6507 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6508 #ifdef LOGIC_OPS_BROKEN
6509 || AOP_NEEDSACC (left) // I think this is a net loss now.
6513 operand *tmp = right;
6518 /* if result = right then exchange them */
6519 if (sameRegs (AOP (result), AOP (right)))
6521 operand *tmp = right;
6526 /* if right is bit then exchange them */
6527 if (AOP_TYPE (right) == AOP_CRY &&
6528 AOP_TYPE (left) != AOP_CRY)
6530 operand *tmp = right;
6534 if (AOP_TYPE (right) == AOP_LIT)
6535 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6537 size = AOP_SIZE (result);
6541 if (AOP_TYPE (left) == AOP_CRY)
6543 if (AOP_TYPE (right) == AOP_LIT)
6545 // c = bit & literal;
6548 // lit != 0 => result = 1
6549 if (AOP_TYPE (result) == AOP_CRY)
6552 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6554 continueIfTrue (ifx);
6557 emitcode ("setb", "c");
6561 // lit == 0 => result = left
6562 if (size && sameRegs (AOP (result), AOP (left)))
6564 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6569 if (AOP_TYPE (right) == AOP_CRY)
6572 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6573 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6578 symbol *tlbl = newiTempLabel (NULL);
6579 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6580 emitcode ("setb", "c");
6581 emitcode ("jb", "%s,!tlabel",
6582 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6584 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6585 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6587 jmpTrueOrFalse (ifx, tlbl);
6593 emitcode ("", "!tlabeldef", tlbl->key + 100);
6602 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6603 genIfxJump (ifx, "c");
6607 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6608 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6609 if ((AOP_TYPE (right) == AOP_LIT) &&
6610 (AOP_TYPE (result) == AOP_CRY) &&
6611 (AOP_TYPE (left) != AOP_CRY))
6617 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6619 continueIfTrue (ifx);
6624 // lit = 0, result = boolean(left)
6626 emitcode ("setb", "c");
6630 symbol *tlbl = newiTempLabel (NULL);
6631 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6633 emitcode ("", "!tlabeldef", tlbl->key + 100);
6637 genIfxJump (ifx, "a");
6645 /* if left is same as result */
6646 if (sameRegs (AOP (result), AOP (left)))
6648 for (; size--; offset++)
6650 if (AOP_TYPE (right) == AOP_LIT)
6652 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6658 if (IS_AOP_PREG (left))
6660 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6661 emitcode ("orl", "a,%s",
6662 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6663 aopPut (AOP (result), "a", offset);
6667 emitcode ("orl", "%s,%s",
6668 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6669 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6675 if (AOP_TYPE (left) == AOP_ACC)
6677 emitcode ("orl", "a,%s",
6678 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6682 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6683 if (IS_AOP_PREG (left))
6685 emitcode ("orl", "a,%s",
6686 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6687 aopPut (AOP (result), "a", offset);
6691 emitcode ("orl", "%s,a",
6692 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6700 // left & result in different registers
6701 if (AOP_TYPE (result) == AOP_CRY)
6704 // if(size), result in bit
6705 // if(!size && ifx), conditional oper: if(left | right)
6706 symbol *tlbl = newiTempLabel (NULL);
6707 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6709 emitcode ("setb", "c");
6712 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6713 emitcode ("orl", "a,%s",
6714 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6716 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6717 emitcode ("orl", "a,%s",
6718 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6720 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6726 emitcode ("", "!tlabeldef", tlbl->key + 100);
6730 jmpTrueOrFalse (ifx, tlbl);
6734 _startLazyDPSEvaluation();
6735 for (; (size--); offset++)
6738 // result = left & right
6739 if (AOP_TYPE (right) == AOP_LIT)
6741 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6743 aopPut (AOP (result),
6744 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6748 D (emitcode (";", "better literal OR."););
6749 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6750 emitcode ("orl", "a, %s",
6751 aopGet (AOP (right), offset,
6752 FALSE, FALSE, DP2_RESULT_REG));
6757 // faster than result <- left, anl result,right
6758 // and better if result is SFR
6759 if (AOP_TYPE (left) == AOP_ACC)
6761 emitcode ("orl", "a,%s",
6762 aopGet (AOP (right), offset,
6763 FALSE, FALSE, DP2_RESULT_REG));
6767 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6769 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6771 emitcode("mov", "b,a");
6775 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6776 emitcode ("orl", "a,%s", rOp);
6779 aopPut (AOP (result), "a", offset);
6781 _endLazyDPSEvaluation();
6786 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6787 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6788 freeAsmop (result, NULL, ic, TRUE);
6791 /*-----------------------------------------------------------------*/
6792 /* genXor - code for xclusive or */
6793 /*-----------------------------------------------------------------*/
6795 genXor (iCode * ic, iCode * ifx)
6797 operand *left, *right, *result;
6798 int size, offset = 0;
6799 unsigned long lit = 0L;
6802 D (emitcode (";", "genXor "););
6804 AOP_OP_3_NOFATAL (ic, pushResult);
6805 AOP_SET_LOCALS (ic);
6809 genFarFarLogicOp(ic, "xrl");
6814 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6816 AOP_TYPE (left), AOP_TYPE (right));
6817 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6819 AOP_SIZE (left), AOP_SIZE (right));
6822 /* if left is a literal & right is not ||
6823 if left needs acc & right does not */
6824 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6825 #ifdef LOGIC_OPS_BROKEN
6826 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6830 operand *tmp = right;
6835 /* if result = right then exchange them */
6836 if (sameRegs (AOP (result), AOP (right)))
6838 operand *tmp = right;
6843 /* if right is bit then exchange them */
6844 if (AOP_TYPE (right) == AOP_CRY &&
6845 AOP_TYPE (left) != AOP_CRY)
6847 operand *tmp = right;
6851 if (AOP_TYPE (right) == AOP_LIT)
6852 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6854 size = AOP_SIZE (result);
6858 if (AOP_TYPE (left) == AOP_CRY)
6860 if (AOP_TYPE (right) == AOP_LIT)
6862 // c = bit & literal;
6865 // lit>>1 != 0 => result = 1
6866 if (AOP_TYPE (result) == AOP_CRY)
6869 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6871 continueIfTrue (ifx);
6874 emitcode ("setb", "c");
6881 // lit == 0, result = left
6882 if (size && sameRegs (AOP (result), AOP (left)))
6884 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6888 // lit == 1, result = not(left)
6889 if (size && sameRegs (AOP (result), AOP (left)))
6891 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6896 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6897 emitcode ("cpl", "c");
6906 symbol *tlbl = newiTempLabel (NULL);
6907 if (AOP_TYPE (right) == AOP_CRY)
6910 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6914 int sizer = AOP_SIZE (right);
6916 // if val>>1 != 0, result = 1
6917 emitcode ("setb", "c");
6920 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
6922 // test the msb of the lsb
6923 emitcode ("anl", "a,#!constbyte",0xfe);
6924 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6928 emitcode ("rrc", "a");
6930 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6931 emitcode ("cpl", "c");
6932 emitcode ("", "!tlabeldef", (tlbl->key + 100));
6939 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6940 genIfxJump (ifx, "c");
6944 if (sameRegs (AOP (result), AOP (left)))
6946 /* if left is same as result */
6947 for (; size--; offset++)
6949 if (AOP_TYPE (right) == AOP_LIT)
6951 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6953 else if (IS_AOP_PREG (left))
6955 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6956 emitcode ("xrl", "a,%s",
6957 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6958 aopPut (AOP (result), "a", offset);
6961 emitcode ("xrl", "%s,%s",
6962 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6963 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6967 if (AOP_TYPE (left) == AOP_ACC)
6968 emitcode ("xrl", "a,%s",
6969 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6972 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6973 if (IS_AOP_PREG (left))
6975 emitcode ("xrl", "a,%s",
6976 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6977 aopPut (AOP (result), "a", offset);
6980 emitcode ("xrl", "%s,a",
6981 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6988 // left & result in different registers
6989 if (AOP_TYPE (result) == AOP_CRY)
6992 // if(size), result in bit
6993 // if(!size && ifx), conditional oper: if(left ^ right)
6994 symbol *tlbl = newiTempLabel (NULL);
6995 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6998 emitcode ("setb", "c");
7001 if ((AOP_TYPE (right) == AOP_LIT) &&
7002 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7004 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7008 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7009 emitcode ("xrl", "a,%s",
7010 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7012 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7013 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7015 emitcode("mov", "b,a");
7019 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7020 emitcode ("xrl", "a,%s", rOp);
7023 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7029 emitcode ("", "!tlabeldef", tlbl->key + 100);
7033 jmpTrueOrFalse (ifx, tlbl);
7037 for (; (size--); offset++)
7040 // result = left & right
7041 if (AOP_TYPE (right) == AOP_LIT)
7043 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7045 aopPut (AOP (result),
7046 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7050 D (emitcode (";", "better literal XOR."););
7051 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7052 emitcode ("xrl", "a, %s",
7053 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7057 // faster than result <- left, anl result,right
7058 // and better if result is SFR
7059 if (AOP_TYPE (left) == AOP_ACC)
7061 emitcode ("xrl", "a,%s",
7062 aopGet (AOP (right), offset,
7063 FALSE, FALSE, DP2_RESULT_REG));
7067 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7068 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7070 emitcode("mov", "b,a");
7074 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7075 emitcode ("xrl", "a,%s", rOp);
7078 aopPut (AOP (result), "a", offset);
7085 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7086 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7087 freeAsmop (result, NULL, ic, TRUE);
7090 /*-----------------------------------------------------------------*/
7091 /* genInline - write the inline code out */
7092 /*-----------------------------------------------------------------*/
7094 genInline (iCode * ic)
7096 char *buffer, *bp, *bp1;
7098 D (emitcode (";", "genInline "); );
7100 _G.inLine += (!options.asmpeep);
7102 buffer = Safe_strdup(IC_INLINE(ic));
7106 /* emit each line as a code */
7131 /* emitcode("",buffer); */
7132 _G.inLine -= (!options.asmpeep);
7135 /*-----------------------------------------------------------------*/
7136 /* genRRC - rotate right with carry */
7137 /*-----------------------------------------------------------------*/
7141 operand *left, *result;
7144 D (emitcode (";", "genRRC "););
7146 /* rotate right with carry */
7147 left = IC_LEFT (ic);
7148 result = IC_RESULT (ic);
7149 aopOp (left, ic, FALSE, FALSE);
7150 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7152 /* move it to the result */
7153 size = AOP_SIZE (result);
7157 _startLazyDPSEvaluation ();
7160 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7161 emitcode ("rrc", "a");
7162 if (AOP_SIZE (result) > 1)
7163 aopPut (AOP (result), "a", offset--);
7165 _endLazyDPSEvaluation ();
7167 /* now we need to put the carry into the
7168 highest order byte of the result */
7169 if (AOP_SIZE (result) > 1)
7171 MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7173 emitcode ("mov", "acc.7,c");
7174 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7175 freeAsmop (left, NULL, ic, TRUE);
7176 freeAsmop (result, NULL, ic, TRUE);
7179 /*-----------------------------------------------------------------*/
7180 /* genRLC - generate code for rotate left with carry */
7181 /*-----------------------------------------------------------------*/
7185 operand *left, *result;
7189 D (emitcode (";", "genRLC "););
7191 /* rotate right with carry */
7192 left = IC_LEFT (ic);
7193 result = IC_RESULT (ic);
7194 aopOp (left, ic, FALSE, FALSE);
7195 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7197 /* move it to the result */
7198 size = AOP_SIZE (result);
7202 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7204 emitcode ("add", "a,acc");
7205 if (AOP_SIZE (result) > 1)
7207 aopPut (AOP (result), "a", offset++);
7210 _startLazyDPSEvaluation ();
7213 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7215 emitcode ("rlc", "a");
7216 if (AOP_SIZE (result) > 1)
7217 aopPut (AOP (result), "a", offset++);
7219 _endLazyDPSEvaluation ();
7221 /* now we need to put the carry into the
7222 highest order byte of the result */
7223 if (AOP_SIZE (result) > 1)
7225 l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7228 emitcode ("mov", "acc.0,c");
7229 aopPut (AOP (result), "a", 0);
7230 freeAsmop (left, NULL, ic, TRUE);
7231 freeAsmop (result, NULL, ic, TRUE);
7234 /*-----------------------------------------------------------------*/
7235 /* genGetHbit - generates code get highest order bit */
7236 /*-----------------------------------------------------------------*/
7238 genGetHbit (iCode * ic)
7240 operand *left, *result;
7241 left = IC_LEFT (ic);
7242 result = IC_RESULT (ic);
7243 aopOp (left, ic, FALSE, FALSE);
7244 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7246 D (emitcode (";", "genGetHbit "););
7248 /* get the highest order byte into a */
7249 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7250 if (AOP_TYPE (result) == AOP_CRY)
7252 emitcode ("rlc", "a");
7257 emitcode ("rl", "a");
7258 emitcode ("anl", "a,#1");
7263 freeAsmop (left, NULL, ic, TRUE);
7264 freeAsmop (result, NULL, ic, TRUE);
7267 /*-----------------------------------------------------------------*/
7268 /* AccRol - rotate left accumulator by known count */
7269 /*-----------------------------------------------------------------*/
7271 AccRol (int shCount)
7273 shCount &= 0x0007; // shCount : 0..7
7280 emitcode ("rl", "a");
7283 emitcode ("rl", "a");
7284 emitcode ("rl", "a");
7287 emitcode ("swap", "a");
7288 emitcode ("rr", "a");
7291 emitcode ("swap", "a");
7294 emitcode ("swap", "a");
7295 emitcode ("rl", "a");
7298 emitcode ("rr", "a");
7299 emitcode ("rr", "a");
7302 emitcode ("rr", "a");
7307 /*-----------------------------------------------------------------*/
7308 /* AccLsh - left shift accumulator by known count */
7309 /*-----------------------------------------------------------------*/
7311 AccLsh (int shCount)
7316 emitcode ("add", "a,acc");
7317 else if (shCount == 2)
7319 emitcode ("add", "a,acc");
7320 emitcode ("add", "a,acc");
7324 /* rotate left accumulator */
7326 /* and kill the lower order bits */
7327 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7332 /*-----------------------------------------------------------------*/
7333 /* AccRsh - right shift accumulator by known count */
7334 /*-----------------------------------------------------------------*/
7336 AccRsh (int shCount)
7343 emitcode ("rrc", "a");
7347 /* rotate right accumulator */
7348 AccRol (8 - shCount);
7349 /* and kill the higher order bits */
7350 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7355 #ifdef BETTER_LITERAL_SHIFT
7356 /*-----------------------------------------------------------------*/
7357 /* AccSRsh - signed right shift accumulator by known count */
7358 /*-----------------------------------------------------------------*/
7360 AccSRsh (int shCount)
7367 emitcode ("mov", "c,acc.7");
7368 emitcode ("rrc", "a");
7370 else if (shCount == 2)
7372 emitcode ("mov", "c,acc.7");
7373 emitcode ("rrc", "a");
7374 emitcode ("mov", "c,acc.7");
7375 emitcode ("rrc", "a");
7379 tlbl = newiTempLabel (NULL);
7380 /* rotate right accumulator */
7381 AccRol (8 - shCount);
7382 /* and kill the higher order bits */
7383 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7384 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7385 emitcode ("orl", "a,#!constbyte",
7386 (unsigned char) ~SRMask[shCount]);
7387 emitcode ("", "!tlabeldef", tlbl->key + 100);
7393 #ifdef BETTER_LITERAL_SHIFT
7394 /*-----------------------------------------------------------------*/
7395 /* shiftR1Left2Result - shift right one byte from left to result */
7396 /*-----------------------------------------------------------------*/
7398 shiftR1Left2Result (operand * left, int offl,
7399 operand * result, int offr,
7400 int shCount, int sign)
7402 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7403 /* shift right accumulator */
7408 aopPut (AOP (result), "a", offr);
7412 #ifdef BETTER_LITERAL_SHIFT
7413 /*-----------------------------------------------------------------*/
7414 /* shiftL1Left2Result - shift left one byte from left to result */
7415 /*-----------------------------------------------------------------*/
7417 shiftL1Left2Result (operand * left, int offl,
7418 operand * result, int offr, int shCount)
7420 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7421 /* shift left accumulator */
7423 aopPut (AOP (result), "a", offr);
7427 #ifdef BETTER_LITERAL_SHIFT
7428 /*-----------------------------------------------------------------*/
7429 /* movLeft2Result - move byte from left to result */
7430 /*-----------------------------------------------------------------*/
7432 movLeft2Result (operand * left, int offl,
7433 operand * result, int offr, int sign)
7436 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7438 l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
7440 if (*l == '@' && (IS_AOP_PREG (result)))
7442 emitcode ("mov", "a,%s", l);
7443 aopPut (AOP (result), "a", offr);
7449 aopPut (AOP (result), l, offr);
7453 /* MSB sign in acc.7 ! */
7454 if (getDataSize (left) == offl + 1)
7456 emitcode ("mov", "a,%s", l);
7457 aopPut (AOP (result), "a", offr);
7465 #ifdef BETTER_LITERAL_SHIFT
7466 /*-----------------------------------------------------------------*/
7467 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7468 /*-----------------------------------------------------------------*/
7472 emitcode ("rrc", "a");
7473 emitcode ("xch", "a,%s", x);
7474 emitcode ("rrc", "a");
7475 emitcode ("xch", "a,%s", x);
7479 #ifdef BETTER_LITERAL_SHIFT
7481 /*-----------------------------------------------------------------*/
7482 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7483 /*-----------------------------------------------------------------*/
7487 emitcode ("xch", "a,%s", x);
7488 emitcode ("rlc", "a");
7489 emitcode ("xch", "a,%s", x);
7490 emitcode ("rlc", "a");
7494 #ifdef BETTER_LITERAL_SHIFT
7495 /*-----------------------------------------------------------------*/
7496 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7497 /*-----------------------------------------------------------------*/
7501 emitcode ("xch", "a,%s", x);
7502 emitcode ("add", "a,acc");
7503 emitcode ("xch", "a,%s", x);
7504 emitcode ("rlc", "a");
7508 #ifdef BETTER_LITERAL_SHIFT
7509 /*-----------------------------------------------------------------*/
7510 /* AccAXLsh - left shift a:x by known count (0..7) */
7511 /*-----------------------------------------------------------------*/
7513 AccAXLsh (char *x, int shCount)
7528 case 5: // AAAAABBB:CCCCCDDD
7530 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7532 emitcode ("anl", "a,#!constbyte",
7533 SLMask[shCount]); // BBB00000:CCCCCDDD
7535 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7537 AccRol (shCount); // DDDCCCCC:BBB00000
7539 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7541 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7543 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7545 emitcode ("anl", "a,#!constbyte",
7546 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7548 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7550 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7553 case 6: // AAAAAABB:CCCCCCDD
7554 emitcode ("anl", "a,#!constbyte",
7555 SRMask[shCount]); // 000000BB:CCCCCCDD
7556 emitcode ("mov", "c,acc.0"); // c = B
7557 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7559 AccAXRrl1 (x); // BCCCCCCD:D000000B
7560 AccAXRrl1 (x); // BBCCCCCC:DD000000
7562 emitcode("rrc","a");
7563 emitcode("xch","a,%s", x);
7564 emitcode("rrc","a");
7565 emitcode("mov","c,acc.0"); //<< get correct bit
7566 emitcode("xch","a,%s", x);
7568 emitcode("rrc","a");
7569 emitcode("xch","a,%s", x);
7570 emitcode("rrc","a");
7571 emitcode("xch","a,%s", x);
7574 case 7: // a:x <<= 7
7576 emitcode ("anl", "a,#!constbyte",
7577 SRMask[shCount]); // 0000000B:CCCCCCCD
7579 emitcode ("mov", "c,acc.0"); // c = B
7581 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7583 AccAXRrl1 (x); // BCCCCCCC:D0000000
7592 #ifdef BETTER_LITERAL_SHIFT
7594 /*-----------------------------------------------------------------*/
7595 /* AccAXRsh - right shift a:x known count (0..7) */
7596 /*-----------------------------------------------------------------*/
7598 AccAXRsh (char *x, int shCount)
7606 AccAXRrl1 (x); // 0->a:x
7611 AccAXRrl1 (x); // 0->a:x
7614 AccAXRrl1 (x); // 0->a:x
7619 case 5: // AAAAABBB:CCCCCDDD = a:x
7621 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7623 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7625 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7627 emitcode ("anl", "a,#!constbyte",
7628 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7630 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7632 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7634 emitcode ("anl", "a,#!constbyte",
7635 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7637 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7639 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7641 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7644 case 6: // AABBBBBB:CCDDDDDD
7646 emitcode ("mov", "c,acc.7");
7647 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7649 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7651 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7653 emitcode ("anl", "a,#!constbyte",
7654 SRMask[shCount]); // 000000AA:BBBBBBCC
7657 case 7: // ABBBBBBB:CDDDDDDD
7659 emitcode ("mov", "c,acc.7"); // c = A
7661 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7663 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7665 emitcode ("anl", "a,#!constbyte",
7666 SRMask[shCount]); // 0000000A:BBBBBBBC
7675 #ifdef BETTER_LITERAL_SHIFT
7676 /*-----------------------------------------------------------------*/
7677 /* AccAXRshS - right shift signed a:x known count (0..7) */
7678 /*-----------------------------------------------------------------*/
7680 AccAXRshS (char *x, int shCount)
7688 emitcode ("mov", "c,acc.7");
7689 AccAXRrl1 (x); // s->a:x
7693 emitcode ("mov", "c,acc.7");
7694 AccAXRrl1 (x); // s->a:x
7696 emitcode ("mov", "c,acc.7");
7697 AccAXRrl1 (x); // s->a:x
7702 case 5: // AAAAABBB:CCCCCDDD = a:x
7704 tlbl = newiTempLabel (NULL);
7705 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7707 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7709 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7711 emitcode ("anl", "a,#!constbyte",
7712 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7714 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7716 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7718 emitcode ("anl", "a,#!constbyte",
7719 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7721 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7723 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7725 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7727 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7728 emitcode ("orl", "a,#!constbyte",
7729 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7731 emitcode ("", "!tlabeldef", tlbl->key + 100);
7732 break; // SSSSAAAA:BBBCCCCC
7734 case 6: // AABBBBBB:CCDDDDDD
7736 tlbl = newiTempLabel (NULL);
7737 emitcode ("mov", "c,acc.7");
7738 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7740 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7742 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7744 emitcode ("anl", "a,#!constbyte",
7745 SRMask[shCount]); // 000000AA:BBBBBBCC
7747 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7748 emitcode ("orl", "a,#!constbyte",
7749 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7751 emitcode ("", "!tlabeldef", tlbl->key + 100);
7753 case 7: // ABBBBBBB:CDDDDDDD
7755 tlbl = newiTempLabel (NULL);
7756 emitcode ("mov", "c,acc.7"); // c = A
7758 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7760 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7762 emitcode ("anl", "a,#!constbyte",
7763 SRMask[shCount]); // 0000000A:BBBBBBBC
7765 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7766 emitcode ("orl", "a,#!constbyte",
7767 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7769 emitcode ("", "!tlabeldef", tlbl->key + 100);
7777 #ifdef BETTER_LITERAL_SHIFT
7779 _loadLeftIntoAx(char **lsb,
7785 // Get the initial value from left into a pair of registers.
7786 // MSB must be in A, LSB can be any register.
7788 // If the result is held in registers, it is an optimization
7789 // if the LSB can be held in the register which will hold the,
7790 // result LSB since this saves us from having to copy it into
7791 // the result following AccAXLsh.
7793 // If the result is addressed indirectly, this is not a gain.
7794 if (AOP_NEEDSACC(result))
7798 _startLazyDPSEvaluation();
7799 if (AOP_TYPE(left) == AOP_DPTR2)
7802 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
7803 // get LSB in DP2_RESULT_REG.
7804 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
7805 assert(!strcmp(leftByte, DP2_RESULT_REG));
7809 // get LSB into DP2_RESULT_REG
7810 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
7811 if (strcmp(leftByte, DP2_RESULT_REG))
7814 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7817 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
7818 assert(strcmp(leftByte, DP2_RESULT_REG));
7821 _endLazyDPSEvaluation();
7822 *lsb = DP2_RESULT_REG;
7826 if (sameRegs (AOP (result), AOP (left)) &&
7827 ((offl + MSB16) == offr))
7829 /* don't crash result[offr] */
7830 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
7831 emitcode ("xch", "a,%s",
7832 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
7836 movLeft2Result (left, offl, result, offr, 0);
7837 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
7839 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
7840 assert(strcmp(*lsb,"a"));
7845 _storeAxResults(char *lsb,
7849 _startLazyDPSEvaluation();
7850 if (AOP_NEEDSACC(result))
7852 /* We have to explicitly update the result LSB.
7854 emitcode("xch","a,%s", lsb);
7855 aopPut(AOP(result), "a", offr);
7856 emitcode("mov","a,%s", lsb);
7858 if (getDataSize (result) > 1)
7860 aopPut (AOP (result), "a", offr + MSB16);
7862 _endLazyDPSEvaluation();
7865 /*-----------------------------------------------------------------*/
7866 /* shiftL2Left2Result - shift left two bytes from left to result */
7867 /*-----------------------------------------------------------------*/
7869 shiftL2Left2Result (operand * left, int offl,
7870 operand * result, int offr, int shCount)
7874 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7876 AccAXLsh (lsb, shCount);
7878 _storeAxResults(lsb, result, offr);
7882 #ifdef BETTER_LITERAL_SHIFT
7883 /*-----------------------------------------------------------------*/
7884 /* shiftR2Left2Result - shift right two bytes from left to result */
7885 /*-----------------------------------------------------------------*/
7887 shiftR2Left2Result (operand * left, int offl,
7888 operand * result, int offr,
7889 int shCount, int sign)
7893 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7895 /* a:x >> shCount (x = lsb(result)) */
7898 AccAXRshS(lsb, shCount);
7902 AccAXRsh(lsb, shCount);
7905 _storeAxResults(lsb, result, offr);
7911 /*-----------------------------------------------------------------*/
7912 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7913 /*-----------------------------------------------------------------*/
7915 shiftLLeftOrResult (operand * left, int offl,
7916 operand * result, int offr, int shCount)
7918 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7919 /* shift left accumulator */
7921 /* or with result */
7922 emitcode ("orl", "a,%s",
7923 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7924 /* back to result */
7925 aopPut (AOP (result), "a", offr);
7931 /*-----------------------------------------------------------------*/
7932 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7933 /*-----------------------------------------------------------------*/
7935 shiftRLeftOrResult (operand * left, int offl,
7936 operand * result, int offr, int shCount)
7938 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7939 /* shift right accumulator */
7941 /* or with result */
7942 emitcode ("orl", "a,%s",
7943 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7944 /* back to result */
7945 aopPut (AOP (result), "a", offr);
7949 #ifdef BETTER_LITERAL_SHIFT
7950 /*-----------------------------------------------------------------*/
7951 /* genlshOne - left shift a one byte quantity by known count */
7952 /*-----------------------------------------------------------------*/
7954 genlshOne (operand * result, operand * left, int shCount)
7956 D (emitcode (";", "genlshOne "););
7957 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7961 #ifdef BETTER_LITERAL_SHIFT
7962 /*-----------------------------------------------------------------*/
7963 /* genlshTwo - left shift two bytes by known amount != 0 */
7964 /*-----------------------------------------------------------------*/
7966 genlshTwo (operand * result, operand * left, int shCount)
7970 D (emitcode (";", "genlshTwo "););
7972 size = getDataSize (result);
7974 /* if shCount >= 8 */
7979 _startLazyDPSEvaluation();
7985 _endLazyDPSEvaluation();
7986 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7987 aopPut (AOP (result), zero, LSB);
7991 movLeft2Result (left, LSB, result, MSB16, 0);
7992 aopPut (AOP (result), zero, LSB);
7993 _endLazyDPSEvaluation();
7998 aopPut (AOP (result), zero, LSB);
7999 _endLazyDPSEvaluation();
8003 /* 1 <= shCount <= 7 */
8008 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8012 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8020 /*-----------------------------------------------------------------*/
8021 /* shiftLLong - shift left one long from left to result */
8022 /* offl = LSB or MSB16 */
8023 /*-----------------------------------------------------------------*/
8025 shiftLLong (operand * left, operand * result, int offr)
8028 int size = AOP_SIZE (result);
8030 if (size >= LSB + offr)
8032 l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8034 emitcode ("add", "a,acc");
8035 if (sameRegs (AOP (left), AOP (result)) &&
8036 size >= MSB16 + offr && offr != LSB)
8037 emitcode ("xch", "a,%s",
8038 aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8040 aopPut (AOP (result), "a", LSB + offr);
8043 if (size >= MSB16 + offr)
8045 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8047 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8049 emitcode ("rlc", "a");
8050 if (sameRegs (AOP (left), AOP (result)) &&
8051 size >= MSB24 + offr && offr != LSB)
8052 emitcode ("xch", "a,%s",
8053 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8055 aopPut (AOP (result), "a", MSB16 + offr);
8058 if (size >= MSB24 + offr)
8060 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8062 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8064 emitcode ("rlc", "a");
8065 if (sameRegs (AOP (left), AOP (result)) &&
8066 size >= MSB32 + offr && offr != LSB)
8067 emitcode ("xch", "a,%s",
8068 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8070 aopPut (AOP (result), "a", MSB24 + offr);
8073 if (size > MSB32 + offr)
8075 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8077 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8079 emitcode ("rlc", "a");
8080 aopPut (AOP (result), "a", MSB32 + offr);
8083 aopPut (AOP (result), zero, LSB);
8089 /*-----------------------------------------------------------------*/
8090 /* genlshFour - shift four byte by a known amount != 0 */
8091 /*-----------------------------------------------------------------*/
8093 genlshFour (operand * result, operand * left, int shCount)
8097 D (emitcode (";", "genlshFour ");
8100 size = AOP_SIZE (result);
8102 /* if shifting more that 3 bytes */
8107 /* lowest order of left goes to the highest
8108 order of the destination */
8109 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8111 movLeft2Result (left, LSB, result, MSB32, 0);
8112 aopPut (AOP (result), zero, LSB);
8113 aopPut (AOP (result), zero, MSB16);
8114 aopPut (AOP (result), zero, MSB24);
8118 /* more than two bytes */
8119 else if (shCount >= 16)
8121 /* lower order two bytes goes to higher order two bytes */
8123 /* if some more remaining */
8125 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8128 movLeft2Result (left, MSB16, result, MSB32, 0);
8129 movLeft2Result (left, LSB, result, MSB24, 0);
8131 aopPut (AOP (result), zero, MSB16);
8132 aopPut (AOP (result), zero, LSB);
8136 /* if more than 1 byte */
8137 else if (shCount >= 8)
8139 /* lower order three bytes goes to higher order three bytes */
8144 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8146 movLeft2Result (left, LSB, result, MSB16, 0);
8152 movLeft2Result (left, MSB24, result, MSB32, 0);
8153 movLeft2Result (left, MSB16, result, MSB24, 0);
8154 movLeft2Result (left, LSB, result, MSB16, 0);
8155 aopPut (AOP (result), zero, LSB);
8157 else if (shCount == 1)
8158 shiftLLong (left, result, MSB16);
8161 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8162 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8163 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8164 aopPut (AOP (result), zero, LSB);
8169 /* 1 <= shCount <= 7 */
8170 else if (shCount <= 2)
8172 shiftLLong (left, result, LSB);
8174 shiftLLong (result, result, LSB);
8176 /* 3 <= shCount <= 7, optimize */
8179 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8180 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8181 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8186 #ifdef BETTER_LITERAL_SHIFT
8187 /*-----------------------------------------------------------------*/
8188 /* genLeftShiftLiteral - left shifting by known count */
8189 /*-----------------------------------------------------------------*/
8191 genLeftShiftLiteral (operand * left,
8196 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8199 size = getSize (operandType (result));
8201 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8203 /* We only handle certain easy cases so far. */
8205 && (shCount < (size * 8))
8209 D(emitcode (";", "genLeftShiftLiteral wimping out"););
8213 freeAsmop (right, NULL, ic, TRUE);
8215 aopOp(left, ic, FALSE, FALSE);
8216 aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8219 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8221 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8222 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8224 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8227 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8229 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8230 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8232 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8238 emitcode ("; shift left ", "result %d, left %d", size,
8242 /* I suppose that the left size >= result size */
8245 _startLazyDPSEvaluation();
8248 movLeft2Result (left, size, result, size, 0);
8250 _endLazyDPSEvaluation();
8252 else if (shCount >= (size * 8))
8254 _startLazyDPSEvaluation();
8257 aopPut (AOP (result), zero, size);
8259 _endLazyDPSEvaluation();
8266 genlshOne (result, left, shCount);
8270 genlshTwo (result, left, shCount);
8274 genlshFour (result, left, shCount);
8278 fprintf(stderr, "*** ack! mystery literal shift!\n");
8282 freeAsmop (left, NULL, ic, TRUE);
8283 freeAsmop (result, NULL, ic, TRUE);
8288 /*-----------------------------------------------------------------*/
8289 /* genLeftShift - generates code for left shifting */
8290 /*-----------------------------------------------------------------*/
8292 genLeftShift (iCode * ic)
8294 operand *left, *right, *result;
8297 symbol *tlbl, *tlbl1;
8299 D (emitcode (";", "genLeftShift "););
8301 right = IC_RIGHT (ic);
8302 left = IC_LEFT (ic);
8303 result = IC_RESULT (ic);
8305 aopOp (right, ic, FALSE, FALSE);
8308 #ifdef BETTER_LITERAL_SHIFT
8309 /* if the shift count is known then do it
8310 as efficiently as possible */
8311 if (AOP_TYPE (right) == AOP_LIT)
8313 if (genLeftShiftLiteral (left, right, result, ic))
8320 /* shift count is unknown then we have to form
8321 a loop get the loop count in B : Note: we take
8322 only the lower order byte since shifting
8323 more that 32 bits make no sense anyway, ( the
8324 largest size of an object can be only 32 bits ) */
8326 if (AOP_TYPE (right) == AOP_LIT)
8328 /* Really should be handled by genLeftShiftLiteral,
8329 * but since I'm too lazy to fix that today, at least we can make
8330 * some small improvement.
8332 emitcode("mov", "b,#!constbyte",
8333 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8337 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8338 emitcode ("inc", "b");
8340 freeAsmop (right, NULL, ic, TRUE);
8341 aopOp (left, ic, FALSE, FALSE);
8342 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8344 /* now move the left to the result if they are not the
8346 if (!sameRegs (AOP (left), AOP (result)) &&
8347 AOP_SIZE (result) > 1)
8350 size = AOP_SIZE (result);
8352 _startLazyDPSEvaluation ();
8355 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8356 if (*l == '@' && (IS_AOP_PREG (result)))
8359 emitcode ("mov", "a,%s", l);
8360 aopPut (AOP (result), "a", offset);
8363 aopPut (AOP (result), l, offset);
8366 _endLazyDPSEvaluation ();
8369 tlbl = newiTempLabel (NULL);
8370 size = AOP_SIZE (result);
8372 tlbl1 = newiTempLabel (NULL);
8374 /* if it is only one byte then */
8377 symbol *tlbl1 = newiTempLabel (NULL);
8379 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8380 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8381 emitcode ("", "!tlabeldef", tlbl->key + 100);
8382 emitcode ("add", "a,acc");
8383 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8384 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8385 aopPut (AOP (result), "a", 0);
8389 reAdjustPreg (AOP (result));
8391 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8392 emitcode ("", "!tlabeldef", tlbl->key + 100);
8393 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8394 emitcode ("add", "a,acc");
8395 aopPut (AOP (result), "a", offset++);
8396 _startLazyDPSEvaluation ();
8399 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8400 emitcode ("rlc", "a");
8401 aopPut (AOP (result), "a", offset++);
8403 _endLazyDPSEvaluation ();
8404 reAdjustPreg (AOP (result));
8406 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8407 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8409 freeAsmop (left, NULL, ic, TRUE);
8410 freeAsmop (result, NULL, ic, TRUE);
8413 #ifdef BETTER_LITERAL_SHIFT
8414 /*-----------------------------------------------------------------*/
8415 /* genrshOne - right shift a one byte quantity by known count */
8416 /*-----------------------------------------------------------------*/
8418 genrshOne (operand * result, operand * left,
8419 int shCount, int sign)
8421 D (emitcode (";", "genrshOne"););
8422 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8426 #ifdef BETTER_LITERAL_SHIFT
8427 /*-----------------------------------------------------------------*/
8428 /* genrshTwo - right shift two bytes by known amount != 0 */
8429 /*-----------------------------------------------------------------*/
8431 genrshTwo (operand * result, operand * left,
8432 int shCount, int sign)
8434 D (emitcode (";", "genrshTwo"););
8436 /* if shCount >= 8 */
8440 _startLazyDPSEvaluation();
8443 shiftR1Left2Result (left, MSB16, result, LSB,
8448 movLeft2Result (left, MSB16, result, LSB, sign);
8450 addSign (result, MSB16, sign);
8451 _endLazyDPSEvaluation();
8454 /* 1 <= shCount <= 7 */
8457 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8464 /*-----------------------------------------------------------------*/
8465 /* shiftRLong - shift right one long from left to result */
8466 /* offl = LSB or MSB16 */
8467 /*-----------------------------------------------------------------*/
8469 shiftRLong (operand * left, int offl,
8470 operand * result, int sign)
8472 int isSameRegs=sameRegs(AOP(left),AOP(result));
8474 if (isSameRegs && offl>1) {
8475 // we are in big trouble, but this shouldn't happen
8476 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8479 MOVA (aopGet (AOP (left), MSB32, FALSE, NULL));
8484 emitcode ("rlc", "a");
8485 emitcode ("subb", "a,acc");
8486 emitcode ("xch", "a,%s",
8487 aopGet(AOP(left), MSB32, FALSE, DP2_RESULT_REG));
8489 aopPut (AOP(result), zero, MSB32);
8494 emitcode ("clr", "c");
8496 emitcode ("mov", "c,acc.7");
8499 emitcode ("rrc", "a");
8501 if (isSameRegs && offl==MSB16) {
8503 "a,%s",aopGet (AOP (left), MSB24, FALSE, DP2_RESULT_REG));
8505 aopPut (AOP (result), "a", MSB32);
8506 MOVA (aopGet (AOP (left), MSB24, FALSE, NULL));
8509 emitcode ("rrc", "a");
8510 if (isSameRegs && offl==1) {
8511 emitcode ("xch", "a,%s",
8512 aopGet (AOP (left), MSB16, FALSE, DP2_RESULT_REG));
8514 aopPut (AOP (result), "a", MSB24);
8515 MOVA (aopGet (AOP (left), MSB16, FALSE, NULL));
8517 emitcode ("rrc", "a");
8518 aopPut (AOP (result), "a", MSB16 - offl);
8522 MOVA (aopGet (AOP (left), LSB, FALSE, NULL));
8523 emitcode ("rrc", "a");
8524 aopPut (AOP (result), "a", LSB);
8531 /*-----------------------------------------------------------------*/
8532 /* genrshFour - shift four byte by a known amount != 0 */
8533 /*-----------------------------------------------------------------*/
8535 genrshFour (operand * result, operand * left,
8536 int shCount, int sign)
8538 D (emitcode (";", "genrshFour");
8541 /* if shifting more that 3 bytes */
8546 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8548 movLeft2Result (left, MSB32, result, LSB, sign);
8549 addSign (result, MSB16, sign);
8551 else if (shCount >= 16)
8555 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8558 movLeft2Result (left, MSB24, result, LSB, 0);
8559 movLeft2Result (left, MSB32, result, MSB16, sign);
8561 addSign (result, MSB24, sign);
8563 else if (shCount >= 8)
8567 shiftRLong (left, MSB16, result, sign);
8568 else if (shCount == 0)
8570 movLeft2Result (left, MSB16, result, LSB, 0);
8571 movLeft2Result (left, MSB24, result, MSB16, 0);
8572 movLeft2Result (left, MSB32, result, MSB24, sign);
8573 addSign (result, MSB32, sign);
8577 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8578 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8579 /* the last shift is signed */
8580 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8581 addSign (result, MSB32, sign);
8585 { /* 1 <= shCount <= 7 */
8588 shiftRLong (left, LSB, result, sign);
8590 shiftRLong (result, LSB, result, sign);
8594 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8595 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8596 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8602 #ifdef BETTER_LITERAL_SHIFT
8603 /*-----------------------------------------------------------------*/
8604 /* genRightShiftLiteral - right shifting by known count */
8605 /*-----------------------------------------------------------------*/
8607 genRightShiftLiteral (operand * left,
8613 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8616 size = getSize (operandType (result));
8618 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8620 /* We only handle certain easy cases so far. */
8622 && (shCount < (size * 8))
8626 D(emitcode (";", "genRightShiftLiteral wimping out"););
8630 freeAsmop (right, NULL, ic, TRUE);
8632 aopOp (left, ic, FALSE, FALSE);
8633 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8636 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8640 /* test the LEFT size !!! */
8642 /* I suppose that the left size >= result size */
8645 size = getDataSize (result);
8646 _startLazyDPSEvaluation();
8649 movLeft2Result (left, size, result, size, 0);
8651 _endLazyDPSEvaluation();
8653 else if (shCount >= (size * 8))
8657 /* get sign in acc.7 */
8658 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
8660 addSign (result, LSB, sign);
8667 genrshOne (result, left, shCount, sign);
8671 genrshTwo (result, left, shCount, sign);
8675 genrshFour (result, left, shCount, sign);
8682 freeAsmop (left, NULL, ic, TRUE);
8683 freeAsmop (result, NULL, ic, TRUE);
8689 /*-----------------------------------------------------------------*/
8690 /* genSignedRightShift - right shift of signed number */
8691 /*-----------------------------------------------------------------*/
8693 genSignedRightShift (iCode * ic)
8695 operand *right, *left, *result;
8698 symbol *tlbl, *tlbl1;
8700 D (emitcode (";", "genSignedRightShift "););
8702 /* we do it the hard way put the shift count in b
8703 and loop thru preserving the sign */
8705 right = IC_RIGHT (ic);
8706 left = IC_LEFT (ic);
8707 result = IC_RESULT (ic);
8709 aopOp (right, ic, FALSE, FALSE);
8711 #ifdef BETTER_LITERAL_SHIFT
8712 if (AOP_TYPE (right) == AOP_LIT)
8714 if (genRightShiftLiteral (left, right, result, ic, 1))
8720 /* shift count is unknown then we have to form
8721 a loop get the loop count in B : Note: we take
8722 only the lower order byte since shifting
8723 more that 32 bits make no sense anyway, ( the
8724 largest size of an object can be only 32 bits ) */
8726 if (AOP_TYPE (right) == AOP_LIT)
8728 /* Really should be handled by genRightShiftLiteral,
8729 * but since I'm too lazy to fix that today, at least we can make
8730 * some small improvement.
8732 emitcode("mov", "b,#!constbyte",
8733 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8737 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8738 emitcode ("inc", "b");
8740 freeAsmop (right, NULL, ic, TRUE);
8741 aopOp (left, ic, FALSE, FALSE);
8742 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8744 /* now move the left to the result if they are not the
8746 if (!sameRegs (AOP (left), AOP (result)) &&
8747 AOP_SIZE (result) > 1)
8750 size = AOP_SIZE (result);
8752 _startLazyDPSEvaluation ();
8755 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8756 if (*l == '@' && IS_AOP_PREG (result))
8759 emitcode ("mov", "a,%s", l);
8760 aopPut (AOP (result), "a", offset);
8763 aopPut (AOP (result), l, offset);
8766 _endLazyDPSEvaluation ();
8769 /* mov the highest order bit to OVR */
8770 tlbl = newiTempLabel (NULL);
8771 tlbl1 = newiTempLabel (NULL);
8773 size = AOP_SIZE (result);
8775 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
8776 emitcode ("rlc", "a");
8777 emitcode ("mov", "ov,c");
8778 /* if it is only one byte then */
8781 MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8782 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8783 emitcode ("", "!tlabeldef", tlbl->key + 100);
8784 emitcode ("mov", "c,ov");
8785 emitcode ("rrc", "a");
8786 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8787 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8788 aopPut (AOP (result), "a", 0);
8792 reAdjustPreg (AOP (result));
8793 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8794 emitcode ("", "!tlabeldef", tlbl->key + 100);
8795 emitcode ("mov", "c,ov");
8796 _startLazyDPSEvaluation ();
8799 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8800 emitcode ("rrc", "a");
8801 aopPut (AOP (result), "a", offset--);
8803 _endLazyDPSEvaluation ();
8804 reAdjustPreg (AOP (result));
8805 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8806 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8809 freeAsmop (left, NULL, ic, TRUE);
8810 freeAsmop (result, NULL, ic, TRUE);
8813 /*-----------------------------------------------------------------*/
8814 /* genRightShift - generate code for right shifting */
8815 /*-----------------------------------------------------------------*/
8817 genRightShift (iCode * ic)
8819 operand *right, *left, *result;
8823 symbol *tlbl, *tlbl1;
8825 D (emitcode (";", "genRightShift "););
8827 /* if signed then we do it the hard way preserve the
8828 sign bit moving it inwards */
8829 retype = getSpec (operandType (IC_RESULT (ic)));
8831 if (!SPEC_USIGN (retype))
8833 genSignedRightShift (ic);
8837 /* signed & unsigned types are treated the same : i.e. the
8838 signed is NOT propagated inwards : quoting from the
8839 ANSI - standard : "for E1 >> E2, is equivalent to division
8840 by 2**E2 if unsigned or if it has a non-negative value,
8841 otherwise the result is implementation defined ", MY definition
8842 is that the sign does not get propagated */
8844 right = IC_RIGHT (ic);
8845 left = IC_LEFT (ic);
8846 result = IC_RESULT (ic);
8848 aopOp (right, ic, FALSE, FALSE);
8850 #ifdef BETTER_LITERAL_SHIFT
8851 /* if the shift count is known then do it
8852 as efficiently as possible */
8853 if (AOP_TYPE (right) == AOP_LIT)
8855 if (genRightShiftLiteral (left, right, result, ic, 0))
8862 /* shift count is unknown then we have to form
8863 a loop get the loop count in B : Note: we take
8864 only the lower order byte since shifting
8865 more that 32 bits make no sense anyway, ( the
8866 largest size of an object can be only 32 bits ) */
8868 if (AOP_TYPE (right) == AOP_LIT)
8870 /* Really should be handled by genRightShiftLiteral,
8871 * but since I'm too lazy to fix that today, at least we can make
8872 * some small improvement.
8874 emitcode("mov", "b,#!constbyte",
8875 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8879 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8880 emitcode ("inc", "b");
8882 freeAsmop (right, NULL, ic, TRUE);
8883 aopOp (left, ic, FALSE, FALSE);
8884 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8886 /* now move the left to the result if they are not the
8888 if (!sameRegs (AOP (left), AOP (result)) &&
8889 AOP_SIZE (result) > 1)
8892 size = AOP_SIZE (result);
8894 _startLazyDPSEvaluation ();
8897 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8898 if (*l == '@' && IS_AOP_PREG (result))
8901 emitcode ("mov", "a,%s", l);
8902 aopPut (AOP (result), "a", offset);
8905 aopPut (AOP (result), l, offset);
8908 _endLazyDPSEvaluation ();
8911 tlbl = newiTempLabel (NULL);
8912 tlbl1 = newiTempLabel (NULL);
8913 size = AOP_SIZE (result);
8916 /* if it is only one byte then */
8919 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8920 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8921 emitcode ("", "!tlabeldef", tlbl->key + 100);
8923 emitcode ("rrc", "a");
8924 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8925 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8926 aopPut (AOP (result), "a", 0);
8930 reAdjustPreg (AOP (result));
8931 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8932 emitcode ("", "!tlabeldef", tlbl->key + 100);
8934 _startLazyDPSEvaluation ();
8937 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8938 emitcode ("rrc", "a");
8939 aopPut (AOP (result), "a", offset--);
8941 _endLazyDPSEvaluation ();
8942 reAdjustPreg (AOP (result));
8944 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8945 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8948 freeAsmop (left, NULL, ic, TRUE);
8949 freeAsmop (result, NULL, ic, TRUE);
8952 /*-----------------------------------------------------------------*/
8953 /* genUnpackBits - generates code for unpacking bits */
8954 /*-----------------------------------------------------------------*/
8956 genUnpackBits (operand * result, char *rname, int ptype)
8963 D (emitcode (";", "genUnpackBits "););
8965 etype = getSpec (operandType (result));
8967 /* read the first byte */
8973 emitcode ("mov", "a,@%s", rname);
8977 emitcode ("movx", "a,@%s", rname);
8981 emitcode ("movx", "a,@dptr");
8985 emitcode ("clr", "a");
8986 emitcode ("movc", "a,@a+dptr");
8990 emitcode ("lcall", "__gptrget");
8994 /* if we have bitdisplacement then it fits */
8995 /* into this byte completely or if length is */
8996 /* less than a byte */
8997 if (((shCnt = SPEC_BSTR (etype)) != 0) || (SPEC_BLEN (etype) <= 8))
9000 /* shift right acc */
9003 emitcode ("anl", "a,#!constbyte",
9004 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
9005 aopPut (AOP (result), "a", offset);
9009 /* bit field did not fit in a byte */
9010 rlen = SPEC_BLEN (etype) - 8;
9011 aopPut (AOP (result), "a", offset++);
9020 emitcode ("inc", "%s", rname);
9021 emitcode ("mov", "a,@%s", rname);
9025 emitcode ("inc", "%s", rname);
9026 emitcode ("movx", "a,@%s", rname);
9030 emitcode ("inc", "dptr");
9031 emitcode ("movx", "a,@dptr");
9035 emitcode ("clr", "a");
9036 emitcode ("inc", "dptr");
9037 emitcode ("movc", "a,@a+dptr");
9041 emitcode ("inc", "dptr");
9042 emitcode ("lcall", "__gptrget");
9047 /* if we are done */
9051 aopPut (AOP (result), "a", offset++);
9057 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (rlen));
9058 aopPut (AOP (result), "a", offset);
9065 /*-----------------------------------------------------------------*/
9066 /* genDataPointerGet - generates code when ptr offset is known */
9067 /*-----------------------------------------------------------------*/
9069 genDataPointerGet (operand * left,
9075 int size, offset = 0;
9076 aopOp (result, ic, TRUE, FALSE);
9078 /* get the string representation of the name */
9079 l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9080 size = AOP_SIZE (result);
9081 _startLazyDPSEvaluation ();
9086 SNPRINTF (buff, sizeof(buff),
9087 "(%s + %d)", l + 1, offset);
9091 SNPRINTF (buff, sizeof(buff),
9094 aopPut (AOP (result), buff, offset++);
9096 _endLazyDPSEvaluation ();
9098 freeAsmop (left, NULL, ic, TRUE);
9099 freeAsmop (result, NULL, ic, TRUE);
9102 /*-----------------------------------------------------------------*/
9103 /* genNearPointerGet - emitcode for near pointer fetch */
9104 /*-----------------------------------------------------------------*/
9106 genNearPointerGet (operand * left,
9114 sym_link *rtype, *retype, *letype;
9115 sym_link *ltype = operandType (left);
9118 rtype = operandType (result);
9119 retype = getSpec (rtype);
9120 letype = getSpec (ltype);
9122 aopOp (left, ic, FALSE, FALSE);
9124 /* if left is rematerialisable and
9125 result is not bit variable type and
9126 the left is pointer to data space i.e
9127 lower 128 bytes of space */
9128 if (AOP_TYPE (left) == AOP_IMMD &&
9129 !IS_BITVAR (retype) &&
9130 !IS_BITVAR (letype) &&
9131 DCL_TYPE (ltype) == POINTER)
9133 genDataPointerGet (left, result, ic);
9137 /* if the value is already in a pointer register
9138 then don't need anything more */
9139 if (!AOP_INPREG (AOP (left)))
9141 /* otherwise get a free pointer register */
9143 preg = getFreePtr (ic, &aop, FALSE);
9144 emitcode ("mov", "%s,%s",
9146 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9150 rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9152 freeAsmop (left, NULL, ic, TRUE);
9153 aopOp (result, ic, FALSE, FALSE);
9155 /* if bitfield then unpack the bits */
9156 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9157 genUnpackBits (result, rname, POINTER);
9160 /* we have can just get the values */
9161 int size = AOP_SIZE (result);
9166 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9169 emitcode ("mov", "a,@%s", rname);
9170 aopPut (AOP (result), "a", offset);
9174 SNPRINTF (buff, sizeof(buff), "@%s", rname);
9175 aopPut (AOP (result), buff, offset);
9180 emitcode ("inc", "%s", rname);
9185 /* now some housekeeping stuff */
9188 /* we had to allocate for this iCode */
9189 if (pi) { /* post increment present */
9190 aopPut(AOP ( left ),rname,0);
9192 freeAsmop (NULL, aop, ic, TRUE);
9196 /* we did not allocate which means left
9197 already in a pointer register, then
9198 if size > 0 && this could be used again
9199 we have to point it back to where it
9201 if (AOP_SIZE (result) > 1 &&
9202 !OP_SYMBOL (left)->remat &&
9203 (OP_SYMBOL (left)->liveTo > ic->seq ||
9207 int size = AOP_SIZE (result) - 1;
9209 emitcode ("dec", "%s", rname);
9214 freeAsmop (result, NULL, ic, TRUE);
9215 if (pi) pi->generated = 1;
9218 /*-----------------------------------------------------------------*/
9219 /* genPagedPointerGet - emitcode for paged pointer fetch */
9220 /*-----------------------------------------------------------------*/
9222 genPagedPointerGet (operand * left,
9230 sym_link *rtype, *retype, *letype;
9232 rtype = operandType (result);
9233 retype = getSpec (rtype);
9234 letype = getSpec (operandType (left));
9235 aopOp (left, ic, FALSE, FALSE);
9237 /* if the value is already in a pointer register
9238 then don't need anything more */
9239 if (!AOP_INPREG (AOP (left)))
9241 /* otherwise get a free pointer register */
9243 preg = getFreePtr (ic, &aop, FALSE);
9244 emitcode ("mov", "%s,%s",
9246 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9250 rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9252 freeAsmop (left, NULL, ic, TRUE);
9253 aopOp (result, ic, FALSE, FALSE);
9255 /* if bitfield then unpack the bits */
9256 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9257 genUnpackBits (result, rname, PPOINTER);
9260 /* we have can just get the values */
9261 int size = AOP_SIZE (result);
9267 emitcode ("movx", "a,@%s", rname);
9268 aopPut (AOP (result), "a", offset);
9273 emitcode ("inc", "%s", rname);
9277 /* now some housekeeping stuff */
9280 /* we had to allocate for this iCode */
9281 if (pi) aopPut ( AOP (left), rname, 0);
9282 freeAsmop (NULL, aop, ic, TRUE);
9286 /* we did not allocate which means left
9287 already in a pointer register, then
9288 if size > 0 && this could be used again
9289 we have to point it back to where it
9291 if (AOP_SIZE (result) > 1 &&
9292 !OP_SYMBOL (left)->remat &&
9293 (OP_SYMBOL (left)->liveTo > ic->seq ||
9297 int size = AOP_SIZE (result) - 1;
9299 emitcode ("dec", "%s", rname);
9304 freeAsmop (result, NULL, ic, TRUE);
9305 if (pi) pi->generated = 1;
9308 /*-----------------------------------------------------------------*/
9309 /* genFarPointerGet - gget value from far space */
9310 /*-----------------------------------------------------------------*/
9312 genFarPointerGet (operand * left,
9313 operand * result, iCode * ic, iCode *pi)
9315 int size, offset, dopi=1;
9316 sym_link *retype = getSpec (operandType (result));
9317 sym_link *letype = getSpec (operandType (left));
9318 D (emitcode (";", "genFarPointerGet"););
9320 aopOp (left, ic, FALSE, FALSE);
9322 /* if the operand is already in dptr
9323 then we do nothing else we move the value to dptr */
9324 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9326 /* if this is remateriazable */
9327 if (AOP_TYPE (left) == AOP_IMMD)
9329 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9333 /* we need to get it byte by byte */
9334 _startLazyDPSEvaluation ();
9335 if (AOP_TYPE (left) != AOP_DPTR)
9337 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9338 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9339 if (options.model == MODEL_FLAT24)
9340 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9344 /* We need to generate a load to DPTR indirect through DPTR. */
9345 D (emitcode (";", "genFarPointerGet -- indirection special case."););
9346 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9347 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9348 if (options.model == MODEL_FLAT24)
9349 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9350 emitcode ("pop", "dph");
9351 emitcode ("pop", "dpl");
9354 _endLazyDPSEvaluation ();
9357 /* so dptr know contains the address */
9358 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9360 /* if bit then unpack */
9361 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9362 if (AOP_INDPTRn(left)) {
9363 genSetDPTR(AOP(left)->aopu.dptr);
9365 genUnpackBits (result, "dptr", FPOINTER);
9366 if (AOP_INDPTRn(left)) {
9371 size = AOP_SIZE (result);
9374 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9376 genSetDPTR(AOP(left)->aopu.dptr);
9377 emitcode ("movx", "a,@dptr");
9378 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9379 emitcode ("inc", "dptr");
9381 aopPut (AOP (result), "a", offset++);
9384 _startLazyDPSEvaluation ();
9386 if (AOP_INDPTRn(left)) {
9387 genSetDPTR(AOP(left)->aopu.dptr);
9393 emitcode ("movx", "a,@dptr");
9394 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9395 emitcode ("inc", "dptr");
9397 aopPut (AOP (result), "a", offset++);
9399 _endLazyDPSEvaluation ();
9402 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9403 if (!AOP_INDPTRn(left)) {
9404 _startLazyDPSEvaluation ();
9405 aopPut ( AOP (left), "dpl", 0);
9406 aopPut ( AOP (left), "dph", 1);
9407 if (options.model == MODEL_FLAT24)
9408 aopPut ( AOP (left), "dpx", 2);
9409 _endLazyDPSEvaluation ();
9412 } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) &&
9413 AOP_SIZE(result) > 1 &&
9415 (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
9417 size = AOP_SIZE (result) - 1;
9418 if (AOP_INDPTRn(left)) {
9419 genSetDPTR(AOP(left)->aopu.dptr);
9421 while (size--) emitcode ("lcall","__decdptr");
9422 if (AOP_INDPTRn(left)) {
9427 freeAsmop (left, NULL, ic, TRUE);
9428 freeAsmop (result, NULL, ic, TRUE);
9431 /*-----------------------------------------------------------------*/
9432 /* genCodePointerGet - get value from code space */
9433 /*-----------------------------------------------------------------*/
9435 genCodePointerGet (operand * left,
9436 operand * result, iCode * ic, iCode *pi)
9438 int size, offset, dopi=1;
9439 sym_link *retype = getSpec (operandType (result));
9441 aopOp (left, ic, FALSE, FALSE);
9443 /* if the operand is already in dptr
9444 then we do nothing else we move the value to dptr */
9445 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
9447 /* if this is remateriazable */
9448 if (AOP_TYPE (left) == AOP_IMMD)
9450 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9453 { /* we need to get it byte by byte */
9454 _startLazyDPSEvaluation ();
9455 if (AOP_TYPE (left) != AOP_DPTR)
9457 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9458 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9459 if (options.model == MODEL_FLAT24)
9460 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9464 /* We need to generate a load to DPTR indirect through DPTR. */
9465 D (emitcode (";", "gencodePointerGet -- indirection special case."););
9466 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9467 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9468 if (options.model == MODEL_FLAT24)
9469 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9470 emitcode ("pop", "dph");
9471 emitcode ("pop", "dpl");
9474 _endLazyDPSEvaluation ();
9477 /* so dptr know contains the address */
9478 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9480 /* if bit then unpack */
9481 if (IS_BITVAR (retype)) {
9482 if (AOP_INDPTRn(left)) {
9483 genSetDPTR(AOP(left)->aopu.dptr);
9485 genUnpackBits (result, "dptr", CPOINTER);
9486 if (AOP_INDPTRn(left)) {
9491 size = AOP_SIZE (result);
9493 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9495 genSetDPTR(AOP(left)->aopu.dptr);
9496 emitcode ("clr", "a");
9497 emitcode ("movc", "a,@a+dptr");
9498 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9499 emitcode ("inc", "dptr");
9501 aopPut (AOP (result), "a", offset++);
9504 _startLazyDPSEvaluation ();
9507 if (AOP_INDPTRn(left)) {
9508 genSetDPTR(AOP(left)->aopu.dptr);
9514 emitcode ("clr", "a");
9515 emitcode ("movc", "a,@a+dptr");
9516 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9517 emitcode ("inc", "dptr");
9518 aopPut (AOP (result), "a", offset++);
9520 _endLazyDPSEvaluation ();
9523 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9524 if (!AOP_INDPTRn(left)) {
9525 _startLazyDPSEvaluation ();
9527 aopPut ( AOP (left), "dpl", 0);
9528 aopPut ( AOP (left), "dph", 1);
9529 if (options.model == MODEL_FLAT24)
9530 aopPut ( AOP (left), "dpx", 2);
9532 _endLazyDPSEvaluation ();
9535 } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
9536 AOP_SIZE(result) > 1 &&
9537 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9539 size = AOP_SIZE (result) - 1;
9540 if (AOP_INDPTRn(left)) {
9541 genSetDPTR(AOP(left)->aopu.dptr);
9543 while (size--) emitcode ("lcall","__decdptr");
9544 if (AOP_INDPTRn(left)) {
9549 freeAsmop (left, NULL, ic, TRUE);
9550 freeAsmop (result, NULL, ic, TRUE);
9553 /*-----------------------------------------------------------------*/
9554 /* genGenPointerGet - gget value from generic pointer space */
9555 /*-----------------------------------------------------------------*/
9557 genGenPointerGet (operand * left,
9558 operand * result, iCode * ic, iCode * pi)
9561 sym_link *retype = getSpec (operandType (result));
9562 sym_link *letype = getSpec (operandType (left));
9564 D (emitcode (";", "genGenPointerGet "); );
9566 aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
9568 /* if the operand is already in dptr
9569 then we do nothing else we move the value to dptr */
9570 if (AOP_TYPE (left) != AOP_STR)
9572 /* if this is remateriazable */
9573 if (AOP_TYPE (left) == AOP_IMMD)
9575 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9576 if (AOP(left)->aopu.aop_immd.from_cast_remat)
9578 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
9582 emitcode ("mov", "b,#%d", pointerCode (retype));
9586 { /* we need to get it byte by byte */
9587 _startLazyDPSEvaluation ();
9588 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
9589 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
9590 if (options.model == MODEL_FLAT24) {
9591 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9592 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
9594 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9596 _endLazyDPSEvaluation ();
9600 /* so dptr-b now contains the address */
9602 aopOp (result, ic, FALSE, TRUE);
9605 /* if bit then unpack */
9606 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9608 genUnpackBits (result, "dptr", GPOINTER);
9612 size = AOP_SIZE (result);
9619 // Get two bytes at a time, results in _AP & A.
9620 // dptr will be incremented ONCE by __gptrgetWord.
9622 // Note: any change here must be coordinated
9623 // with the implementation of __gptrgetWord
9624 // in device/lib/_gptrget.c
9625 emitcode ("lcall", "__gptrgetWord");
9626 aopPut (AOP (result), DP2_RESULT_REG, offset++);
9627 aopPut (AOP (result), "a", offset++);
9632 // Only one byte to get.
9633 emitcode ("lcall", "__gptrget");
9634 aopPut (AOP (result), "a", offset++);
9637 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9639 emitcode ("inc", "dptr");
9644 if (pi && AOP_TYPE (left) != AOP_IMMD) {
9645 _startLazyDPSEvaluation ();
9647 aopPut ( AOP (left), "dpl", 0);
9648 aopPut ( AOP (left), "dph", 1);
9649 if (options.model == MODEL_FLAT24) {
9650 aopPut ( AOP (left), "dpx", 2);
9651 aopPut ( AOP (left), "b", 3);
9652 } else aopPut ( AOP (left), "b", 2);
9654 _endLazyDPSEvaluation ();
9657 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9658 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9660 size = AOP_SIZE (result) - 1;
9661 while (size--) emitcode ("lcall","__decdptr");
9664 freeAsmop (left, NULL, ic, TRUE);
9665 freeAsmop (result, NULL, ic, TRUE);
9668 /*-----------------------------------------------------------------*/
9669 /* genPointerGet - generate code for pointer get */
9670 /*-----------------------------------------------------------------*/
9672 genPointerGet (iCode * ic, iCode *pi)
9674 operand *left, *result;
9675 sym_link *type, *etype;
9678 D (emitcode (";", "genPointerGet ");
9681 left = IC_LEFT (ic);
9682 result = IC_RESULT (ic);
9684 /* depending on the type of pointer we need to
9685 move it to the correct pointer register */
9686 type = operandType (left);
9687 etype = getSpec (type);
9688 /* if left is of type of pointer then it is simple */
9689 if (IS_PTR (type) && !IS_FUNC (type->next))
9690 p_type = DCL_TYPE (type);
9693 /* we have to go by the storage class */
9694 p_type = PTR_TYPE (SPEC_OCLS (etype));
9696 /* special case when cast remat */
9697 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9698 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9699 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9700 type = operandType (left);
9701 p_type = DCL_TYPE (type);
9703 /* now that we have the pointer type we assign
9704 the pointer values */
9710 genNearPointerGet (left, result, ic, pi);
9714 genPagedPointerGet (left, result, ic, pi);
9718 genFarPointerGet (left, result, ic, pi);
9722 genCodePointerGet (left, result, ic, pi);
9726 genGenPointerGet (left, result, ic, pi);
9732 /*-----------------------------------------------------------------*/
9733 /* genPackBits - generates code for packed bit storage */
9734 /*-----------------------------------------------------------------*/
9736 genPackBits (sym_link * etype,
9738 char *rname, int p_type)
9745 blen = SPEC_BLEN (etype);
9746 bstr = SPEC_BSTR (etype);
9748 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9750 /* if the bit lenth is less than or */
9751 /* it exactly fits a byte then */
9752 if (SPEC_BLEN (etype) <= 8)
9754 /* shift left acc */
9755 AccLsh (SPEC_BSTR (etype));
9757 if (SPEC_BLEN (etype) < 8)
9758 { /* if smaller than a byte */
9764 emitcode ("mov", "b,a");
9765 emitcode ("mov", "a,@%s", rname);
9769 emitcode ("mov", "b,a");
9770 emitcode ("movx", "a,@dptr");
9774 emitcode ("push", "b");
9775 emitcode ("push", "acc");
9776 emitcode ("lcall", "__gptrget");
9777 emitcode ("pop", "b");
9781 emitcode ("anl", "a,#!constbyte", (unsigned char)
9782 ((unsigned char) (0xFF << (blen + bstr)) |
9783 (unsigned char) (0xFF >> (8 - bstr))));
9784 emitcode ("orl", "a,b");
9785 if (p_type == GPOINTER)
9786 emitcode ("pop", "b");
9793 emitcode ("mov", "@%s,a", rname);
9797 emitcode ("movx", "@dptr,a");
9801 emitcode ("lcall", "__gptrput");
9806 if (SPEC_BLEN (etype) <= 8)
9809 emitcode ("inc", "%s", rname);
9810 rLen = SPEC_BLEN (etype);
9812 /* now generate for lengths greater than one byte */
9816 l = aopGet (AOP (right), offset++, FALSE, TRUE, NULL);
9828 emitcode ("mov", "@%s,a", rname);
9831 emitcode ("mov", "@%s,%s", rname, l);
9836 emitcode ("movx", "@dptr,a");
9841 emitcode ("lcall", "__gptrput");
9844 emitcode ("inc", "%s", rname);
9849 /* last last was not complete */
9852 /* save the byte & read byte */
9856 emitcode ("mov", "b,a");
9857 emitcode ("mov", "a,@%s", rname);
9861 emitcode ("mov", "b,a");
9862 emitcode ("movx", "a,@dptr");
9866 emitcode ("push", "b");
9867 emitcode ("push", "acc");
9868 emitcode ("lcall", "__gptrget");
9869 emitcode ("pop", "b");
9873 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1 << rLen));
9874 emitcode ("orl", "a,b");
9877 if (p_type == GPOINTER)
9878 emitcode ("pop", "b");
9884 emitcode ("mov", "@%s,a", rname);
9888 emitcode ("movx", "@dptr,a");
9892 emitcode ("lcall", "__gptrput");
9896 /*-----------------------------------------------------------------*/
9897 /* genDataPointerSet - remat pointer to data space */
9898 /*-----------------------------------------------------------------*/
9900 genDataPointerSet (operand * right,
9904 int size, offset = 0;
9907 aopOp (right, ic, FALSE, FALSE);
9909 l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
9910 size = AOP_SIZE (right);
9915 SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
9919 SNPRINTF (buff, sizeof(buff), "%s", l + 1);
9922 emitcode ("mov", "%s,%s", buff,
9923 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9926 freeAsmop (right, NULL, ic, TRUE);
9927 freeAsmop (result, NULL, ic, TRUE);
9930 /*-----------------------------------------------------------------*/
9931 /* genNearPointerSet - emitcode for near pointer put */
9932 /*-----------------------------------------------------------------*/
9934 genNearPointerSet (operand * right,
9941 sym_link *retype, *letype;
9942 sym_link *ptype = operandType (result);
9944 retype = getSpec (operandType (right));
9945 letype = getSpec (ptype);
9947 aopOp (result, ic, FALSE, FALSE);
9949 /* if the result is rematerializable &
9950 in data space & not a bit variable */
9951 if (AOP_TYPE (result) == AOP_IMMD &&
9952 DCL_TYPE (ptype) == POINTER &&
9953 !IS_BITVAR (retype) &&
9954 !IS_BITVAR (letype))
9956 genDataPointerSet (right, result, ic);
9960 /* if the value is already in a pointer register
9961 then don't need anything more */
9962 if (!AOP_INPREG (AOP (result)))
9964 /* otherwise get a free pointer register */
9968 preg = getFreePtr (ic, &aop, FALSE);
9969 emitcode ("mov", "%s,%s",
9971 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
9975 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
9977 aopOp (right, ic, FALSE, FALSE);
9979 /* if bitfield then unpack the bits */
9980 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9981 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9984 /* we have can just get the values */
9985 int size = AOP_SIZE (right);
9990 l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
9994 emitcode ("mov", "@%s,a", rname);
9997 emitcode ("mov", "@%s,%s", rname, l);
9999 emitcode ("inc", "%s", rname);
10004 /* now some housekeeping stuff */
10007 /* we had to allocate for this iCode */
10008 if (pi) aopPut (AOP (result),rname,0);
10009 freeAsmop (NULL, aop, ic, TRUE);
10013 /* we did not allocate which means left
10014 already in a pointer register, then
10015 if size > 0 && this could be used again
10016 we have to point it back to where it
10018 if (AOP_SIZE (right) > 1 &&
10019 !OP_SYMBOL (result)->remat &&
10020 (OP_SYMBOL (result)->liveTo > ic->seq ||
10024 int size = AOP_SIZE (right) - 1;
10026 emitcode ("dec", "%s", rname);
10031 if (pi) pi->generated = 1;
10032 freeAsmop (result, NULL, ic, TRUE);
10033 freeAsmop (right, NULL, ic, TRUE);
10038 /*-----------------------------------------------------------------*/
10039 /* genPagedPointerSet - emitcode for Paged pointer put */
10040 /*-----------------------------------------------------------------*/
10042 genPagedPointerSet (operand * right,
10049 sym_link *retype, *letype;
10051 retype = getSpec (operandType (right));
10052 letype = getSpec (operandType (result));
10054 aopOp (result, ic, FALSE, FALSE);
10056 /* if the value is already in a pointer register
10057 then don't need anything more */
10058 if (!AOP_INPREG (AOP (result)))
10060 /* otherwise get a free pointer register */
10063 aop = newAsmop (0);
10064 preg = getFreePtr (ic, &aop, FALSE);
10065 emitcode ("mov", "%s,%s",
10067 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10068 rname = preg->name;
10071 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10073 aopOp (right, ic, FALSE, FALSE);
10075 /* if bitfield then unpack the bits */
10076 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10077 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
10080 /* we have can just get the values */
10081 int size = AOP_SIZE (right);
10086 MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10088 emitcode ("movx", "@%s,a", rname);
10091 emitcode ("inc", "%s", rname);
10097 /* now some housekeeping stuff */
10100 if (pi) aopPut (AOP (result),rname,0);
10101 /* we had to allocate for this iCode */
10102 freeAsmop (NULL, aop, ic, TRUE);
10106 /* we did not allocate which means left
10107 already in a pointer register, then
10108 if size > 0 && this could be used again
10109 we have to point it back to where it
10111 if (AOP_SIZE (right) > 1 &&
10112 !OP_SYMBOL (result)->remat &&
10113 (OP_SYMBOL (result)->liveTo > ic->seq ||
10117 int size = AOP_SIZE (right) - 1;
10119 emitcode ("dec", "%s", rname);
10124 if (pi) pi->generated = 1;
10125 freeAsmop (result, NULL, ic, TRUE);
10126 freeAsmop (right, NULL, ic, TRUE);
10131 /*-----------------------------------------------------------------*/
10132 /* genFarPointerSet - set value from far space */
10133 /*-----------------------------------------------------------------*/
10135 genFarPointerSet (operand * right,
10136 operand * result, iCode * ic, iCode *pi)
10138 int size, offset, dopi=1;
10139 sym_link *retype = getSpec (operandType (right));
10140 sym_link *letype = getSpec (operandType (result));
10142 aopOp (result, ic, FALSE, FALSE);
10144 /* if the operand is already in dptr
10145 then we do nothing else we move the value to dptr */
10146 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10148 /* if this is remateriazable */
10149 if (AOP_TYPE (result) == AOP_IMMD)
10150 emitcode ("mov", "dptr,%s",
10151 aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10154 /* we need to get it byte by byte */
10155 _startLazyDPSEvaluation ();
10156 if (AOP_TYPE (result) != AOP_DPTR)
10158 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10159 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10160 if (options.model == MODEL_FLAT24)
10161 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10165 /* We need to generate a load to DPTR indirect through DPTR. */
10166 D (emitcode (";", "genFarPointerSet -- indirection special case."););
10168 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10169 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10170 if (options.model == MODEL_FLAT24)
10171 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10172 emitcode ("pop", "dph");
10173 emitcode ("pop", "dpl");
10176 _endLazyDPSEvaluation ();
10179 /* so dptr know contains the address */
10180 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10182 /* if bit then unpack */
10183 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
10184 if (AOP_INDPTRn(result)) {
10185 genSetDPTR(AOP(result)->aopu.dptr);
10187 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
10188 if (AOP_INDPTRn(result)) {
10192 size = AOP_SIZE (right);
10194 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10196 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10198 genSetDPTR(AOP(result)->aopu.dptr);
10199 emitcode ("movx", "@dptr,a");
10200 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10201 emitcode ("inc", "dptr");
10205 _startLazyDPSEvaluation ();
10207 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10209 if (AOP_INDPTRn(result)) {
10210 genSetDPTR(AOP(result)->aopu.dptr);
10216 emitcode ("movx", "@dptr,a");
10217 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10218 emitcode ("inc", "dptr");
10220 _endLazyDPSEvaluation ();
10224 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10225 if (!AOP_INDPTRn(result)) {
10226 _startLazyDPSEvaluation ();
10228 aopPut (AOP(result),"dpl",0);
10229 aopPut (AOP(result),"dph",1);
10230 if (options.model == MODEL_FLAT24)
10231 aopPut (AOP(result),"dpx",2);
10233 _endLazyDPSEvaluation ();
10236 } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
10237 AOP_SIZE(right) > 1 &&
10238 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10240 size = AOP_SIZE (right) - 1;
10241 if (AOP_INDPTRn(result)) {
10242 genSetDPTR(AOP(result)->aopu.dptr);
10244 while (size--) emitcode ("lcall","__decdptr");
10245 if (AOP_INDPTRn(result)) {
10249 freeAsmop (result, NULL, ic, TRUE);
10250 freeAsmop (right, NULL, ic, TRUE);
10253 /*-----------------------------------------------------------------*/
10254 /* genGenPointerSet - set value from generic pointer space */
10255 /*-----------------------------------------------------------------*/
10257 genGenPointerSet (operand * right,
10258 operand * result, iCode * ic, iCode *pi)
10261 sym_link *retype = getSpec (operandType (right));
10262 sym_link *letype = getSpec (operandType (result));
10264 aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10266 /* if the operand is already in dptr
10267 then we do nothing else we move the value to dptr */
10268 if (AOP_TYPE (result) != AOP_STR)
10270 _startLazyDPSEvaluation ();
10271 /* if this is remateriazable */
10272 if (AOP_TYPE (result) == AOP_IMMD)
10274 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10275 if (AOP(result)->aopu.aop_immd.from_cast_remat)
10277 MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10282 "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10286 { /* we need to get it byte by byte */
10287 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10288 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10289 if (options.model == MODEL_FLAT24) {
10290 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10291 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10293 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10296 _endLazyDPSEvaluation ();
10298 /* so dptr + b now contains the address */
10300 aopOp (right, ic, FALSE, TRUE);
10304 /* if bit then unpack */
10305 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10307 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
10311 size = AOP_SIZE (right);
10314 _startLazyDPSEvaluation ();
10319 // Set two bytes at a time, passed in _AP & A.
10320 // dptr will be incremented ONCE by __gptrputWord.
10322 // Note: any change here must be coordinated
10323 // with the implementation of __gptrputWord
10324 // in device/lib/_gptrput.c
10325 emitcode("mov", "_ap, %s",
10326 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10327 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10331 emitcode ("lcall", "__gptrputWord");
10336 // Only one byte to put.
10337 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10341 emitcode ("lcall", "__gptrput");
10344 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10346 emitcode ("inc", "dptr");
10349 _endLazyDPSEvaluation ();
10352 if (pi && AOP_TYPE (result) != AOP_IMMD) {
10353 _startLazyDPSEvaluation ();
10355 aopPut (AOP(result),"dpl",0);
10356 aopPut (AOP(result),"dph",1);
10357 if (options.model == MODEL_FLAT24) {
10358 aopPut (AOP(result),"dpx",2);
10359 aopPut (AOP(result),"b",3);
10361 aopPut (AOP(result),"b",2);
10363 _endLazyDPSEvaluation ();
10366 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10367 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10369 size = AOP_SIZE (right) - 1;
10370 while (size--) emitcode ("lcall","__decdptr");
10372 freeAsmop (result, NULL, ic, TRUE);
10373 freeAsmop (right, NULL, ic, TRUE);
10376 /*-----------------------------------------------------------------*/
10377 /* genPointerSet - stores the value into a pointer location */
10378 /*-----------------------------------------------------------------*/
10380 genPointerSet (iCode * ic, iCode *pi)
10382 operand *right, *result;
10383 sym_link *type, *etype;
10386 D (emitcode (";", "genPointerSet "););
10388 right = IC_RIGHT (ic);
10389 result = IC_RESULT (ic);
10391 /* depending on the type of pointer we need to
10392 move it to the correct pointer register */
10393 type = operandType (result);
10394 etype = getSpec (type);
10395 /* if left is of type of pointer then it is simple */
10396 if (IS_PTR (type) && !IS_FUNC (type->next))
10398 p_type = DCL_TYPE (type);
10402 /* we have to go by the storage class */
10403 p_type = PTR_TYPE (SPEC_OCLS (etype));
10405 /* special case when cast remat */
10406 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10407 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10408 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10409 type = operandType (result);
10410 p_type = DCL_TYPE (type);
10413 /* now that we have the pointer type we assign
10414 the pointer values */
10420 genNearPointerSet (right, result, ic, pi);
10424 genPagedPointerSet (right, result, ic, pi);
10428 genFarPointerSet (right, result, ic, pi);
10432 genGenPointerSet (right, result, ic, pi);
10436 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10437 "genPointerSet: illegal pointer type");
10442 /*-----------------------------------------------------------------*/
10443 /* genIfx - generate code for Ifx statement */
10444 /*-----------------------------------------------------------------*/
10446 genIfx (iCode * ic, iCode * popIc)
10448 operand *cond = IC_COND (ic);
10451 D (emitcode (";", "genIfx "););
10453 aopOp (cond, ic, FALSE, FALSE);
10455 /* get the value into acc */
10456 if (AOP_TYPE (cond) != AOP_CRY)
10465 /* the result is now in the accumulator */
10466 freeAsmop (cond, NULL, ic, TRUE);
10468 /* if there was something to be popped then do it */
10472 /* if the condition is a bit variable */
10473 if (isbit && IS_ITEMP (cond) &&
10476 genIfxJump (ic, SPIL_LOC (cond)->rname);
10478 else if (isbit && !IS_ITEMP (cond))
10480 genIfxJump (ic, OP_SYMBOL (cond)->rname);
10484 genIfxJump (ic, "a");
10490 /*-----------------------------------------------------------------*/
10491 /* genAddrOf - generates code for address of */
10492 /*-----------------------------------------------------------------*/
10494 genAddrOf (iCode * ic)
10496 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10499 D (emitcode (";", "genAddrOf ");
10502 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10504 /* if the operand is on the stack then we
10505 need to get the stack offset of this
10507 if (sym->onStack) {
10509 /* if 10 bit stack */
10510 if (options.stack10bit) {
10512 tsprintf(buff, sizeof(buff),
10513 "#!constbyte",(options.stack_loc >> 16) & 0xff);
10514 /* if it has an offset then we need to compute it */
10515 /* emitcode ("subb", "a,#!constbyte", */
10516 /* -((sym->stack < 0) ? */
10517 /* ((short) (sym->stack - _G.nRegsSaved)) : */
10518 /* ((short) sym->stack)) & 0xff); */
10519 /* emitcode ("mov","b,a"); */
10520 /* emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
10521 /* ((short) (sym->stack - _G.nRegsSaved)) : */
10522 /* ((short) sym->stack)) >> 8) & 0xff); */
10524 emitcode ("mov", "a,_bpx");
10525 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
10526 ((char) (sym->stack - _G.nRegsSaved)) :
10527 ((char) sym->stack )) & 0xff);
10528 emitcode ("mov", "b,a");
10529 emitcode ("mov", "a,_bpx+1");
10530 emitcode ("addc","a,#!constbyte", (((sym->stack < 0) ?
10531 ((short) (sym->stack - _G.nRegsSaved)) :
10532 ((short) sym->stack )) >> 8) & 0xff);
10533 aopPut (AOP (IC_RESULT (ic)), "b", 0);
10534 aopPut (AOP (IC_RESULT (ic)), "a", 1);
10535 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10537 /* we can just move _bp */
10538 aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10539 aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10540 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10543 /* if it has an offset then we need to compute it */
10545 emitcode ("mov", "a,_bp");
10546 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10547 aopPut (AOP (IC_RESULT (ic)), "a", 0);
10549 /* we can just move _bp */
10550 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10552 /* fill the result with zero */
10553 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10556 if (options.stack10bit && size < (FPTRSIZE - 1)) {
10558 "*** warning: pointer to stack var truncated.\n");
10563 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10569 /* object not on stack then we need the name */
10570 size = AOP_SIZE (IC_RESULT (ic));
10575 char s[SDCC_NAME_MAX];
10579 tsprintf(s, sizeof(s), "#!his",sym->rname);
10582 tsprintf(s, sizeof(s), "#!hihis",sym->rname);
10585 tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
10587 default: /* should not need this (just in case) */
10588 SNPRINTF (s, sizeof(s), "#(%s >> %d)",
10595 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10598 aopPut (AOP (IC_RESULT (ic)), s, offset++);
10602 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10606 /*-----------------------------------------------------------------*/
10607 /* genArrayInit - generates code for address of */
10608 /*-----------------------------------------------------------------*/
10610 genArrayInit (iCode * ic)
10612 literalList *iLoop;
10614 int elementSize = 0, eIndex;
10615 unsigned val, lastVal;
10617 operand *left=IC_LEFT(ic);
10619 D (emitcode (";", "genArrayInit "););
10621 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10623 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10625 // Load immediate value into DPTR.
10626 emitcode("mov", "dptr, %s",
10627 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
10629 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10632 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10633 "Unexpected operand to genArrayInit.\n");
10636 // a regression because of SDCCcse.c:1.52
10637 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10638 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10639 if (options.model == MODEL_FLAT24)
10640 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10644 type = operandType(IC_LEFT(ic));
10646 if (type && type->next)
10648 elementSize = getSize(type->next);
10652 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10653 "can't determine element size in genArrayInit.\n");
10657 iLoop = IC_ARRAYILIST(ic);
10662 bool firstpass = TRUE;
10664 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
10665 iLoop->count, (int)iLoop->literalValue, elementSize);
10671 symbol *tlbl = NULL;
10673 count = ix > 256 ? 256 : ix;
10677 tlbl = newiTempLabel (NULL);
10678 if (firstpass || (count & 0xff))
10680 emitcode("mov", "b, #!constbyte", count & 0xff);
10683 emitcode ("", "!tlabeldef", tlbl->key + 100);
10688 for (eIndex = 0; eIndex < elementSize; eIndex++)
10690 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10691 if (val != lastVal)
10693 emitcode("mov", "a, #!constbyte", val);
10697 emitcode("movx", "@dptr, a");
10698 emitcode("inc", "dptr");
10703 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10709 iLoop = iLoop->next;
10712 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10715 /*-----------------------------------------------------------------*/
10716 /* genFarFarAssign - assignment when both are in far space */
10717 /*-----------------------------------------------------------------*/
10719 genFarFarAssign (operand * result, operand * right, iCode * ic)
10721 int size = AOP_SIZE (right);
10723 symbol *rSym = NULL;
10727 /* quick & easy case. */
10728 D(emitcode(";","genFarFarAssign (1 byte case)"););
10729 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
10730 freeAsmop (right, NULL, ic, FALSE);
10731 /* now assign DPTR to result */
10733 aopOp(result, ic, FALSE, FALSE);
10735 aopPut(AOP(result), "a", 0);
10736 freeAsmop(result, NULL, ic, FALSE);
10740 /* See if we've got an underlying symbol to abuse. */
10741 if (IS_SYMOP(result) && OP_SYMBOL(result))
10743 if (IS_TRUE_SYMOP(result))
10745 rSym = OP_SYMBOL(result);
10747 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10749 rSym = OP_SYMBOL(result)->usl.spillLoc;
10753 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10755 /* We can use the '390 auto-toggle feature to good effect here. */
10757 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10758 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
10759 emitcode ("mov", "dptr,#%s", rSym->rname);
10760 /* DP2 = result, DP1 = right, DP1 is current. */
10763 emitcode("movx", "a,@dptr");
10764 emitcode("movx", "@dptr,a");
10767 emitcode("inc", "dptr");
10768 emitcode("inc", "dptr");
10771 emitcode("mov", "dps,#0");
10772 freeAsmop (right, NULL, ic, FALSE);
10774 some alternative code for processors without auto-toggle
10775 no time to test now, so later well put in...kpb
10776 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10777 emitcode("mov", "dps,#1"); /* Select DPTR2. */
10778 emitcode ("mov", "dptr,#%s", rSym->rname);
10779 /* DP2 = result, DP1 = right, DP1 is current. */
10783 emitcode("movx", "a,@dptr");
10785 emitcode("inc", "dptr");
10786 emitcode("inc", "dps");
10787 emitcode("movx", "@dptr,a");
10789 emitcode("inc", "dptr");
10790 emitcode("inc", "dps");
10792 emitcode("mov", "dps,#0");
10793 freeAsmop (right, NULL, ic, FALSE);
10798 D (emitcode (";", "genFarFarAssign"););
10799 aopOp (result, ic, TRUE, TRUE);
10801 _startLazyDPSEvaluation ();
10805 aopPut (AOP (result),
10806 aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
10809 _endLazyDPSEvaluation ();
10810 freeAsmop (result, NULL, ic, FALSE);
10811 freeAsmop (right, NULL, ic, FALSE);
10815 /*-----------------------------------------------------------------*/
10816 /* genAssign - generate code for assignment */
10817 /*-----------------------------------------------------------------*/
10819 genAssign (iCode * ic)
10821 operand *result, *right;
10823 unsigned long lit = 0L;
10825 D (emitcode (";", "genAssign ");
10828 result = IC_RESULT (ic);
10829 right = IC_RIGHT (ic);
10831 /* if they are the same */
10832 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10835 aopOp (right, ic, FALSE, FALSE);
10837 emitcode (";", "genAssign: resultIsFar = %s",
10838 isOperandInFarSpace (result) ?
10841 /* special case both in far space */
10842 if ((AOP_TYPE (right) == AOP_DPTR ||
10843 AOP_TYPE (right) == AOP_DPTR2) &&
10844 /* IS_TRUE_SYMOP(result) && */
10845 isOperandInFarSpace (result))
10847 genFarFarAssign (result, right, ic);
10851 aopOp (result, ic, TRUE, FALSE);
10853 /* if they are the same registers */
10854 if (sameRegs (AOP (right), AOP (result)))
10857 /* if the result is a bit */
10858 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10860 /* if the right size is a literal then
10861 we know what the value is */
10862 if (AOP_TYPE (right) == AOP_LIT)
10864 if (((int) operandLitValue (right)))
10865 aopPut (AOP (result), one, 0);
10867 aopPut (AOP (result), zero, 0);
10871 /* the right is also a bit variable */
10872 if (AOP_TYPE (right) == AOP_CRY)
10874 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10875 aopPut (AOP (result), "c", 0);
10879 /* we need to or */
10881 aopPut (AOP (result), "a", 0);
10885 /* bit variables done */
10887 size = AOP_SIZE (result);
10889 if (AOP_TYPE (right) == AOP_LIT)
10890 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10893 (AOP_TYPE (result) != AOP_REG) &&
10894 (AOP_TYPE (right) == AOP_LIT) &&
10895 !IS_FLOAT (operandType (right)))
10897 _startLazyDPSEvaluation ();
10898 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10900 aopPut (AOP (result),
10901 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10906 /* And now fill the rest with zeros. */
10909 emitcode ("clr", "a");
10913 aopPut (AOP (result), "a", offset++);
10915 _endLazyDPSEvaluation ();
10919 _startLazyDPSEvaluation ();
10922 aopPut (AOP (result),
10923 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10927 _endLazyDPSEvaluation ();
10931 freeAsmop (right, NULL, ic, FALSE);
10932 freeAsmop (result, NULL, ic, TRUE);
10935 /*-----------------------------------------------------------------*/
10936 /* genJumpTab - generates code for jump table */
10937 /*-----------------------------------------------------------------*/
10939 genJumpTab (iCode * ic)
10944 D (emitcode (";", "genJumpTab ");
10947 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10948 /* get the condition into accumulator */
10949 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
10951 /* multiply by four! */
10952 emitcode ("add", "a,acc");
10953 emitcode ("add", "a,acc");
10954 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10956 jtab = newiTempLabel (NULL);
10957 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
10958 emitcode ("jmp", "@a+dptr");
10959 emitcode ("", "!tlabeldef", jtab->key + 100);
10960 /* now generate the jump labels */
10961 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10962 jtab = setNextItem (IC_JTLABELS (ic)))
10963 emitcode ("ljmp", "!tlabel", jtab->key + 100);
10967 /*-----------------------------------------------------------------*/
10968 /* genCast - gen code for casting */
10969 /*-----------------------------------------------------------------*/
10971 genCast (iCode * ic)
10973 operand *result = IC_RESULT (ic);
10974 sym_link *ctype = operandType (IC_LEFT (ic));
10975 sym_link *rtype = operandType (IC_RIGHT (ic));
10976 operand *right = IC_RIGHT (ic);
10979 D (emitcode (";", "genCast "););
10981 /* if they are equivalent then do nothing */
10982 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10985 aopOp (right, ic, FALSE, FALSE);
10986 aopOp (result, ic, FALSE, AOP_USESDPTR(right));
10988 /* if the result is a bit */
10989 // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10990 if (IS_BITVAR(OP_SYMBOL(result)->type))
10992 /* if the right size is a literal then
10993 we know what the value is */
10994 if (AOP_TYPE (right) == AOP_LIT)
10996 if (((int) operandLitValue (right)))
10997 aopPut (AOP (result), one, 0);
10999 aopPut (AOP (result), zero, 0);
11004 /* the right is also a bit variable */
11005 if (AOP_TYPE (right) == AOP_CRY)
11007 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11008 aopPut (AOP (result), "c", 0);
11012 /* we need to or */
11014 aopPut (AOP (result), "a", 0);
11018 /* if they are the same size : or less */
11019 if (AOP_SIZE (result) <= AOP_SIZE (right))
11022 /* if they are in the same place */
11023 if (sameRegs (AOP (right), AOP (result)))
11026 /* if they in different places then copy */
11027 size = AOP_SIZE (result);
11029 _startLazyDPSEvaluation ();
11032 aopPut (AOP (result),
11033 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11037 _endLazyDPSEvaluation ();
11042 /* if the result is of type pointer */
11043 if (IS_PTR (ctype))
11047 sym_link *type = operandType (right);
11049 /* pointer to generic pointer */
11050 if (IS_GENPTR (ctype))
11054 p_type = DCL_TYPE (type);
11058 #if OLD_CAST_BEHAVIOR
11059 /* KV: we are converting a non-pointer type to
11060 * a generic pointer. This (ifdef'd out) code
11061 * says that the resulting generic pointer
11062 * should have the same class as the storage
11063 * location of the non-pointer variable.
11065 * For example, converting an int (which happens
11066 * to be stored in DATA space) to a pointer results
11067 * in a DATA generic pointer; if the original int
11068 * in XDATA space, so will be the resulting pointer.
11070 * I don't like that behavior, and thus this change:
11071 * all such conversions will be forced to XDATA and
11072 * throw a warning. If you want some non-XDATA
11073 * type, or you want to suppress the warning, you
11074 * must go through an intermediate cast, like so:
11076 * char _generic *gp = (char _xdata *)(intVar);
11078 sym_link *etype = getSpec (type);
11080 /* we have to go by the storage class */
11081 if (SPEC_OCLS (etype) != generic)
11083 p_type = PTR_TYPE (SPEC_OCLS (etype));
11088 /* Converting unknown class (i.e. register variable)
11089 * to generic pointer. This is not good, but
11090 * we'll make a guess (and throw a warning).
11093 werror (W_INT_TO_GEN_PTR_CAST);
11097 /* the first two bytes are known */
11098 size = GPTRSIZE - 1;
11100 _startLazyDPSEvaluation ();
11103 aopPut (AOP (result),
11104 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11108 _endLazyDPSEvaluation ();
11110 /* the last byte depending on type */
11112 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11117 // pointerTypeToGPByte will have bitched.
11121 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11122 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11127 /* just copy the pointers */
11128 size = AOP_SIZE (result);
11130 _startLazyDPSEvaluation ();
11133 aopPut (AOP (result),
11134 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11138 _endLazyDPSEvaluation ();
11142 /* so we now know that the size of destination is greater
11143 than the size of the source */
11144 /* we move to result for the size of source */
11145 size = AOP_SIZE (right);
11147 _startLazyDPSEvaluation ();
11150 aopPut (AOP (result),
11151 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11155 _endLazyDPSEvaluation ();
11157 /* now depending on the sign of the source && destination */
11158 size = AOP_SIZE (result) - AOP_SIZE (right);
11159 /* if unsigned or not an integral type */
11160 /* also, if the source is a bit, we don't need to sign extend, because
11161 * it can't possibly have set the sign bit.
11163 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
11167 aopPut (AOP (result), zero, offset++);
11172 /* we need to extend the sign :{ */
11173 MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11174 FALSE, FALSE, NULL));
11175 emitcode ("rlc", "a");
11176 emitcode ("subb", "a,acc");
11178 aopPut (AOP (result), "a", offset++);
11181 /* we are done hurray !!!! */
11184 freeAsmop (right, NULL, ic, TRUE);
11185 freeAsmop (result, NULL, ic, TRUE);
11189 /*-----------------------------------------------------------------*/
11190 /* genDjnz - generate decrement & jump if not zero instrucion */
11191 /*-----------------------------------------------------------------*/
11193 genDjnz (iCode * ic, iCode * ifx)
11195 symbol *lbl, *lbl1;
11199 /* if the if condition has a false label
11200 then we cannot save */
11201 if (IC_FALSE (ifx))
11204 /* if the minus is not of the form
11206 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11207 !IS_OP_LITERAL (IC_RIGHT (ic)))
11210 if (operandLitValue (IC_RIGHT (ic)) != 1)
11213 /* if the size of this greater than one then no
11215 if (getSize (operandType (IC_RESULT (ic))) > 1)
11218 /* otherwise we can save BIG */
11219 D(emitcode(";", "genDjnz"););
11221 lbl = newiTempLabel (NULL);
11222 lbl1 = newiTempLabel (NULL);
11224 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11226 if (AOP_NEEDSACC(IC_RESULT(ic)))
11228 /* If the result is accessed indirectly via
11229 * the accumulator, we must explicitly write
11230 * it back after the decrement.
11232 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11234 if (strcmp(rByte, "a"))
11236 /* Something is hopelessly wrong */
11237 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11238 __FILE__, __LINE__);
11239 /* We can just give up; the generated code will be inefficient,
11240 * but what the hey.
11242 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11245 emitcode ("dec", "%s", rByte);
11246 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11247 emitcode ("jnz", "!tlabel", lbl->key + 100);
11249 else if (IS_AOP_PREG (IC_RESULT (ic)))
11251 emitcode ("dec", "%s",
11252 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11253 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11254 emitcode ("jnz", "!tlabel", lbl->key + 100);
11258 emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11261 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11262 emitcode ("", "!tlabeldef", lbl->key + 100);
11263 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11264 emitcode ("", "!tlabeldef", lbl1->key + 100);
11266 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11267 ifx->generated = 1;
11271 /*-----------------------------------------------------------------*/
11272 /* genReceive - generate code for a receive iCode */
11273 /*-----------------------------------------------------------------*/
11275 genReceive (iCode * ic)
11277 int size = getSize (operandType (IC_RESULT (ic)));
11281 D (emitcode (";", "genReceive "););
11283 if (ic->argreg == 1)
11285 /* first parameter */
11286 if (AOP_IS_STR(IC_RESULT(ic)))
11288 /* Nothing to do: it's already in the proper place. */
11295 useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11296 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11297 IS_TRUE_SYMOP (IC_RESULT (ic)));
11300 aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11303 /* Sanity checking... */
11304 if (AOP_USESDPTR(IC_RESULT(ic)))
11306 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11307 "genReceive got unexpected DPTR.");
11309 assignResultValue (IC_RESULT (ic));
11314 /* second receive onwards */
11315 /* this gets a little tricky since unused recevies will be
11316 eliminated, we have saved the reg in the type field . and
11317 we use that to figure out which register to use */
11318 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11319 rb1off = ic->argreg;
11322 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11325 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11328 /*-----------------------------------------------------------------*/
11329 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
11330 /*-----------------------------------------------------------------*/
11331 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11333 operand *from , *to , *count;
11338 /* we know it has to be 3 parameters */
11339 assert (nparms == 3);
11341 rsave = newBitVect(16);
11342 /* save DPTR if it needs to be saved */
11343 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11344 if (bitVectBitValue(ic->rMask,i))
11345 rsave = bitVectSetBit(rsave,i);
11347 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11348 ds390_rUmaskForOp (IC_RESULT(ic))));
11355 aopOp (from, ic->next, FALSE, FALSE);
11357 /* get from into DPTR1 */
11358 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11359 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11360 if (options.model == MODEL_FLAT24) {
11361 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11364 freeAsmop (from, NULL, ic, FALSE);
11365 aopOp (to, ic, FALSE, FALSE);
11366 /* get "to" into DPTR */
11367 /* if the operand is already in dptr
11368 then we do nothing else we move the value to dptr */
11369 if (AOP_TYPE (to) != AOP_STR) {
11370 /* if already in DPTR then we need to push */
11371 if (AOP_TYPE(to) == AOP_DPTR) {
11372 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11373 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11374 if (options.model == MODEL_FLAT24)
11375 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11376 emitcode ("pop", "dph");
11377 emitcode ("pop", "dpl");
11379 _startLazyDPSEvaluation ();
11380 /* if this is remateriazable */
11381 if (AOP_TYPE (to) == AOP_IMMD) {
11382 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11383 } else { /* we need to get it byte by byte */
11384 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11385 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11386 if (options.model == MODEL_FLAT24) {
11387 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11390 _endLazyDPSEvaluation ();
11393 freeAsmop (to, NULL, ic, FALSE);
11394 _G.dptrInUse = _G.dptr1InUse = 1;
11395 aopOp (count, ic->next->next, FALSE,FALSE);
11396 lbl =newiTempLabel(NULL);
11398 /* now for the actual copy */
11399 if (AOP_TYPE(count) == AOP_LIT &&
11400 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11401 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11403 emitcode ("lcall","__bi_memcpyc2x_s");
11405 emitcode ("lcall","__bi_memcpyx2x_s");
11407 freeAsmop (count, NULL, ic, FALSE);
11409 symbol *lbl1 = newiTempLabel(NULL);
11411 emitcode (";"," Auto increment but no djnz");
11412 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11413 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11414 freeAsmop (count, NULL, ic, FALSE);
11415 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11416 emitcode ("","!tlabeldef",lbl->key+100);
11418 emitcode ("clr","a");
11419 emitcode ("movc", "a,@a+dptr");
11421 emitcode ("movx", "a,@dptr");
11422 emitcode ("movx", "@dptr,a");
11423 emitcode ("inc", "dptr");
11424 emitcode ("inc", "dptr");
11425 emitcode ("mov","a,b");
11426 emitcode ("orl","a,_ap");
11427 emitcode ("jz","!tlabel",lbl1->key+100);
11428 emitcode ("mov","a,_ap");
11429 emitcode ("add","a,#!constbyte",0xFF);
11430 emitcode ("mov","_ap,a");
11431 emitcode ("mov","a,b");
11432 emitcode ("addc","a,#!constbyte",0xFF);
11433 emitcode ("mov","b,a");
11434 emitcode ("sjmp","!tlabel",lbl->key+100);
11435 emitcode ("","!tlabeldef",lbl1->key+100);
11437 emitcode ("mov", "dps,#0");
11438 _G.dptrInUse = _G.dptr1InUse = 0;
11439 unsavermask(rsave);
11443 /*-----------------------------------------------------------------*/
11444 /* genMemcmpX2X - gen code for memcmp xdata to xdata */
11445 /*-----------------------------------------------------------------*/
11446 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11448 operand *from , *to , *count;
11453 /* we know it has to be 3 parameters */
11454 assert (nparms == 3);
11456 rsave = newBitVect(16);
11457 /* save DPTR if it needs to be saved */
11458 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11459 if (bitVectBitValue(ic->rMask,i))
11460 rsave = bitVectSetBit(rsave,i);
11462 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11463 ds390_rUmaskForOp (IC_RESULT(ic))));
11470 aopOp (from, ic->next, FALSE, FALSE);
11472 /* get from into DPTR1 */
11473 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11474 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11475 if (options.model == MODEL_FLAT24) {
11476 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11479 freeAsmop (from, NULL, ic, FALSE);
11480 aopOp (to, ic, FALSE, FALSE);
11481 /* get "to" into DPTR */
11482 /* if the operand is already in dptr
11483 then we do nothing else we move the value to dptr */
11484 if (AOP_TYPE (to) != AOP_STR) {
11485 /* if already in DPTR then we need to push */
11486 if (AOP_TYPE(to) == AOP_DPTR) {
11487 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11488 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11489 if (options.model == MODEL_FLAT24)
11490 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11491 emitcode ("pop", "dph");
11492 emitcode ("pop", "dpl");
11494 _startLazyDPSEvaluation ();
11495 /* if this is remateriazable */
11496 if (AOP_TYPE (to) == AOP_IMMD) {
11497 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11498 } else { /* we need to get it byte by byte */
11499 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11500 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11501 if (options.model == MODEL_FLAT24) {
11502 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11505 _endLazyDPSEvaluation ();
11508 freeAsmop (to, NULL, ic, FALSE);
11509 _G.dptrInUse = _G.dptr1InUse = 1;
11510 aopOp (count, ic->next->next, FALSE,FALSE);
11511 lbl =newiTempLabel(NULL);
11512 lbl2 =newiTempLabel(NULL);
11514 /* now for the actual compare */
11515 if (AOP_TYPE(count) == AOP_LIT &&
11516 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11517 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11519 emitcode("lcall","__bi_memcmpc2x_s");
11521 emitcode("lcall","__bi_memcmpx2x_s");
11522 freeAsmop (count, NULL, ic, FALSE);
11523 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11524 aopPut(AOP(IC_RESULT(ic)),"a",0);
11525 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11527 symbol *lbl1 = newiTempLabel(NULL);
11529 emitcode("push","ar0");
11530 emitcode (";"," Auto increment but no djnz");
11531 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11532 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11533 freeAsmop (count, NULL, ic, FALSE);
11534 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11535 emitcode ("","!tlabeldef",lbl->key+100);
11537 emitcode ("clr","a");
11538 emitcode ("movc", "a,@a+dptr");
11540 emitcode ("movx", "a,@dptr");
11541 emitcode ("mov","r0,a");
11542 emitcode ("movx", "a,@dptr");
11543 emitcode ("clr","c");
11544 emitcode ("subb","a,r0");
11545 emitcode ("jnz","!tlabel",lbl2->key+100);
11546 emitcode ("inc", "dptr");
11547 emitcode ("inc", "dptr");
11548 emitcode ("mov","a,b");
11549 emitcode ("orl","a,_ap");
11550 emitcode ("jz","!tlabel",lbl1->key+100);
11551 emitcode ("mov","a,_ap");
11552 emitcode ("add","a,#!constbyte",0xFF);
11553 emitcode ("mov","_ap,a");
11554 emitcode ("mov","a,b");
11555 emitcode ("addc","a,#!constbyte",0xFF);
11556 emitcode ("mov","b,a");
11557 emitcode ("sjmp","!tlabel",lbl->key+100);
11558 emitcode ("","!tlabeldef",lbl1->key+100);
11559 emitcode ("clr","a");
11560 emitcode ("","!tlabeldef",lbl2->key+100);
11561 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11562 aopPut(AOP(IC_RESULT(ic)),"a",0);
11563 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11564 emitcode("pop","ar0");
11565 emitcode ("mov", "dps,#0");
11567 _G.dptrInUse = _G.dptr1InUse = 0;
11568 unsavermask(rsave);
11572 /*-----------------------------------------------------------------*/
11573 /* genInp - gen code for __builtin_inp read data from a mem mapped */
11574 /* port, first parameter output area second parameter pointer to */
11575 /* port third parameter count */
11576 /*-----------------------------------------------------------------*/
11577 static void genInp( iCode *ic, int nparms, operand **parms)
11579 operand *from , *to , *count;
11584 /* we know it has to be 3 parameters */
11585 assert (nparms == 3);
11587 rsave = newBitVect(16);
11588 /* save DPTR if it needs to be saved */
11589 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11590 if (bitVectBitValue(ic->rMask,i))
11591 rsave = bitVectSetBit(rsave,i);
11593 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11594 ds390_rUmaskForOp (IC_RESULT(ic))));
11601 aopOp (from, ic->next, FALSE, FALSE);
11603 /* get from into DPTR1 */
11604 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11605 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11606 if (options.model == MODEL_FLAT24) {
11607 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11610 freeAsmop (from, NULL, ic, FALSE);
11611 aopOp (to, ic, FALSE, FALSE);
11612 /* get "to" into DPTR */
11613 /* if the operand is already in dptr
11614 then we do nothing else we move the value to dptr */
11615 if (AOP_TYPE (to) != AOP_STR) {
11616 /* if already in DPTR then we need to push */
11617 if (AOP_TYPE(to) == AOP_DPTR) {
11618 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11619 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11620 if (options.model == MODEL_FLAT24)
11621 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11622 emitcode ("pop", "dph");
11623 emitcode ("pop", "dpl");
11625 _startLazyDPSEvaluation ();
11626 /* if this is remateriazable */
11627 if (AOP_TYPE (to) == AOP_IMMD) {
11628 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11629 } else { /* we need to get it byte by byte */
11630 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11631 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11632 if (options.model == MODEL_FLAT24) {
11633 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11636 _endLazyDPSEvaluation ();
11639 freeAsmop (to, NULL, ic, FALSE);
11641 _G.dptrInUse = _G.dptr1InUse = 1;
11642 aopOp (count, ic->next->next, FALSE,FALSE);
11643 lbl =newiTempLabel(NULL);
11645 /* now for the actual copy */
11646 if (AOP_TYPE(count) == AOP_LIT &&
11647 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11648 emitcode (";","OH JOY auto increment with djnz (very fast)");
11649 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11650 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11651 freeAsmop (count, NULL, ic, FALSE);
11652 emitcode ("","!tlabeldef",lbl->key+100);
11653 emitcode ("movx", "a,@dptr"); /* read data from port */
11654 emitcode ("dec","dps"); /* switch to DPTR */
11655 emitcode ("movx", "@dptr,a"); /* save into location */
11656 emitcode ("inc", "dptr"); /* point to next area */
11657 emitcode ("inc","dps"); /* switch to DPTR2 */
11658 emitcode ("djnz","b,!tlabel",lbl->key+100);
11660 symbol *lbl1 = newiTempLabel(NULL);
11662 emitcode (";"," Auto increment but no djnz");
11663 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11664 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11665 freeAsmop (count, NULL, ic, FALSE);
11666 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11667 emitcode ("","!tlabeldef",lbl->key+100);
11668 emitcode ("movx", "a,@dptr");
11669 emitcode ("dec","dps"); /* switch to DPTR */
11670 emitcode ("movx", "@dptr,a");
11671 emitcode ("inc", "dptr");
11672 emitcode ("inc","dps"); /* switch to DPTR2 */
11673 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
11674 /* emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
11675 emitcode ("mov","a,b");
11676 emitcode ("orl","a,_ap");
11677 emitcode ("jz","!tlabel",lbl1->key+100);
11678 emitcode ("mov","a,_ap");
11679 emitcode ("add","a,#!constbyte",0xFF);
11680 emitcode ("mov","_ap,a");
11681 emitcode ("mov","a,b");
11682 emitcode ("addc","a,#!constbyte",0xFF);
11683 emitcode ("mov","b,a");
11684 emitcode ("sjmp","!tlabel",lbl->key+100);
11685 emitcode ("","!tlabeldef",lbl1->key+100);
11687 emitcode ("mov", "dps,#0");
11688 _G.dptrInUse = _G.dptr1InUse = 0;
11689 unsavermask(rsave);
11693 /*-----------------------------------------------------------------*/
11694 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
11695 /* port, first parameter output area second parameter pointer to */
11696 /* port third parameter count */
11697 /*-----------------------------------------------------------------*/
11698 static void genOutp( iCode *ic, int nparms, operand **parms)
11700 operand *from , *to , *count;
11705 /* we know it has to be 3 parameters */
11706 assert (nparms == 3);
11708 rsave = newBitVect(16);
11709 /* save DPTR if it needs to be saved */
11710 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11711 if (bitVectBitValue(ic->rMask,i))
11712 rsave = bitVectSetBit(rsave,i);
11714 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11715 ds390_rUmaskForOp (IC_RESULT(ic))));
11722 aopOp (from, ic->next, FALSE, FALSE);
11724 /* get from into DPTR1 */
11725 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11726 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11727 if (options.model == MODEL_FLAT24) {
11728 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11731 freeAsmop (from, NULL, ic, FALSE);
11732 aopOp (to, ic, FALSE, FALSE);
11733 /* get "to" into DPTR */
11734 /* if the operand is already in dptr
11735 then we do nothing else we move the value to dptr */
11736 if (AOP_TYPE (to) != AOP_STR) {
11737 /* if already in DPTR then we need to push */
11738 if (AOP_TYPE(to) == AOP_DPTR) {
11739 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11740 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11741 if (options.model == MODEL_FLAT24)
11742 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11743 emitcode ("pop", "dph");
11744 emitcode ("pop", "dpl");
11746 _startLazyDPSEvaluation ();
11747 /* if this is remateriazable */
11748 if (AOP_TYPE (to) == AOP_IMMD) {
11749 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11750 } else { /* we need to get it byte by byte */
11751 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11752 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11753 if (options.model == MODEL_FLAT24) {
11754 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11757 _endLazyDPSEvaluation ();
11760 freeAsmop (to, NULL, ic, FALSE);
11762 _G.dptrInUse = _G.dptr1InUse = 1;
11763 aopOp (count, ic->next->next, FALSE,FALSE);
11764 lbl =newiTempLabel(NULL);
11766 /* now for the actual copy */
11767 if (AOP_TYPE(count) == AOP_LIT &&
11768 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11769 emitcode (";","OH JOY auto increment with djnz (very fast)");
11770 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
11771 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11772 emitcode ("","!tlabeldef",lbl->key+100);
11773 emitcode ("movx", "a,@dptr"); /* read data from port */
11774 emitcode ("inc","dps"); /* switch to DPTR2 */
11775 emitcode ("movx", "@dptr,a"); /* save into location */
11776 emitcode ("inc", "dptr"); /* point to next area */
11777 emitcode ("dec","dps"); /* switch to DPTR */
11778 emitcode ("djnz","b,!tlabel",lbl->key+100);
11779 freeAsmop (count, NULL, ic, FALSE);
11781 symbol *lbl1 = newiTempLabel(NULL);
11783 emitcode (";"," Auto increment but no djnz");
11784 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11785 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11786 freeAsmop (count, NULL, ic, FALSE);
11787 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
11788 emitcode ("","!tlabeldef",lbl->key+100);
11789 emitcode ("movx", "a,@dptr");
11790 emitcode ("inc", "dptr");
11791 emitcode ("inc","dps"); /* switch to DPTR2 */
11792 emitcode ("movx", "@dptr,a");
11793 emitcode ("dec","dps"); /* switch to DPTR */
11794 emitcode ("mov","a,b");
11795 emitcode ("orl","a,_ap");
11796 emitcode ("jz","!tlabel",lbl1->key+100);
11797 emitcode ("mov","a,_ap");
11798 emitcode ("add","a,#!constbyte",0xFF);
11799 emitcode ("mov","_ap,a");
11800 emitcode ("mov","a,b");
11801 emitcode ("addc","a,#!constbyte",0xFF);
11802 emitcode ("mov","b,a");
11803 emitcode ("sjmp","!tlabel",lbl->key+100);
11804 emitcode ("","!tlabeldef",lbl1->key+100);
11806 emitcode ("mov", "dps,#0");
11807 _G.dptrInUse = _G.dptr1InUse = 0;
11808 unsavermask(rsave);
11812 /*-----------------------------------------------------------------*/
11813 /* genSwapW - swap lower & high order bytes */
11814 /*-----------------------------------------------------------------*/
11815 static void genSwapW(iCode *ic, int nparms, operand **parms)
11819 assert (nparms==1);
11822 dest=IC_RESULT(ic);
11824 assert(getSize(operandType(src))==2);
11826 aopOp (src, ic, FALSE, FALSE);
11827 emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
11829 MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
11831 freeAsmop (src, NULL, ic, FALSE);
11833 aopOp (dest,ic, FALSE, FALSE);
11834 aopPut(AOP(dest),"b",0);
11835 aopPut(AOP(dest),"a",1);
11836 freeAsmop (dest, NULL, ic, FALSE);
11839 /*-----------------------------------------------------------------*/
11840 /* genMemsetX - gencode for memSetX data */
11841 /*-----------------------------------------------------------------*/
11842 static void genMemsetX(iCode *ic, int nparms, operand **parms)
11844 operand *to , *val , *count;
11850 /* we know it has to be 3 parameters */
11851 assert (nparms == 3);
11857 /* save DPTR if it needs to be saved */
11858 rsave = newBitVect(16);
11859 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11860 if (bitVectBitValue(ic->rMask,i))
11861 rsave = bitVectSetBit(rsave,i);
11863 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11864 ds390_rUmaskForOp (IC_RESULT(ic))));
11867 aopOp (to, ic, FALSE, FALSE);
11868 /* get "to" into DPTR */
11869 /* if the operand is already in dptr
11870 then we do nothing else we move the value to dptr */
11871 if (AOP_TYPE (to) != AOP_STR) {
11872 /* if already in DPTR then we need to push */
11873 if (AOP_TYPE(to) == AOP_DPTR) {
11874 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11875 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11876 if (options.model == MODEL_FLAT24)
11877 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11878 emitcode ("pop", "dph");
11879 emitcode ("pop", "dpl");
11881 _startLazyDPSEvaluation ();
11882 /* if this is remateriazable */
11883 if (AOP_TYPE (to) == AOP_IMMD) {
11884 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11885 } else { /* we need to get it byte by byte */
11886 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11887 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11888 if (options.model == MODEL_FLAT24) {
11889 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11892 _endLazyDPSEvaluation ();
11895 freeAsmop (to, NULL, ic, FALSE);
11897 aopOp (val, ic->next->next, FALSE,FALSE);
11898 aopOp (count, ic->next->next, FALSE,FALSE);
11899 lbl =newiTempLabel(NULL);
11900 /* now for the actual copy */
11901 if (AOP_TYPE(count) == AOP_LIT &&
11902 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11903 l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
11904 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11906 emitcode ("","!tlabeldef",lbl->key+100);
11907 emitcode ("movx", "@dptr,a");
11908 emitcode ("inc", "dptr");
11909 emitcode ("djnz","b,!tlabel",lbl->key+100);
11911 symbol *lbl1 = newiTempLabel(NULL);
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 emitcode ("","!tlabeldef",lbl->key+100);
11916 MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
11917 emitcode ("movx", "@dptr,a");
11918 emitcode ("inc", "dptr");
11919 emitcode ("mov","a,b");
11920 emitcode ("orl","a,_ap");
11921 emitcode ("jz","!tlabel",lbl1->key+100);
11922 emitcode ("mov","a,_ap");
11923 emitcode ("add","a,#!constbyte",0xFF);
11924 emitcode ("mov","_ap,a");
11925 emitcode ("mov","a,b");
11926 emitcode ("addc","a,#!constbyte",0xFF);
11927 emitcode ("mov","b,a");
11928 emitcode ("sjmp","!tlabel",lbl->key+100);
11929 emitcode ("","!tlabeldef",lbl1->key+100);
11931 freeAsmop (count, NULL, ic, FALSE);
11932 unsavermask(rsave);
11935 /*-----------------------------------------------------------------*/
11936 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
11937 /*-----------------------------------------------------------------*/
11938 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
11941 operand *pnum, *result;
11944 assert (nparms==1);
11945 /* save registers that need to be saved */
11946 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11947 ds390_rUmaskForOp (IC_RESULT(ic))));
11950 aopOp (pnum, ic, FALSE, FALSE);
11951 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
11952 freeAsmop (pnum, NULL, ic, FALSE);
11953 emitcode ("lcall","NatLib_LoadPrimitive");
11954 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11955 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
11956 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
11957 for (i = (size-1) ; i >= 0 ; i-- ) {
11958 emitcode ("push","a%s",javaRet[i]);
11960 for (i=0; i < size ; i++ ) {
11961 emitcode ("pop","a%s",
11962 aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
11965 for (i = 0 ; i < size ; i++ ) {
11966 aopPut(AOP(result),javaRet[i],i);
11969 freeAsmop (result, NULL, ic, FALSE);
11970 unsavermask(rsave);
11973 /*-----------------------------------------------------------------*/
11974 /* genNatLibLoadPointer - calls TINI api function to load pointer */
11975 /*-----------------------------------------------------------------*/
11976 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
11979 operand *pnum, *result;
11983 assert (nparms==1);
11984 /* save registers that need to be saved */
11985 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11986 ds390_rUmaskForOp (IC_RESULT(ic))));
11989 aopOp (pnum, ic, FALSE, FALSE);
11990 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
11991 freeAsmop (pnum, NULL, ic, FALSE);
11992 emitcode ("lcall","NatLib_LoadPointer");
11993 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11994 if (AOP_TYPE(result)!=AOP_STR) {
11995 for (i = 0 ; i < size ; i++ ) {
11996 aopPut(AOP(result),fReturn[i],i);
11999 freeAsmop (result, NULL, ic, FALSE);
12000 unsavermask(rsave);
12003 /*-----------------------------------------------------------------*/
12004 /* genNatLibInstallStateBlock - */
12005 /*-----------------------------------------------------------------*/
12006 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
12007 operand **parms, const char *name)
12010 operand *psb, *handle;
12011 assert (nparms==2);
12013 /* save registers that need to be saved */
12014 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12015 ds390_rUmaskForOp (IC_RESULT(ic))));
12019 /* put pointer to state block into DPTR1 */
12020 aopOp (psb, ic, FALSE, FALSE);
12021 if (AOP_TYPE (psb) == AOP_IMMD) {
12022 emitcode ("mov","dps,#1");
12023 emitcode ("mov", "dptr,%s",
12024 aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12025 emitcode ("mov","dps,#0");
12027 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12028 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12029 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12031 freeAsmop (psb, NULL, ic, FALSE);
12033 /* put libraryID into DPTR */
12034 emitcode ("mov","dptr,#LibraryID");
12036 /* put handle into r3:r2 */
12037 aopOp (handle, ic, FALSE, FALSE);
12038 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12039 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12040 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12041 emitcode ("pop","ar3");
12042 emitcode ("pop","ar2");
12044 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12045 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12047 freeAsmop (psb, NULL, ic, FALSE);
12049 /* make the call */
12050 emitcode ("lcall","NatLib_Install%sStateBlock",name);
12052 /* put return value into place*/
12054 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12056 aopPut(AOP(IC_RESULT(ic)),"a",0);
12057 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12058 unsavermask(rsave);
12061 /*-----------------------------------------------------------------*/
12062 /* genNatLibRemoveStateBlock - */
12063 /*-----------------------------------------------------------------*/
12064 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12070 /* save registers that need to be saved */
12071 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12072 ds390_rUmaskForOp (IC_RESULT(ic))));
12074 /* put libraryID into DPTR */
12075 emitcode ("mov","dptr,#LibraryID");
12076 /* make the call */
12077 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12078 unsavermask(rsave);
12081 /*-----------------------------------------------------------------*/
12082 /* genNatLibGetStateBlock - */
12083 /*-----------------------------------------------------------------*/
12084 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12085 operand **parms,const char *name)
12088 symbol *lbl = newiTempLabel(NULL);
12091 /* save registers that need to be saved */
12092 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12093 ds390_rUmaskForOp (IC_RESULT(ic))));
12095 /* put libraryID into DPTR */
12096 emitcode ("mov","dptr,#LibraryID");
12097 /* make the call */
12098 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12099 emitcode ("jnz","!tlabel",lbl->key+100);
12101 /* put return value into place */
12102 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12103 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12104 emitcode ("push","ar3");
12105 emitcode ("push","ar2");
12106 emitcode ("pop","%s",
12107 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12108 emitcode ("pop","%s",
12109 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12111 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12112 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12114 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12115 emitcode ("","!tlabeldef",lbl->key+100);
12116 unsavermask(rsave);
12119 /*-----------------------------------------------------------------*/
12120 /* genMMMalloc - */
12121 /*-----------------------------------------------------------------*/
12122 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12123 int size, const char *name)
12128 symbol *lbl = newiTempLabel(NULL);
12130 assert (nparms == 1);
12131 /* save registers that need to be saved */
12132 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12133 ds390_rUmaskForOp (IC_RESULT(ic))));
12136 aopOp (bsize,ic,FALSE,FALSE);
12138 /* put the size in R4-R2 */
12139 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12140 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12141 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12143 emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12144 emitcode("pop","ar4");
12146 emitcode("pop","ar3");
12147 emitcode("pop","ar2");
12149 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12150 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12152 emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12155 freeAsmop (bsize, NULL, ic, FALSE);
12157 /* make the call */
12158 emitcode ("lcall","MM_%s",name);
12159 emitcode ("jz","!tlabel",lbl->key+100);
12160 emitcode ("mov","r2,#!constbyte",0xff);
12161 emitcode ("mov","r3,#!constbyte",0xff);
12162 emitcode ("","!tlabeldef",lbl->key+100);
12163 /* we don't care about the pointer : we just save the handle */
12164 rsym = OP_SYMBOL(IC_RESULT(ic));
12165 if (rsym->liveFrom != rsym->liveTo) {
12166 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12167 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12168 emitcode ("push","ar3");
12169 emitcode ("push","ar2");
12170 emitcode ("pop","%s",
12171 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12172 emitcode ("pop","%s",
12173 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12175 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12176 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12178 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12180 unsavermask(rsave);
12183 /*-----------------------------------------------------------------*/
12185 /*-----------------------------------------------------------------*/
12186 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12191 assert (nparms == 1);
12192 /* save registers that need to be saved */
12193 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12194 ds390_rUmaskForOp (IC_RESULT(ic))));
12197 aopOp (handle,ic,FALSE,FALSE);
12199 /* put the size in R4-R2 */
12200 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12201 emitcode("push","%s",
12202 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12203 emitcode("push","%s",
12204 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12205 emitcode("pop","ar3");
12206 emitcode("pop","ar2");
12208 emitcode ("mov","r2,%s",
12209 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12210 emitcode ("mov","r3,%s",
12211 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12213 freeAsmop (handle, NULL, ic, FALSE);
12215 /* make the call */
12216 emitcode ("lcall","MM_Deref");
12219 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12220 if (rsym->liveFrom != rsym->liveTo) {
12221 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12222 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12223 _startLazyDPSEvaluation ();
12225 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12226 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12227 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12229 _endLazyDPSEvaluation ();
12234 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12235 unsavermask(rsave);
12238 /*-----------------------------------------------------------------*/
12239 /* genMMUnrestrictedPersist - */
12240 /*-----------------------------------------------------------------*/
12241 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12246 assert (nparms == 1);
12247 /* save registers that need to be saved */
12248 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12249 ds390_rUmaskForOp (IC_RESULT(ic))));
12252 aopOp (handle,ic,FALSE,FALSE);
12254 /* put the size in R3-R2 */
12255 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12256 emitcode("push","%s",
12257 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12258 emitcode("push","%s",
12259 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12260 emitcode("pop","ar3");
12261 emitcode("pop","ar2");
12263 emitcode ("mov","r2,%s",
12264 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12265 emitcode ("mov","r3,%s",
12266 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12268 freeAsmop (handle, NULL, ic, FALSE);
12270 /* make the call */
12271 emitcode ("lcall","MM_UnrestrictedPersist");
12274 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12275 if (rsym->liveFrom != rsym->liveTo) {
12276 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12277 aopPut(AOP(IC_RESULT(ic)),"a",0);
12278 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12281 unsavermask(rsave);
12284 /*-----------------------------------------------------------------*/
12285 /* genSystemExecJavaProcess - */
12286 /*-----------------------------------------------------------------*/
12287 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12290 operand *handle, *pp;
12292 assert (nparms==2);
12293 /* save registers that need to be saved */
12294 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12295 ds390_rUmaskForOp (IC_RESULT(ic))));
12300 /* put the handle in R3-R2 */
12301 aopOp (handle,ic,FALSE,FALSE);
12302 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12303 emitcode("push","%s",
12304 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12305 emitcode("push","%s",
12306 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12307 emitcode("pop","ar3");
12308 emitcode("pop","ar2");
12310 emitcode ("mov","r2,%s",
12311 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12312 emitcode ("mov","r3,%s",
12313 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12315 freeAsmop (handle, NULL, ic, FALSE);
12317 /* put pointer in DPTR */
12318 aopOp (pp,ic,FALSE,FALSE);
12319 if (AOP_TYPE(pp) == AOP_IMMD) {
12320 emitcode ("mov", "dptr,%s",
12321 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12322 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12323 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12324 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12325 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12327 freeAsmop (handle, NULL, ic, FALSE);
12329 /* make the call */
12330 emitcode ("lcall","System_ExecJavaProcess");
12332 /* put result in place */
12334 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12335 if (rsym->liveFrom != rsym->liveTo) {
12336 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12337 aopPut(AOP(IC_RESULT(ic)),"a",0);
12338 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12342 unsavermask(rsave);
12345 /*-----------------------------------------------------------------*/
12346 /* genSystemRTCRegisters - */
12347 /*-----------------------------------------------------------------*/
12348 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12354 assert (nparms==1);
12355 /* save registers that need to be saved */
12356 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12357 ds390_rUmaskForOp (IC_RESULT(ic))));
12360 /* put pointer in DPTR */
12361 aopOp (pp,ic,FALSE,FALSE);
12362 if (AOP_TYPE (pp) == AOP_IMMD) {
12363 emitcode ("mov","dps,#1");
12364 emitcode ("mov", "dptr,%s",
12365 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12366 emitcode ("mov","dps,#0");
12368 emitcode ("mov","dpl1,%s",
12369 aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12370 emitcode ("mov","dph1,%s",
12371 aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12372 emitcode ("mov","dpx1,%s",
12373 aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12375 freeAsmop (pp, NULL, ic, FALSE);
12377 /* make the call */
12378 emitcode ("lcall","System_%sRTCRegisters",name);
12380 unsavermask(rsave);
12383 /*-----------------------------------------------------------------*/
12384 /* genSystemThreadSleep - */
12385 /*-----------------------------------------------------------------*/
12386 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12391 assert (nparms==1);
12392 /* save registers that need to be saved */
12393 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12394 ds390_rUmaskForOp (IC_RESULT(ic))));
12397 aopOp(to,ic,FALSE,FALSE);
12398 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12399 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12400 emitcode ("push","%s",
12401 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12402 emitcode ("push","%s",
12403 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12404 emitcode ("push","%s",
12405 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12406 emitcode ("push","%s",
12407 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12408 emitcode ("pop","ar3");
12409 emitcode ("pop","ar2");
12410 emitcode ("pop","ar1");
12411 emitcode ("pop","ar0");
12413 emitcode ("mov","r0,%s",
12414 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12415 emitcode ("mov","r1,%s",
12416 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12417 emitcode ("mov","r2,%s",
12418 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12419 emitcode ("mov","r3,%s",
12420 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12422 freeAsmop (to, NULL, ic, FALSE);
12424 /* suspend in acc */
12426 aopOp(s,ic,FALSE,FALSE);
12427 emitcode ("mov","a,%s",
12428 aopGet(AOP(s),0,FALSE,TRUE,NULL));
12429 freeAsmop (s, NULL, ic, FALSE);
12431 /* make the call */
12432 emitcode ("lcall","System_%s",name);
12434 unsavermask(rsave);
12437 /*-----------------------------------------------------------------*/
12438 /* genSystemThreadResume - */
12439 /*-----------------------------------------------------------------*/
12440 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12445 assert (nparms==2);
12446 /* save registers that need to be saved */
12447 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12448 ds390_rUmaskForOp (IC_RESULT(ic))));
12454 aopOp(pid,ic,FALSE,FALSE);
12455 emitcode ("mov","r0,%s",
12456 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12457 freeAsmop (pid, NULL, ic, FALSE);
12460 aopOp(tid,ic,FALSE,FALSE);
12461 emitcode ("mov","a,%s",
12462 aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
12463 freeAsmop (tid, NULL, ic, FALSE);
12465 emitcode ("lcall","System_ThreadResume");
12467 /* put result into place */
12469 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12470 if (rsym->liveFrom != rsym->liveTo) {
12471 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12472 aopPut(AOP(IC_RESULT(ic)),"a",0);
12473 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12476 unsavermask(rsave);
12479 /*-----------------------------------------------------------------*/
12480 /* genSystemProcessResume - */
12481 /*-----------------------------------------------------------------*/
12482 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
12487 assert (nparms==1);
12488 /* save registers that need to be saved */
12489 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12490 ds390_rUmaskForOp (IC_RESULT(ic))));
12495 aopOp(pid,ic,FALSE,FALSE);
12496 emitcode ("mov","a,%s",
12497 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12498 freeAsmop (pid, NULL, ic, FALSE);
12500 emitcode ("lcall","System_ProcessResume");
12502 unsavermask(rsave);
12505 /*-----------------------------------------------------------------*/
12507 /*-----------------------------------------------------------------*/
12508 static void genSystem (iCode *ic,int nparms,char *name)
12510 assert(nparms == 0);
12512 emitcode ("lcall","System_%s",name);
12515 /*-----------------------------------------------------------------*/
12516 /* genSystemPoll - */
12517 /*-----------------------------------------------------------------*/
12518 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
12523 assert (nparms==1);
12524 /* save registers that need to be saved */
12525 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12526 ds390_rUmaskForOp (IC_RESULT(ic))));
12529 aopOp (fp,ic,FALSE,FALSE);
12530 if (AOP_TYPE (fp) == AOP_IMMD) {
12531 emitcode ("mov", "dptr,%s",
12532 aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
12533 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
12534 emitcode ("mov","dpl,%s",
12535 aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
12536 emitcode ("mov","dph,%s",
12537 aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
12538 emitcode ("mov","dpx,%s",
12539 aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
12541 freeAsmop (fp, NULL, ic, FALSE);
12543 emitcode ("lcall","System_%sPoll",name);
12545 /* put result into place */
12547 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12548 if (rsym->liveFrom != rsym->liveTo) {
12549 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12550 aopPut(AOP(IC_RESULT(ic)),"a",0);
12551 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12554 unsavermask(rsave);
12557 /*-----------------------------------------------------------------*/
12558 /* genSystemGetCurrentID - */
12559 /*-----------------------------------------------------------------*/
12560 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
12562 assert (nparms==0);
12564 emitcode ("lcall","System_GetCurrent%sId",name);
12565 /* put result into place */
12567 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12568 if (rsym->liveFrom != rsym->liveTo) {
12569 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12570 aopPut(AOP(IC_RESULT(ic)),"a",0);
12571 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12576 /*-----------------------------------------------------------------*/
12577 /* genBuiltIn - calls the appropriate function to generating code */
12578 /* for a built in function */
12579 /*-----------------------------------------------------------------*/
12580 static void genBuiltIn (iCode *ic)
12582 operand *bi_parms[MAX_BUILTIN_ARGS];
12587 /* get all the arguments for a built in function */
12588 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
12590 /* which function is it */
12591 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
12592 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
12593 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
12594 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
12595 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
12596 } else if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
12597 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
12598 } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
12599 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
12600 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
12601 genMemsetX(bi_iCode,nbi_parms,bi_parms);
12602 } else if (strcmp(bif->name,"__builtin_inp")==0) {
12603 genInp(bi_iCode,nbi_parms,bi_parms);
12604 } else if (strcmp(bif->name,"__builtin_outp")==0) {
12605 genOutp(bi_iCode,nbi_parms,bi_parms);
12606 } else if (strcmp(bif->name,"__builtin_swapw")==0) {
12607 genSwapW(bi_iCode,nbi_parms,bi_parms);
12608 /* JavaNative builtIns */
12609 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
12610 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
12611 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
12612 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
12613 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
12614 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
12615 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
12616 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
12617 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
12618 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12619 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
12620 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12621 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
12622 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
12623 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
12624 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
12625 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
12626 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12627 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
12628 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12629 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
12630 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
12631 } else if (strcmp(bif->name,"MM_Malloc")==0) {
12632 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
12633 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
12634 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
12635 } else if (strcmp(bif->name,"MM_Free")==0) {
12636 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
12637 } else if (strcmp(bif->name,"MM_Deref")==0) {
12638 genMMDeref(bi_iCode,nbi_parms,bi_parms);
12639 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
12640 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
12641 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
12642 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
12643 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
12644 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
12645 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
12646 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
12647 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
12648 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
12649 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
12650 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
12651 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
12652 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
12653 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
12654 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
12655 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12656 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12657 } else if (strcmp(bif->name,"System_SaveThread")==0) {
12658 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12659 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12660 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12661 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
12662 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
12663 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
12664 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
12665 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
12666 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
12667 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
12668 genSystem(bi_iCode,nbi_parms,"ProcessYield");
12669 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
12670 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
12671 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
12672 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
12673 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
12674 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
12675 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
12676 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
12677 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
12678 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
12680 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
12686 /*-----------------------------------------------------------------*/
12687 /* gen390Code - generate code for Dallas 390 based controllers */
12688 /*-----------------------------------------------------------------*/
12690 gen390Code (iCode * lic)
12695 lineHead = lineCurr = NULL;
12696 dptrn[1][0] = "dpl1";
12697 dptrn[1][1] = "dph1";
12698 dptrn[1][2] = "dpx1";
12700 if (options.model == MODEL_FLAT24) {
12701 fReturnSizeDS390 = 5;
12702 fReturn = fReturn24;
12704 fReturnSizeDS390 = 4;
12705 fReturn = fReturn16;
12706 options.stack10bit=0;
12709 /* print the allocation information */
12710 if (allocInfo && currFunc)
12711 printAllocInfo (currFunc, codeOutFile);
12713 /* if debug information required */
12714 if (options.debug && currFunc)
12716 debugFile->writeFunction(currFunc);
12718 if (IS_STATIC (currFunc->etype))
12719 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
12721 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
12724 /* stack pointer name */
12725 if (options.useXstack)
12731 for (ic = lic; ic; ic = ic->next)
12734 if (ic->lineno && cln != ic->lineno)
12739 emitcode ("", "C$%s$%d$%d$%d ==.",
12740 FileBaseName (ic->filename), ic->lineno,
12741 ic->level, ic->block);
12744 if (!options.noCcodeInAsm) {
12745 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
12746 printCLine(ic->filename, ic->lineno));
12750 if (options.iCodeInAsm) {
12751 emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
12753 /* if the result is marked as
12754 spilt and rematerializable or code for
12755 this has already been generated then
12757 if (resultRemat (ic) || ic->generated)
12760 /* depending on the operation */
12780 /* IPOP happens only when trying to restore a
12781 spilt live range, if there is an ifx statement
12782 following this pop then the if statement might
12783 be using some of the registers being popped which
12784 would destory the contents of the register so
12785 we need to check for this condition and handle it */
12787 ic->next->op == IFX &&
12788 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
12789 genIfx (ic->next, ic);
12807 genEndFunction (ic);
12827 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
12844 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
12848 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
12855 /* note these two are xlated by algebraic equivalence
12856 during parsing SDCC.y */
12857 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12858 "got '>=' or '<=' shouldn't have come here");
12862 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
12874 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
12878 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
12882 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
12906 genRightShift (ic);
12909 case GET_VALUE_AT_ADDRESS:
12910 genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
12914 if (POINTER_SET (ic))
12915 genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
12941 if (ic->builtinSEND) genBuiltIn(ic);
12942 else addSet (&_G.sendSet, ic);
12955 /* now we are ready to call the
12956 peep hole optimizer */
12957 if (!options.nopeep)
12958 peepHole (&lineHead);
12960 /* now do the actual printing */
12961 printLine (lineHead, codeOutFile);