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");
3818 // Right uses DPTR unless left or result is an AOP_STR.
3819 aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)));
3821 // if the right used DPTR, left MUST use DPTR2.
3822 // if the right used DPTR2, left MUST use DPTR.
3823 // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
3824 // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
3825 // enabling us to assign DPTR to result.
3827 if (AOP_USESDPTR(IC_RIGHT(ic)))
3831 else if (AOP_USESDPTR2(IC_RIGHT(ic)))
3837 if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
3847 aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
3849 // We've op'd the left & right. So, if left or right are the same operand as result,
3850 // we know aopOp will succeed, and we can just do it & bail.
3851 if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)) ||
3852 isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
3854 // D(emitcode(";", "aopOp3: (left | right) & result equal"););
3855 aopOp(IC_RESULT(ic),ic,TRUE, FALSE);
3859 // Note which dptrs are currently in use.
3860 dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
3861 dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
3863 // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot
3865 if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
3870 // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
3871 if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
3876 // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck
3877 if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
3882 aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
3884 // Some sanity checking...
3885 if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
3888 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
3889 __FILE__, __LINE__, ic->filename, ic->lineno);
3890 emitcode(";", ">>> unexpected DPTR here.");
3893 if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
3896 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
3897 __FILE__, __LINE__, ic->filename, ic->lineno);
3898 emitcode(";", ">>> unexpected DPTR2 here.");
3904 // Macro to aopOp all three operands of an ic. If this cannot be done,
3905 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3906 // will be set TRUE. The caller must then handle the case specially, noting
3907 // that the IC_RESULT operand is not aopOp'd.
3909 #define AOP_OP_3_NOFATAL(ic, rc) \
3910 do { rc = !aopOp3(ic); } while (0)
3912 // aopOp the left & right operands of an ic.
3913 #define AOP_OP_2(ic) \
3914 aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
3915 aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
3917 // convienience macro.
3918 #define AOP_SET_LOCALS(ic) \
3919 left = IC_LEFT(ic); \
3920 right = IC_RIGHT(ic); \
3921 result = IC_RESULT(ic);
3924 // Given an integer value of pushedSize bytes on the stack,
3925 // adjust it to be resultSize bytes, either by discarding
3926 // the most significant bytes or by zero-padding.
3928 // On exit from this macro, pushedSize will have been adjusted to
3929 // equal resultSize, and ACC may be trashed.
3930 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3931 /* If the pushed data is bigger than the result, \
3932 * simply discard unused bytes. Icky, but works. \
3934 while (pushedSize > resultSize) \
3936 D (emitcode (";", "discarding unused result byte."););\
3937 emitcode ("pop", "acc"); \
3940 if (pushedSize < resultSize) \
3942 emitcode ("clr", "a"); \
3943 /* Conversly, we haven't pushed enough here. \
3944 * just zero-pad, and all is well. \
3946 while (pushedSize < resultSize) \
3948 emitcode("push", "acc"); \
3952 assert(pushedSize == resultSize);
3954 /*-----------------------------------------------------------------*/
3955 /* genPlus - generates code for addition */
3956 /*-----------------------------------------------------------------*/
3958 genPlus (iCode * ic)
3960 int size, offset = 0;
3964 D (emitcode (";", "genPlus "););
3966 /* special cases :- */
3967 if ( AOP_IS_STR(IC_LEFT(ic)) &&
3968 isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
3969 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
3970 size = floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
3972 while (size--) emitcode ("inc","dptr");
3974 emitcode ("mov","a,dpl");
3975 emitcode ("add","a,#!constbyte",size & 0xff);
3976 emitcode ("mov","dpl,a");
3977 emitcode ("mov","a,dph");
3978 emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
3979 emitcode ("mov","dph,a");
3980 emitcode ("mov","a,dpx");
3981 emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
3982 emitcode ("mov","dpx,a");
3984 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
3987 if ( IS_SYMOP(IC_LEFT(ic)) &&
3988 OP_SYMBOL(IC_LEFT(ic))->remat &&
3989 isOperandInFarSpace(IC_RIGHT(ic))) {
3990 operand *op = IC_RIGHT(ic);
3991 IC_RIGHT(ic) = IC_LEFT(ic);
3995 AOP_OP_3_NOFATAL (ic, pushResult);
3999 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
4004 /* if literal, literal on the right or
4005 if left requires ACC or right is already
4007 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4008 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
4009 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4011 operand *t = IC_RIGHT (ic);
4012 IC_RIGHT (ic) = IC_LEFT (ic);
4014 emitcode (";", "Swapped plus args.");
4017 /* if both left & right are in bit
4019 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4020 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4026 /* if left in bit space & right literal */
4027 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4028 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4030 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4031 /* if result in bit space */
4032 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4034 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4035 emitcode ("cpl", "c");
4036 outBitC (IC_RESULT (ic));
4040 size = getDataSize (IC_RESULT (ic));
4041 _startLazyDPSEvaluation ();
4044 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4045 emitcode ("addc", "a,#0");
4046 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4048 _endLazyDPSEvaluation ();
4053 /* if I can do an increment instead
4054 of add then GOOD for ME */
4055 if (genPlusIncr (ic) == TRUE)
4057 emitcode (";", "did genPlusIncr");
4062 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4064 _startLazyDPSEvaluation ();
4067 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4069 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4071 emitcode ("add", "a,%s",
4072 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4074 emitcode ("addc", "a,%s",
4075 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4079 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4081 /* right is going to use ACC or we would have taken the
4084 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4086 D(emitcode(";", "+ AOP_ACC special case."););
4087 emitcode("xch", "a, %s", DP2_RESULT_REG);
4089 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4092 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4095 emitcode("add", "a, %s", DP2_RESULT_REG);
4099 emitcode ("add", "a,%s",
4100 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE,
4106 emitcode ("addc", "a,%s",
4107 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE,
4113 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4117 emitcode ("push", "acc");
4121 _endLazyDPSEvaluation ();
4125 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4127 size = getDataSize (IC_LEFT (ic));
4128 rSize = getDataSize (IC_RESULT (ic));
4130 ADJUST_PUSHED_RESULT(size, rSize);
4132 _startLazyDPSEvaluation ();
4135 emitcode ("pop", "acc");
4136 aopPut (AOP (IC_RESULT (ic)), "a", size);
4138 _endLazyDPSEvaluation ();
4141 adjustArithmeticResult (ic);
4144 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4145 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4146 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4149 /*-----------------------------------------------------------------*/
4150 /* genMinusDec :- does subtraction with deccrement if possible */
4151 /*-----------------------------------------------------------------*/
4153 genMinusDec (iCode * ic)
4155 unsigned int icount;
4156 unsigned int size = getDataSize (IC_RESULT (ic));
4158 /* will try to generate an increment */
4159 /* if the right side is not a literal
4161 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4164 /* if the literal value of the right hand side
4165 is greater than 4 then it is not worth it */
4166 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4169 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4170 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4172 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
4176 /* if decrement 16 bits in register */
4177 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4178 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4179 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4188 /* If the next instruction is a goto and the goto target
4189 * is <= 5 instructions previous to this, we can generate
4190 * jumps straight to that target.
4192 if (ic->next && ic->next->op == GOTO
4193 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4196 emitcode (";", "tail decrement optimized (range %d)", labelRange);
4197 tlbl = IC_LABEL (ic->next);
4202 tlbl = newiTempLabel (NULL);
4206 l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
4207 emitcode ("dec", "%s", l);
4209 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4210 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4211 IS_AOP_PREG (IC_RESULT (ic)))
4213 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4217 emitcode ("mov", "a,#!constbyte",0xff);
4218 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4220 l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
4221 emitcode ("dec", "%s", l);
4224 if (!strcmp(l, "acc"))
4226 emitcode("jnz", "!tlabel", tlbl->key + 100);
4228 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4229 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4230 IS_AOP_PREG (IC_RESULT (ic)))
4232 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4236 emitcode ("mov", "a,#!constbyte",0xff);
4237 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4239 l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
4240 emitcode ("dec", "%s", l);
4244 if (!strcmp(l, "acc"))
4246 emitcode("jnz", "!tlabel", tlbl->key + 100);
4248 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4249 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4250 IS_AOP_PREG (IC_RESULT (ic)))
4252 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4256 emitcode ("mov", "a,#!constbyte",0xff);
4257 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4259 l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
4260 emitcode ("dec", "%s", l);
4264 emitcode ("", "!tlabeldef", tlbl->key + 100);
4269 /* if the sizes are greater than 1 then we cannot */
4270 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4271 AOP_SIZE (IC_LEFT (ic)) > 1)
4274 /* we can if the aops of the left & result match or
4275 if they are in registers and the registers are the
4278 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4279 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4280 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4283 _startLazyDPSEvaluation ();
4286 emitcode ("dec", "%s",
4287 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
4289 _endLazyDPSEvaluation ();
4297 /*-----------------------------------------------------------------*/
4298 /* addSign - complete with sign */
4299 /*-----------------------------------------------------------------*/
4301 addSign (operand * result, int offset, int sign)
4303 int size = (getDataSize (result) - offset);
4306 _startLazyDPSEvaluation();
4309 emitcode ("rlc", "a");
4310 emitcode ("subb", "a,acc");
4313 aopPut (AOP (result), "a", offset++);
4320 aopPut (AOP (result), zero, offset++);
4323 _endLazyDPSEvaluation();
4327 /*-----------------------------------------------------------------*/
4328 /* genMinusBits - generates code for subtraction of two bits */
4329 /*-----------------------------------------------------------------*/
4331 genMinusBits (iCode * ic)
4333 symbol *lbl = newiTempLabel (NULL);
4335 D (emitcode (";", "genMinusBits "););
4337 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4339 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4340 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4341 emitcode ("cpl", "c");
4342 emitcode ("", "!tlabeldef", (lbl->key + 100));
4343 outBitC (IC_RESULT (ic));
4347 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4348 emitcode ("subb", "a,acc");
4349 emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4350 emitcode ("inc", "a");
4351 emitcode ("", "!tlabeldef", (lbl->key + 100));
4352 aopPut (AOP (IC_RESULT (ic)), "a", 0);
4353 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4357 /*-----------------------------------------------------------------*/
4358 /* genMinus - generates code for subtraction */
4359 /*-----------------------------------------------------------------*/
4361 genMinus (iCode * ic)
4363 int size, offset = 0;
4368 D (emitcode (";", "genMinus "););
4370 AOP_OP_3_NOFATAL(ic, pushResult);
4374 /* special cases :- */
4375 /* if both left & right are in bit space */
4376 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4377 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4383 /* if I can do an decrement instead
4384 of subtract then GOOD for ME */
4385 if (genMinusDec (ic) == TRUE)
4390 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4392 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4398 lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4403 /* if literal, add a,#-lit, else normal subb */
4404 _startLazyDPSEvaluation ();
4406 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4407 if (AOP_USESDPTR(IC_RIGHT(ic))) {
4408 emitcode ("mov","b,%s",
4409 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4410 MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4411 emitcode ("subb","a,b");
4413 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4414 emitcode ("subb", "a,%s",
4415 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE,
4419 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4420 /* first add without previous c */
4422 if (!size && lit==-1) {
4423 emitcode ("dec", "a");
4425 emitcode ("add", "a,#!constbyte",
4426 (unsigned int) (lit & 0x0FFL));
4429 emitcode ("addc", "a,#!constbyte",
4430 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4435 emitcode ("push", "acc");
4437 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4441 _endLazyDPSEvaluation ();
4445 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4447 size = getDataSize (IC_LEFT (ic));
4448 rSize = getDataSize (IC_RESULT (ic));
4450 ADJUST_PUSHED_RESULT(size, rSize);
4452 _startLazyDPSEvaluation ();
4455 emitcode ("pop", "acc");
4456 aopPut (AOP (IC_RESULT (ic)), "a", size);
4458 _endLazyDPSEvaluation ();
4461 adjustArithmeticResult (ic);
4464 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4465 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4466 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4470 /*-----------------------------------------------------------------*/
4471 /* genMultbits :- multiplication of bits */
4472 /*-----------------------------------------------------------------*/
4474 genMultbits (operand * left,
4479 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4480 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4481 aopOp(result, ic, TRUE, FALSE);
4486 /*-----------------------------------------------------------------*/
4487 /* genMultOneByte : 8*8=8/16 bit multiplication */
4488 /*-----------------------------------------------------------------*/
4490 genMultOneByte (operand * left,
4495 sym_link *opetype = operandType (result);
4499 /* (if two literals: the value is computed before) */
4500 /* if one literal, literal on the right */
4501 if (AOP_TYPE (left) == AOP_LIT)
4506 emitcode (";", "swapped left and right");
4509 if (SPEC_USIGN(opetype)
4510 // ignore the sign of left and right, what else can we do?
4511 || (SPEC_USIGN(operandType(left)) &&
4512 SPEC_USIGN(operandType(right)))) {
4513 // just an unsigned 8*8=8/16 multiply
4514 //emitcode (";","unsigned");
4515 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4516 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4517 emitcode ("mul", "ab");
4519 _G.accInUse++; _G.bInUse++;
4520 aopOp(result, ic, TRUE, FALSE);
4522 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4524 // this should never happen
4525 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4526 AOP_SIZE(result), __FILE__, lineno);
4530 aopPut (AOP (result), "a", 0);
4531 _G.accInUse--; _G.bInUse--;
4532 if (AOP_SIZE(result)==2)
4534 aopPut (AOP (result), "b", 1);
4539 // we have to do a signed multiply
4541 emitcode (";", "signed");
4542 emitcode ("clr", "F0"); // reset sign flag
4543 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4545 lbl=newiTempLabel(NULL);
4546 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4547 // left side is negative, 8-bit two's complement, this fails for -128
4548 emitcode ("setb", "F0"); // set sign flag
4549 emitcode ("cpl", "a");
4550 emitcode ("inc", "a");
4552 emitcode ("", "!tlabeldef", lbl->key+100);
4555 if (AOP_TYPE(right)==AOP_LIT) {
4556 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4557 /* AND literal negative */
4558 if ((int) val < 0) {
4559 emitcode ("cpl", "F0"); // complement sign flag
4560 emitcode ("mov", "b,#!constbyte", -val);
4562 emitcode ("mov", "b,#!constbyte", val);
4565 lbl=newiTempLabel(NULL);
4566 emitcode ("mov", "b,a");
4567 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4568 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4569 // right side is negative, 8-bit two's complement
4570 emitcode ("cpl", "F0"); // complement sign flag
4571 emitcode ("cpl", "a");
4572 emitcode ("inc", "a");
4573 emitcode ("", "!tlabeldef", lbl->key+100);
4575 emitcode ("mul", "ab");
4577 _G.accInUse++;_G.bInUse++;
4578 aopOp(result, ic, TRUE, FALSE);
4580 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4582 // this should never happen
4583 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4584 AOP_SIZE(result), __FILE__, lineno);
4588 lbl=newiTempLabel(NULL);
4589 emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4590 // only ONE op was negative, we have to do a 8/16-bit two's complement
4591 emitcode ("cpl", "a"); // lsb
4592 if (AOP_SIZE(result)==1) {
4593 emitcode ("inc", "a");
4595 emitcode ("add", "a,#1");
4596 emitcode ("xch", "a,b");
4597 emitcode ("cpl", "a"); // msb
4598 emitcode ("addc", "a,#0");
4599 emitcode ("xch", "a,b");
4602 emitcode ("", "!tlabeldef", lbl->key+100);
4603 aopPut (AOP (result), "a", 0);
4604 _G.accInUse--;_G.bInUse--;
4605 if (AOP_SIZE(result)==2) {
4606 aopPut (AOP (result), "b", 1);
4610 /*-----------------------------------------------------------------*/
4611 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
4612 /*-----------------------------------------------------------------*/
4613 static void genMultTwoByte (operand *left, operand *right,
4614 operand *result, iCode *ic)
4616 sym_link *retype = getSpec(operandType(right));
4617 sym_link *letype = getSpec(operandType(left));
4618 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4621 if (AOP_TYPE (left) == AOP_LIT) {
4626 /* save EA bit in F1 */
4627 lbl = newiTempLabel(NULL);
4628 emitcode ("setb","F1");
4629 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4630 emitcode ("clr","F1");
4631 emitcode("","!tlabeldef",lbl->key+100);
4633 /* load up MB with right */
4635 emitcode("clr","F0");
4636 if (AOP_TYPE(right) == AOP_LIT) {
4637 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4639 emitcode("setb","F0");
4642 emitcode ("mov","mb,#!constbyte",val & 0xff);
4643 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4645 lbl = newiTempLabel(NULL);
4646 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4647 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4648 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4649 emitcode ("xch", "a,b");
4650 emitcode ("cpl","a");
4651 emitcode ("add", "a,#1");
4652 emitcode ("xch", "a,b");
4653 emitcode ("cpl", "a"); // msb
4654 emitcode ("addc", "a,#0");
4655 emitcode ("setb","F0");
4656 emitcode ("","!tlabeldef",lbl->key+100);
4657 emitcode ("mov","mb,b");
4658 emitcode ("mov","mb,a");
4661 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4662 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4664 /* load up MA with left */
4666 lbl = newiTempLabel(NULL);
4667 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4668 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4669 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4670 emitcode ("xch", "a,b");
4671 emitcode ("cpl","a");
4672 emitcode ("add", "a,#1");
4673 emitcode ("xch", "a,b");
4674 emitcode ("cpl", "a"); // msb
4675 emitcode ("addc","a,#0");
4676 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4677 emitcode ("setb","F0");
4678 emitcode ("","!tlabeldef",lbl->key+100);
4679 emitcode ("mov","ma,b");
4680 emitcode ("mov","ma,a");
4682 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4683 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4685 /* wait for multiplication to finish */
4686 lbl = newiTempLabel(NULL);
4687 emitcode("","!tlabeldef", lbl->key+100);
4688 emitcode("mov","a,mcnt1");
4689 emitcode("anl","a,#!constbyte",0x80);
4690 emitcode("jnz","!tlabel",lbl->key+100);
4692 freeAsmop (left, NULL, ic, TRUE);
4693 freeAsmop (right, NULL, ic,TRUE);
4694 aopOp(result, ic, TRUE, FALSE);
4696 /* if unsigned then simple */
4698 emitcode ("mov","a,ma");
4699 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4700 emitcode ("mov","a,ma");
4701 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4702 aopPut(AOP(result),"ma",1);
4703 aopPut(AOP(result),"ma",0);
4705 emitcode("push","ma");
4706 emitcode("push","ma");
4707 emitcode("push","ma");
4709 /* negate result if needed */
4710 lbl = newiTempLabel(NULL);
4711 emitcode("jnb","F0,!tlabel",lbl->key+100);
4712 emitcode("cpl","a");
4713 emitcode("add","a,#1");
4714 emitcode("","!tlabeldef", lbl->key+100);
4715 if (AOP_TYPE(result) == AOP_ACC)
4717 D(emitcode(";", "ACC special case."););
4718 /* We know result is the only live aop, and
4719 * it's obviously not a DPTR2, so AP is available.
4721 emitcode("mov", "%s,acc", DP2_RESULT_REG);
4725 aopPut(AOP(result),"a",0);
4728 emitcode("pop","acc");
4729 lbl = newiTempLabel(NULL);
4730 emitcode("jnb","F0,!tlabel",lbl->key+100);
4731 emitcode("cpl","a");
4732 emitcode("addc","a,#0");
4733 emitcode("","!tlabeldef", lbl->key+100);
4734 aopPut(AOP(result),"a",1);
4735 emitcode("pop","acc");
4736 if (AOP_SIZE(result) >= 3) {
4737 lbl = newiTempLabel(NULL);
4738 emitcode("jnb","F0,!tlabel",lbl->key+100);
4739 emitcode("cpl","a");
4740 emitcode("addc","a,#0");
4741 emitcode("","!tlabeldef", lbl->key+100);
4742 aopPut(AOP(result),"a",2);
4744 emitcode("pop","acc");
4745 if (AOP_SIZE(result) >= 4) {
4746 lbl = newiTempLabel(NULL);
4747 emitcode("jnb","F0,!tlabel",lbl->key+100);
4748 emitcode("cpl","a");
4749 emitcode("addc","a,#0");
4750 emitcode("","!tlabeldef", lbl->key+100);
4751 aopPut(AOP(result),"a",3);
4753 if (AOP_TYPE(result) == AOP_ACC)
4755 /* We stashed the result away above. */
4756 emitcode("mov", "acc,%s", DP2_RESULT_REG);
4760 freeAsmop (result, NULL, ic, TRUE);
4762 /* restore EA bit in F1 */
4763 lbl = newiTempLabel(NULL);
4764 emitcode ("jnb","F1,!tlabel",lbl->key+100);
4765 emitcode ("setb","EA");
4766 emitcode("","!tlabeldef",lbl->key+100);
4770 /*-----------------------------------------------------------------*/
4771 /* genMult - generates code for multiplication */
4772 /*-----------------------------------------------------------------*/
4774 genMult (iCode * ic)
4776 operand *left = IC_LEFT (ic);
4777 operand *right = IC_RIGHT (ic);
4778 operand *result = IC_RESULT (ic);
4780 D (emitcode (";", "genMult "););
4782 /* assign the amsops */
4785 /* special cases first */
4787 if (AOP_TYPE (left) == AOP_CRY &&
4788 AOP_TYPE (right) == AOP_CRY)
4790 genMultbits (left, right, result, ic);
4794 /* if both are of size == 1 */
4795 if (AOP_SIZE (left) == 1 &&
4796 AOP_SIZE (right) == 1)
4798 genMultOneByte (left, right, result, ic);
4802 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4803 /* use the ds390 ARITHMETIC accel UNIT */
4804 genMultTwoByte (left, right, result, ic);
4807 /* should have been converted to function call */
4811 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4812 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4813 freeAsmop (result, NULL, ic, TRUE);
4816 /*-----------------------------------------------------------------*/
4817 /* genDivbits :- division of bits */
4818 /*-----------------------------------------------------------------*/
4820 genDivbits (operand * left,
4828 /* the result must be bit */
4829 LOAD_AB_FOR_DIV (left, right, l);
4830 emitcode ("div", "ab");
4831 emitcode ("rrc", "a");
4832 aopOp(result, ic, TRUE, FALSE);
4834 aopPut (AOP (result), "c", 0);
4837 /*-----------------------------------------------------------------*/
4838 /* genDivOneByte : 8 bit division */
4839 /*-----------------------------------------------------------------*/
4841 genDivOneByte (operand * left,
4846 sym_link *opetype = operandType (result);
4852 /* signed or unsigned */
4853 if (SPEC_USIGN (opetype))
4855 /* unsigned is easy */
4856 LOAD_AB_FOR_DIV (left, right, l);
4857 emitcode ("div", "ab");
4860 aopOp(result, ic, TRUE, FALSE);
4861 aopPut (AOP (result), "a", 0);
4864 size = AOP_SIZE (result) - 1;
4868 aopPut (AOP (result), zero, offset++);
4873 /* signed is a little bit more difficult */
4875 /* save the signs of the operands */
4876 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4877 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4878 emitcode ("push", "acc"); /* save it on the stack */
4880 /* now sign adjust for both left & right */
4881 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4882 lbl = newiTempLabel (NULL);
4883 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4884 emitcode ("cpl", "a");
4885 emitcode ("inc", "a");
4886 emitcode ("", "!tlabeldef", (lbl->key + 100));
4887 emitcode ("mov", "b,a");
4889 /* sign adjust left side */
4890 MOVA( aopGet (AOP (left), 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));
4898 /* now the division */
4899 emitcode ("nop", "; workaround for DS80C390 div bug.");
4900 emitcode ("div", "ab");
4901 /* we are interested in the lower order
4903 emitcode ("mov", "b,a");
4904 lbl = newiTempLabel (NULL);
4905 emitcode ("pop", "acc");
4906 /* if there was an over flow we don't
4907 adjust the sign of the result */
4908 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4909 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4911 emitcode ("clr", "a");
4912 emitcode ("subb", "a,b");
4913 emitcode ("mov", "b,a");
4914 emitcode ("", "!tlabeldef", (lbl->key + 100));
4916 /* now we are done */
4917 _G.accInUse++; _G.bInUse++;
4918 aopOp(result, ic, TRUE, FALSE);
4920 aopPut (AOP (result), "b", 0);
4922 size = AOP_SIZE (result) - 1;
4926 emitcode ("mov", "c,b.7");
4927 emitcode ("subb", "a,acc");
4931 aopPut (AOP (result), "a", offset++);
4933 _G.accInUse--; _G.bInUse--;
4937 /*-----------------------------------------------------------------*/
4938 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
4939 /*-----------------------------------------------------------------*/
4940 static void genDivTwoByte (operand *left, operand *right,
4941 operand *result, iCode *ic)
4943 sym_link *retype = getSpec(operandType(right));
4944 sym_link *letype = getSpec(operandType(left));
4945 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4948 /* save EA bit in F1 */
4949 lbl = newiTempLabel(NULL);
4950 emitcode ("setb","F1");
4951 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4952 emitcode ("clr","F1");
4953 emitcode("","!tlabeldef",lbl->key+100);
4955 /* load up MA with left */
4957 emitcode("clr","F0");
4958 lbl = newiTempLabel(NULL);
4959 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4960 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4961 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4962 emitcode ("xch", "a,b");
4963 emitcode ("cpl","a");
4964 emitcode ("add", "a,#1");
4965 emitcode ("xch", "a,b");
4966 emitcode ("cpl", "a"); // msb
4967 emitcode ("addc","a,#0");
4968 emitcode ("setb","F0");
4969 emitcode ("","!tlabeldef",lbl->key+100);
4970 emitcode ("mov","ma,b");
4971 emitcode ("mov","ma,a");
4973 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4974 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4977 /* load up MB with right */
4979 if (AOP_TYPE(right) == AOP_LIT) {
4980 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4982 lbl = newiTempLabel(NULL);
4983 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4984 emitcode("setb","F0");
4985 emitcode ("","!tlabeldef",lbl->key+100);
4988 emitcode ("mov","mb,#!constbyte",val & 0xff);
4989 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4991 lbl = newiTempLabel(NULL);
4992 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4993 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4994 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4995 emitcode ("xch", "a,b");
4996 emitcode ("cpl","a");
4997 emitcode ("add", "a,#1");
4998 emitcode ("xch", "a,b");
4999 emitcode ("cpl", "a"); // msb
5000 emitcode ("addc", "a,#0");
5001 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5002 emitcode ("setb","F0");
5003 emitcode ("","!tlabeldef",lbl->key+100);
5004 emitcode ("mov","mb,b");
5005 emitcode ("mov","mb,a");
5008 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5009 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5012 /* wait for multiplication to finish */
5013 lbl = newiTempLabel(NULL);
5014 emitcode("","!tlabeldef", lbl->key+100);
5015 emitcode("mov","a,mcnt1");
5016 emitcode("anl","a,#!constbyte",0x80);
5017 emitcode("jnz","!tlabel",lbl->key+100);
5019 freeAsmop (left, NULL, ic, TRUE);
5020 freeAsmop (right, NULL, ic,TRUE);
5021 aopOp(result, ic, TRUE, FALSE);
5023 /* if unsigned then simple */
5025 aopPut(AOP(result),"ma",1);
5026 aopPut(AOP(result),"ma",0);
5028 emitcode("push","ma");
5030 /* negate result if needed */
5031 lbl = newiTempLabel(NULL);
5032 emitcode("jnb","F0,!tlabel",lbl->key+100);
5033 emitcode("cpl","a");
5034 emitcode("add","a,#1");
5035 emitcode("","!tlabeldef", lbl->key+100);
5036 aopPut(AOP(result),"a",0);
5037 emitcode("pop","acc");
5038 lbl = newiTempLabel(NULL);
5039 emitcode("jnb","F0,!tlabel",lbl->key+100);
5040 emitcode("cpl","a");
5041 emitcode("addc","a,#0");
5042 emitcode("","!tlabeldef", lbl->key+100);
5043 aopPut(AOP(result),"a",1);
5045 freeAsmop (result, NULL, ic, TRUE);
5046 /* restore EA bit in F1 */
5047 lbl = newiTempLabel(NULL);
5048 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5049 emitcode ("setb","EA");
5050 emitcode("","!tlabeldef",lbl->key+100);
5054 /*-----------------------------------------------------------------*/
5055 /* genDiv - generates code for division */
5056 /*-----------------------------------------------------------------*/
5060 operand *left = IC_LEFT (ic);
5061 operand *right = IC_RIGHT (ic);
5062 operand *result = IC_RESULT (ic);
5064 D (emitcode (";", "genDiv "););
5066 /* assign the amsops */
5069 /* special cases first */
5071 if (AOP_TYPE (left) == AOP_CRY &&
5072 AOP_TYPE (right) == AOP_CRY)
5074 genDivbits (left, right, result, ic);
5078 /* if both are of size == 1 */
5079 if (AOP_SIZE (left) == 1 &&
5080 AOP_SIZE (right) == 1)
5082 genDivOneByte (left, right, result, ic);
5086 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5087 /* use the ds390 ARITHMETIC accel UNIT */
5088 genDivTwoByte (left, right, result, ic);
5091 /* should have been converted to function call */
5094 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5095 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5096 freeAsmop (result, NULL, ic, TRUE);
5099 /*-----------------------------------------------------------------*/
5100 /* genModbits :- modulus of bits */
5101 /*-----------------------------------------------------------------*/
5103 genModbits (operand * left,
5111 /* the result must be bit */
5112 LOAD_AB_FOR_DIV (left, right, l);
5113 emitcode ("div", "ab");
5114 emitcode ("mov", "a,b");
5115 emitcode ("rrc", "a");
5116 aopOp(result, ic, TRUE, FALSE);
5117 aopPut (AOP (result), "c", 0);
5120 /*-----------------------------------------------------------------*/
5121 /* genModOneByte : 8 bit modulus */
5122 /*-----------------------------------------------------------------*/
5124 genModOneByte (operand * left,
5129 sym_link *opetype = operandType (result);
5133 /* signed or unsigned */
5134 if (SPEC_USIGN (opetype))
5136 /* unsigned is easy */
5137 LOAD_AB_FOR_DIV (left, right, l);
5138 emitcode ("div", "ab");
5139 aopOp(result, ic, TRUE, FALSE);
5140 aopPut (AOP (result), "b", 0);
5144 /* signed is a little bit more difficult */
5146 /* save the signs of the operands */
5147 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5149 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
5150 emitcode ("push", "acc"); /* save it on the stack */
5152 /* now sign adjust for both left & right */
5153 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5155 lbl = newiTempLabel (NULL);
5156 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5157 emitcode ("cpl", "a");
5158 emitcode ("inc", "a");
5159 emitcode ("", "!tlabeldef", (lbl->key + 100));
5160 emitcode ("mov", "b,a");
5162 /* sign adjust left side */
5163 MOVA (aopGet (AOP (left), 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));
5171 /* now the multiplication */
5172 emitcode ("nop", "; workaround for DS80C390 div bug.");
5173 emitcode ("div", "ab");
5174 /* we are interested in the lower order
5176 lbl = newiTempLabel (NULL);
5177 emitcode ("pop", "acc");
5178 /* if there was an over flow we don't
5179 adjust the sign of the result */
5180 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
5181 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5183 emitcode ("clr", "a");
5184 emitcode ("subb", "a,b");
5185 emitcode ("mov", "b,a");
5186 emitcode ("", "!tlabeldef", (lbl->key + 100));
5189 /* now we are done */
5190 aopOp(result, ic, TRUE, FALSE);
5191 aopPut (AOP (result), "b", 0);
5196 /*-----------------------------------------------------------------*/
5197 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
5198 /*-----------------------------------------------------------------*/
5199 static void genModTwoByte (operand *left, operand *right,
5200 operand *result, iCode *ic)
5202 sym_link *retype = getSpec(operandType(right));
5203 sym_link *letype = getSpec(operandType(left));
5204 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5207 /* load up MA with left */
5208 /* save EA bit in F1 */
5209 lbl = newiTempLabel(NULL);
5210 emitcode ("setb","F1");
5211 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5212 emitcode ("clr","F1");
5213 emitcode("","!tlabeldef",lbl->key+100);
5216 lbl = newiTempLabel(NULL);
5217 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5218 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5219 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5220 emitcode ("xch", "a,b");
5221 emitcode ("cpl","a");
5222 emitcode ("add", "a,#1");
5223 emitcode ("xch", "a,b");
5224 emitcode ("cpl", "a"); // msb
5225 emitcode ("addc","a,#0");
5226 emitcode ("","!tlabeldef",lbl->key+100);
5227 emitcode ("mov","ma,b");
5228 emitcode ("mov","ma,a");
5230 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5231 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5234 /* load up MB with right */
5236 if (AOP_TYPE(right) == AOP_LIT) {
5237 int val=floatFromVal (AOP (right)->aopu.aop_lit);
5241 emitcode ("mov","mb,#!constbyte",val & 0xff);
5242 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5244 lbl = newiTempLabel(NULL);
5245 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5246 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5247 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5248 emitcode ("xch", "a,b");
5249 emitcode ("cpl","a");
5250 emitcode ("add", "a,#1");
5251 emitcode ("xch", "a,b");
5252 emitcode ("cpl", "a"); // msb
5253 emitcode ("addc", "a,#0");
5254 emitcode ("","!tlabeldef",lbl->key+100);
5255 emitcode ("mov","mb,b");
5256 emitcode ("mov","mb,a");
5259 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5260 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5263 /* wait for multiplication to finish */
5264 lbl = newiTempLabel(NULL);
5265 emitcode("","!tlabeldef", lbl->key+100);
5266 emitcode("mov","a,mcnt1");
5267 emitcode("anl","a,#!constbyte",0x80);
5268 emitcode("jnz","!tlabel",lbl->key+100);
5270 freeAsmop (left, NULL, ic, TRUE);
5271 freeAsmop (right, NULL, ic,TRUE);
5272 aopOp(result, ic, TRUE, FALSE);
5274 aopPut(AOP(result),"mb",1);
5275 aopPut(AOP(result),"mb",0);
5276 freeAsmop (result, NULL, ic, TRUE);
5278 /* restore EA bit in F1 */
5279 lbl = newiTempLabel(NULL);
5280 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5281 emitcode ("setb","EA");
5282 emitcode("","!tlabeldef",lbl->key+100);
5286 /*-----------------------------------------------------------------*/
5287 /* genMod - generates code for division */
5288 /*-----------------------------------------------------------------*/
5292 operand *left = IC_LEFT (ic);
5293 operand *right = IC_RIGHT (ic);
5294 operand *result = IC_RESULT (ic);
5296 D (emitcode (";", "genMod "); );
5298 /* assign the amsops */
5301 /* special cases first */
5303 if (AOP_TYPE (left) == AOP_CRY &&
5304 AOP_TYPE (right) == AOP_CRY)
5306 genModbits (left, right, result, ic);
5310 /* if both are of size == 1 */
5311 if (AOP_SIZE (left) == 1 &&
5312 AOP_SIZE (right) == 1)
5314 genModOneByte (left, right, result, ic);
5318 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5319 /* use the ds390 ARITHMETIC accel UNIT */
5320 genModTwoByte (left, right, result, ic);
5324 /* should have been converted to function call */
5328 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5329 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5330 freeAsmop (result, NULL, ic, TRUE);
5333 /*-----------------------------------------------------------------*/
5334 /* genIfxJump :- will create a jump depending on the ifx */
5335 /*-----------------------------------------------------------------*/
5337 genIfxJump (iCode * ic, char *jval)
5340 symbol *tlbl = newiTempLabel (NULL);
5343 D (emitcode (";", "genIfxJump"););
5345 /* if true label then we jump if condition
5349 jlbl = IC_TRUE (ic);
5350 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5351 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5355 /* false label is present */
5356 jlbl = IC_FALSE (ic);
5357 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5358 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5360 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5361 emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5363 emitcode (inst, "!tlabel", tlbl->key + 100);
5364 emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5365 emitcode ("", "!tlabeldef", tlbl->key + 100);
5367 /* mark the icode as generated */
5371 /*-----------------------------------------------------------------*/
5372 /* genCmp :- greater or less than comparison */
5373 /*-----------------------------------------------------------------*/
5375 genCmp (operand * left, operand * right,
5376 iCode * ic, iCode * ifx, int sign)
5378 int size, offset = 0;
5379 unsigned long lit = 0L;
5382 D (emitcode (";", "genCmp"););
5384 result = IC_RESULT (ic);
5386 /* if left & right are bit variables */
5387 if (AOP_TYPE (left) == AOP_CRY &&
5388 AOP_TYPE (right) == AOP_CRY)
5390 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5391 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5395 /* subtract right from left if at the
5396 end the carry flag is set then we know that
5397 left is greater than right */
5398 size = max (AOP_SIZE (left), AOP_SIZE (right));
5400 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5401 if ((size == 1) && !sign
5402 && (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5404 symbol *lbl = newiTempLabel (NULL);
5405 emitcode ("cjne", "%s,%s,!tlabel",
5406 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
5407 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5409 emitcode ("", "!tlabeldef", lbl->key + 100);
5413 if (AOP_TYPE (right) == AOP_LIT)
5415 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5416 /* optimize if(x < 0) or if(x >= 0) */
5425 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
5427 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5428 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5430 aopOp (result, ic, FALSE, FALSE);
5432 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5434 freeAsmop (result, NULL, ic, TRUE);
5435 genIfxJump (ifx, "acc.7");
5440 emitcode ("rlc", "a");
5442 goto release_freedLR;
5450 // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5451 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5452 // emitcode (";", "genCmp #2");
5453 if (sign && (size == 0))
5455 // emitcode (";", "genCmp #3");
5456 emitcode ("xrl", "a,#!constbyte",0x80);
5457 if (AOP_TYPE (right) == AOP_LIT)
5459 unsigned long lit = (unsigned long)
5460 floatFromVal (AOP (right)->aopu.aop_lit);
5461 // emitcode (";", "genCmp #3.1");
5462 emitcode ("subb", "a,#!constbyte",
5463 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5467 // emitcode (";", "genCmp #3.2");
5469 MOVB(aopGet (AOP (right), offset++, FALSE, FALSE, "b"));
5470 saveAccWarn = DEFAULT_ACC_WARNING;
5471 emitcode ("xrl", "b,#!constbyte",0x80);
5472 emitcode ("subb", "a,b");
5479 // emitcode (";", "genCmp #4");
5481 s = aopGet (AOP (right), offset++, FALSE, FALSE, "b");
5482 saveAccWarn = DEFAULT_ACC_WARNING;
5484 emitcode ("subb", "a,%s", s);
5491 /* Don't need the left & right operands any more; do need the result. */
5492 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5493 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5495 aopOp (result, ic, FALSE, FALSE);
5499 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5505 /* if the result is used in the next
5506 ifx conditional branch then generate
5507 code a little differently */
5510 genIfxJump (ifx, "c");
5516 /* leave the result in acc */
5518 freeAsmop (result, NULL, ic, TRUE);
5521 /*-----------------------------------------------------------------*/
5522 /* genCmpGt :- greater than comparison */
5523 /*-----------------------------------------------------------------*/
5525 genCmpGt (iCode * ic, iCode * ifx)
5527 operand *left, *right;
5528 sym_link *letype, *retype;
5531 D (emitcode (";", "genCmpGt ");
5534 left = IC_LEFT (ic);
5535 right = IC_RIGHT (ic);
5537 letype = getSpec (operandType (left));
5538 retype = getSpec (operandType (right));
5539 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5541 /* assign the left & right amsops */
5544 genCmp (right, left, ic, ifx, sign);
5547 /*-----------------------------------------------------------------*/
5548 /* genCmpLt - less than comparisons */
5549 /*-----------------------------------------------------------------*/
5551 genCmpLt (iCode * ic, iCode * ifx)
5553 operand *left, *right;
5554 sym_link *letype, *retype;
5557 D (emitcode (";", "genCmpLt "););
5559 left = IC_LEFT (ic);
5560 right = IC_RIGHT (ic);
5562 letype = getSpec (operandType (left));
5563 retype = getSpec (operandType (right));
5564 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5566 /* assign the left & right amsops */
5569 genCmp (left, right, ic, ifx, sign);
5572 /*-----------------------------------------------------------------*/
5573 /* gencjneshort - compare and jump if not equal */
5574 /*-----------------------------------------------------------------*/
5576 gencjneshort (operand * left, operand * right, symbol * lbl)
5578 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5580 unsigned long lit = 0L;
5582 D (emitcode (";", "gencjneshort");
5585 /* if the left side is a literal or
5586 if the right is in a pointer register and left
5588 if ((AOP_TYPE (left) == AOP_LIT) ||
5589 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5596 if (AOP_TYPE (right) == AOP_LIT)
5597 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5599 if (opIsGptr (left) || opIsGptr (right))
5601 /* We are comparing a generic pointer to something.
5602 * Exclude the generic type byte from the comparison.
5605 D (emitcode (";", "cjneshort: generic ptr special case."););
5609 /* if the right side is a literal then anything goes */
5610 if (AOP_TYPE (right) == AOP_LIT &&
5611 AOP_TYPE (left) != AOP_DIR)
5615 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5616 emitcode ("cjne", "a,%s,!tlabel",
5617 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5623 /* if the right side is in a register or in direct space or
5624 if the left is a pointer register & right is not */
5625 else if (AOP_TYPE (right) == AOP_REG ||
5626 AOP_TYPE (right) == AOP_DIR ||
5627 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5628 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5632 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5633 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5634 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5635 emitcode ("jnz", "!tlabel", lbl->key + 100);
5637 emitcode ("cjne", "a,%s,!tlabel",
5638 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
5645 /* right is a pointer reg need both a & b */
5648 MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5649 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
5650 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5656 /*-----------------------------------------------------------------*/
5657 /* gencjne - compare and jump if not equal */
5658 /*-----------------------------------------------------------------*/
5660 gencjne (operand * left, operand * right, symbol * lbl)
5662 symbol *tlbl = newiTempLabel (NULL);
5664 D (emitcode (";", "gencjne");
5667 gencjneshort (left, right, lbl);
5669 emitcode ("mov", "a,%s", one);
5670 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5671 emitcode ("", "!tlabeldef", lbl->key + 100);
5672 emitcode ("clr", "a");
5673 emitcode ("", "!tlabeldef", tlbl->key + 100);
5676 /*-----------------------------------------------------------------*/
5677 /* genCmpEq - generates code for equal to */
5678 /*-----------------------------------------------------------------*/
5680 genCmpEq (iCode * ic, iCode * ifx)
5682 operand *left, *right, *result;
5684 D (emitcode (";", "genCmpEq ");
5688 AOP_SET_LOCALS (ic);
5690 /* if literal, literal on the right or
5691 if the right is in a pointer register and left
5693 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5694 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5696 operand *t = IC_RIGHT (ic);
5697 IC_RIGHT (ic) = IC_LEFT (ic);
5701 if (ifx && /* !AOP_SIZE(result) */
5702 OP_SYMBOL (result) &&
5703 OP_SYMBOL (result)->regType == REG_CND)
5706 /* if they are both bit variables */
5707 if (AOP_TYPE (left) == AOP_CRY &&
5708 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5710 if (AOP_TYPE (right) == AOP_LIT)
5712 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5715 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5716 emitcode ("cpl", "c");
5720 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5724 emitcode ("clr", "c");
5726 /* AOP_TYPE(right) == AOP_CRY */
5730 symbol *lbl = newiTempLabel (NULL);
5731 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5732 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5733 emitcode ("cpl", "c");
5734 emitcode ("", "!tlabeldef", (lbl->key + 100));
5736 /* if true label then we jump if condition
5738 tlbl = newiTempLabel (NULL);
5741 emitcode ("jnc", "!tlabel", tlbl->key + 100);
5742 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5746 emitcode ("jc", "!tlabel", tlbl->key + 100);
5747 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5749 emitcode ("", "!tlabeldef", tlbl->key + 100);
5753 tlbl = newiTempLabel (NULL);
5754 gencjneshort (left, right, tlbl);
5757 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5758 emitcode ("", "!tlabeldef", tlbl->key + 100);
5762 symbol *lbl = newiTempLabel (NULL);
5763 emitcode ("sjmp", "!tlabel", lbl->key + 100);
5764 emitcode ("", "!tlabeldef", tlbl->key + 100);
5765 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5766 emitcode ("", "!tlabeldef", lbl->key + 100);
5769 /* mark the icode as generated */
5772 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5773 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5777 /* if they are both bit variables */
5778 if (AOP_TYPE (left) == AOP_CRY &&
5779 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5781 if (AOP_TYPE (right) == AOP_LIT)
5783 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5786 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5787 emitcode ("cpl", "c");
5791 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5795 emitcode ("clr", "c");
5797 /* AOP_TYPE(right) == AOP_CRY */
5801 symbol *lbl = newiTempLabel (NULL);
5802 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5803 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5804 emitcode ("cpl", "c");
5805 emitcode ("", "!tlabeldef", (lbl->key + 100));
5808 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5809 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5811 aopOp (result, ic, TRUE, FALSE);
5814 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5821 genIfxJump (ifx, "c");
5824 /* if the result is used in an arithmetic operation
5825 then put the result in place */
5830 gencjne (left, right, newiTempLabel (NULL));
5832 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5833 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5835 aopOp (result, ic, TRUE, FALSE);
5837 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5839 aopPut (AOP (result), "a", 0);
5844 genIfxJump (ifx, "a");
5847 /* if the result is used in an arithmetic operation
5848 then put the result in place */
5849 if (AOP_TYPE (result) != AOP_CRY)
5851 /* leave the result in acc */
5855 freeAsmop (result, NULL, ic, TRUE);
5858 /*-----------------------------------------------------------------*/
5859 /* ifxForOp - returns the icode containing the ifx for operand */
5860 /*-----------------------------------------------------------------*/
5862 ifxForOp (operand * op, iCode * ic)
5864 /* if true symbol then needs to be assigned */
5865 if (IS_TRUE_SYMOP (op))
5868 /* if this has register type condition and
5869 the next instruction is ifx with the same operand
5870 and live to of the operand is upto the ifx only then */
5872 ic->next->op == IFX &&
5873 IC_COND (ic->next)->key == op->key &&
5874 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5879 /*-----------------------------------------------------------------*/
5880 /* hasInc - operand is incremented before any other use */
5881 /*-----------------------------------------------------------------*/
5883 hasInc (operand *op, iCode *ic, int osize)
5885 sym_link *type = operandType(op);
5886 sym_link *retype = getSpec (type);
5887 iCode *lic = ic->next;
5890 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5891 if (!IS_SYMOP(op)) return NULL;
5893 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5894 if (IS_AGGREGATE(type->next)) return NULL;
5895 if (osize != (isize = getSize(type->next))) return NULL;
5898 /* if operand of the form op = op + <sizeof *op> */
5899 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5900 isOperandEqual(IC_RESULT(lic),op) &&
5901 isOperandLiteral(IC_RIGHT(lic)) &&
5902 operandLitValue(IC_RIGHT(lic)) == isize) {
5905 /* if the operand used or deffed */
5906 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5909 /* if GOTO or IFX */
5910 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5916 /*-----------------------------------------------------------------*/
5917 /* genAndOp - for && operation */
5918 /*-----------------------------------------------------------------*/
5920 genAndOp (iCode * ic)
5922 operand *left, *right, *result;
5925 D (emitcode (";", "genAndOp "););
5927 /* note here that && operations that are in an
5928 if statement are taken away by backPatchLabels
5929 only those used in arthmetic operations remain */
5931 AOP_SET_LOCALS (ic);
5933 /* if both are bit variables */
5934 if (AOP_TYPE (left) == AOP_CRY &&
5935 AOP_TYPE (right) == AOP_CRY)
5937 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5938 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5939 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5940 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5942 aopOp (result,ic,FALSE, FALSE);
5947 tlbl = newiTempLabel (NULL);
5949 emitcode ("jz", "!tlabel", tlbl->key + 100);
5951 emitcode ("", "!tlabeldef", tlbl->key + 100);
5952 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5953 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5955 aopOp (result,ic,FALSE, FALSE);
5958 freeAsmop (result, NULL, ic, TRUE);
5962 /*-----------------------------------------------------------------*/
5963 /* genOrOp - for || operation */
5964 /*-----------------------------------------------------------------*/
5966 genOrOp (iCode * ic)
5968 operand *left, *right, *result;
5971 D (emitcode (";", "genOrOp "););
5973 /* note here that || operations that are in an
5974 if statement are taken away by backPatchLabels
5975 only those used in arthmetic operations remain */
5977 AOP_SET_LOCALS (ic);
5979 /* if both are bit variables */
5980 if (AOP_TYPE (left) == AOP_CRY &&
5981 AOP_TYPE (right) == AOP_CRY)
5983 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5984 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5985 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5986 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5988 aopOp (result,ic,FALSE, FALSE);
5994 tlbl = newiTempLabel (NULL);
5996 emitcode ("jnz", "!tlabel", tlbl->key + 100);
5998 emitcode ("", "!tlabeldef", tlbl->key + 100);
5999 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6000 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6002 aopOp (result,ic,FALSE, FALSE);
6007 freeAsmop (result, NULL, ic, TRUE);
6010 /*-----------------------------------------------------------------*/
6011 /* isLiteralBit - test if lit == 2^n */
6012 /*-----------------------------------------------------------------*/
6014 isLiteralBit (unsigned long lit)
6016 unsigned long pw[32] =
6017 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6018 0x100L, 0x200L, 0x400L, 0x800L,
6019 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6020 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6021 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6022 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6023 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6026 for (idx = 0; idx < 32; idx++)
6032 /*-----------------------------------------------------------------*/
6033 /* continueIfTrue - */
6034 /*-----------------------------------------------------------------*/
6036 continueIfTrue (iCode * ic)
6039 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6043 /*-----------------------------------------------------------------*/
6045 /*-----------------------------------------------------------------*/
6047 jumpIfTrue (iCode * ic)
6050 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6054 /*-----------------------------------------------------------------*/
6055 /* jmpTrueOrFalse - */
6056 /*-----------------------------------------------------------------*/
6058 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6060 // ugly but optimized by peephole
6063 symbol *nlbl = newiTempLabel (NULL);
6064 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6065 emitcode ("", "!tlabeldef", tlbl->key + 100);
6066 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6067 emitcode ("", "!tlabeldef", nlbl->key + 100);
6071 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6072 emitcode ("", "!tlabeldef", tlbl->key + 100);
6077 // Generate code to perform a bit-wise logic operation
6078 // on two operands in far space (assumed to already have been
6079 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6080 // in far space. This requires pushing the result on the stack
6081 // then popping it into the result.
6083 genFarFarLogicOp(iCode *ic, char *logicOp)
6085 int size, resultSize, compSize;
6089 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6090 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
6091 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6093 _startLazyDPSEvaluation();
6094 for (size = compSize; (size--); offset++)
6096 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6097 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6098 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6100 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6101 emitcode ("push", "acc");
6103 _endLazyDPSEvaluation();
6105 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6106 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6107 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6109 resultSize = AOP_SIZE(IC_RESULT(ic));
6111 ADJUST_PUSHED_RESULT(compSize, resultSize);
6113 _startLazyDPSEvaluation();
6116 emitcode ("pop", "acc");
6117 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6119 _endLazyDPSEvaluation();
6120 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6124 /*-----------------------------------------------------------------*/
6125 /* genAnd - code for and */
6126 /*-----------------------------------------------------------------*/
6128 genAnd (iCode * ic, iCode * ifx)
6130 operand *left, *right, *result;
6131 int size, offset = 0;
6132 unsigned long lit = 0L;
6137 D (emitcode (";", "genAnd "););
6139 AOP_OP_3_NOFATAL (ic, pushResult);
6140 AOP_SET_LOCALS (ic);
6144 genFarFarLogicOp(ic, "anl");
6149 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6151 AOP_TYPE (left), AOP_TYPE (right));
6152 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6154 AOP_SIZE (left), AOP_SIZE (right));
6157 /* if left is a literal & right is not then exchange them */
6158 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6159 #ifdef LOGIC_OPS_BROKEN
6160 || AOP_NEEDSACC (left)
6164 operand *tmp = right;
6169 /* if result = right then exchange them */
6170 if (sameRegs (AOP (result), AOP (right)))
6172 operand *tmp = right;
6177 /* if right is bit then exchange them */
6178 if (AOP_TYPE (right) == AOP_CRY &&
6179 AOP_TYPE (left) != AOP_CRY)
6181 operand *tmp = right;
6185 if (AOP_TYPE (right) == AOP_LIT)
6186 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6188 size = AOP_SIZE (result);
6191 // result = bit & yy;
6192 if (AOP_TYPE (left) == AOP_CRY)
6194 // c = bit & literal;
6195 if (AOP_TYPE (right) == AOP_LIT)
6199 if (size && sameRegs (AOP (result), AOP (left)))
6202 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6207 if (size && (AOP_TYPE (result) == AOP_CRY))
6209 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6212 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6217 emitcode ("clr", "c");
6222 if (AOP_TYPE (right) == AOP_CRY)
6225 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6226 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6231 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6233 emitcode ("rrc", "a");
6234 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6242 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6243 genIfxJump (ifx, "c");
6247 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6248 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6249 if ((AOP_TYPE (right) == AOP_LIT) &&
6250 (AOP_TYPE (result) == AOP_CRY) &&
6251 (AOP_TYPE (left) != AOP_CRY))
6253 int posbit = isLiteralBit (lit);
6258 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6261 emitcode ("mov", "c,acc.%d", posbit & 0x07);
6267 SNPRINTF (buff, sizeof(buff),
6268 "acc.%d", posbit & 0x07);
6269 genIfxJump (ifx, buff);
6273 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6280 symbol *tlbl = newiTempLabel (NULL);
6281 int sizel = AOP_SIZE (left);
6283 emitcode ("setb", "c");
6286 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6288 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6290 if ((posbit = isLiteralBit (bytelit)) != 0)
6291 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6294 if (bytelit != 0x0FFL)
6295 emitcode ("anl", "a,%s",
6296 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6297 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6302 // bit = left & literal
6305 emitcode ("clr", "c");
6306 emitcode ("", "!tlabeldef", tlbl->key + 100);
6308 // if(left & literal)
6312 jmpTrueOrFalse (ifx, tlbl);
6320 /* if left is same as result */
6321 if (sameRegs (AOP (result), AOP (left)))
6323 for (; size--; offset++)
6325 if (AOP_TYPE (right) == AOP_LIT)
6327 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6329 else if (bytelit == 0)
6330 aopPut (AOP (result), zero, offset);
6331 else if (IS_AOP_PREG (result))
6333 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6334 emitcode ("anl", "a,%s",
6335 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6336 aopPut (AOP (result), "a", offset);
6339 emitcode ("anl", "%s,%s",
6340 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6341 aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6345 if (AOP_TYPE (left) == AOP_ACC)
6346 emitcode ("anl", "a,%s",
6347 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6350 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6351 if (IS_AOP_PREG (result))
6353 emitcode ("anl", "a,%s",
6354 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6355 aopPut (AOP (result), "a", offset);
6358 emitcode ("anl", "%s,a",
6359 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6366 // left & result in different registers
6367 if (AOP_TYPE (result) == AOP_CRY)
6370 // if(size), result in bit
6371 // if(!size && ifx), conditional oper: if(left & right)
6372 symbol *tlbl = newiTempLabel (NULL);
6373 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6375 emitcode ("setb", "c");
6378 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6379 emitcode ("anl", "a,%s",
6380 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6382 if (AOP_TYPE(left)==AOP_ACC) {
6383 emitcode("mov", "b,a");
6384 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6385 emitcode("anl", "a,b");
6387 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6388 emitcode ("anl", "a,%s",
6389 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6392 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6398 emitcode ("", "!tlabeldef", tlbl->key + 100);
6402 jmpTrueOrFalse (ifx, tlbl);
6406 for (; (size--); offset++)
6409 // result = left & right
6410 if (AOP_TYPE (right) == AOP_LIT)
6412 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6414 aopPut (AOP (result),
6415 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6419 else if (bytelit == 0)
6421 aopPut (AOP (result), zero, offset);
6424 D (emitcode (";", "better literal AND."););
6425 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6426 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6427 FALSE, FALSE, DP2_RESULT_REG));
6432 // faster than result <- left, anl result,right
6433 // and better if result is SFR
6434 if (AOP_TYPE (left) == AOP_ACC)
6436 emitcode ("anl", "a,%s",
6437 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6441 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6442 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6444 emitcode("mov", "b,a");
6448 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6449 emitcode ("anl", "a,%s", rOp);
6452 aopPut (AOP (result), "a", offset);
6458 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6459 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6460 freeAsmop (result, NULL, ic, TRUE);
6464 /*-----------------------------------------------------------------*/
6465 /* genOr - code for or */
6466 /*-----------------------------------------------------------------*/
6468 genOr (iCode * ic, iCode * ifx)
6470 operand *left, *right, *result;
6471 int size, offset = 0;
6472 unsigned long lit = 0L;
6475 D (emitcode (";", "genOr "););
6477 AOP_OP_3_NOFATAL (ic, pushResult);
6478 AOP_SET_LOCALS (ic);
6482 genFarFarLogicOp(ic, "orl");
6488 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6490 AOP_TYPE (left), AOP_TYPE (right));
6491 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6493 AOP_SIZE (left), AOP_SIZE (right));
6496 /* if left is a literal & right is not then exchange them */
6497 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6498 #ifdef LOGIC_OPS_BROKEN
6499 || AOP_NEEDSACC (left) // I think this is a net loss now.
6503 operand *tmp = right;
6508 /* if result = right then exchange them */
6509 if (sameRegs (AOP (result), AOP (right)))
6511 operand *tmp = right;
6516 /* if right is bit then exchange them */
6517 if (AOP_TYPE (right) == AOP_CRY &&
6518 AOP_TYPE (left) != AOP_CRY)
6520 operand *tmp = right;
6524 if (AOP_TYPE (right) == AOP_LIT)
6525 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6527 size = AOP_SIZE (result);
6531 if (AOP_TYPE (left) == AOP_CRY)
6533 if (AOP_TYPE (right) == AOP_LIT)
6535 // c = bit & literal;
6538 // lit != 0 => result = 1
6539 if (AOP_TYPE (result) == AOP_CRY)
6542 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6544 continueIfTrue (ifx);
6547 emitcode ("setb", "c");
6551 // lit == 0 => result = left
6552 if (size && sameRegs (AOP (result), AOP (left)))
6554 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6559 if (AOP_TYPE (right) == AOP_CRY)
6562 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6563 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6568 symbol *tlbl = newiTempLabel (NULL);
6569 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6570 emitcode ("setb", "c");
6571 emitcode ("jb", "%s,!tlabel",
6572 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6574 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6575 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6577 jmpTrueOrFalse (ifx, tlbl);
6583 emitcode ("", "!tlabeldef", tlbl->key + 100);
6592 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6593 genIfxJump (ifx, "c");
6597 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6598 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6599 if ((AOP_TYPE (right) == AOP_LIT) &&
6600 (AOP_TYPE (result) == AOP_CRY) &&
6601 (AOP_TYPE (left) != AOP_CRY))
6607 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6609 continueIfTrue (ifx);
6614 // lit = 0, result = boolean(left)
6616 emitcode ("setb", "c");
6620 symbol *tlbl = newiTempLabel (NULL);
6621 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6623 emitcode ("", "!tlabeldef", tlbl->key + 100);
6627 genIfxJump (ifx, "a");
6635 /* if left is same as result */
6636 if (sameRegs (AOP (result), AOP (left)))
6638 for (; size--; offset++)
6640 if (AOP_TYPE (right) == AOP_LIT)
6642 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6648 if (IS_AOP_PREG (left))
6650 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6651 emitcode ("orl", "a,%s",
6652 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6653 aopPut (AOP (result), "a", offset);
6657 emitcode ("orl", "%s,%s",
6658 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6659 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6665 if (AOP_TYPE (left) == AOP_ACC)
6667 emitcode ("orl", "a,%s",
6668 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6672 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6673 if (IS_AOP_PREG (left))
6675 emitcode ("orl", "a,%s",
6676 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6677 aopPut (AOP (result), "a", offset);
6681 emitcode ("orl", "%s,a",
6682 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6690 // left & result in different registers
6691 if (AOP_TYPE (result) == AOP_CRY)
6694 // if(size), result in bit
6695 // if(!size && ifx), conditional oper: if(left | right)
6696 symbol *tlbl = newiTempLabel (NULL);
6697 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6699 emitcode ("setb", "c");
6702 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6703 emitcode ("orl", "a,%s",
6704 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6706 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6707 emitcode ("orl", "a,%s",
6708 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6710 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6716 emitcode ("", "!tlabeldef", tlbl->key + 100);
6720 jmpTrueOrFalse (ifx, tlbl);
6724 _startLazyDPSEvaluation();
6725 for (; (size--); offset++)
6728 // result = left & right
6729 if (AOP_TYPE (right) == AOP_LIT)
6731 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6733 aopPut (AOP (result),
6734 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6738 D (emitcode (";", "better literal OR."););
6739 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6740 emitcode ("orl", "a, %s",
6741 aopGet (AOP (right), offset,
6742 FALSE, FALSE, DP2_RESULT_REG));
6747 // faster than result <- left, anl result,right
6748 // and better if result is SFR
6749 if (AOP_TYPE (left) == AOP_ACC)
6751 emitcode ("orl", "a,%s",
6752 aopGet (AOP (right), offset,
6753 FALSE, FALSE, DP2_RESULT_REG));
6757 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6759 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6761 emitcode("mov", "b,a");
6765 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6766 emitcode ("orl", "a,%s", rOp);
6769 aopPut (AOP (result), "a", offset);
6771 _endLazyDPSEvaluation();
6776 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6777 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6778 freeAsmop (result, NULL, ic, TRUE);
6781 /*-----------------------------------------------------------------*/
6782 /* genXor - code for xclusive or */
6783 /*-----------------------------------------------------------------*/
6785 genXor (iCode * ic, iCode * ifx)
6787 operand *left, *right, *result;
6788 int size, offset = 0;
6789 unsigned long lit = 0L;
6792 D (emitcode (";", "genXor "););
6794 AOP_OP_3_NOFATAL (ic, pushResult);
6795 AOP_SET_LOCALS (ic);
6799 genFarFarLogicOp(ic, "xrl");
6804 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6806 AOP_TYPE (left), AOP_TYPE (right));
6807 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6809 AOP_SIZE (left), AOP_SIZE (right));
6812 /* if left is a literal & right is not ||
6813 if left needs acc & right does not */
6814 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6815 #ifdef LOGIC_OPS_BROKEN
6816 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6820 operand *tmp = right;
6825 /* if result = right then exchange them */
6826 if (sameRegs (AOP (result), AOP (right)))
6828 operand *tmp = right;
6833 /* if right is bit then exchange them */
6834 if (AOP_TYPE (right) == AOP_CRY &&
6835 AOP_TYPE (left) != AOP_CRY)
6837 operand *tmp = right;
6841 if (AOP_TYPE (right) == AOP_LIT)
6842 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6844 size = AOP_SIZE (result);
6848 if (AOP_TYPE (left) == AOP_CRY)
6850 if (AOP_TYPE (right) == AOP_LIT)
6852 // c = bit & literal;
6855 // lit>>1 != 0 => result = 1
6856 if (AOP_TYPE (result) == AOP_CRY)
6859 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6861 continueIfTrue (ifx);
6864 emitcode ("setb", "c");
6871 // lit == 0, result = left
6872 if (size && sameRegs (AOP (result), AOP (left)))
6874 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6878 // lit == 1, result = not(left)
6879 if (size && sameRegs (AOP (result), AOP (left)))
6881 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6886 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6887 emitcode ("cpl", "c");
6896 symbol *tlbl = newiTempLabel (NULL);
6897 if (AOP_TYPE (right) == AOP_CRY)
6900 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6904 int sizer = AOP_SIZE (right);
6906 // if val>>1 != 0, result = 1
6907 emitcode ("setb", "c");
6910 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
6912 // test the msb of the lsb
6913 emitcode ("anl", "a,#!constbyte",0xfe);
6914 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6918 emitcode ("rrc", "a");
6920 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6921 emitcode ("cpl", "c");
6922 emitcode ("", "!tlabeldef", (tlbl->key + 100));
6929 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6930 genIfxJump (ifx, "c");
6934 if (sameRegs (AOP (result), AOP (left)))
6936 /* if left is same as result */
6937 for (; size--; offset++)
6939 if (AOP_TYPE (right) == AOP_LIT)
6941 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6943 else if (IS_AOP_PREG (left))
6945 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6946 emitcode ("xrl", "a,%s",
6947 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6948 aopPut (AOP (result), "a", offset);
6951 emitcode ("xrl", "%s,%s",
6952 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6953 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6957 if (AOP_TYPE (left) == AOP_ACC)
6958 emitcode ("xrl", "a,%s",
6959 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6962 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6963 if (IS_AOP_PREG (left))
6965 emitcode ("xrl", "a,%s",
6966 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6967 aopPut (AOP (result), "a", offset);
6970 emitcode ("xrl", "%s,a",
6971 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6978 // left & result in different registers
6979 if (AOP_TYPE (result) == AOP_CRY)
6982 // if(size), result in bit
6983 // if(!size && ifx), conditional oper: if(left ^ right)
6984 symbol *tlbl = newiTempLabel (NULL);
6985 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6988 emitcode ("setb", "c");
6991 if ((AOP_TYPE (right) == AOP_LIT) &&
6992 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6994 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6998 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6999 emitcode ("xrl", "a,%s",
7000 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7002 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7003 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7005 emitcode("mov", "b,a");
7009 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7010 emitcode ("xrl", "a,%s", rOp);
7013 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7019 emitcode ("", "!tlabeldef", tlbl->key + 100);
7023 jmpTrueOrFalse (ifx, tlbl);
7027 for (; (size--); offset++)
7030 // result = left & right
7031 if (AOP_TYPE (right) == AOP_LIT)
7033 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7035 aopPut (AOP (result),
7036 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7040 D (emitcode (";", "better literal XOR."););
7041 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7042 emitcode ("xrl", "a, %s",
7043 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7047 // faster than result <- left, anl result,right
7048 // and better if result is SFR
7049 if (AOP_TYPE (left) == AOP_ACC)
7051 emitcode ("xrl", "a,%s",
7052 aopGet (AOP (right), offset,
7053 FALSE, FALSE, DP2_RESULT_REG));
7057 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7058 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7060 emitcode("mov", "b,a");
7064 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7065 emitcode ("xrl", "a,%s", rOp);
7068 aopPut (AOP (result), "a", offset);
7075 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7076 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7077 freeAsmop (result, NULL, ic, TRUE);
7080 /*-----------------------------------------------------------------*/
7081 /* genInline - write the inline code out */
7082 /*-----------------------------------------------------------------*/
7084 genInline (iCode * ic)
7086 char *buffer, *bp, *bp1;
7088 D (emitcode (";", "genInline "); );
7090 _G.inLine += (!options.asmpeep);
7092 buffer = Safe_strdup(IC_INLINE(ic));
7096 /* emit each line as a code */
7121 /* emitcode("",buffer); */
7122 _G.inLine -= (!options.asmpeep);
7125 /*-----------------------------------------------------------------*/
7126 /* genRRC - rotate right with carry */
7127 /*-----------------------------------------------------------------*/
7131 operand *left, *result;
7134 D (emitcode (";", "genRRC "););
7136 /* rotate right with carry */
7137 left = IC_LEFT (ic);
7138 result = IC_RESULT (ic);
7139 aopOp (left, ic, FALSE, FALSE);
7140 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7142 /* move it to the result */
7143 size = AOP_SIZE (result);
7147 _startLazyDPSEvaluation ();
7150 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7151 emitcode ("rrc", "a");
7152 if (AOP_SIZE (result) > 1)
7153 aopPut (AOP (result), "a", offset--);
7155 _endLazyDPSEvaluation ();
7157 /* now we need to put the carry into the
7158 highest order byte of the result */
7159 if (AOP_SIZE (result) > 1)
7161 MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7163 emitcode ("mov", "acc.7,c");
7164 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7165 freeAsmop (left, NULL, ic, TRUE);
7166 freeAsmop (result, NULL, ic, TRUE);
7169 /*-----------------------------------------------------------------*/
7170 /* genRLC - generate code for rotate left with carry */
7171 /*-----------------------------------------------------------------*/
7175 operand *left, *result;
7179 D (emitcode (";", "genRLC "););
7181 /* rotate right with carry */
7182 left = IC_LEFT (ic);
7183 result = IC_RESULT (ic);
7184 aopOp (left, ic, FALSE, FALSE);
7185 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7187 /* move it to the result */
7188 size = AOP_SIZE (result);
7192 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7194 emitcode ("add", "a,acc");
7195 if (AOP_SIZE (result) > 1)
7197 aopPut (AOP (result), "a", offset++);
7200 _startLazyDPSEvaluation ();
7203 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7205 emitcode ("rlc", "a");
7206 if (AOP_SIZE (result) > 1)
7207 aopPut (AOP (result), "a", offset++);
7209 _endLazyDPSEvaluation ();
7211 /* now we need to put the carry into the
7212 highest order byte of the result */
7213 if (AOP_SIZE (result) > 1)
7215 l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7218 emitcode ("mov", "acc.0,c");
7219 aopPut (AOP (result), "a", 0);
7220 freeAsmop (left, NULL, ic, TRUE);
7221 freeAsmop (result, NULL, ic, TRUE);
7224 /*-----------------------------------------------------------------*/
7225 /* genGetHbit - generates code get highest order bit */
7226 /*-----------------------------------------------------------------*/
7228 genGetHbit (iCode * ic)
7230 operand *left, *result;
7231 left = IC_LEFT (ic);
7232 result = IC_RESULT (ic);
7233 aopOp (left, ic, FALSE, FALSE);
7234 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7236 D (emitcode (";", "genGetHbit "););
7238 /* get the highest order byte into a */
7239 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7240 if (AOP_TYPE (result) == AOP_CRY)
7242 emitcode ("rlc", "a");
7247 emitcode ("rl", "a");
7248 emitcode ("anl", "a,#1");
7253 freeAsmop (left, NULL, ic, TRUE);
7254 freeAsmop (result, NULL, ic, TRUE);
7257 /*-----------------------------------------------------------------*/
7258 /* AccRol - rotate left accumulator by known count */
7259 /*-----------------------------------------------------------------*/
7261 AccRol (int shCount)
7263 shCount &= 0x0007; // shCount : 0..7
7270 emitcode ("rl", "a");
7273 emitcode ("rl", "a");
7274 emitcode ("rl", "a");
7277 emitcode ("swap", "a");
7278 emitcode ("rr", "a");
7281 emitcode ("swap", "a");
7284 emitcode ("swap", "a");
7285 emitcode ("rl", "a");
7288 emitcode ("rr", "a");
7289 emitcode ("rr", "a");
7292 emitcode ("rr", "a");
7297 /*-----------------------------------------------------------------*/
7298 /* AccLsh - left shift accumulator by known count */
7299 /*-----------------------------------------------------------------*/
7301 AccLsh (int shCount)
7306 emitcode ("add", "a,acc");
7307 else if (shCount == 2)
7309 emitcode ("add", "a,acc");
7310 emitcode ("add", "a,acc");
7314 /* rotate left accumulator */
7316 /* and kill the lower order bits */
7317 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7322 /*-----------------------------------------------------------------*/
7323 /* AccRsh - right shift accumulator by known count */
7324 /*-----------------------------------------------------------------*/
7326 AccRsh (int shCount)
7333 emitcode ("rrc", "a");
7337 /* rotate right accumulator */
7338 AccRol (8 - shCount);
7339 /* and kill the higher order bits */
7340 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7345 #ifdef BETTER_LITERAL_SHIFT
7346 /*-----------------------------------------------------------------*/
7347 /* AccSRsh - signed right shift accumulator by known count */
7348 /*-----------------------------------------------------------------*/
7350 AccSRsh (int shCount)
7357 emitcode ("mov", "c,acc.7");
7358 emitcode ("rrc", "a");
7360 else if (shCount == 2)
7362 emitcode ("mov", "c,acc.7");
7363 emitcode ("rrc", "a");
7364 emitcode ("mov", "c,acc.7");
7365 emitcode ("rrc", "a");
7369 tlbl = newiTempLabel (NULL);
7370 /* rotate right accumulator */
7371 AccRol (8 - shCount);
7372 /* and kill the higher order bits */
7373 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7374 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7375 emitcode ("orl", "a,#!constbyte",
7376 (unsigned char) ~SRMask[shCount]);
7377 emitcode ("", "!tlabeldef", tlbl->key + 100);
7383 #ifdef BETTER_LITERAL_SHIFT
7384 /*-----------------------------------------------------------------*/
7385 /* shiftR1Left2Result - shift right one byte from left to result */
7386 /*-----------------------------------------------------------------*/
7388 shiftR1Left2Result (operand * left, int offl,
7389 operand * result, int offr,
7390 int shCount, int sign)
7392 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7393 /* shift right accumulator */
7398 aopPut (AOP (result), "a", offr);
7402 #ifdef BETTER_LITERAL_SHIFT
7403 /*-----------------------------------------------------------------*/
7404 /* shiftL1Left2Result - shift left one byte from left to result */
7405 /*-----------------------------------------------------------------*/
7407 shiftL1Left2Result (operand * left, int offl,
7408 operand * result, int offr, int shCount)
7410 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7411 /* shift left accumulator */
7413 aopPut (AOP (result), "a", offr);
7417 #ifdef BETTER_LITERAL_SHIFT
7418 /*-----------------------------------------------------------------*/
7419 /* movLeft2Result - move byte from left to result */
7420 /*-----------------------------------------------------------------*/
7422 movLeft2Result (operand * left, int offl,
7423 operand * result, int offr, int sign)
7426 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7428 l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
7430 if (*l == '@' && (IS_AOP_PREG (result)))
7432 emitcode ("mov", "a,%s", l);
7433 aopPut (AOP (result), "a", offr);
7439 aopPut (AOP (result), l, offr);
7443 /* MSB sign in acc.7 ! */
7444 if (getDataSize (left) == offl + 1)
7446 emitcode ("mov", "a,%s", l);
7447 aopPut (AOP (result), "a", offr);
7455 #ifdef BETTER_LITERAL_SHIFT
7456 /*-----------------------------------------------------------------*/
7457 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7458 /*-----------------------------------------------------------------*/
7462 emitcode ("rrc", "a");
7463 emitcode ("xch", "a,%s", x);
7464 emitcode ("rrc", "a");
7465 emitcode ("xch", "a,%s", x);
7469 #ifdef BETTER_LITERAL_SHIFT
7471 /*-----------------------------------------------------------------*/
7472 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7473 /*-----------------------------------------------------------------*/
7477 emitcode ("xch", "a,%s", x);
7478 emitcode ("rlc", "a");
7479 emitcode ("xch", "a,%s", x);
7480 emitcode ("rlc", "a");
7484 #ifdef BETTER_LITERAL_SHIFT
7485 /*-----------------------------------------------------------------*/
7486 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7487 /*-----------------------------------------------------------------*/
7491 emitcode ("xch", "a,%s", x);
7492 emitcode ("add", "a,acc");
7493 emitcode ("xch", "a,%s", x);
7494 emitcode ("rlc", "a");
7498 #ifdef BETTER_LITERAL_SHIFT
7499 /*-----------------------------------------------------------------*/
7500 /* AccAXLsh - left shift a:x by known count (0..7) */
7501 /*-----------------------------------------------------------------*/
7503 AccAXLsh (char *x, int shCount)
7518 case 5: // AAAAABBB:CCCCCDDD
7520 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7522 emitcode ("anl", "a,#!constbyte",
7523 SLMask[shCount]); // BBB00000:CCCCCDDD
7525 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7527 AccRol (shCount); // DDDCCCCC:BBB00000
7529 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7531 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7533 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7535 emitcode ("anl", "a,#!constbyte",
7536 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7538 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7540 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7543 case 6: // AAAAAABB:CCCCCCDD
7544 emitcode ("anl", "a,#!constbyte",
7545 SRMask[shCount]); // 000000BB:CCCCCCDD
7546 emitcode ("mov", "c,acc.0"); // c = B
7547 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7549 AccAXRrl1 (x); // BCCCCCCD:D000000B
7550 AccAXRrl1 (x); // BBCCCCCC:DD000000
7552 emitcode("rrc","a");
7553 emitcode("xch","a,%s", x);
7554 emitcode("rrc","a");
7555 emitcode("mov","c,acc.0"); //<< get correct bit
7556 emitcode("xch","a,%s", x);
7558 emitcode("rrc","a");
7559 emitcode("xch","a,%s", x);
7560 emitcode("rrc","a");
7561 emitcode("xch","a,%s", x);
7564 case 7: // a:x <<= 7
7566 emitcode ("anl", "a,#!constbyte",
7567 SRMask[shCount]); // 0000000B:CCCCCCCD
7569 emitcode ("mov", "c,acc.0"); // c = B
7571 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7573 AccAXRrl1 (x); // BCCCCCCC:D0000000
7582 #ifdef BETTER_LITERAL_SHIFT
7584 /*-----------------------------------------------------------------*/
7585 /* AccAXRsh - right shift a:x known count (0..7) */
7586 /*-----------------------------------------------------------------*/
7588 AccAXRsh (char *x, int shCount)
7596 AccAXRrl1 (x); // 0->a:x
7601 AccAXRrl1 (x); // 0->a:x
7604 AccAXRrl1 (x); // 0->a:x
7609 case 5: // AAAAABBB:CCCCCDDD = a:x
7611 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7613 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7615 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7617 emitcode ("anl", "a,#!constbyte",
7618 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7620 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7622 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7624 emitcode ("anl", "a,#!constbyte",
7625 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7627 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7629 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7631 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7634 case 6: // AABBBBBB:CCDDDDDD
7636 emitcode ("mov", "c,acc.7");
7637 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7639 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7641 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7643 emitcode ("anl", "a,#!constbyte",
7644 SRMask[shCount]); // 000000AA:BBBBBBCC
7647 case 7: // ABBBBBBB:CDDDDDDD
7649 emitcode ("mov", "c,acc.7"); // c = A
7651 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7653 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7655 emitcode ("anl", "a,#!constbyte",
7656 SRMask[shCount]); // 0000000A:BBBBBBBC
7665 #ifdef BETTER_LITERAL_SHIFT
7666 /*-----------------------------------------------------------------*/
7667 /* AccAXRshS - right shift signed a:x known count (0..7) */
7668 /*-----------------------------------------------------------------*/
7670 AccAXRshS (char *x, int shCount)
7678 emitcode ("mov", "c,acc.7");
7679 AccAXRrl1 (x); // s->a:x
7683 emitcode ("mov", "c,acc.7");
7684 AccAXRrl1 (x); // s->a:x
7686 emitcode ("mov", "c,acc.7");
7687 AccAXRrl1 (x); // s->a:x
7692 case 5: // AAAAABBB:CCCCCDDD = a:x
7694 tlbl = newiTempLabel (NULL);
7695 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7697 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7699 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7701 emitcode ("anl", "a,#!constbyte",
7702 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7704 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7706 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7708 emitcode ("anl", "a,#!constbyte",
7709 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7711 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7713 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7715 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7717 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7718 emitcode ("orl", "a,#!constbyte",
7719 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7721 emitcode ("", "!tlabeldef", tlbl->key + 100);
7722 break; // SSSSAAAA:BBBCCCCC
7724 case 6: // AABBBBBB:CCDDDDDD
7726 tlbl = newiTempLabel (NULL);
7727 emitcode ("mov", "c,acc.7");
7728 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7730 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7732 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7734 emitcode ("anl", "a,#!constbyte",
7735 SRMask[shCount]); // 000000AA:BBBBBBCC
7737 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7738 emitcode ("orl", "a,#!constbyte",
7739 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7741 emitcode ("", "!tlabeldef", tlbl->key + 100);
7743 case 7: // ABBBBBBB:CDDDDDDD
7745 tlbl = newiTempLabel (NULL);
7746 emitcode ("mov", "c,acc.7"); // c = A
7748 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7750 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7752 emitcode ("anl", "a,#!constbyte",
7753 SRMask[shCount]); // 0000000A:BBBBBBBC
7755 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7756 emitcode ("orl", "a,#!constbyte",
7757 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7759 emitcode ("", "!tlabeldef", tlbl->key + 100);
7767 #ifdef BETTER_LITERAL_SHIFT
7769 _loadLeftIntoAx(char **lsb,
7775 // Get the initial value from left into a pair of registers.
7776 // MSB must be in A, LSB can be any register.
7778 // If the result is held in registers, it is an optimization
7779 // if the LSB can be held in the register which will hold the,
7780 // result LSB since this saves us from having to copy it into
7781 // the result following AccAXLsh.
7783 // If the result is addressed indirectly, this is not a gain.
7784 if (AOP_NEEDSACC(result))
7788 _startLazyDPSEvaluation();
7789 if (AOP_TYPE(left) == AOP_DPTR2)
7792 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
7793 // get LSB in DP2_RESULT_REG.
7794 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
7795 assert(!strcmp(leftByte, DP2_RESULT_REG));
7799 // get LSB into DP2_RESULT_REG
7800 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
7801 if (strcmp(leftByte, DP2_RESULT_REG))
7804 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7807 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
7808 assert(strcmp(leftByte, DP2_RESULT_REG));
7811 _endLazyDPSEvaluation();
7812 *lsb = DP2_RESULT_REG;
7816 if (sameRegs (AOP (result), AOP (left)) &&
7817 ((offl + MSB16) == offr))
7819 /* don't crash result[offr] */
7820 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
7821 emitcode ("xch", "a,%s",
7822 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
7826 movLeft2Result (left, offl, result, offr, 0);
7827 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
7829 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
7830 assert(strcmp(*lsb,"a"));
7835 _storeAxResults(char *lsb,
7839 _startLazyDPSEvaluation();
7840 if (AOP_NEEDSACC(result))
7842 /* We have to explicitly update the result LSB.
7844 emitcode("xch","a,%s", lsb);
7845 aopPut(AOP(result), "a", offr);
7846 emitcode("mov","a,%s", lsb);
7848 if (getDataSize (result) > 1)
7850 aopPut (AOP (result), "a", offr + MSB16);
7852 _endLazyDPSEvaluation();
7855 /*-----------------------------------------------------------------*/
7856 /* shiftL2Left2Result - shift left two bytes from left to result */
7857 /*-----------------------------------------------------------------*/
7859 shiftL2Left2Result (operand * left, int offl,
7860 operand * result, int offr, int shCount)
7864 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7866 AccAXLsh (lsb, shCount);
7868 _storeAxResults(lsb, result, offr);
7872 #ifdef BETTER_LITERAL_SHIFT
7873 /*-----------------------------------------------------------------*/
7874 /* shiftR2Left2Result - shift right two bytes from left to result */
7875 /*-----------------------------------------------------------------*/
7877 shiftR2Left2Result (operand * left, int offl,
7878 operand * result, int offr,
7879 int shCount, int sign)
7883 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7885 /* a:x >> shCount (x = lsb(result)) */
7888 AccAXRshS(lsb, shCount);
7892 AccAXRsh(lsb, shCount);
7895 _storeAxResults(lsb, result, offr);
7901 /*-----------------------------------------------------------------*/
7902 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7903 /*-----------------------------------------------------------------*/
7905 shiftLLeftOrResult (operand * left, int offl,
7906 operand * result, int offr, int shCount)
7908 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7909 /* shift left accumulator */
7911 /* or with result */
7912 emitcode ("orl", "a,%s",
7913 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7914 /* back to result */
7915 aopPut (AOP (result), "a", offr);
7921 /*-----------------------------------------------------------------*/
7922 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7923 /*-----------------------------------------------------------------*/
7925 shiftRLeftOrResult (operand * left, int offl,
7926 operand * result, int offr, int shCount)
7928 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7929 /* shift right accumulator */
7931 /* or with result */
7932 emitcode ("orl", "a,%s",
7933 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7934 /* back to result */
7935 aopPut (AOP (result), "a", offr);
7939 #ifdef BETTER_LITERAL_SHIFT
7940 /*-----------------------------------------------------------------*/
7941 /* genlshOne - left shift a one byte quantity by known count */
7942 /*-----------------------------------------------------------------*/
7944 genlshOne (operand * result, operand * left, int shCount)
7946 D (emitcode (";", "genlshOne "););
7947 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7951 #ifdef BETTER_LITERAL_SHIFT
7952 /*-----------------------------------------------------------------*/
7953 /* genlshTwo - left shift two bytes by known amount != 0 */
7954 /*-----------------------------------------------------------------*/
7956 genlshTwo (operand * result, operand * left, int shCount)
7960 D (emitcode (";", "genlshTwo "););
7962 size = getDataSize (result);
7964 /* if shCount >= 8 */
7969 _startLazyDPSEvaluation();
7975 _endLazyDPSEvaluation();
7976 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7977 aopPut (AOP (result), zero, LSB);
7981 movLeft2Result (left, LSB, result, MSB16, 0);
7982 aopPut (AOP (result), zero, LSB);
7983 _endLazyDPSEvaluation();
7988 aopPut (AOP (result), zero, LSB);
7989 _endLazyDPSEvaluation();
7993 /* 1 <= shCount <= 7 */
7998 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8002 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8010 /*-----------------------------------------------------------------*/
8011 /* shiftLLong - shift left one long from left to result */
8012 /* offl = LSB or MSB16 */
8013 /*-----------------------------------------------------------------*/
8015 shiftLLong (operand * left, operand * result, int offr)
8018 int size = AOP_SIZE (result);
8020 if (size >= LSB + offr)
8022 l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8024 emitcode ("add", "a,acc");
8025 if (sameRegs (AOP (left), AOP (result)) &&
8026 size >= MSB16 + offr && offr != LSB)
8027 emitcode ("xch", "a,%s",
8028 aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8030 aopPut (AOP (result), "a", LSB + offr);
8033 if (size >= MSB16 + offr)
8035 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8037 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8039 emitcode ("rlc", "a");
8040 if (sameRegs (AOP (left), AOP (result)) &&
8041 size >= MSB24 + offr && offr != LSB)
8042 emitcode ("xch", "a,%s",
8043 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8045 aopPut (AOP (result), "a", MSB16 + offr);
8048 if (size >= MSB24 + offr)
8050 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8052 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8054 emitcode ("rlc", "a");
8055 if (sameRegs (AOP (left), AOP (result)) &&
8056 size >= MSB32 + offr && offr != LSB)
8057 emitcode ("xch", "a,%s",
8058 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8060 aopPut (AOP (result), "a", MSB24 + offr);
8063 if (size > MSB32 + offr)
8065 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8067 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8069 emitcode ("rlc", "a");
8070 aopPut (AOP (result), "a", MSB32 + offr);
8073 aopPut (AOP (result), zero, LSB);
8079 /*-----------------------------------------------------------------*/
8080 /* genlshFour - shift four byte by a known amount != 0 */
8081 /*-----------------------------------------------------------------*/
8083 genlshFour (operand * result, operand * left, int shCount)
8087 D (emitcode (";", "genlshFour ");
8090 size = AOP_SIZE (result);
8092 /* if shifting more that 3 bytes */
8097 /* lowest order of left goes to the highest
8098 order of the destination */
8099 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8101 movLeft2Result (left, LSB, result, MSB32, 0);
8102 aopPut (AOP (result), zero, LSB);
8103 aopPut (AOP (result), zero, MSB16);
8104 aopPut (AOP (result), zero, MSB24);
8108 /* more than two bytes */
8109 else if (shCount >= 16)
8111 /* lower order two bytes goes to higher order two bytes */
8113 /* if some more remaining */
8115 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8118 movLeft2Result (left, MSB16, result, MSB32, 0);
8119 movLeft2Result (left, LSB, result, MSB24, 0);
8121 aopPut (AOP (result), zero, MSB16);
8122 aopPut (AOP (result), zero, LSB);
8126 /* if more than 1 byte */
8127 else if (shCount >= 8)
8129 /* lower order three bytes goes to higher order three bytes */
8134 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8136 movLeft2Result (left, LSB, result, MSB16, 0);
8142 movLeft2Result (left, MSB24, result, MSB32, 0);
8143 movLeft2Result (left, MSB16, result, MSB24, 0);
8144 movLeft2Result (left, LSB, result, MSB16, 0);
8145 aopPut (AOP (result), zero, LSB);
8147 else if (shCount == 1)
8148 shiftLLong (left, result, MSB16);
8151 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8152 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8153 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8154 aopPut (AOP (result), zero, LSB);
8159 /* 1 <= shCount <= 7 */
8160 else if (shCount <= 2)
8162 shiftLLong (left, result, LSB);
8164 shiftLLong (result, result, LSB);
8166 /* 3 <= shCount <= 7, optimize */
8169 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8170 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8171 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8176 #ifdef BETTER_LITERAL_SHIFT
8177 /*-----------------------------------------------------------------*/
8178 /* genLeftShiftLiteral - left shifting by known count */
8179 /*-----------------------------------------------------------------*/
8181 genLeftShiftLiteral (operand * left,
8186 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8189 size = getSize (operandType (result));
8191 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8193 /* We only handle certain easy cases so far. */
8195 && (shCount < (size * 8))
8199 D(emitcode (";", "genLeftShiftLiteral wimping out"););
8203 freeAsmop (right, NULL, ic, TRUE);
8205 aopOp(left, ic, FALSE, FALSE);
8206 aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8209 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8211 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8212 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8214 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8217 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8219 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8220 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8222 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8228 emitcode ("; shift left ", "result %d, left %d", size,
8232 /* I suppose that the left size >= result size */
8235 _startLazyDPSEvaluation();
8238 movLeft2Result (left, size, result, size, 0);
8240 _endLazyDPSEvaluation();
8242 else if (shCount >= (size * 8))
8244 _startLazyDPSEvaluation();
8247 aopPut (AOP (result), zero, size);
8249 _endLazyDPSEvaluation();
8256 genlshOne (result, left, shCount);
8260 genlshTwo (result, left, shCount);
8264 genlshFour (result, left, shCount);
8268 fprintf(stderr, "*** ack! mystery literal shift!\n");
8272 freeAsmop (left, NULL, ic, TRUE);
8273 freeAsmop (result, NULL, ic, TRUE);
8278 /*-----------------------------------------------------------------*/
8279 /* genLeftShift - generates code for left shifting */
8280 /*-----------------------------------------------------------------*/
8282 genLeftShift (iCode * ic)
8284 operand *left, *right, *result;
8287 symbol *tlbl, *tlbl1;
8289 D (emitcode (";", "genLeftShift "););
8291 right = IC_RIGHT (ic);
8292 left = IC_LEFT (ic);
8293 result = IC_RESULT (ic);
8295 aopOp (right, ic, FALSE, FALSE);
8298 #ifdef BETTER_LITERAL_SHIFT
8299 /* if the shift count is known then do it
8300 as efficiently as possible */
8301 if (AOP_TYPE (right) == AOP_LIT)
8303 if (genLeftShiftLiteral (left, right, result, ic))
8310 /* shift count is unknown then we have to form
8311 a loop get the loop count in B : Note: we take
8312 only the lower order byte since shifting
8313 more that 32 bits make no sense anyway, ( the
8314 largest size of an object can be only 32 bits ) */
8316 if (AOP_TYPE (right) == AOP_LIT)
8318 /* Really should be handled by genLeftShiftLiteral,
8319 * but since I'm too lazy to fix that today, at least we can make
8320 * some small improvement.
8322 emitcode("mov", "b,#!constbyte",
8323 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8327 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8328 emitcode ("inc", "b");
8330 freeAsmop (right, NULL, ic, TRUE);
8331 aopOp (left, ic, FALSE, FALSE);
8332 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8334 /* now move the left to the result if they are not the
8336 if (!sameRegs (AOP (left), AOP (result)) &&
8337 AOP_SIZE (result) > 1)
8340 size = AOP_SIZE (result);
8342 _startLazyDPSEvaluation ();
8345 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8346 if (*l == '@' && (IS_AOP_PREG (result)))
8349 emitcode ("mov", "a,%s", l);
8350 aopPut (AOP (result), "a", offset);
8353 aopPut (AOP (result), l, offset);
8356 _endLazyDPSEvaluation ();
8359 tlbl = newiTempLabel (NULL);
8360 size = AOP_SIZE (result);
8362 tlbl1 = newiTempLabel (NULL);
8364 /* if it is only one byte then */
8367 symbol *tlbl1 = newiTempLabel (NULL);
8369 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8370 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8371 emitcode ("", "!tlabeldef", tlbl->key + 100);
8372 emitcode ("add", "a,acc");
8373 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8374 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8375 aopPut (AOP (result), "a", 0);
8379 reAdjustPreg (AOP (result));
8381 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8382 emitcode ("", "!tlabeldef", tlbl->key + 100);
8383 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8384 emitcode ("add", "a,acc");
8385 aopPut (AOP (result), "a", offset++);
8386 _startLazyDPSEvaluation ();
8389 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8390 emitcode ("rlc", "a");
8391 aopPut (AOP (result), "a", offset++);
8393 _endLazyDPSEvaluation ();
8394 reAdjustPreg (AOP (result));
8396 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8397 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8399 freeAsmop (left, NULL, ic, TRUE);
8400 freeAsmop (result, NULL, ic, TRUE);
8403 #ifdef BETTER_LITERAL_SHIFT
8404 /*-----------------------------------------------------------------*/
8405 /* genrshOne - right shift a one byte quantity by known count */
8406 /*-----------------------------------------------------------------*/
8408 genrshOne (operand * result, operand * left,
8409 int shCount, int sign)
8411 D (emitcode (";", "genrshOne"););
8412 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8416 #ifdef BETTER_LITERAL_SHIFT
8417 /*-----------------------------------------------------------------*/
8418 /* genrshTwo - right shift two bytes by known amount != 0 */
8419 /*-----------------------------------------------------------------*/
8421 genrshTwo (operand * result, operand * left,
8422 int shCount, int sign)
8424 D (emitcode (";", "genrshTwo"););
8426 /* if shCount >= 8 */
8430 _startLazyDPSEvaluation();
8433 shiftR1Left2Result (left, MSB16, result, LSB,
8438 movLeft2Result (left, MSB16, result, LSB, sign);
8440 addSign (result, MSB16, sign);
8441 _endLazyDPSEvaluation();
8444 /* 1 <= shCount <= 7 */
8447 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8454 /*-----------------------------------------------------------------*/
8455 /* shiftRLong - shift right one long from left to result */
8456 /* offl = LSB or MSB16 */
8457 /*-----------------------------------------------------------------*/
8459 shiftRLong (operand * left, int offl,
8460 operand * result, int sign)
8462 int isSameRegs=sameRegs(AOP(left),AOP(result));
8464 if (isSameRegs && offl>1) {
8465 // we are in big trouble, but this shouldn't happen
8466 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8469 MOVA (aopGet (AOP (left), MSB32, FALSE, NULL));
8474 emitcode ("rlc", "a");
8475 emitcode ("subb", "a,acc");
8476 emitcode ("xch", "a,%s",
8477 aopGet(AOP(left), MSB32, FALSE, DP2_RESULT_REG));
8479 aopPut (AOP(result), zero, MSB32);
8484 emitcode ("clr", "c");
8486 emitcode ("mov", "c,acc.7");
8489 emitcode ("rrc", "a");
8491 if (isSameRegs && offl==MSB16) {
8493 "a,%s",aopGet (AOP (left), MSB24, FALSE, DP2_RESULT_REG));
8495 aopPut (AOP (result), "a", MSB32);
8496 MOVA (aopGet (AOP (left), MSB24, FALSE, NULL));
8499 emitcode ("rrc", "a");
8500 if (isSameRegs && offl==1) {
8501 emitcode ("xch", "a,%s",
8502 aopGet (AOP (left), MSB16, FALSE, DP2_RESULT_REG));
8504 aopPut (AOP (result), "a", MSB24);
8505 MOVA (aopGet (AOP (left), MSB16, FALSE, NULL));
8507 emitcode ("rrc", "a");
8508 aopPut (AOP (result), "a", MSB16 - offl);
8512 MOVA (aopGet (AOP (left), LSB, FALSE, NULL));
8513 emitcode ("rrc", "a");
8514 aopPut (AOP (result), "a", LSB);
8521 /*-----------------------------------------------------------------*/
8522 /* genrshFour - shift four byte by a known amount != 0 */
8523 /*-----------------------------------------------------------------*/
8525 genrshFour (operand * result, operand * left,
8526 int shCount, int sign)
8528 D (emitcode (";", "genrshFour");
8531 /* if shifting more that 3 bytes */
8536 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8538 movLeft2Result (left, MSB32, result, LSB, sign);
8539 addSign (result, MSB16, sign);
8541 else if (shCount >= 16)
8545 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8548 movLeft2Result (left, MSB24, result, LSB, 0);
8549 movLeft2Result (left, MSB32, result, MSB16, sign);
8551 addSign (result, MSB24, sign);
8553 else if (shCount >= 8)
8557 shiftRLong (left, MSB16, result, sign);
8558 else if (shCount == 0)
8560 movLeft2Result (left, MSB16, result, LSB, 0);
8561 movLeft2Result (left, MSB24, result, MSB16, 0);
8562 movLeft2Result (left, MSB32, result, MSB24, sign);
8563 addSign (result, MSB32, sign);
8567 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8568 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8569 /* the last shift is signed */
8570 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8571 addSign (result, MSB32, sign);
8575 { /* 1 <= shCount <= 7 */
8578 shiftRLong (left, LSB, result, sign);
8580 shiftRLong (result, LSB, result, sign);
8584 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8585 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8586 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8592 #ifdef BETTER_LITERAL_SHIFT
8593 /*-----------------------------------------------------------------*/
8594 /* genRightShiftLiteral - right shifting by known count */
8595 /*-----------------------------------------------------------------*/
8597 genRightShiftLiteral (operand * left,
8603 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8606 size = getSize (operandType (result));
8608 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8610 /* We only handle certain easy cases so far. */
8612 && (shCount < (size * 8))
8616 D(emitcode (";", "genRightShiftLiteral wimping out"););
8620 freeAsmop (right, NULL, ic, TRUE);
8622 aopOp (left, ic, FALSE, FALSE);
8623 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8626 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8630 /* test the LEFT size !!! */
8632 /* I suppose that the left size >= result size */
8635 size = getDataSize (result);
8636 _startLazyDPSEvaluation();
8639 movLeft2Result (left, size, result, size, 0);
8641 _endLazyDPSEvaluation();
8643 else if (shCount >= (size * 8))
8647 /* get sign in acc.7 */
8648 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
8650 addSign (result, LSB, sign);
8657 genrshOne (result, left, shCount, sign);
8661 genrshTwo (result, left, shCount, sign);
8665 genrshFour (result, left, shCount, sign);
8672 freeAsmop (left, NULL, ic, TRUE);
8673 freeAsmop (result, NULL, ic, TRUE);
8679 /*-----------------------------------------------------------------*/
8680 /* genSignedRightShift - right shift of signed number */
8681 /*-----------------------------------------------------------------*/
8683 genSignedRightShift (iCode * ic)
8685 operand *right, *left, *result;
8688 symbol *tlbl, *tlbl1;
8690 D (emitcode (";", "genSignedRightShift "););
8692 /* we do it the hard way put the shift count in b
8693 and loop thru preserving the sign */
8695 right = IC_RIGHT (ic);
8696 left = IC_LEFT (ic);
8697 result = IC_RESULT (ic);
8699 aopOp (right, ic, FALSE, FALSE);
8701 #ifdef BETTER_LITERAL_SHIFT
8702 if (AOP_TYPE (right) == AOP_LIT)
8704 if (genRightShiftLiteral (left, right, result, ic, 1))
8710 /* shift count is unknown then we have to form
8711 a loop get the loop count in B : Note: we take
8712 only the lower order byte since shifting
8713 more that 32 bits make no sense anyway, ( the
8714 largest size of an object can be only 32 bits ) */
8716 if (AOP_TYPE (right) == AOP_LIT)
8718 /* Really should be handled by genRightShiftLiteral,
8719 * but since I'm too lazy to fix that today, at least we can make
8720 * some small improvement.
8722 emitcode("mov", "b,#!constbyte",
8723 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8727 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8728 emitcode ("inc", "b");
8730 freeAsmop (right, NULL, ic, TRUE);
8731 aopOp (left, ic, FALSE, FALSE);
8732 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8734 /* now move the left to the result if they are not the
8736 if (!sameRegs (AOP (left), AOP (result)) &&
8737 AOP_SIZE (result) > 1)
8740 size = AOP_SIZE (result);
8742 _startLazyDPSEvaluation ();
8745 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8746 if (*l == '@' && IS_AOP_PREG (result))
8749 emitcode ("mov", "a,%s", l);
8750 aopPut (AOP (result), "a", offset);
8753 aopPut (AOP (result), l, offset);
8756 _endLazyDPSEvaluation ();
8759 /* mov the highest order bit to OVR */
8760 tlbl = newiTempLabel (NULL);
8761 tlbl1 = newiTempLabel (NULL);
8763 size = AOP_SIZE (result);
8765 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
8766 emitcode ("rlc", "a");
8767 emitcode ("mov", "ov,c");
8768 /* if it is only one byte then */
8771 MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8772 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8773 emitcode ("", "!tlabeldef", tlbl->key + 100);
8774 emitcode ("mov", "c,ov");
8775 emitcode ("rrc", "a");
8776 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8777 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8778 aopPut (AOP (result), "a", 0);
8782 reAdjustPreg (AOP (result));
8783 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8784 emitcode ("", "!tlabeldef", tlbl->key + 100);
8785 emitcode ("mov", "c,ov");
8786 _startLazyDPSEvaluation ();
8789 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8790 emitcode ("rrc", "a");
8791 aopPut (AOP (result), "a", offset--);
8793 _endLazyDPSEvaluation ();
8794 reAdjustPreg (AOP (result));
8795 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8796 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8799 freeAsmop (left, NULL, ic, TRUE);
8800 freeAsmop (result, NULL, ic, TRUE);
8803 /*-----------------------------------------------------------------*/
8804 /* genRightShift - generate code for right shifting */
8805 /*-----------------------------------------------------------------*/
8807 genRightShift (iCode * ic)
8809 operand *right, *left, *result;
8813 symbol *tlbl, *tlbl1;
8815 D (emitcode (";", "genRightShift "););
8817 /* if signed then we do it the hard way preserve the
8818 sign bit moving it inwards */
8819 retype = getSpec (operandType (IC_RESULT (ic)));
8821 if (!SPEC_USIGN (retype))
8823 genSignedRightShift (ic);
8827 /* signed & unsigned types are treated the same : i.e. the
8828 signed is NOT propagated inwards : quoting from the
8829 ANSI - standard : "for E1 >> E2, is equivalent to division
8830 by 2**E2 if unsigned or if it has a non-negative value,
8831 otherwise the result is implementation defined ", MY definition
8832 is that the sign does not get propagated */
8834 right = IC_RIGHT (ic);
8835 left = IC_LEFT (ic);
8836 result = IC_RESULT (ic);
8838 aopOp (right, ic, FALSE, FALSE);
8840 #ifdef BETTER_LITERAL_SHIFT
8841 /* if the shift count is known then do it
8842 as efficiently as possible */
8843 if (AOP_TYPE (right) == AOP_LIT)
8845 if (genRightShiftLiteral (left, right, result, ic, 0))
8852 /* shift count is unknown then we have to form
8853 a loop get the loop count in B : Note: we take
8854 only the lower order byte since shifting
8855 more that 32 bits make no sense anyway, ( the
8856 largest size of an object can be only 32 bits ) */
8858 if (AOP_TYPE (right) == AOP_LIT)
8860 /* Really should be handled by genRightShiftLiteral,
8861 * but since I'm too lazy to fix that today, at least we can make
8862 * some small improvement.
8864 emitcode("mov", "b,#!constbyte",
8865 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8869 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8870 emitcode ("inc", "b");
8872 freeAsmop (right, NULL, ic, TRUE);
8873 aopOp (left, ic, FALSE, FALSE);
8874 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8876 /* now move the left to the result if they are not the
8878 if (!sameRegs (AOP (left), AOP (result)) &&
8879 AOP_SIZE (result) > 1)
8882 size = AOP_SIZE (result);
8884 _startLazyDPSEvaluation ();
8887 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8888 if (*l == '@' && IS_AOP_PREG (result))
8891 emitcode ("mov", "a,%s", l);
8892 aopPut (AOP (result), "a", offset);
8895 aopPut (AOP (result), l, offset);
8898 _endLazyDPSEvaluation ();
8901 tlbl = newiTempLabel (NULL);
8902 tlbl1 = newiTempLabel (NULL);
8903 size = AOP_SIZE (result);
8906 /* if it is only one byte then */
8909 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8910 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8911 emitcode ("", "!tlabeldef", tlbl->key + 100);
8913 emitcode ("rrc", "a");
8914 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8915 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8916 aopPut (AOP (result), "a", 0);
8920 reAdjustPreg (AOP (result));
8921 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8922 emitcode ("", "!tlabeldef", tlbl->key + 100);
8924 _startLazyDPSEvaluation ();
8927 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8928 emitcode ("rrc", "a");
8929 aopPut (AOP (result), "a", offset--);
8931 _endLazyDPSEvaluation ();
8932 reAdjustPreg (AOP (result));
8934 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8935 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8938 freeAsmop (left, NULL, ic, TRUE);
8939 freeAsmop (result, NULL, ic, TRUE);
8942 /*-----------------------------------------------------------------*/
8943 /* genUnpackBits - generates code for unpacking bits */
8944 /*-----------------------------------------------------------------*/
8946 genUnpackBits (operand * result, char *rname, int ptype)
8953 D (emitcode (";", "genUnpackBits "););
8955 etype = getSpec (operandType (result));
8957 /* read the first byte */
8963 emitcode ("mov", "a,@%s", rname);
8967 emitcode ("movx", "a,@%s", rname);
8971 emitcode ("movx", "a,@dptr");
8975 emitcode ("clr", "a");
8976 emitcode ("movc", "a,@a+dptr");
8980 emitcode ("lcall", "__gptrget");
8984 /* if we have bitdisplacement then it fits */
8985 /* into this byte completely or if length is */
8986 /* less than a byte */
8987 if (((shCnt = SPEC_BSTR (etype)) != 0) || (SPEC_BLEN (etype) <= 8))
8990 /* shift right acc */
8993 emitcode ("anl", "a,#!constbyte",
8994 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8995 aopPut (AOP (result), "a", offset);
8999 /* bit field did not fit in a byte */
9000 rlen = SPEC_BLEN (etype) - 8;
9001 aopPut (AOP (result), "a", offset++);
9010 emitcode ("inc", "%s", rname);
9011 emitcode ("mov", "a,@%s", rname);
9015 emitcode ("inc", "%s", rname);
9016 emitcode ("movx", "a,@%s", rname);
9020 emitcode ("inc", "dptr");
9021 emitcode ("movx", "a,@dptr");
9025 emitcode ("clr", "a");
9026 emitcode ("inc", "dptr");
9027 emitcode ("movc", "a,@a+dptr");
9031 emitcode ("inc", "dptr");
9032 emitcode ("lcall", "__gptrget");
9037 /* if we are done */
9041 aopPut (AOP (result), "a", offset++);
9047 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (rlen));
9048 aopPut (AOP (result), "a", offset);
9055 /*-----------------------------------------------------------------*/
9056 /* genDataPointerGet - generates code when ptr offset is known */
9057 /*-----------------------------------------------------------------*/
9059 genDataPointerGet (operand * left,
9065 int size, offset = 0;
9066 aopOp (result, ic, TRUE, FALSE);
9068 /* get the string representation of the name */
9069 l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9070 size = AOP_SIZE (result);
9071 _startLazyDPSEvaluation ();
9076 SNPRINTF (buff, sizeof(buff),
9077 "(%s + %d)", l + 1, offset);
9081 SNPRINTF (buff, sizeof(buff),
9084 aopPut (AOP (result), buff, offset++);
9086 _endLazyDPSEvaluation ();
9088 freeAsmop (left, NULL, ic, TRUE);
9089 freeAsmop (result, NULL, ic, TRUE);
9092 /*-----------------------------------------------------------------*/
9093 /* genNearPointerGet - emitcode for near pointer fetch */
9094 /*-----------------------------------------------------------------*/
9096 genNearPointerGet (operand * left,
9104 sym_link *rtype, *retype, *letype;
9105 sym_link *ltype = operandType (left);
9108 rtype = operandType (result);
9109 retype = getSpec (rtype);
9110 letype = getSpec (ltype);
9112 aopOp (left, ic, FALSE, FALSE);
9114 /* if left is rematerialisable and
9115 result is not bit variable type and
9116 the left is pointer to data space i.e
9117 lower 128 bytes of space */
9118 if (AOP_TYPE (left) == AOP_IMMD &&
9119 !IS_BITVAR (retype) &&
9120 !IS_BITVAR (letype) &&
9121 DCL_TYPE (ltype) == POINTER)
9123 genDataPointerGet (left, result, ic);
9127 /* if the value is already in a pointer register
9128 then don't need anything more */
9129 if (!AOP_INPREG (AOP (left)))
9131 /* otherwise get a free pointer register */
9133 preg = getFreePtr (ic, &aop, FALSE);
9134 emitcode ("mov", "%s,%s",
9136 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9140 rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9142 freeAsmop (left, NULL, ic, TRUE);
9143 aopOp (result, ic, FALSE, FALSE);
9145 /* if bitfield then unpack the bits */
9146 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9147 genUnpackBits (result, rname, POINTER);
9150 /* we have can just get the values */
9151 int size = AOP_SIZE (result);
9156 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9159 emitcode ("mov", "a,@%s", rname);
9160 aopPut (AOP (result), "a", offset);
9164 SNPRINTF (buff, sizeof(buff), "@%s", rname);
9165 aopPut (AOP (result), buff, offset);
9170 emitcode ("inc", "%s", rname);
9175 /* now some housekeeping stuff */
9178 /* we had to allocate for this iCode */
9179 if (pi) { /* post increment present */
9180 aopPut(AOP ( left ),rname,0);
9182 freeAsmop (NULL, aop, ic, TRUE);
9186 /* we did not allocate which means left
9187 already in a pointer register, then
9188 if size > 0 && this could be used again
9189 we have to point it back to where it
9191 if (AOP_SIZE (result) > 1 &&
9192 !OP_SYMBOL (left)->remat &&
9193 (OP_SYMBOL (left)->liveTo > ic->seq ||
9197 int size = AOP_SIZE (result) - 1;
9199 emitcode ("dec", "%s", rname);
9204 freeAsmop (result, NULL, ic, TRUE);
9205 if (pi) pi->generated = 1;
9208 /*-----------------------------------------------------------------*/
9209 /* genPagedPointerGet - emitcode for paged pointer fetch */
9210 /*-----------------------------------------------------------------*/
9212 genPagedPointerGet (operand * left,
9220 sym_link *rtype, *retype, *letype;
9222 rtype = operandType (result);
9223 retype = getSpec (rtype);
9224 letype = getSpec (operandType (left));
9225 aopOp (left, ic, FALSE, FALSE);
9227 /* if the value is already in a pointer register
9228 then don't need anything more */
9229 if (!AOP_INPREG (AOP (left)))
9231 /* otherwise get a free pointer register */
9233 preg = getFreePtr (ic, &aop, FALSE);
9234 emitcode ("mov", "%s,%s",
9236 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9240 rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9242 freeAsmop (left, NULL, ic, TRUE);
9243 aopOp (result, ic, FALSE, FALSE);
9245 /* if bitfield then unpack the bits */
9246 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9247 genUnpackBits (result, rname, PPOINTER);
9250 /* we have can just get the values */
9251 int size = AOP_SIZE (result);
9257 emitcode ("movx", "a,@%s", rname);
9258 aopPut (AOP (result), "a", offset);
9263 emitcode ("inc", "%s", rname);
9267 /* now some housekeeping stuff */
9270 /* we had to allocate for this iCode */
9271 if (pi) aopPut ( AOP (left), rname, 0);
9272 freeAsmop (NULL, aop, ic, TRUE);
9276 /* we did not allocate which means left
9277 already in a pointer register, then
9278 if size > 0 && this could be used again
9279 we have to point it back to where it
9281 if (AOP_SIZE (result) > 1 &&
9282 !OP_SYMBOL (left)->remat &&
9283 (OP_SYMBOL (left)->liveTo > ic->seq ||
9287 int size = AOP_SIZE (result) - 1;
9289 emitcode ("dec", "%s", rname);
9294 freeAsmop (result, NULL, ic, TRUE);
9295 if (pi) pi->generated = 1;
9298 /*-----------------------------------------------------------------*/
9299 /* genFarPointerGet - gget value from far space */
9300 /*-----------------------------------------------------------------*/
9302 genFarPointerGet (operand * left,
9303 operand * result, iCode * ic, iCode *pi)
9305 int size, offset, dopi=1;
9306 sym_link *retype = getSpec (operandType (result));
9307 sym_link *letype = getSpec (operandType (left));
9308 D (emitcode (";", "genFarPointerGet"););
9310 aopOp (left, ic, FALSE, FALSE);
9312 /* if the operand is already in dptr
9313 then we do nothing else we move the value to dptr */
9314 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9316 /* if this is remateriazable */
9317 if (AOP_TYPE (left) == AOP_IMMD)
9319 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9323 /* we need to get it byte by byte */
9324 _startLazyDPSEvaluation ();
9325 if (AOP_TYPE (left) != AOP_DPTR)
9327 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9328 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9329 if (options.model == MODEL_FLAT24)
9330 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9334 /* We need to generate a load to DPTR indirect through DPTR. */
9335 D (emitcode (";", "genFarPointerGet -- indirection special case."););
9336 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9337 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9338 if (options.model == MODEL_FLAT24)
9339 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9340 emitcode ("pop", "dph");
9341 emitcode ("pop", "dpl");
9344 _endLazyDPSEvaluation ();
9347 /* so dptr know contains the address */
9348 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9350 /* if bit then unpack */
9351 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9352 if (AOP_INDPTRn(left)) {
9353 genSetDPTR(AOP(left)->aopu.dptr);
9355 genUnpackBits (result, "dptr", FPOINTER);
9356 if (AOP_INDPTRn(left)) {
9361 size = AOP_SIZE (result);
9364 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9366 genSetDPTR(AOP(left)->aopu.dptr);
9367 emitcode ("movx", "a,@dptr");
9368 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9369 emitcode ("inc", "dptr");
9371 aopPut (AOP (result), "a", offset++);
9374 _startLazyDPSEvaluation ();
9376 if (AOP_INDPTRn(left)) {
9377 genSetDPTR(AOP(left)->aopu.dptr);
9383 emitcode ("movx", "a,@dptr");
9384 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9385 emitcode ("inc", "dptr");
9387 aopPut (AOP (result), "a", offset++);
9389 _endLazyDPSEvaluation ();
9392 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9393 if (!AOP_INDPTRn(left)) {
9394 _startLazyDPSEvaluation ();
9395 aopPut ( AOP (left), "dpl", 0);
9396 aopPut ( AOP (left), "dph", 1);
9397 if (options.model == MODEL_FLAT24)
9398 aopPut ( AOP (left), "dpx", 2);
9399 _endLazyDPSEvaluation ();
9402 } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) &&
9403 AOP_SIZE(result) > 1 &&
9405 (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
9407 size = AOP_SIZE (result) - 1;
9408 if (AOP_INDPTRn(left)) {
9409 genSetDPTR(AOP(left)->aopu.dptr);
9411 while (size--) emitcode ("lcall","__decdptr");
9412 if (AOP_INDPTRn(left)) {
9417 freeAsmop (left, NULL, ic, TRUE);
9418 freeAsmop (result, NULL, ic, TRUE);
9421 /*-----------------------------------------------------------------*/
9422 /* genCodePointerGet - get value from code space */
9423 /*-----------------------------------------------------------------*/
9425 genCodePointerGet (operand * left,
9426 operand * result, iCode * ic, iCode *pi)
9428 int size, offset, dopi=1;
9429 sym_link *retype = getSpec (operandType (result));
9431 aopOp (left, ic, FALSE, FALSE);
9433 /* if the operand is already in dptr
9434 then we do nothing else we move the value to dptr */
9435 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
9437 /* if this is remateriazable */
9438 if (AOP_TYPE (left) == AOP_IMMD)
9440 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9443 { /* we need to get it byte by byte */
9444 _startLazyDPSEvaluation ();
9445 if (AOP_TYPE (left) != AOP_DPTR)
9447 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9448 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9449 if (options.model == MODEL_FLAT24)
9450 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9454 /* We need to generate a load to DPTR indirect through DPTR. */
9455 D (emitcode (";", "gencodePointerGet -- indirection special case."););
9456 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9457 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9458 if (options.model == MODEL_FLAT24)
9459 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9460 emitcode ("pop", "dph");
9461 emitcode ("pop", "dpl");
9464 _endLazyDPSEvaluation ();
9467 /* so dptr know contains the address */
9468 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9470 /* if bit then unpack */
9471 if (IS_BITVAR (retype)) {
9472 if (AOP_INDPTRn(left)) {
9473 genSetDPTR(AOP(left)->aopu.dptr);
9475 genUnpackBits (result, "dptr", CPOINTER);
9476 if (AOP_INDPTRn(left)) {
9481 size = AOP_SIZE (result);
9483 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9485 genSetDPTR(AOP(left)->aopu.dptr);
9486 emitcode ("clr", "a");
9487 emitcode ("movc", "a,@a+dptr");
9488 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9489 emitcode ("inc", "dptr");
9491 aopPut (AOP (result), "a", offset++);
9494 _startLazyDPSEvaluation ();
9497 if (AOP_INDPTRn(left)) {
9498 genSetDPTR(AOP(left)->aopu.dptr);
9504 emitcode ("clr", "a");
9505 emitcode ("movc", "a,@a+dptr");
9506 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9507 emitcode ("inc", "dptr");
9508 aopPut (AOP (result), "a", offset++);
9510 _endLazyDPSEvaluation ();
9513 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9514 if (!AOP_INDPTRn(left)) {
9515 _startLazyDPSEvaluation ();
9517 aopPut ( AOP (left), "dpl", 0);
9518 aopPut ( AOP (left), "dph", 1);
9519 if (options.model == MODEL_FLAT24)
9520 aopPut ( AOP (left), "dpx", 2);
9522 _endLazyDPSEvaluation ();
9525 } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
9526 AOP_SIZE(result) > 1 &&
9527 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9529 size = AOP_SIZE (result) - 1;
9530 if (AOP_INDPTRn(left)) {
9531 genSetDPTR(AOP(left)->aopu.dptr);
9533 while (size--) emitcode ("lcall","__decdptr");
9534 if (AOP_INDPTRn(left)) {
9539 freeAsmop (left, NULL, ic, TRUE);
9540 freeAsmop (result, NULL, ic, TRUE);
9543 /*-----------------------------------------------------------------*/
9544 /* genGenPointerGet - gget value from generic pointer space */
9545 /*-----------------------------------------------------------------*/
9547 genGenPointerGet (operand * left,
9548 operand * result, iCode * ic, iCode * pi)
9551 sym_link *retype = getSpec (operandType (result));
9552 sym_link *letype = getSpec (operandType (left));
9554 D (emitcode (";", "genGenPointerGet "); );
9556 aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
9558 /* if the operand is already in dptr
9559 then we do nothing else we move the value to dptr */
9560 if (AOP_TYPE (left) != AOP_STR)
9562 /* if this is remateriazable */
9563 if (AOP_TYPE (left) == AOP_IMMD)
9565 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9566 if (AOP(left)->aopu.aop_immd.from_cast_remat)
9568 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
9572 emitcode ("mov", "b,#%d", pointerCode (retype));
9576 { /* we need to get it byte by byte */
9577 _startLazyDPSEvaluation ();
9578 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
9579 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
9580 if (options.model == MODEL_FLAT24) {
9581 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9582 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
9584 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9586 _endLazyDPSEvaluation ();
9590 /* so dptr-b now contains the address */
9592 aopOp (result, ic, FALSE, TRUE);
9595 /* if bit then unpack */
9596 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9598 genUnpackBits (result, "dptr", GPOINTER);
9602 size = AOP_SIZE (result);
9609 // Get two bytes at a time, results in _AP & A.
9610 // dptr will be incremented ONCE by __gptrgetWord.
9612 // Note: any change here must be coordinated
9613 // with the implementation of __gptrgetWord
9614 // in device/lib/_gptrget.c
9615 emitcode ("lcall", "__gptrgetWord");
9616 aopPut (AOP (result), DP2_RESULT_REG, offset++);
9617 aopPut (AOP (result), "a", offset++);
9622 // Only one byte to get.
9623 emitcode ("lcall", "__gptrget");
9624 aopPut (AOP (result), "a", offset++);
9627 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9629 emitcode ("inc", "dptr");
9634 if (pi && AOP_TYPE (left) != AOP_IMMD) {
9635 _startLazyDPSEvaluation ();
9637 aopPut ( AOP (left), "dpl", 0);
9638 aopPut ( AOP (left), "dph", 1);
9639 if (options.model == MODEL_FLAT24) {
9640 aopPut ( AOP (left), "dpx", 2);
9641 aopPut ( AOP (left), "b", 3);
9642 } else aopPut ( AOP (left), "b", 2);
9644 _endLazyDPSEvaluation ();
9647 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9648 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9650 size = AOP_SIZE (result) - 1;
9651 while (size--) emitcode ("lcall","__decdptr");
9654 freeAsmop (left, NULL, ic, TRUE);
9655 freeAsmop (result, NULL, ic, TRUE);
9658 /*-----------------------------------------------------------------*/
9659 /* genPointerGet - generate code for pointer get */
9660 /*-----------------------------------------------------------------*/
9662 genPointerGet (iCode * ic, iCode *pi)
9664 operand *left, *result;
9665 sym_link *type, *etype;
9668 D (emitcode (";", "genPointerGet ");
9671 left = IC_LEFT (ic);
9672 result = IC_RESULT (ic);
9674 /* depending on the type of pointer we need to
9675 move it to the correct pointer register */
9676 type = operandType (left);
9677 etype = getSpec (type);
9678 /* if left is of type of pointer then it is simple */
9679 if (IS_PTR (type) && !IS_FUNC (type->next))
9680 p_type = DCL_TYPE (type);
9683 /* we have to go by the storage class */
9684 p_type = PTR_TYPE (SPEC_OCLS (etype));
9686 /* special case when cast remat */
9687 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9688 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9689 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9690 type = operandType (left);
9691 p_type = DCL_TYPE (type);
9693 /* now that we have the pointer type we assign
9694 the pointer values */
9700 genNearPointerGet (left, result, ic, pi);
9704 genPagedPointerGet (left, result, ic, pi);
9708 genFarPointerGet (left, result, ic, pi);
9712 genCodePointerGet (left, result, ic, pi);
9716 genGenPointerGet (left, result, ic, pi);
9722 /*-----------------------------------------------------------------*/
9723 /* genPackBits - generates code for packed bit storage */
9724 /*-----------------------------------------------------------------*/
9726 genPackBits (sym_link * etype,
9728 char *rname, int p_type)
9735 blen = SPEC_BLEN (etype);
9736 bstr = SPEC_BSTR (etype);
9738 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9740 /* if the bit lenth is less than or */
9741 /* it exactly fits a byte then */
9742 if (SPEC_BLEN (etype) <= 8)
9744 /* shift left acc */
9745 AccLsh (SPEC_BSTR (etype));
9747 if (SPEC_BLEN (etype) < 8)
9748 { /* if smaller than a byte */
9754 emitcode ("mov", "b,a");
9755 emitcode ("mov", "a,@%s", rname);
9759 emitcode ("mov", "b,a");
9760 emitcode ("movx", "a,@dptr");
9764 emitcode ("push", "b");
9765 emitcode ("push", "acc");
9766 emitcode ("lcall", "__gptrget");
9767 emitcode ("pop", "b");
9771 emitcode ("anl", "a,#!constbyte", (unsigned char)
9772 ((unsigned char) (0xFF << (blen + bstr)) |
9773 (unsigned char) (0xFF >> (8 - bstr))));
9774 emitcode ("orl", "a,b");
9775 if (p_type == GPOINTER)
9776 emitcode ("pop", "b");
9783 emitcode ("mov", "@%s,a", rname);
9787 emitcode ("movx", "@dptr,a");
9791 emitcode ("lcall", "__gptrput");
9796 if (SPEC_BLEN (etype) <= 8)
9799 emitcode ("inc", "%s", rname);
9800 rLen = SPEC_BLEN (etype);
9802 /* now generate for lengths greater than one byte */
9806 l = aopGet (AOP (right), offset++, FALSE, TRUE, NULL);
9818 emitcode ("mov", "@%s,a", rname);
9821 emitcode ("mov", "@%s,%s", rname, l);
9826 emitcode ("movx", "@dptr,a");
9831 emitcode ("lcall", "__gptrput");
9834 emitcode ("inc", "%s", rname);
9839 /* last last was not complete */
9842 /* save the byte & read byte */
9846 emitcode ("mov", "b,a");
9847 emitcode ("mov", "a,@%s", rname);
9851 emitcode ("mov", "b,a");
9852 emitcode ("movx", "a,@dptr");
9856 emitcode ("push", "b");
9857 emitcode ("push", "acc");
9858 emitcode ("lcall", "__gptrget");
9859 emitcode ("pop", "b");
9863 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1 << rLen));
9864 emitcode ("orl", "a,b");
9867 if (p_type == GPOINTER)
9868 emitcode ("pop", "b");
9874 emitcode ("mov", "@%s,a", rname);
9878 emitcode ("movx", "@dptr,a");
9882 emitcode ("lcall", "__gptrput");
9886 /*-----------------------------------------------------------------*/
9887 /* genDataPointerSet - remat pointer to data space */
9888 /*-----------------------------------------------------------------*/
9890 genDataPointerSet (operand * right,
9894 int size, offset = 0;
9897 aopOp (right, ic, FALSE, FALSE);
9899 l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
9900 size = AOP_SIZE (right);
9905 SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
9909 SNPRINTF (buff, sizeof(buff), "%s", l + 1);
9912 emitcode ("mov", "%s,%s", buff,
9913 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9916 freeAsmop (right, NULL, ic, TRUE);
9917 freeAsmop (result, NULL, ic, TRUE);
9920 /*-----------------------------------------------------------------*/
9921 /* genNearPointerSet - emitcode for near pointer put */
9922 /*-----------------------------------------------------------------*/
9924 genNearPointerSet (operand * right,
9931 sym_link *retype, *letype;
9932 sym_link *ptype = operandType (result);
9934 retype = getSpec (operandType (right));
9935 letype = getSpec (ptype);
9937 aopOp (result, ic, FALSE, FALSE);
9939 /* if the result is rematerializable &
9940 in data space & not a bit variable */
9941 if (AOP_TYPE (result) == AOP_IMMD &&
9942 DCL_TYPE (ptype) == POINTER &&
9943 !IS_BITVAR (retype) &&
9944 !IS_BITVAR (letype))
9946 genDataPointerSet (right, result, ic);
9950 /* if the value is already in a pointer register
9951 then don't need anything more */
9952 if (!AOP_INPREG (AOP (result)))
9954 /* otherwise get a free pointer register */
9958 preg = getFreePtr (ic, &aop, FALSE);
9959 emitcode ("mov", "%s,%s",
9961 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
9965 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
9967 aopOp (right, ic, FALSE, FALSE);
9969 /* if bitfield then unpack the bits */
9970 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9971 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9974 /* we have can just get the values */
9975 int size = AOP_SIZE (right);
9980 l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
9984 emitcode ("mov", "@%s,a", rname);
9987 emitcode ("mov", "@%s,%s", rname, l);
9989 emitcode ("inc", "%s", rname);
9994 /* now some housekeeping stuff */
9997 /* we had to allocate for this iCode */
9998 if (pi) aopPut (AOP (result),rname,0);
9999 freeAsmop (NULL, aop, ic, TRUE);
10003 /* we did not allocate which means left
10004 already in a pointer register, then
10005 if size > 0 && this could be used again
10006 we have to point it back to where it
10008 if (AOP_SIZE (right) > 1 &&
10009 !OP_SYMBOL (result)->remat &&
10010 (OP_SYMBOL (result)->liveTo > ic->seq ||
10014 int size = AOP_SIZE (right) - 1;
10016 emitcode ("dec", "%s", rname);
10021 if (pi) pi->generated = 1;
10022 freeAsmop (result, NULL, ic, TRUE);
10023 freeAsmop (right, NULL, ic, TRUE);
10028 /*-----------------------------------------------------------------*/
10029 /* genPagedPointerSet - emitcode for Paged pointer put */
10030 /*-----------------------------------------------------------------*/
10032 genPagedPointerSet (operand * right,
10039 sym_link *retype, *letype;
10041 retype = getSpec (operandType (right));
10042 letype = getSpec (operandType (result));
10044 aopOp (result, ic, FALSE, FALSE);
10046 /* if the value is already in a pointer register
10047 then don't need anything more */
10048 if (!AOP_INPREG (AOP (result)))
10050 /* otherwise get a free pointer register */
10053 aop = newAsmop (0);
10054 preg = getFreePtr (ic, &aop, FALSE);
10055 emitcode ("mov", "%s,%s",
10057 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10058 rname = preg->name;
10061 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10063 aopOp (right, ic, FALSE, FALSE);
10065 /* if bitfield then unpack the bits */
10066 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10067 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
10070 /* we have can just get the values */
10071 int size = AOP_SIZE (right);
10076 MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10078 emitcode ("movx", "@%s,a", rname);
10081 emitcode ("inc", "%s", rname);
10087 /* now some housekeeping stuff */
10090 if (pi) aopPut (AOP (result),rname,0);
10091 /* we had to allocate for this iCode */
10092 freeAsmop (NULL, aop, ic, TRUE);
10096 /* we did not allocate which means left
10097 already in a pointer register, then
10098 if size > 0 && this could be used again
10099 we have to point it back to where it
10101 if (AOP_SIZE (right) > 1 &&
10102 !OP_SYMBOL (result)->remat &&
10103 (OP_SYMBOL (result)->liveTo > ic->seq ||
10107 int size = AOP_SIZE (right) - 1;
10109 emitcode ("dec", "%s", rname);
10114 if (pi) pi->generated = 1;
10115 freeAsmop (result, NULL, ic, TRUE);
10116 freeAsmop (right, NULL, ic, TRUE);
10121 /*-----------------------------------------------------------------*/
10122 /* genFarPointerSet - set value from far space */
10123 /*-----------------------------------------------------------------*/
10125 genFarPointerSet (operand * right,
10126 operand * result, iCode * ic, iCode *pi)
10128 int size, offset, dopi=1;
10129 sym_link *retype = getSpec (operandType (right));
10130 sym_link *letype = getSpec (operandType (result));
10132 aopOp (result, ic, FALSE, FALSE);
10134 /* if the operand is already in dptr
10135 then we do nothing else we move the value to dptr */
10136 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10138 /* if this is remateriazable */
10139 if (AOP_TYPE (result) == AOP_IMMD)
10140 emitcode ("mov", "dptr,%s",
10141 aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10144 /* we need to get it byte by byte */
10145 _startLazyDPSEvaluation ();
10146 if (AOP_TYPE (result) != AOP_DPTR)
10148 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10149 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10150 if (options.model == MODEL_FLAT24)
10151 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10155 /* We need to generate a load to DPTR indirect through DPTR. */
10156 D (emitcode (";", "genFarPointerSet -- indirection special case."););
10158 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10159 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10160 if (options.model == MODEL_FLAT24)
10161 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10162 emitcode ("pop", "dph");
10163 emitcode ("pop", "dpl");
10166 _endLazyDPSEvaluation ();
10169 /* so dptr know contains the address */
10170 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10172 /* if bit then unpack */
10173 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
10174 if (AOP_INDPTRn(result)) {
10175 genSetDPTR(AOP(result)->aopu.dptr);
10177 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
10178 if (AOP_INDPTRn(result)) {
10182 size = AOP_SIZE (right);
10184 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10186 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10188 genSetDPTR(AOP(result)->aopu.dptr);
10189 emitcode ("movx", "@dptr,a");
10190 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10191 emitcode ("inc", "dptr");
10195 _startLazyDPSEvaluation ();
10197 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10199 if (AOP_INDPTRn(result)) {
10200 genSetDPTR(AOP(result)->aopu.dptr);
10206 emitcode ("movx", "@dptr,a");
10207 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10208 emitcode ("inc", "dptr");
10210 _endLazyDPSEvaluation ();
10214 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10215 if (!AOP_INDPTRn(result)) {
10216 _startLazyDPSEvaluation ();
10218 aopPut (AOP(result),"dpl",0);
10219 aopPut (AOP(result),"dph",1);
10220 if (options.model == MODEL_FLAT24)
10221 aopPut (AOP(result),"dpx",2);
10223 _endLazyDPSEvaluation ();
10226 } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
10227 AOP_SIZE(right) > 1 &&
10228 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10230 size = AOP_SIZE (right) - 1;
10231 if (AOP_INDPTRn(result)) {
10232 genSetDPTR(AOP(result)->aopu.dptr);
10234 while (size--) emitcode ("lcall","__decdptr");
10235 if (AOP_INDPTRn(result)) {
10239 freeAsmop (result, NULL, ic, TRUE);
10240 freeAsmop (right, NULL, ic, TRUE);
10243 /*-----------------------------------------------------------------*/
10244 /* genGenPointerSet - set value from generic pointer space */
10245 /*-----------------------------------------------------------------*/
10247 genGenPointerSet (operand * right,
10248 operand * result, iCode * ic, iCode *pi)
10251 sym_link *retype = getSpec (operandType (right));
10252 sym_link *letype = getSpec (operandType (result));
10254 aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10256 /* if the operand is already in dptr
10257 then we do nothing else we move the value to dptr */
10258 if (AOP_TYPE (result) != AOP_STR)
10260 _startLazyDPSEvaluation ();
10261 /* if this is remateriazable */
10262 if (AOP_TYPE (result) == AOP_IMMD)
10264 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10265 if (AOP(result)->aopu.aop_immd.from_cast_remat)
10267 MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10272 "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10276 { /* we need to get it byte by byte */
10277 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10278 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10279 if (options.model == MODEL_FLAT24) {
10280 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10281 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10283 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10286 _endLazyDPSEvaluation ();
10288 /* so dptr + b now contains the address */
10290 aopOp (right, ic, FALSE, TRUE);
10294 /* if bit then unpack */
10295 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10297 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
10301 size = AOP_SIZE (right);
10304 _startLazyDPSEvaluation ();
10309 // Set two bytes at a time, passed in _AP & A.
10310 // dptr will be incremented ONCE by __gptrputWord.
10312 // Note: any change here must be coordinated
10313 // with the implementation of __gptrputWord
10314 // in device/lib/_gptrput.c
10315 emitcode("mov", "_ap, %s",
10316 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10317 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10321 emitcode ("lcall", "__gptrputWord");
10326 // Only one byte to put.
10327 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10331 emitcode ("lcall", "__gptrput");
10334 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10336 emitcode ("inc", "dptr");
10339 _endLazyDPSEvaluation ();
10342 if (pi && AOP_TYPE (result) != AOP_IMMD) {
10343 _startLazyDPSEvaluation ();
10345 aopPut (AOP(result),"dpl",0);
10346 aopPut (AOP(result),"dph",1);
10347 if (options.model == MODEL_FLAT24) {
10348 aopPut (AOP(result),"dpx",2);
10349 aopPut (AOP(result),"b",3);
10351 aopPut (AOP(result),"b",2);
10353 _endLazyDPSEvaluation ();
10356 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10357 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10359 size = AOP_SIZE (right) - 1;
10360 while (size--) emitcode ("lcall","__decdptr");
10362 freeAsmop (result, NULL, ic, TRUE);
10363 freeAsmop (right, NULL, ic, TRUE);
10366 /*-----------------------------------------------------------------*/
10367 /* genPointerSet - stores the value into a pointer location */
10368 /*-----------------------------------------------------------------*/
10370 genPointerSet (iCode * ic, iCode *pi)
10372 operand *right, *result;
10373 sym_link *type, *etype;
10376 D (emitcode (";", "genPointerSet "););
10378 right = IC_RIGHT (ic);
10379 result = IC_RESULT (ic);
10381 /* depending on the type of pointer we need to
10382 move it to the correct pointer register */
10383 type = operandType (result);
10384 etype = getSpec (type);
10385 /* if left is of type of pointer then it is simple */
10386 if (IS_PTR (type) && !IS_FUNC (type->next))
10388 p_type = DCL_TYPE (type);
10392 /* we have to go by the storage class */
10393 p_type = PTR_TYPE (SPEC_OCLS (etype));
10395 /* special case when cast remat */
10396 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10397 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10398 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10399 type = operandType (result);
10400 p_type = DCL_TYPE (type);
10403 /* now that we have the pointer type we assign
10404 the pointer values */
10410 genNearPointerSet (right, result, ic, pi);
10414 genPagedPointerSet (right, result, ic, pi);
10418 genFarPointerSet (right, result, ic, pi);
10422 genGenPointerSet (right, result, ic, pi);
10426 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10427 "genPointerSet: illegal pointer type");
10432 /*-----------------------------------------------------------------*/
10433 /* genIfx - generate code for Ifx statement */
10434 /*-----------------------------------------------------------------*/
10436 genIfx (iCode * ic, iCode * popIc)
10438 operand *cond = IC_COND (ic);
10441 D (emitcode (";", "genIfx "););
10443 aopOp (cond, ic, FALSE, FALSE);
10445 /* get the value into acc */
10446 if (AOP_TYPE (cond) != AOP_CRY)
10455 /* the result is now in the accumulator */
10456 freeAsmop (cond, NULL, ic, TRUE);
10458 /* if there was something to be popped then do it */
10462 /* if the condition is a bit variable */
10463 if (isbit && IS_ITEMP (cond) &&
10466 genIfxJump (ic, SPIL_LOC (cond)->rname);
10468 else if (isbit && !IS_ITEMP (cond))
10470 genIfxJump (ic, OP_SYMBOL (cond)->rname);
10474 genIfxJump (ic, "a");
10480 /*-----------------------------------------------------------------*/
10481 /* genAddrOf - generates code for address of */
10482 /*-----------------------------------------------------------------*/
10484 genAddrOf (iCode * ic)
10486 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10489 D (emitcode (";", "genAddrOf ");
10492 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10494 /* if the operand is on the stack then we
10495 need to get the stack offset of this
10497 if (sym->onStack) {
10499 /* if 10 bit stack */
10500 if (options.stack10bit) {
10502 tsprintf(buff, sizeof(buff),
10503 "#!constbyte",(options.stack_loc >> 16) & 0xff);
10504 /* if it has an offset then we need to compute it */
10505 /* emitcode ("subb", "a,#!constbyte", */
10506 /* -((sym->stack < 0) ? */
10507 /* ((short) (sym->stack - _G.nRegsSaved)) : */
10508 /* ((short) sym->stack)) & 0xff); */
10509 /* emitcode ("mov","b,a"); */
10510 /* emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
10511 /* ((short) (sym->stack - _G.nRegsSaved)) : */
10512 /* ((short) sym->stack)) >> 8) & 0xff); */
10514 emitcode ("mov", "a,_bpx");
10515 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
10516 ((char) (sym->stack - _G.nRegsSaved)) :
10517 ((char) sym->stack )) & 0xff);
10518 emitcode ("mov", "b,a");
10519 emitcode ("mov", "a,_bpx+1");
10520 emitcode ("addc","a,#!constbyte", (((sym->stack < 0) ?
10521 ((short) (sym->stack - _G.nRegsSaved)) :
10522 ((short) sym->stack )) >> 8) & 0xff);
10523 aopPut (AOP (IC_RESULT (ic)), "b", 0);
10524 aopPut (AOP (IC_RESULT (ic)), "a", 1);
10525 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10527 /* we can just move _bp */
10528 aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10529 aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10530 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10533 /* if it has an offset then we need to compute it */
10535 emitcode ("mov", "a,_bp");
10536 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10537 aopPut (AOP (IC_RESULT (ic)), "a", 0);
10539 /* we can just move _bp */
10540 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10542 /* fill the result with zero */
10543 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10546 if (options.stack10bit && size < (FPTRSIZE - 1)) {
10548 "*** warning: pointer to stack var truncated.\n");
10553 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10559 /* object not on stack then we need the name */
10560 size = AOP_SIZE (IC_RESULT (ic));
10565 char s[SDCC_NAME_MAX];
10569 tsprintf(s, sizeof(s), "#!his",sym->rname);
10572 tsprintf(s, sizeof(s), "#!hihis",sym->rname);
10575 tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
10577 default: /* should not need this (just in case) */
10578 SNPRINTF (s, sizeof(s), "#(%s >> %d)",
10585 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10588 aopPut (AOP (IC_RESULT (ic)), s, offset++);
10592 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10596 /*-----------------------------------------------------------------*/
10597 /* genArrayInit - generates code for address of */
10598 /*-----------------------------------------------------------------*/
10600 genArrayInit (iCode * ic)
10602 literalList *iLoop;
10604 int elementSize = 0, eIndex;
10605 unsigned val, lastVal;
10607 operand *left=IC_LEFT(ic);
10609 D (emitcode (";", "genArrayInit "););
10611 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10613 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10615 // Load immediate value into DPTR.
10616 emitcode("mov", "dptr, %s",
10617 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
10619 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10622 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10623 "Unexpected operand to genArrayInit.\n");
10626 // a regression because of SDCCcse.c:1.52
10627 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10628 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10629 if (options.model == MODEL_FLAT24)
10630 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10634 type = operandType(IC_LEFT(ic));
10636 if (type && type->next)
10638 elementSize = getSize(type->next);
10642 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10643 "can't determine element size in genArrayInit.\n");
10647 iLoop = IC_ARRAYILIST(ic);
10652 bool firstpass = TRUE;
10654 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
10655 iLoop->count, (int)iLoop->literalValue, elementSize);
10661 symbol *tlbl = NULL;
10663 count = ix > 256 ? 256 : ix;
10667 tlbl = newiTempLabel (NULL);
10668 if (firstpass || (count & 0xff))
10670 emitcode("mov", "b, #!constbyte", count & 0xff);
10673 emitcode ("", "!tlabeldef", tlbl->key + 100);
10678 for (eIndex = 0; eIndex < elementSize; eIndex++)
10680 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10681 if (val != lastVal)
10683 emitcode("mov", "a, #!constbyte", val);
10687 emitcode("movx", "@dptr, a");
10688 emitcode("inc", "dptr");
10693 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10699 iLoop = iLoop->next;
10702 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10705 /*-----------------------------------------------------------------*/
10706 /* genFarFarAssign - assignment when both are in far space */
10707 /*-----------------------------------------------------------------*/
10709 genFarFarAssign (operand * result, operand * right, iCode * ic)
10711 int size = AOP_SIZE (right);
10713 symbol *rSym = NULL;
10717 /* quick & easy case. */
10718 D(emitcode(";","genFarFarAssign (1 byte case)"););
10719 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
10720 freeAsmop (right, NULL, ic, FALSE);
10721 /* now assign DPTR to result */
10723 aopOp(result, ic, FALSE, FALSE);
10725 aopPut(AOP(result), "a", 0);
10726 freeAsmop(result, NULL, ic, FALSE);
10730 /* See if we've got an underlying symbol to abuse. */
10731 if (IS_SYMOP(result) && OP_SYMBOL(result))
10733 if (IS_TRUE_SYMOP(result))
10735 rSym = OP_SYMBOL(result);
10737 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10739 rSym = OP_SYMBOL(result)->usl.spillLoc;
10743 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10745 /* We can use the '390 auto-toggle feature to good effect here. */
10747 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10748 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
10749 emitcode ("mov", "dptr,#%s", rSym->rname);
10750 /* DP2 = result, DP1 = right, DP1 is current. */
10753 emitcode("movx", "a,@dptr");
10754 emitcode("movx", "@dptr,a");
10757 emitcode("inc", "dptr");
10758 emitcode("inc", "dptr");
10761 emitcode("mov", "dps,#0");
10762 freeAsmop (right, NULL, ic, FALSE);
10764 some alternative code for processors without auto-toggle
10765 no time to test now, so later well put in...kpb
10766 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10767 emitcode("mov", "dps,#1"); /* Select DPTR2. */
10768 emitcode ("mov", "dptr,#%s", rSym->rname);
10769 /* DP2 = result, DP1 = right, DP1 is current. */
10773 emitcode("movx", "a,@dptr");
10775 emitcode("inc", "dptr");
10776 emitcode("inc", "dps");
10777 emitcode("movx", "@dptr,a");
10779 emitcode("inc", "dptr");
10780 emitcode("inc", "dps");
10782 emitcode("mov", "dps,#0");
10783 freeAsmop (right, NULL, ic, FALSE);
10788 D (emitcode (";", "genFarFarAssign"););
10789 aopOp (result, ic, TRUE, TRUE);
10791 _startLazyDPSEvaluation ();
10795 aopPut (AOP (result),
10796 aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
10799 _endLazyDPSEvaluation ();
10800 freeAsmop (result, NULL, ic, FALSE);
10801 freeAsmop (right, NULL, ic, FALSE);
10805 /*-----------------------------------------------------------------*/
10806 /* genAssign - generate code for assignment */
10807 /*-----------------------------------------------------------------*/
10809 genAssign (iCode * ic)
10811 operand *result, *right;
10813 unsigned long lit = 0L;
10815 D (emitcode (";", "genAssign ");
10818 result = IC_RESULT (ic);
10819 right = IC_RIGHT (ic);
10821 /* if they are the same */
10822 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10825 aopOp (right, ic, FALSE, FALSE);
10827 emitcode (";", "genAssign: resultIsFar = %s",
10828 isOperandInFarSpace (result) ?
10831 /* special case both in far space */
10832 if ((AOP_TYPE (right) == AOP_DPTR ||
10833 AOP_TYPE (right) == AOP_DPTR2) &&
10834 /* IS_TRUE_SYMOP(result) && */
10835 isOperandInFarSpace (result))
10837 genFarFarAssign (result, right, ic);
10841 aopOp (result, ic, TRUE, FALSE);
10843 /* if they are the same registers */
10844 if (sameRegs (AOP (right), AOP (result)))
10847 /* if the result is a bit */
10848 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10850 /* if the right size is a literal then
10851 we know what the value is */
10852 if (AOP_TYPE (right) == AOP_LIT)
10854 if (((int) operandLitValue (right)))
10855 aopPut (AOP (result), one, 0);
10857 aopPut (AOP (result), zero, 0);
10861 /* the right is also a bit variable */
10862 if (AOP_TYPE (right) == AOP_CRY)
10864 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10865 aopPut (AOP (result), "c", 0);
10869 /* we need to or */
10871 aopPut (AOP (result), "a", 0);
10875 /* bit variables done */
10877 size = AOP_SIZE (result);
10879 if (AOP_TYPE (right) == AOP_LIT)
10880 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10883 (AOP_TYPE (result) != AOP_REG) &&
10884 (AOP_TYPE (right) == AOP_LIT) &&
10885 !IS_FLOAT (operandType (right)))
10887 _startLazyDPSEvaluation ();
10888 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10890 aopPut (AOP (result),
10891 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10896 /* And now fill the rest with zeros. */
10899 emitcode ("clr", "a");
10903 aopPut (AOP (result), "a", offset++);
10905 _endLazyDPSEvaluation ();
10909 _startLazyDPSEvaluation ();
10912 aopPut (AOP (result),
10913 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10917 _endLazyDPSEvaluation ();
10921 freeAsmop (right, NULL, ic, FALSE);
10922 freeAsmop (result, NULL, ic, TRUE);
10925 /*-----------------------------------------------------------------*/
10926 /* genJumpTab - generates code for jump table */
10927 /*-----------------------------------------------------------------*/
10929 genJumpTab (iCode * ic)
10934 D (emitcode (";", "genJumpTab ");
10937 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10938 /* get the condition into accumulator */
10939 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
10941 /* multiply by four! */
10942 emitcode ("add", "a,acc");
10943 emitcode ("add", "a,acc");
10944 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10946 jtab = newiTempLabel (NULL);
10947 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
10948 emitcode ("jmp", "@a+dptr");
10949 emitcode ("", "!tlabeldef", jtab->key + 100);
10950 /* now generate the jump labels */
10951 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10952 jtab = setNextItem (IC_JTLABELS (ic)))
10953 emitcode ("ljmp", "!tlabel", jtab->key + 100);
10957 /*-----------------------------------------------------------------*/
10958 /* genCast - gen code for casting */
10959 /*-----------------------------------------------------------------*/
10961 genCast (iCode * ic)
10963 operand *result = IC_RESULT (ic);
10964 sym_link *ctype = operandType (IC_LEFT (ic));
10965 sym_link *rtype = operandType (IC_RIGHT (ic));
10966 operand *right = IC_RIGHT (ic);
10969 D (emitcode (";", "genCast "););
10971 /* if they are equivalent then do nothing */
10972 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10975 aopOp (right, ic, FALSE, FALSE);
10976 aopOp (result, ic, FALSE, AOP_USESDPTR(right));
10978 /* if the result is a bit */
10979 // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10980 if (IS_BITVAR(OP_SYMBOL(result)->type))
10982 /* if the right size is a literal then
10983 we know what the value is */
10984 if (AOP_TYPE (right) == AOP_LIT)
10986 if (((int) operandLitValue (right)))
10987 aopPut (AOP (result), one, 0);
10989 aopPut (AOP (result), zero, 0);
10994 /* the right is also a bit variable */
10995 if (AOP_TYPE (right) == AOP_CRY)
10997 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10998 aopPut (AOP (result), "c", 0);
11002 /* we need to or */
11004 aopPut (AOP (result), "a", 0);
11008 /* if they are the same size : or less */
11009 if (AOP_SIZE (result) <= AOP_SIZE (right))
11012 /* if they are in the same place */
11013 if (sameRegs (AOP (right), AOP (result)))
11016 /* if they in different places then copy */
11017 size = AOP_SIZE (result);
11019 _startLazyDPSEvaluation ();
11022 aopPut (AOP (result),
11023 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11027 _endLazyDPSEvaluation ();
11032 /* if the result is of type pointer */
11033 if (IS_PTR (ctype))
11037 sym_link *type = operandType (right);
11039 /* pointer to generic pointer */
11040 if (IS_GENPTR (ctype))
11044 p_type = DCL_TYPE (type);
11048 #if OLD_CAST_BEHAVIOR
11049 /* KV: we are converting a non-pointer type to
11050 * a generic pointer. This (ifdef'd out) code
11051 * says that the resulting generic pointer
11052 * should have the same class as the storage
11053 * location of the non-pointer variable.
11055 * For example, converting an int (which happens
11056 * to be stored in DATA space) to a pointer results
11057 * in a DATA generic pointer; if the original int
11058 * in XDATA space, so will be the resulting pointer.
11060 * I don't like that behavior, and thus this change:
11061 * all such conversions will be forced to XDATA and
11062 * throw a warning. If you want some non-XDATA
11063 * type, or you want to suppress the warning, you
11064 * must go through an intermediate cast, like so:
11066 * char _generic *gp = (char _xdata *)(intVar);
11068 sym_link *etype = getSpec (type);
11070 /* we have to go by the storage class */
11071 if (SPEC_OCLS (etype) != generic)
11073 p_type = PTR_TYPE (SPEC_OCLS (etype));
11078 /* Converting unknown class (i.e. register variable)
11079 * to generic pointer. This is not good, but
11080 * we'll make a guess (and throw a warning).
11083 werror (W_INT_TO_GEN_PTR_CAST);
11087 /* the first two bytes are known */
11088 size = GPTRSIZE - 1;
11090 _startLazyDPSEvaluation ();
11093 aopPut (AOP (result),
11094 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11098 _endLazyDPSEvaluation ();
11100 /* the last byte depending on type */
11102 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11107 // pointerTypeToGPByte will have bitched.
11111 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11112 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11117 /* just copy the pointers */
11118 size = AOP_SIZE (result);
11120 _startLazyDPSEvaluation ();
11123 aopPut (AOP (result),
11124 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11128 _endLazyDPSEvaluation ();
11132 /* so we now know that the size of destination is greater
11133 than the size of the source */
11134 /* we move to result for the size of source */
11135 size = AOP_SIZE (right);
11137 _startLazyDPSEvaluation ();
11140 aopPut (AOP (result),
11141 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11145 _endLazyDPSEvaluation ();
11147 /* now depending on the sign of the source && destination */
11148 size = AOP_SIZE (result) - AOP_SIZE (right);
11149 /* if unsigned or not an integral type */
11150 /* also, if the source is a bit, we don't need to sign extend, because
11151 * it can't possibly have set the sign bit.
11153 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
11157 aopPut (AOP (result), zero, offset++);
11162 /* we need to extend the sign :{ */
11163 MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11164 FALSE, FALSE, NULL));
11165 emitcode ("rlc", "a");
11166 emitcode ("subb", "a,acc");
11168 aopPut (AOP (result), "a", offset++);
11171 /* we are done hurray !!!! */
11174 freeAsmop (right, NULL, ic, TRUE);
11175 freeAsmop (result, NULL, ic, TRUE);
11179 /*-----------------------------------------------------------------*/
11180 /* genDjnz - generate decrement & jump if not zero instrucion */
11181 /*-----------------------------------------------------------------*/
11183 genDjnz (iCode * ic, iCode * ifx)
11185 symbol *lbl, *lbl1;
11189 /* if the if condition has a false label
11190 then we cannot save */
11191 if (IC_FALSE (ifx))
11194 /* if the minus is not of the form
11196 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11197 !IS_OP_LITERAL (IC_RIGHT (ic)))
11200 if (operandLitValue (IC_RIGHT (ic)) != 1)
11203 /* if the size of this greater than one then no
11205 if (getSize (operandType (IC_RESULT (ic))) > 1)
11208 /* otherwise we can save BIG */
11209 D(emitcode(";", "genDjnz"););
11211 lbl = newiTempLabel (NULL);
11212 lbl1 = newiTempLabel (NULL);
11214 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11216 if (AOP_NEEDSACC(IC_RESULT(ic)))
11218 /* If the result is accessed indirectly via
11219 * the accumulator, we must explicitly write
11220 * it back after the decrement.
11222 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11224 if (strcmp(rByte, "a"))
11226 /* Something is hopelessly wrong */
11227 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11228 __FILE__, __LINE__);
11229 /* We can just give up; the generated code will be inefficient,
11230 * but what the hey.
11232 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11235 emitcode ("dec", "%s", rByte);
11236 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11237 emitcode ("jnz", "!tlabel", lbl->key + 100);
11239 else if (IS_AOP_PREG (IC_RESULT (ic)))
11241 emitcode ("dec", "%s",
11242 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11243 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11244 emitcode ("jnz", "!tlabel", lbl->key + 100);
11248 emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11251 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11252 emitcode ("", "!tlabeldef", lbl->key + 100);
11253 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11254 emitcode ("", "!tlabeldef", lbl1->key + 100);
11256 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11257 ifx->generated = 1;
11261 /*-----------------------------------------------------------------*/
11262 /* genReceive - generate code for a receive iCode */
11263 /*-----------------------------------------------------------------*/
11265 genReceive (iCode * ic)
11267 int size = getSize (operandType (IC_RESULT (ic)));
11271 D (emitcode (";", "genReceive "););
11273 if (ic->argreg == 1)
11275 /* first parameter */
11276 if (AOP_IS_STR(IC_RESULT(ic)))
11278 /* Nothing to do: it's already in the proper place. */
11285 useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11286 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11287 IS_TRUE_SYMOP (IC_RESULT (ic)));
11290 aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11293 /* Sanity checking... */
11294 if (AOP_USESDPTR(IC_RESULT(ic)))
11296 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11297 "genReceive got unexpected DPTR.");
11299 assignResultValue (IC_RESULT (ic));
11304 /* second receive onwards */
11305 /* this gets a little tricky since unused recevies will be
11306 eliminated, we have saved the reg in the type field . and
11307 we use that to figure out which register to use */
11308 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11309 rb1off = ic->argreg;
11312 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11315 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11318 /*-----------------------------------------------------------------*/
11319 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
11320 /*-----------------------------------------------------------------*/
11321 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11323 operand *from , *to , *count;
11328 /* we know it has to be 3 parameters */
11329 assert (nparms == 3);
11331 rsave = newBitVect(16);
11332 /* save DPTR if it needs to be saved */
11333 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11334 if (bitVectBitValue(ic->rMask,i))
11335 rsave = bitVectSetBit(rsave,i);
11337 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11338 ds390_rUmaskForOp (IC_RESULT(ic))));
11345 aopOp (from, ic->next, FALSE, FALSE);
11347 /* get from into DPTR1 */
11348 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11349 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11350 if (options.model == MODEL_FLAT24) {
11351 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11354 freeAsmop (from, NULL, ic, FALSE);
11355 aopOp (to, ic, FALSE, FALSE);
11356 /* get "to" into DPTR */
11357 /* if the operand is already in dptr
11358 then we do nothing else we move the value to dptr */
11359 if (AOP_TYPE (to) != AOP_STR) {
11360 /* if already in DPTR then we need to push */
11361 if (AOP_TYPE(to) == AOP_DPTR) {
11362 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11363 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11364 if (options.model == MODEL_FLAT24)
11365 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11366 emitcode ("pop", "dph");
11367 emitcode ("pop", "dpl");
11369 _startLazyDPSEvaluation ();
11370 /* if this is remateriazable */
11371 if (AOP_TYPE (to) == AOP_IMMD) {
11372 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11373 } else { /* we need to get it byte by byte */
11374 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11375 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11376 if (options.model == MODEL_FLAT24) {
11377 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11380 _endLazyDPSEvaluation ();
11383 freeAsmop (to, NULL, ic, FALSE);
11384 _G.dptrInUse = _G.dptr1InUse = 1;
11385 aopOp (count, ic->next->next, FALSE,FALSE);
11386 lbl =newiTempLabel(NULL);
11388 /* now for the actual copy */
11389 if (AOP_TYPE(count) == AOP_LIT &&
11390 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11391 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11393 emitcode ("lcall","__bi_memcpyc2x_s");
11395 emitcode ("lcall","__bi_memcpyx2x_s");
11397 freeAsmop (count, NULL, ic, FALSE);
11399 symbol *lbl1 = newiTempLabel(NULL);
11401 emitcode (";"," Auto increment but no djnz");
11402 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11403 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11404 freeAsmop (count, NULL, ic, FALSE);
11405 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11406 emitcode ("","!tlabeldef",lbl->key+100);
11408 emitcode ("clr","a");
11409 emitcode ("movc", "a,@a+dptr");
11411 emitcode ("movx", "a,@dptr");
11412 emitcode ("movx", "@dptr,a");
11413 emitcode ("inc", "dptr");
11414 emitcode ("inc", "dptr");
11415 emitcode ("mov","a,b");
11416 emitcode ("orl","a,_ap");
11417 emitcode ("jz","!tlabel",lbl1->key+100);
11418 emitcode ("mov","a,_ap");
11419 emitcode ("add","a,#!constbyte",0xFF);
11420 emitcode ("mov","_ap,a");
11421 emitcode ("mov","a,b");
11422 emitcode ("addc","a,#!constbyte",0xFF);
11423 emitcode ("mov","b,a");
11424 emitcode ("sjmp","!tlabel",lbl->key+100);
11425 emitcode ("","!tlabeldef",lbl1->key+100);
11427 emitcode ("mov", "dps,#0");
11428 _G.dptrInUse = _G.dptr1InUse = 0;
11429 unsavermask(rsave);
11433 /*-----------------------------------------------------------------*/
11434 /* genMemcmpX2X - gen code for memcmp xdata to xdata */
11435 /*-----------------------------------------------------------------*/
11436 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11438 operand *from , *to , *count;
11443 /* we know it has to be 3 parameters */
11444 assert (nparms == 3);
11446 rsave = newBitVect(16);
11447 /* save DPTR if it needs to be saved */
11448 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11449 if (bitVectBitValue(ic->rMask,i))
11450 rsave = bitVectSetBit(rsave,i);
11452 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11453 ds390_rUmaskForOp (IC_RESULT(ic))));
11460 aopOp (from, ic->next, FALSE, FALSE);
11462 /* get from into DPTR1 */
11463 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11464 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11465 if (options.model == MODEL_FLAT24) {
11466 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11469 freeAsmop (from, NULL, ic, FALSE);
11470 aopOp (to, ic, FALSE, FALSE);
11471 /* get "to" into DPTR */
11472 /* if the operand is already in dptr
11473 then we do nothing else we move the value to dptr */
11474 if (AOP_TYPE (to) != AOP_STR) {
11475 /* if already in DPTR then we need to push */
11476 if (AOP_TYPE(to) == AOP_DPTR) {
11477 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11478 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11479 if (options.model == MODEL_FLAT24)
11480 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11481 emitcode ("pop", "dph");
11482 emitcode ("pop", "dpl");
11484 _startLazyDPSEvaluation ();
11485 /* if this is remateriazable */
11486 if (AOP_TYPE (to) == AOP_IMMD) {
11487 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11488 } else { /* we need to get it byte by byte */
11489 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11490 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11491 if (options.model == MODEL_FLAT24) {
11492 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11495 _endLazyDPSEvaluation ();
11498 freeAsmop (to, NULL, ic, FALSE);
11499 _G.dptrInUse = _G.dptr1InUse = 1;
11500 aopOp (count, ic->next->next, FALSE,FALSE);
11501 lbl =newiTempLabel(NULL);
11502 lbl2 =newiTempLabel(NULL);
11504 /* now for the actual compare */
11505 if (AOP_TYPE(count) == AOP_LIT &&
11506 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11507 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11509 emitcode("lcall","__bi_memcmpc2x_s");
11511 emitcode("lcall","__bi_memcmpx2x_s");
11512 freeAsmop (count, NULL, ic, FALSE);
11513 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11514 aopPut(AOP(IC_RESULT(ic)),"a",0);
11515 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11517 symbol *lbl1 = newiTempLabel(NULL);
11519 emitcode("push","ar0");
11520 emitcode (";"," Auto increment but no djnz");
11521 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11522 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11523 freeAsmop (count, NULL, ic, FALSE);
11524 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11525 emitcode ("","!tlabeldef",lbl->key+100);
11527 emitcode ("clr","a");
11528 emitcode ("movc", "a,@a+dptr");
11530 emitcode ("movx", "a,@dptr");
11531 emitcode ("mov","r0,a");
11532 emitcode ("movx", "a,@dptr");
11533 emitcode ("clr","c");
11534 emitcode ("subb","a,r0");
11535 emitcode ("jnz","!tlabel",lbl2->key+100);
11536 emitcode ("inc", "dptr");
11537 emitcode ("inc", "dptr");
11538 emitcode ("mov","a,b");
11539 emitcode ("orl","a,_ap");
11540 emitcode ("jz","!tlabel",lbl1->key+100);
11541 emitcode ("mov","a,_ap");
11542 emitcode ("add","a,#!constbyte",0xFF);
11543 emitcode ("mov","_ap,a");
11544 emitcode ("mov","a,b");
11545 emitcode ("addc","a,#!constbyte",0xFF);
11546 emitcode ("mov","b,a");
11547 emitcode ("sjmp","!tlabel",lbl->key+100);
11548 emitcode ("","!tlabeldef",lbl1->key+100);
11549 emitcode ("clr","a");
11550 emitcode ("","!tlabeldef",lbl2->key+100);
11551 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11552 aopPut(AOP(IC_RESULT(ic)),"a",0);
11553 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11554 emitcode("pop","ar0");
11555 emitcode ("mov", "dps,#0");
11557 _G.dptrInUse = _G.dptr1InUse = 0;
11558 unsavermask(rsave);
11562 /*-----------------------------------------------------------------*/
11563 /* genInp - gen code for __builtin_inp read data from a mem mapped */
11564 /* port, first parameter output area second parameter pointer to */
11565 /* port third parameter count */
11566 /*-----------------------------------------------------------------*/
11567 static void genInp( iCode *ic, int nparms, operand **parms)
11569 operand *from , *to , *count;
11574 /* we know it has to be 3 parameters */
11575 assert (nparms == 3);
11577 rsave = newBitVect(16);
11578 /* save DPTR if it needs to be saved */
11579 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11580 if (bitVectBitValue(ic->rMask,i))
11581 rsave = bitVectSetBit(rsave,i);
11583 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11584 ds390_rUmaskForOp (IC_RESULT(ic))));
11591 aopOp (from, ic->next, FALSE, FALSE);
11593 /* get from into DPTR1 */
11594 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11595 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11596 if (options.model == MODEL_FLAT24) {
11597 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11600 freeAsmop (from, NULL, ic, FALSE);
11601 aopOp (to, ic, FALSE, FALSE);
11602 /* get "to" into DPTR */
11603 /* if the operand is already in dptr
11604 then we do nothing else we move the value to dptr */
11605 if (AOP_TYPE (to) != AOP_STR) {
11606 /* if already in DPTR then we need to push */
11607 if (AOP_TYPE(to) == AOP_DPTR) {
11608 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11609 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11610 if (options.model == MODEL_FLAT24)
11611 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11612 emitcode ("pop", "dph");
11613 emitcode ("pop", "dpl");
11615 _startLazyDPSEvaluation ();
11616 /* if this is remateriazable */
11617 if (AOP_TYPE (to) == AOP_IMMD) {
11618 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11619 } else { /* we need to get it byte by byte */
11620 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11621 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11622 if (options.model == MODEL_FLAT24) {
11623 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11626 _endLazyDPSEvaluation ();
11629 freeAsmop (to, NULL, ic, FALSE);
11631 _G.dptrInUse = _G.dptr1InUse = 1;
11632 aopOp (count, ic->next->next, FALSE,FALSE);
11633 lbl =newiTempLabel(NULL);
11635 /* now for the actual copy */
11636 if (AOP_TYPE(count) == AOP_LIT &&
11637 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11638 emitcode (";","OH JOY auto increment with djnz (very fast)");
11639 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11640 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11641 freeAsmop (count, NULL, ic, FALSE);
11642 emitcode ("","!tlabeldef",lbl->key+100);
11643 emitcode ("movx", "a,@dptr"); /* read data from port */
11644 emitcode ("dec","dps"); /* switch to DPTR */
11645 emitcode ("movx", "@dptr,a"); /* save into location */
11646 emitcode ("inc", "dptr"); /* point to next area */
11647 emitcode ("inc","dps"); /* switch to DPTR2 */
11648 emitcode ("djnz","b,!tlabel",lbl->key+100);
11650 symbol *lbl1 = newiTempLabel(NULL);
11652 emitcode (";"," Auto increment but no djnz");
11653 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11654 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11655 freeAsmop (count, NULL, ic, FALSE);
11656 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11657 emitcode ("","!tlabeldef",lbl->key+100);
11658 emitcode ("movx", "a,@dptr");
11659 emitcode ("dec","dps"); /* switch to DPTR */
11660 emitcode ("movx", "@dptr,a");
11661 emitcode ("inc", "dptr");
11662 emitcode ("inc","dps"); /* switch to DPTR2 */
11663 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
11664 /* emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
11665 emitcode ("mov","a,b");
11666 emitcode ("orl","a,_ap");
11667 emitcode ("jz","!tlabel",lbl1->key+100);
11668 emitcode ("mov","a,_ap");
11669 emitcode ("add","a,#!constbyte",0xFF);
11670 emitcode ("mov","_ap,a");
11671 emitcode ("mov","a,b");
11672 emitcode ("addc","a,#!constbyte",0xFF);
11673 emitcode ("mov","b,a");
11674 emitcode ("sjmp","!tlabel",lbl->key+100);
11675 emitcode ("","!tlabeldef",lbl1->key+100);
11677 emitcode ("mov", "dps,#0");
11678 _G.dptrInUse = _G.dptr1InUse = 0;
11679 unsavermask(rsave);
11683 /*-----------------------------------------------------------------*/
11684 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
11685 /* port, first parameter output area second parameter pointer to */
11686 /* port third parameter count */
11687 /*-----------------------------------------------------------------*/
11688 static void genOutp( iCode *ic, int nparms, operand **parms)
11690 operand *from , *to , *count;
11695 /* we know it has to be 3 parameters */
11696 assert (nparms == 3);
11698 rsave = newBitVect(16);
11699 /* save DPTR if it needs to be saved */
11700 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11701 if (bitVectBitValue(ic->rMask,i))
11702 rsave = bitVectSetBit(rsave,i);
11704 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11705 ds390_rUmaskForOp (IC_RESULT(ic))));
11712 aopOp (from, ic->next, FALSE, FALSE);
11714 /* get from into DPTR1 */
11715 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11716 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11717 if (options.model == MODEL_FLAT24) {
11718 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11721 freeAsmop (from, NULL, ic, FALSE);
11722 aopOp (to, ic, FALSE, FALSE);
11723 /* get "to" into DPTR */
11724 /* if the operand is already in dptr
11725 then we do nothing else we move the value to dptr */
11726 if (AOP_TYPE (to) != AOP_STR) {
11727 /* if already in DPTR then we need to push */
11728 if (AOP_TYPE(to) == AOP_DPTR) {
11729 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11730 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11731 if (options.model == MODEL_FLAT24)
11732 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11733 emitcode ("pop", "dph");
11734 emitcode ("pop", "dpl");
11736 _startLazyDPSEvaluation ();
11737 /* if this is remateriazable */
11738 if (AOP_TYPE (to) == AOP_IMMD) {
11739 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11740 } else { /* we need to get it byte by byte */
11741 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11742 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11743 if (options.model == MODEL_FLAT24) {
11744 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11747 _endLazyDPSEvaluation ();
11750 freeAsmop (to, NULL, ic, FALSE);
11752 _G.dptrInUse = _G.dptr1InUse = 1;
11753 aopOp (count, ic->next->next, FALSE,FALSE);
11754 lbl =newiTempLabel(NULL);
11756 /* now for the actual copy */
11757 if (AOP_TYPE(count) == AOP_LIT &&
11758 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11759 emitcode (";","OH JOY auto increment with djnz (very fast)");
11760 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
11761 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11762 emitcode ("","!tlabeldef",lbl->key+100);
11763 emitcode ("movx", "a,@dptr"); /* read data from port */
11764 emitcode ("inc","dps"); /* switch to DPTR2 */
11765 emitcode ("movx", "@dptr,a"); /* save into location */
11766 emitcode ("inc", "dptr"); /* point to next area */
11767 emitcode ("dec","dps"); /* switch to DPTR */
11768 emitcode ("djnz","b,!tlabel",lbl->key+100);
11769 freeAsmop (count, NULL, ic, FALSE);
11771 symbol *lbl1 = newiTempLabel(NULL);
11773 emitcode (";"," Auto increment but no djnz");
11774 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11775 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11776 freeAsmop (count, NULL, ic, FALSE);
11777 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
11778 emitcode ("","!tlabeldef",lbl->key+100);
11779 emitcode ("movx", "a,@dptr");
11780 emitcode ("inc", "dptr");
11781 emitcode ("inc","dps"); /* switch to DPTR2 */
11782 emitcode ("movx", "@dptr,a");
11783 emitcode ("dec","dps"); /* switch to DPTR */
11784 emitcode ("mov","a,b");
11785 emitcode ("orl","a,_ap");
11786 emitcode ("jz","!tlabel",lbl1->key+100);
11787 emitcode ("mov","a,_ap");
11788 emitcode ("add","a,#!constbyte",0xFF);
11789 emitcode ("mov","_ap,a");
11790 emitcode ("mov","a,b");
11791 emitcode ("addc","a,#!constbyte",0xFF);
11792 emitcode ("mov","b,a");
11793 emitcode ("sjmp","!tlabel",lbl->key+100);
11794 emitcode ("","!tlabeldef",lbl1->key+100);
11796 emitcode ("mov", "dps,#0");
11797 _G.dptrInUse = _G.dptr1InUse = 0;
11798 unsavermask(rsave);
11802 /*-----------------------------------------------------------------*/
11803 /* genSwapW - swap lower & high order bytes */
11804 /*-----------------------------------------------------------------*/
11805 static void genSwapW(iCode *ic, int nparms, operand **parms)
11809 assert (nparms==1);
11812 dest=IC_RESULT(ic);
11814 assert(getSize(operandType(src))==2);
11816 aopOp (src, ic, FALSE, FALSE);
11817 emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
11819 MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
11821 freeAsmop (src, NULL, ic, FALSE);
11823 aopOp (dest,ic, FALSE, FALSE);
11824 aopPut(AOP(dest),"b",0);
11825 aopPut(AOP(dest),"a",1);
11826 freeAsmop (dest, NULL, ic, FALSE);
11829 /*-----------------------------------------------------------------*/
11830 /* genMemsetX - gencode for memSetX data */
11831 /*-----------------------------------------------------------------*/
11832 static void genMemsetX(iCode *ic, int nparms, operand **parms)
11834 operand *to , *val , *count;
11840 /* we know it has to be 3 parameters */
11841 assert (nparms == 3);
11847 /* save DPTR if it needs to be saved */
11848 rsave = newBitVect(16);
11849 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11850 if (bitVectBitValue(ic->rMask,i))
11851 rsave = bitVectSetBit(rsave,i);
11853 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11854 ds390_rUmaskForOp (IC_RESULT(ic))));
11857 aopOp (to, ic, FALSE, FALSE);
11858 /* get "to" into DPTR */
11859 /* if the operand is already in dptr
11860 then we do nothing else we move the value to dptr */
11861 if (AOP_TYPE (to) != AOP_STR) {
11862 /* if already in DPTR then we need to push */
11863 if (AOP_TYPE(to) == AOP_DPTR) {
11864 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11865 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11866 if (options.model == MODEL_FLAT24)
11867 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11868 emitcode ("pop", "dph");
11869 emitcode ("pop", "dpl");
11871 _startLazyDPSEvaluation ();
11872 /* if this is remateriazable */
11873 if (AOP_TYPE (to) == AOP_IMMD) {
11874 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11875 } else { /* we need to get it byte by byte */
11876 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11877 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11878 if (options.model == MODEL_FLAT24) {
11879 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11882 _endLazyDPSEvaluation ();
11885 freeAsmop (to, NULL, ic, FALSE);
11887 aopOp (val, ic->next->next, FALSE,FALSE);
11888 aopOp (count, ic->next->next, FALSE,FALSE);
11889 lbl =newiTempLabel(NULL);
11890 /* now for the actual copy */
11891 if (AOP_TYPE(count) == AOP_LIT &&
11892 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11893 l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
11894 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11896 emitcode ("","!tlabeldef",lbl->key+100);
11897 emitcode ("movx", "@dptr,a");
11898 emitcode ("inc", "dptr");
11899 emitcode ("djnz","b,!tlabel",lbl->key+100);
11901 symbol *lbl1 = newiTempLabel(NULL);
11903 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11904 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11905 emitcode ("","!tlabeldef",lbl->key+100);
11906 MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
11907 emitcode ("movx", "@dptr,a");
11908 emitcode ("inc", "dptr");
11909 emitcode ("mov","a,b");
11910 emitcode ("orl","a,_ap");
11911 emitcode ("jz","!tlabel",lbl1->key+100);
11912 emitcode ("mov","a,_ap");
11913 emitcode ("add","a,#!constbyte",0xFF);
11914 emitcode ("mov","_ap,a");
11915 emitcode ("mov","a,b");
11916 emitcode ("addc","a,#!constbyte",0xFF);
11917 emitcode ("mov","b,a");
11918 emitcode ("sjmp","!tlabel",lbl->key+100);
11919 emitcode ("","!tlabeldef",lbl1->key+100);
11921 freeAsmop (count, NULL, ic, FALSE);
11922 unsavermask(rsave);
11925 /*-----------------------------------------------------------------*/
11926 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
11927 /*-----------------------------------------------------------------*/
11928 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
11931 operand *pnum, *result;
11934 assert (nparms==1);
11935 /* save registers that need to be saved */
11936 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11937 ds390_rUmaskForOp (IC_RESULT(ic))));
11940 aopOp (pnum, ic, FALSE, FALSE);
11941 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
11942 freeAsmop (pnum, NULL, ic, FALSE);
11943 emitcode ("lcall","NatLib_LoadPrimitive");
11944 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11945 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
11946 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
11947 for (i = (size-1) ; i >= 0 ; i-- ) {
11948 emitcode ("push","a%s",javaRet[i]);
11950 for (i=0; i < size ; i++ ) {
11951 emitcode ("pop","a%s",
11952 aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
11955 for (i = 0 ; i < size ; i++ ) {
11956 aopPut(AOP(result),javaRet[i],i);
11959 freeAsmop (result, NULL, ic, FALSE);
11960 unsavermask(rsave);
11963 /*-----------------------------------------------------------------*/
11964 /* genNatLibLoadPointer - calls TINI api function to load pointer */
11965 /*-----------------------------------------------------------------*/
11966 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
11969 operand *pnum, *result;
11973 assert (nparms==1);
11974 /* save registers that need to be saved */
11975 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11976 ds390_rUmaskForOp (IC_RESULT(ic))));
11979 aopOp (pnum, ic, FALSE, FALSE);
11980 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
11981 freeAsmop (pnum, NULL, ic, FALSE);
11982 emitcode ("lcall","NatLib_LoadPointer");
11983 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11984 if (AOP_TYPE(result)!=AOP_STR) {
11985 for (i = 0 ; i < size ; i++ ) {
11986 aopPut(AOP(result),fReturn[i],i);
11989 freeAsmop (result, NULL, ic, FALSE);
11990 unsavermask(rsave);
11993 /*-----------------------------------------------------------------*/
11994 /* genNatLibInstallStateBlock - */
11995 /*-----------------------------------------------------------------*/
11996 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
11997 operand **parms, const char *name)
12000 operand *psb, *handle;
12001 assert (nparms==2);
12003 /* save registers that need to be saved */
12004 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12005 ds390_rUmaskForOp (IC_RESULT(ic))));
12009 /* put pointer to state block into DPTR1 */
12010 aopOp (psb, ic, FALSE, FALSE);
12011 if (AOP_TYPE (psb) == AOP_IMMD) {
12012 emitcode ("mov","dps,#1");
12013 emitcode ("mov", "dptr,%s",
12014 aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12015 emitcode ("mov","dps,#0");
12017 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12018 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12019 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12021 freeAsmop (psb, NULL, ic, FALSE);
12023 /* put libraryID into DPTR */
12024 emitcode ("mov","dptr,#LibraryID");
12026 /* put handle into r3:r2 */
12027 aopOp (handle, ic, FALSE, FALSE);
12028 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12029 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12030 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12031 emitcode ("pop","ar3");
12032 emitcode ("pop","ar2");
12034 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12035 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12037 freeAsmop (psb, NULL, ic, FALSE);
12039 /* make the call */
12040 emitcode ("lcall","NatLib_Install%sStateBlock",name);
12042 /* put return value into place*/
12044 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12046 aopPut(AOP(IC_RESULT(ic)),"a",0);
12047 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12048 unsavermask(rsave);
12051 /*-----------------------------------------------------------------*/
12052 /* genNatLibRemoveStateBlock - */
12053 /*-----------------------------------------------------------------*/
12054 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12060 /* save registers that need to be saved */
12061 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12062 ds390_rUmaskForOp (IC_RESULT(ic))));
12064 /* put libraryID into DPTR */
12065 emitcode ("mov","dptr,#LibraryID");
12066 /* make the call */
12067 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12068 unsavermask(rsave);
12071 /*-----------------------------------------------------------------*/
12072 /* genNatLibGetStateBlock - */
12073 /*-----------------------------------------------------------------*/
12074 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12075 operand **parms,const char *name)
12078 symbol *lbl = newiTempLabel(NULL);
12081 /* save registers that need to be saved */
12082 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12083 ds390_rUmaskForOp (IC_RESULT(ic))));
12085 /* put libraryID into DPTR */
12086 emitcode ("mov","dptr,#LibraryID");
12087 /* make the call */
12088 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12089 emitcode ("jnz","!tlabel",lbl->key+100);
12091 /* put return value into place */
12092 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12093 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12094 emitcode ("push","ar3");
12095 emitcode ("push","ar2");
12096 emitcode ("pop","%s",
12097 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12098 emitcode ("pop","%s",
12099 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12101 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12102 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12104 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12105 emitcode ("","!tlabeldef",lbl->key+100);
12106 unsavermask(rsave);
12109 /*-----------------------------------------------------------------*/
12110 /* genMMMalloc - */
12111 /*-----------------------------------------------------------------*/
12112 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12113 int size, const char *name)
12118 symbol *lbl = newiTempLabel(NULL);
12120 assert (nparms == 1);
12121 /* save registers that need to be saved */
12122 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12123 ds390_rUmaskForOp (IC_RESULT(ic))));
12126 aopOp (bsize,ic,FALSE,FALSE);
12128 /* put the size in R4-R2 */
12129 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12130 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12131 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12133 emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12134 emitcode("pop","ar4");
12136 emitcode("pop","ar3");
12137 emitcode("pop","ar2");
12139 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12140 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12142 emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12145 freeAsmop (bsize, NULL, ic, FALSE);
12147 /* make the call */
12148 emitcode ("lcall","MM_%s",name);
12149 emitcode ("jz","!tlabel",lbl->key+100);
12150 emitcode ("mov","r2,#!constbyte",0xff);
12151 emitcode ("mov","r3,#!constbyte",0xff);
12152 emitcode ("","!tlabeldef",lbl->key+100);
12153 /* we don't care about the pointer : we just save the handle */
12154 rsym = OP_SYMBOL(IC_RESULT(ic));
12155 if (rsym->liveFrom != rsym->liveTo) {
12156 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12157 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12158 emitcode ("push","ar3");
12159 emitcode ("push","ar2");
12160 emitcode ("pop","%s",
12161 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12162 emitcode ("pop","%s",
12163 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12165 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12166 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12168 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12170 unsavermask(rsave);
12173 /*-----------------------------------------------------------------*/
12175 /*-----------------------------------------------------------------*/
12176 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12181 assert (nparms == 1);
12182 /* save registers that need to be saved */
12183 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12184 ds390_rUmaskForOp (IC_RESULT(ic))));
12187 aopOp (handle,ic,FALSE,FALSE);
12189 /* put the size in R4-R2 */
12190 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12191 emitcode("push","%s",
12192 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12193 emitcode("push","%s",
12194 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12195 emitcode("pop","ar3");
12196 emitcode("pop","ar2");
12198 emitcode ("mov","r2,%s",
12199 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12200 emitcode ("mov","r3,%s",
12201 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12203 freeAsmop (handle, NULL, ic, FALSE);
12205 /* make the call */
12206 emitcode ("lcall","MM_Deref");
12209 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12210 if (rsym->liveFrom != rsym->liveTo) {
12211 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12212 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12213 _startLazyDPSEvaluation ();
12215 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12216 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12217 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12219 _endLazyDPSEvaluation ();
12224 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12225 unsavermask(rsave);
12228 /*-----------------------------------------------------------------*/
12229 /* genMMUnrestrictedPersist - */
12230 /*-----------------------------------------------------------------*/
12231 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12236 assert (nparms == 1);
12237 /* save registers that need to be saved */
12238 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12239 ds390_rUmaskForOp (IC_RESULT(ic))));
12242 aopOp (handle,ic,FALSE,FALSE);
12244 /* put the size in R3-R2 */
12245 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12246 emitcode("push","%s",
12247 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12248 emitcode("push","%s",
12249 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12250 emitcode("pop","ar3");
12251 emitcode("pop","ar2");
12253 emitcode ("mov","r2,%s",
12254 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12255 emitcode ("mov","r3,%s",
12256 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12258 freeAsmop (handle, NULL, ic, FALSE);
12260 /* make the call */
12261 emitcode ("lcall","MM_UnrestrictedPersist");
12264 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12265 if (rsym->liveFrom != rsym->liveTo) {
12266 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12267 aopPut(AOP(IC_RESULT(ic)),"a",0);
12268 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12271 unsavermask(rsave);
12274 /*-----------------------------------------------------------------*/
12275 /* genSystemExecJavaProcess - */
12276 /*-----------------------------------------------------------------*/
12277 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12280 operand *handle, *pp;
12282 assert (nparms==2);
12283 /* save registers that need to be saved */
12284 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12285 ds390_rUmaskForOp (IC_RESULT(ic))));
12290 /* put the handle in R3-R2 */
12291 aopOp (handle,ic,FALSE,FALSE);
12292 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12293 emitcode("push","%s",
12294 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12295 emitcode("push","%s",
12296 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12297 emitcode("pop","ar3");
12298 emitcode("pop","ar2");
12300 emitcode ("mov","r2,%s",
12301 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12302 emitcode ("mov","r3,%s",
12303 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12305 freeAsmop (handle, NULL, ic, FALSE);
12307 /* put pointer in DPTR */
12308 aopOp (pp,ic,FALSE,FALSE);
12309 if (AOP_TYPE(pp) == AOP_IMMD) {
12310 emitcode ("mov", "dptr,%s",
12311 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12312 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12313 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12314 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12315 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12317 freeAsmop (handle, NULL, ic, FALSE);
12319 /* make the call */
12320 emitcode ("lcall","System_ExecJavaProcess");
12322 /* put result in place */
12324 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12325 if (rsym->liveFrom != rsym->liveTo) {
12326 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12327 aopPut(AOP(IC_RESULT(ic)),"a",0);
12328 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12332 unsavermask(rsave);
12335 /*-----------------------------------------------------------------*/
12336 /* genSystemRTCRegisters - */
12337 /*-----------------------------------------------------------------*/
12338 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12344 assert (nparms==1);
12345 /* save registers that need to be saved */
12346 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12347 ds390_rUmaskForOp (IC_RESULT(ic))));
12350 /* put pointer in DPTR */
12351 aopOp (pp,ic,FALSE,FALSE);
12352 if (AOP_TYPE (pp) == AOP_IMMD) {
12353 emitcode ("mov","dps,#1");
12354 emitcode ("mov", "dptr,%s",
12355 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12356 emitcode ("mov","dps,#0");
12358 emitcode ("mov","dpl1,%s",
12359 aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12360 emitcode ("mov","dph1,%s",
12361 aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12362 emitcode ("mov","dpx1,%s",
12363 aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12365 freeAsmop (pp, NULL, ic, FALSE);
12367 /* make the call */
12368 emitcode ("lcall","System_%sRTCRegisters",name);
12370 unsavermask(rsave);
12373 /*-----------------------------------------------------------------*/
12374 /* genSystemThreadSleep - */
12375 /*-----------------------------------------------------------------*/
12376 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12381 assert (nparms==1);
12382 /* save registers that need to be saved */
12383 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12384 ds390_rUmaskForOp (IC_RESULT(ic))));
12387 aopOp(to,ic,FALSE,FALSE);
12388 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12389 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12390 emitcode ("push","%s",
12391 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12392 emitcode ("push","%s",
12393 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12394 emitcode ("push","%s",
12395 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12396 emitcode ("push","%s",
12397 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12398 emitcode ("pop","ar3");
12399 emitcode ("pop","ar2");
12400 emitcode ("pop","ar1");
12401 emitcode ("pop","ar0");
12403 emitcode ("mov","r0,%s",
12404 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12405 emitcode ("mov","r1,%s",
12406 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12407 emitcode ("mov","r2,%s",
12408 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12409 emitcode ("mov","r3,%s",
12410 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12412 freeAsmop (to, NULL, ic, FALSE);
12414 /* suspend in acc */
12416 aopOp(s,ic,FALSE,FALSE);
12417 emitcode ("mov","a,%s",
12418 aopGet(AOP(s),0,FALSE,TRUE,NULL));
12419 freeAsmop (s, NULL, ic, FALSE);
12421 /* make the call */
12422 emitcode ("lcall","System_%s",name);
12424 unsavermask(rsave);
12427 /*-----------------------------------------------------------------*/
12428 /* genSystemThreadResume - */
12429 /*-----------------------------------------------------------------*/
12430 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12435 assert (nparms==2);
12436 /* save registers that need to be saved */
12437 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12438 ds390_rUmaskForOp (IC_RESULT(ic))));
12444 aopOp(pid,ic,FALSE,FALSE);
12445 emitcode ("mov","r0,%s",
12446 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12447 freeAsmop (pid, NULL, ic, FALSE);
12450 aopOp(tid,ic,FALSE,FALSE);
12451 emitcode ("mov","a,%s",
12452 aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
12453 freeAsmop (tid, NULL, ic, FALSE);
12455 emitcode ("lcall","System_ThreadResume");
12457 /* put result into place */
12459 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12460 if (rsym->liveFrom != rsym->liveTo) {
12461 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12462 aopPut(AOP(IC_RESULT(ic)),"a",0);
12463 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12466 unsavermask(rsave);
12469 /*-----------------------------------------------------------------*/
12470 /* genSystemProcessResume - */
12471 /*-----------------------------------------------------------------*/
12472 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
12477 assert (nparms==1);
12478 /* save registers that need to be saved */
12479 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12480 ds390_rUmaskForOp (IC_RESULT(ic))));
12485 aopOp(pid,ic,FALSE,FALSE);
12486 emitcode ("mov","a,%s",
12487 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12488 freeAsmop (pid, NULL, ic, FALSE);
12490 emitcode ("lcall","System_ProcessResume");
12492 unsavermask(rsave);
12495 /*-----------------------------------------------------------------*/
12497 /*-----------------------------------------------------------------*/
12498 static void genSystem (iCode *ic,int nparms,char *name)
12500 assert(nparms == 0);
12502 emitcode ("lcall","System_%s",name);
12505 /*-----------------------------------------------------------------*/
12506 /* genSystemPoll - */
12507 /*-----------------------------------------------------------------*/
12508 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
12513 assert (nparms==1);
12514 /* save registers that need to be saved */
12515 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12516 ds390_rUmaskForOp (IC_RESULT(ic))));
12519 aopOp (fp,ic,FALSE,FALSE);
12520 if (AOP_TYPE (fp) == AOP_IMMD) {
12521 emitcode ("mov", "dptr,%s",
12522 aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
12523 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
12524 emitcode ("mov","dpl,%s",
12525 aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
12526 emitcode ("mov","dph,%s",
12527 aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
12528 emitcode ("mov","dpx,%s",
12529 aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
12531 freeAsmop (fp, NULL, ic, FALSE);
12533 emitcode ("lcall","System_%sPoll",name);
12535 /* put result into place */
12537 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12538 if (rsym->liveFrom != rsym->liveTo) {
12539 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12540 aopPut(AOP(IC_RESULT(ic)),"a",0);
12541 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12544 unsavermask(rsave);
12547 /*-----------------------------------------------------------------*/
12548 /* genSystemGetCurrentID - */
12549 /*-----------------------------------------------------------------*/
12550 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
12552 assert (nparms==0);
12554 emitcode ("lcall","System_GetCurrent%sId",name);
12555 /* put result into place */
12557 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12558 if (rsym->liveFrom != rsym->liveTo) {
12559 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12560 aopPut(AOP(IC_RESULT(ic)),"a",0);
12561 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12566 /*-----------------------------------------------------------------*/
12567 /* genBuiltIn - calls the appropriate function to generating code */
12568 /* for a built in function */
12569 /*-----------------------------------------------------------------*/
12570 static void genBuiltIn (iCode *ic)
12572 operand *bi_parms[MAX_BUILTIN_ARGS];
12577 /* get all the arguments for a built in function */
12578 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
12580 /* which function is it */
12581 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
12582 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
12583 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
12584 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
12585 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
12586 } else if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
12587 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
12588 } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
12589 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
12590 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
12591 genMemsetX(bi_iCode,nbi_parms,bi_parms);
12592 } else if (strcmp(bif->name,"__builtin_inp")==0) {
12593 genInp(bi_iCode,nbi_parms,bi_parms);
12594 } else if (strcmp(bif->name,"__builtin_outp")==0) {
12595 genOutp(bi_iCode,nbi_parms,bi_parms);
12596 } else if (strcmp(bif->name,"__builtin_swapw")==0) {
12597 genSwapW(bi_iCode,nbi_parms,bi_parms);
12598 /* JavaNative builtIns */
12599 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
12600 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
12601 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
12602 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
12603 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
12604 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
12605 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
12606 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
12607 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
12608 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12609 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
12610 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12611 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
12612 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
12613 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
12614 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
12615 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
12616 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12617 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
12618 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12619 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
12620 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
12621 } else if (strcmp(bif->name,"MM_Malloc")==0) {
12622 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
12623 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
12624 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
12625 } else if (strcmp(bif->name,"MM_Free")==0) {
12626 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
12627 } else if (strcmp(bif->name,"MM_Deref")==0) {
12628 genMMDeref(bi_iCode,nbi_parms,bi_parms);
12629 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
12630 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
12631 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
12632 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
12633 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
12634 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
12635 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
12636 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
12637 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
12638 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
12639 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
12640 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
12641 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
12642 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
12643 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
12644 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
12645 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12646 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12647 } else if (strcmp(bif->name,"System_SaveThread")==0) {
12648 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12649 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12650 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12651 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
12652 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
12653 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
12654 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
12655 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
12656 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
12657 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
12658 genSystem(bi_iCode,nbi_parms,"ProcessYield");
12659 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
12660 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
12661 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
12662 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
12663 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
12664 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
12665 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
12666 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
12667 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
12668 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
12670 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
12676 /*-----------------------------------------------------------------*/
12677 /* gen390Code - generate code for Dallas 390 based controllers */
12678 /*-----------------------------------------------------------------*/
12680 gen390Code (iCode * lic)
12685 lineHead = lineCurr = NULL;
12686 dptrn[1][0] = "dpl1";
12687 dptrn[1][1] = "dph1";
12688 dptrn[1][2] = "dpx1";
12690 if (options.model == MODEL_FLAT24) {
12691 fReturnSizeDS390 = 5;
12692 fReturn = fReturn24;
12694 fReturnSizeDS390 = 4;
12695 fReturn = fReturn16;
12696 options.stack10bit=0;
12699 /* print the allocation information */
12701 printAllocInfo (currFunc, codeOutFile);
12703 /* if debug information required */
12704 if (options.debug && currFunc)
12706 debugFile->writeFunction(currFunc);
12708 if (IS_STATIC (currFunc->etype))
12709 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
12711 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
12714 /* stack pointer name */
12715 if (options.useXstack)
12721 for (ic = lic; ic; ic = ic->next)
12724 if (ic->lineno && cln != ic->lineno)
12729 emitcode ("", "C$%s$%d$%d$%d ==.",
12730 FileBaseName (ic->filename), ic->lineno,
12731 ic->level, ic->block);
12734 if (!options.noCcodeInAsm) {
12735 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
12736 printCLine(ic->filename, ic->lineno));
12740 if (options.iCodeInAsm) {
12741 emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
12743 /* if the result is marked as
12744 spilt and rematerializable or code for
12745 this has already been generated then
12747 if (resultRemat (ic) || ic->generated)
12750 /* depending on the operation */
12770 /* IPOP happens only when trying to restore a
12771 spilt live range, if there is an ifx statement
12772 following this pop then the if statement might
12773 be using some of the registers being popped which
12774 would destory the contents of the register so
12775 we need to check for this condition and handle it */
12777 ic->next->op == IFX &&
12778 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
12779 genIfx (ic->next, ic);
12797 genEndFunction (ic);
12817 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
12834 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
12838 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
12845 /* note these two are xlated by algebraic equivalence
12846 during parsing SDCC.y */
12847 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12848 "got '>=' or '<=' shouldn't have come here");
12852 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
12864 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
12868 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
12872 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
12896 genRightShift (ic);
12899 case GET_VALUE_AT_ADDRESS:
12900 genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
12904 if (POINTER_SET (ic))
12905 genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
12931 if (ic->builtinSEND) genBuiltIn(ic);
12932 else addSet (&_G.sendSet, ic);
12945 /* now we are ready to call the
12946 peep hole optimizer */
12947 if (!options.nopeep)
12948 peepHole (&lineHead);
12950 /* now do the actual printing */
12951 printLine (lineHead, codeOutFile);