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 || IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic)))) return ;
2039 /* special case if DPTR alive across a function call then must save it
2040 even though callee saves */
2041 if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2043 rsave = newBitVect(ic->rMask->size);
2044 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2045 if (bitVectBitValue(ic->rMask,i))
2046 rsave = bitVectSetBit(rsave,i);
2048 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2050 /* safe the registers in use at this time but skip the
2051 ones for the result */
2052 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2053 ds390_rUmaskForOp (IC_RESULT(ic)));
2059 /*-----------------------------------------------------------------*/
2060 /* usavermask - restore registers with mask */
2061 /*-----------------------------------------------------------------*/
2062 static void unsavermask(bitVect *rs_mask)
2065 if (options.useXstack) {
2066 emitcode ("mov", "r0,%s", spname);
2067 for (i = ds390_nRegs; i >= 0; i--) {
2068 if (bitVectBitValue (rs_mask, i)) {
2069 emitcode ("dec", "r0");
2070 emitcode ("movx", "a,@r0");
2072 emitcode ("mov", "b,a");
2074 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
2077 emitcode ("mov", "%s,r0", spname);
2078 if (bitVectBitValue (rs_mask, R0_IDX))
2079 emitcode ("mov", "r0,b");
2081 for (i = ds390_nRegs; i >= 0; i--) {
2082 if (bitVectBitValue (rs_mask, i))
2083 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2088 /*-----------------------------------------------------------------*/
2089 /* unsaveRegisters - pop the pushed registers */
2090 /*-----------------------------------------------------------------*/
2092 unsaveRegisters (iCode * ic)
2096 if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2098 rsave = newBitVect(ic->rMask->size);
2099 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2100 if (bitVectBitValue(ic->rMask,i))
2101 rsave = bitVectSetBit(rsave,i);
2103 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2105 /* restore the registers in use at this time but skip the
2106 ones for the result */
2107 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2108 ds390_rUmaskForOp (IC_RESULT(ic)));
2114 /*-----------------------------------------------------------------*/
2116 /*-----------------------------------------------------------------*/
2118 pushSide (operand * oper, int size)
2121 _startLazyDPSEvaluation ();
2124 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, NULL);
2125 if (AOP_TYPE (oper) != AOP_REG &&
2126 AOP_TYPE (oper) != AOP_DIR &&
2129 emitcode ("mov", "a,%s", l);
2130 emitcode ("push", "acc");
2133 emitcode ("push", "%s", l);
2135 _endLazyDPSEvaluation ();
2138 /*-----------------------------------------------------------------*/
2139 /* assignResultValue - */
2140 /*-----------------------------------------------------------------*/
2142 assignResultValue (operand * oper)
2145 int size = AOP_SIZE (oper);
2146 bool pushedAcc = FALSE;
2148 if (size == fReturnSizeDS390)
2150 /* I don't think this case can ever happen... */
2151 /* ACC is the last part of this. If writing the result
2152 * uses AC, we must preserve it.
2154 if (AOP_NEEDSACC(oper))
2156 emitcode(";", "assignResultValue special case for ACC.");
2157 emitcode("push", "acc");
2164 _startLazyDPSEvaluation ();
2167 aopPut (AOP (oper), fReturn[offset], offset);
2170 _endLazyDPSEvaluation ();
2174 emitcode("pop", "acc");
2175 aopPut(AOP(oper), "a", offset);
2180 /*-----------------------------------------------------------------*/
2181 /* genXpush - pushes onto the external stack */
2182 /*-----------------------------------------------------------------*/
2184 genXpush (iCode * ic)
2186 asmop *aop = newAsmop (0);
2188 int size, offset = 0;
2190 D (emitcode (";", "genXpush ");
2193 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2194 r = getFreePtr (ic, &aop, FALSE);
2197 emitcode ("mov", "%s,_spx", r->name);
2199 size = AOP_SIZE (IC_LEFT (ic));
2200 _startLazyDPSEvaluation ();
2204 MOVA (aopGet (AOP (IC_LEFT (ic)),
2205 offset++, FALSE, FALSE, NULL));
2206 emitcode ("movx", "@%s,a", r->name);
2207 emitcode ("inc", "%s", r->name);
2210 _endLazyDPSEvaluation ();
2213 emitcode ("mov", "_spx,%s", r->name);
2215 freeAsmop (NULL, aop, ic, TRUE);
2216 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2219 /*-----------------------------------------------------------------*/
2220 /* genIpush - generate code for pushing this gets a little complex */
2221 /*-----------------------------------------------------------------*/
2223 genIpush (iCode * ic)
2225 int size, offset = 0;
2228 D (emitcode (";", "genIpush ");
2231 /* if this is not a parm push : ie. it is spill push
2232 and spill push is always done on the local stack */
2236 /* and the item is spilt then do nothing */
2237 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2240 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2241 size = AOP_SIZE (IC_LEFT (ic));
2242 /* push it on the stack */
2243 _startLazyDPSEvaluation ();
2246 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2252 emitcode ("push", "%s", l);
2254 _endLazyDPSEvaluation ();
2258 /* this is a paramter push: in this case we call
2259 the routine to find the call and save those
2260 registers that need to be saved */
2263 /* if use external stack then call the external
2264 stack pushing routine */
2265 if (options.useXstack)
2271 /* then do the push */
2272 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2274 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2275 size = AOP_SIZE (IC_LEFT (ic));
2277 _startLazyDPSEvaluation ();
2280 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2281 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2282 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2285 emitcode ("mov", "a,%s", l);
2286 emitcode ("push", "acc");
2290 emitcode ("push", "%s", l);
2293 _endLazyDPSEvaluation ();
2295 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2298 /*-----------------------------------------------------------------*/
2299 /* genIpop - recover the registers: can happen only for spilling */
2300 /*-----------------------------------------------------------------*/
2302 genIpop (iCode * ic)
2306 D (emitcode (";", "genIpop ");
2310 /* if the temp was not pushed then */
2311 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2314 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2315 size = AOP_SIZE (IC_LEFT (ic));
2316 offset = (size - 1);
2317 _startLazyDPSEvaluation ();
2320 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2321 FALSE, TRUE, NULL));
2323 _endLazyDPSEvaluation ();
2325 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2328 /*-----------------------------------------------------------------*/
2329 /* unsaveRBank - restores the resgister bank from stack */
2330 /*-----------------------------------------------------------------*/
2332 unsaveRBank (int bank, iCode * ic, bool popPsw)
2338 if (options.useXstack)
2342 /* Assume r0 is available for use. */
2343 r = ds390_regWithIdx (R0_IDX);;
2348 r = getFreePtr (ic, &aop, FALSE);
2350 emitcode ("mov", "%s,_spx", r->name);
2355 if (options.useXstack)
2357 emitcode ("movx", "a,@%s", r->name);
2358 emitcode ("mov", "psw,a");
2359 emitcode ("dec", "%s", r->name);
2363 emitcode ("pop", "psw");
2367 for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2369 if (options.useXstack)
2371 emitcode ("movx", "a,@%s", r->name);
2372 emitcode ("mov", "(%s+%d),a",
2373 regs390[i].base, 8 * bank + regs390[i].offset);
2374 emitcode ("dec", "%s", r->name);
2378 emitcode ("pop", "(%s+%d)",
2379 regs390[i].base, 8 * bank + regs390[i].offset);
2382 if (options.useXstack)
2384 emitcode ("mov", "_spx,%s", r->name);
2389 freeAsmop (NULL, aop, ic, TRUE);
2393 /*-----------------------------------------------------------------*/
2394 /* saveRBank - saves an entire register bank on the stack */
2395 /*-----------------------------------------------------------------*/
2397 saveRBank (int bank, iCode * ic, bool pushPsw)
2403 if (options.useXstack)
2407 /* Assume r0 is available for use. */
2408 r = ds390_regWithIdx (R0_IDX);;
2413 r = getFreePtr (ic, &aop, FALSE);
2415 emitcode ("mov", "%s,_spx", r->name);
2418 for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2420 if (options.useXstack)
2422 emitcode ("inc", "%s", r->name);
2423 emitcode ("mov", "a,(%s+%d)",
2424 regs390[i].base, 8 * bank + regs390[i].offset);
2425 emitcode ("movx", "@%s,a", r->name);
2428 emitcode ("push", "(%s+%d)",
2429 regs390[i].base, 8 * bank + regs390[i].offset);
2434 if (options.useXstack)
2436 emitcode ("mov", "a,psw");
2437 emitcode ("movx", "@%s,a", r->name);
2438 emitcode ("inc", "%s", r->name);
2439 emitcode ("mov", "_spx,%s", r->name);
2443 emitcode ("push", "psw");
2446 emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2451 freeAsmop (NULL, aop, ic, TRUE);
2460 /*-----------------------------------------------------------------*/
2461 /* genSend - gen code for SEND */
2462 /*-----------------------------------------------------------------*/
2463 static void genSend(set *sendSet)
2467 static int rb1_count = 0;
2469 for (sic = setFirstItem (sendSet); sic;
2470 sic = setNextItem (sendSet)) {
2471 int size, offset = 0;
2473 size=getSize(operandType(IC_LEFT(sic)));
2474 D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2475 if (sendCount == 0) { /* first parameter */
2476 // we know that dpl(hxb) is the result, so
2478 _startLazyDPSEvaluation ();
2480 aopOp (IC_LEFT (sic), sic, FALSE,
2481 (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2483 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2486 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2487 FALSE, FALSE, NULL);
2488 if (strcmp (l, fReturn[offset])) {
2489 emitcode ("mov", "%s,%s",
2495 _endLazyDPSEvaluation ();
2496 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2498 } else { /* if more parameter in registers */
2499 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2501 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
2502 FALSE, FALSE, NULL));
2504 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2510 /*-----------------------------------------------------------------*/
2511 /* genCall - generates a call statement */
2512 /*-----------------------------------------------------------------*/
2514 genCall (iCode * ic)
2517 bool restoreBank = FALSE;
2518 bool swapBanks = FALSE;
2520 D (emitcode (";", "genCall "););
2522 /* if we are calling a not _naked function that is not using
2523 the same register bank then we need to save the
2524 destination registers on the stack */
2525 dtype = operandType (IC_LEFT (ic));
2526 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2527 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2528 IFFUNC_ISISR (currFunc->type))
2532 /* This is unexpected; the bank should have been saved in
2535 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2541 /* if caller saves & we have not saved then */
2545 /* if send set is not empty the assign */
2546 /* We've saved all the registers we care about;
2547 * therefore, we may clobber any register not used
2548 * in the calling convention (i.e. anything not in
2553 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2554 genSend(reverseSet(_G.sendSet));
2556 genSend(_G.sendSet);
2563 emitcode ("mov", "psw,#!constbyte",
2564 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2568 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2569 OP_SYMBOL (IC_LEFT (ic))->rname :
2570 OP_SYMBOL (IC_LEFT (ic))->name));
2574 emitcode ("mov", "psw,#!constbyte",
2575 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2578 /* if we need assign a result value */
2579 if ((IS_ITEMP (IC_RESULT (ic)) &&
2580 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2581 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2582 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2583 IS_TRUE_SYMOP (IC_RESULT (ic)))
2585 if (isOperandInFarSpace (IC_RESULT (ic))
2586 && getSize (operandType (IC_RESULT (ic))) <= 2)
2588 int size = getSize (operandType (IC_RESULT (ic)));
2590 /* Special case for 1 or 2 byte return in far space. */
2594 emitcode ("mov", "b,%s", fReturn[1]);
2597 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2598 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2602 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2604 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2609 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2612 assignResultValue (IC_RESULT (ic));
2614 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2618 /* adjust the stack for parameters if
2620 if (ic->parmBytes) {
2622 if (options.stack10bit) {
2623 if (ic->parmBytes <= 10) {
2624 emitcode(";","stack adjustment for parms");
2625 for (i=0; i < ic->parmBytes ; i++) {
2626 emitcode("pop","acc");
2630 emitcode ("clr","c");
2631 emitcode ("mov","a,sp");
2632 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2633 emitcode ("mov","sp,a");
2634 emitcode ("mov","a,esp");
2635 emitcode ("anl","a,#3");
2636 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2637 emitcode ("mov","esp,a");
2641 if (ic->parmBytes > 3) {
2642 emitcode ("mov", "a,%s", spname);
2643 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2644 emitcode ("mov", "%s,a", spname);
2646 for (i = 0; i < ic->parmBytes; i++)
2647 emitcode ("dec", "%s", spname);
2651 /* if we hade saved some registers then unsave them */
2653 unsaveRegisters (ic);
2655 /* if register bank was saved then pop them */
2657 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2660 /*-----------------------------------------------------------------*/
2661 /* genPcall - generates a call by pointer statement */
2662 /*-----------------------------------------------------------------*/
2664 genPcall (iCode * ic)
2667 symbol *rlbl = newiTempLabel (NULL);
2668 bool restoreBank=FALSE;
2670 D (emitcode (";", "genPcall ");
2674 /* if caller saves & we have not saved then */
2678 /* if we are calling a function that is not using
2679 the same register bank then we need to save the
2680 destination registers on the stack */
2681 dtype = operandType (IC_LEFT (ic));
2682 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2683 IFFUNC_ISISR (currFunc->type) &&
2684 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2685 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2689 /* push the return address on to the stack */
2690 emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2691 emitcode ("push", "acc");
2692 emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2693 emitcode ("push", "acc");
2695 if (options.model == MODEL_FLAT24)
2697 emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2698 emitcode ("push", "acc");
2701 /* now push the calling address */
2702 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2704 pushSide (IC_LEFT (ic), FPTRSIZE);
2706 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2708 /* if send set is not empty the assign */
2711 genSend(reverseSet(_G.sendSet));
2715 emitcode ("ret", "");
2716 emitcode ("", "!tlabeldef", (rlbl->key + 100));
2719 /* if we need assign a result value */
2720 if ((IS_ITEMP (IC_RESULT (ic)) &&
2721 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2722 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2723 IS_TRUE_SYMOP (IC_RESULT (ic)))
2727 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2730 assignResultValue (IC_RESULT (ic));
2732 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2735 /* adjust the stack for parameters if
2740 if (options.stack10bit) {
2741 if (ic->parmBytes <= 10) {
2742 emitcode(";","stack adjustment for parms");
2743 for (i=0; i < ic->parmBytes ; i++) {
2744 emitcode("pop","acc");
2748 emitcode ("clr","c");
2749 emitcode ("mov","a,sp");
2750 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2751 emitcode ("mov","sp,a");
2752 emitcode ("mov","a,esp");
2753 emitcode ("anl","a,#3");
2754 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2755 emitcode ("mov","esp,a");
2759 if (ic->parmBytes > 3) {
2760 emitcode ("mov", "a,%s", spname);
2761 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2762 emitcode ("mov", "%s,a", spname);
2765 for (i = 0; i < ic->parmBytes; i++)
2766 emitcode ("dec", "%s", spname);
2770 /* if register bank was saved then unsave them */
2772 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2774 /* if we hade saved some registers then
2777 unsaveRegisters (ic);
2781 /*-----------------------------------------------------------------*/
2782 /* resultRemat - result is rematerializable */
2783 /*-----------------------------------------------------------------*/
2785 resultRemat (iCode * ic)
2787 if (SKIP_IC (ic) || ic->op == IFX)
2790 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2792 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2793 if (sym->remat && !POINTER_SET (ic))
2800 #if defined(__BORLANDC__) || defined(_MSC_VER)
2801 #define STRCASECMP stricmp
2803 #define STRCASECMP strcasecmp
2806 /*-----------------------------------------------------------------*/
2807 /* inExcludeList - return 1 if the string is in exclude Reg list */
2808 /*-----------------------------------------------------------------*/
2810 inExcludeList (char *s)
2814 if (options.excludeRegs[i] &&
2815 STRCASECMP (options.excludeRegs[i], "none") == 0)
2818 for (i = 0; options.excludeRegs[i]; i++)
2820 if (options.excludeRegs[i] &&
2821 STRCASECMP (s, options.excludeRegs[i]) == 0)
2827 /*-----------------------------------------------------------------*/
2828 /* genFunction - generated code for function entry */
2829 /*-----------------------------------------------------------------*/
2831 genFunction (iCode * ic)
2835 bool switchedPSW = FALSE;
2837 D (emitcode (";", "genFunction "););
2840 /* create the function header */
2841 emitcode (";", "-----------------------------------------");
2842 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2843 emitcode (";", "-----------------------------------------");
2845 emitcode ("", "%s:", sym->rname);
2846 ftype = operandType (IC_LEFT (ic));
2848 if (IFFUNC_ISNAKED(ftype))
2850 emitcode(";", "naked function: no prologue.");
2854 if (options.stack_probe)
2855 emitcode ("lcall","__stack_probe");
2856 /* if critical function then turn interrupts off */
2857 if (IFFUNC_ISCRITICAL (ftype))
2858 emitcode ("clr", "ea");
2860 /* here we need to generate the equates for the
2861 register bank if required */
2862 if (FUNC_REGBANK (ftype) != rbank)
2866 rbank = FUNC_REGBANK (ftype);
2867 for (i = 0; i < ds390_nRegs; i++)
2869 if (regs390[i].print) {
2870 if (strcmp (regs390[i].base, "0") == 0)
2871 emitcode ("", "%s !equ !constbyte",
2873 8 * rbank + regs390[i].offset);
2875 emitcode ("", "%s !equ %s + !constbyte",
2878 8 * rbank + regs390[i].offset);
2883 /* if this is an interrupt service routine then
2884 save acc, b, dpl, dph */
2885 if (IFFUNC_ISISR (sym->type))
2887 if (!inExcludeList ("acc"))
2888 emitcode ("push", "acc");
2889 if (!inExcludeList ("b"))
2890 emitcode ("push", "b");
2891 if (!inExcludeList ("dpl"))
2892 emitcode ("push", "dpl");
2893 if (!inExcludeList ("dph"))
2894 emitcode ("push", "dph");
2895 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2897 emitcode ("push", "dpx");
2898 /* Make sure we're using standard DPTR */
2899 emitcode ("push", "dps");
2900 emitcode ("mov", "dps,#0");
2901 if (options.stack10bit)
2903 /* This ISR could conceivably use DPTR2. Better save it. */
2904 emitcode ("push", "dpl1");
2905 emitcode ("push", "dph1");
2906 emitcode ("push", "dpx1");
2907 emitcode ("push", DP2_RESULT_REG);
2910 /* if this isr has no bank i.e. is going to
2911 run with bank 0 , then we need to save more
2913 if (!FUNC_REGBANK (sym->type))
2917 /* if this function does not call any other
2918 function then we can be economical and
2919 save only those registers that are used */
2920 if (!IFFUNC_HASFCALL(sym->type))
2923 /* if any registers used */
2926 /* save the registers used */
2927 for (i = 0; i < sym->regsUsed->size; i++)
2929 if (bitVectBitValue (sym->regsUsed, i) ||
2930 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2931 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2938 /* this function has a function call cannot
2939 determines register usage so we will have to push the
2941 saveRBank (0, ic, FALSE);
2942 if (options.parms_in_bank1) {
2943 for (i=0; i < 8 ; i++ ) {
2944 emitcode ("push","%s",rb1regs[i]);
2951 /* This ISR uses a non-zero bank.
2953 * We assume that the bank is available for our
2956 * However, if this ISR calls a function which uses some
2957 * other bank, we must save that bank entirely.
2959 unsigned long banksToSave = 0;
2961 if (IFFUNC_HASFCALL(sym->type))
2964 #define MAX_REGISTER_BANKS 4
2969 for (i = ic; i; i = i->next)
2971 if (i->op == ENDFUNCTION)
2973 /* we got to the end OK. */
2981 dtype = operandType (IC_LEFT(i));
2983 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2985 /* Mark this bank for saving. */
2986 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2988 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2992 banksToSave |= (1 << FUNC_REGBANK(dtype));
2995 /* And note that we don't need to do it in
3003 /* This is a mess; we have no idea what
3004 * register bank the called function might
3007 * The only thing I can think of to do is
3008 * throw a warning and hope.
3010 werror(W_FUNCPTR_IN_USING_ISR);
3014 if (banksToSave && options.useXstack)
3016 /* Since we aren't passing it an ic,
3017 * saveRBank will assume r0 is available to abuse.
3019 * So switch to our (trashable) bank now, so
3020 * the caller's R0 isn't trashed.
3022 emitcode ("push", "psw");
3023 emitcode ("mov", "psw,#!constbyte",
3024 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3028 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3030 if (banksToSave & (1 << ix))
3032 saveRBank(ix, NULL, FALSE);
3036 // TODO: this needs a closer look
3037 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3042 /* if callee-save to be used for this function
3043 then save the registers being used in this function */
3044 if (IFFUNC_CALLEESAVES(sym->type))
3048 /* if any registers used */
3051 /* save the registers used */
3052 for (i = 0; i < sym->regsUsed->size; i++)
3054 if (bitVectBitValue (sym->regsUsed, i) ||
3055 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3057 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3065 /* set the register bank to the desired value */
3066 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3069 emitcode ("push", "psw");
3070 emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3073 if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3074 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3075 if (options.stack10bit) {
3076 emitcode ("push","_bpx");
3077 emitcode ("push","_bpx+1");
3078 emitcode ("mov","_bpx,%s",spname);
3079 emitcode ("mov","_bpx+1,esp");
3080 emitcode ("anl","_bpx+1,#3");
3082 if (options.useXstack) {
3083 emitcode ("mov", "r0,%s", spname);
3084 emitcode ("mov", "a,_bp");
3085 emitcode ("movx", "@r0,a");
3086 emitcode ("inc", "%s", spname);
3088 /* set up the stack */
3089 emitcode ("push", "_bp"); /* save the callers stack */
3091 emitcode ("mov", "_bp,%s", spname);
3095 /* adjust the stack for the function */
3098 if (options.stack10bit) {
3099 if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
3100 assert (sym->recvSize <= 4);
3101 if (sym->stack <= 8) {
3102 while (i--) emitcode ("push","acc");
3105 emitcode ("mov","a,sp");
3106 emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3107 emitcode ("mov","sp,a");
3108 emitcode ("mov","a,esp");
3109 emitcode ("anl","a,#3");
3110 emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3111 emitcode ("mov","esp,a");
3116 werror (W_STACK_OVERFLOW, sym->name);
3118 if (i > 3 && sym->recvSize < 4) {
3120 emitcode ("mov", "a,sp");
3121 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3122 emitcode ("mov", "sp,a");
3126 emitcode ("inc", "sp");
3133 emitcode ("mov", "a,_spx");
3134 emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3135 emitcode ("mov", "_spx,a");
3140 /*-----------------------------------------------------------------*/
3141 /* genEndFunction - generates epilogue for functions */
3142 /*-----------------------------------------------------------------*/
3144 genEndFunction (iCode * ic)
3146 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3148 D (emitcode (";", "genEndFunction "););
3150 if (IFFUNC_ISNAKED(sym->type))
3152 emitcode(";", "naked function: no epilogue.");
3156 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3157 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3159 if (options.stack10bit) {
3161 emitcode ("mov", "sp,_bpx", spname);
3162 emitcode ("mov", "esp,_bpx+1", spname);
3165 emitcode ("mov", "%s,_bp", spname);
3169 /* if use external stack but some variables were
3170 added to the local stack then decrement the
3172 if (options.useXstack && sym->stack) {
3173 emitcode ("mov", "a,sp");
3174 emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3175 emitcode ("mov", "sp,a");
3179 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3180 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3182 if (options.useXstack) {
3183 emitcode ("mov", "r0,%s", spname);
3184 emitcode ("movx", "a,@r0");
3185 emitcode ("mov", "_bp,a");
3186 emitcode ("dec", "%s", spname);
3188 if (options.stack10bit) {
3189 emitcode ("pop", "_bpx+1");
3190 emitcode ("pop", "_bpx");
3192 emitcode ("pop", "_bp");
3197 /* restore the register bank */
3198 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3200 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3201 || !options.useXstack)
3203 /* Special case of ISR using non-zero bank with useXstack
3206 emitcode ("pop", "psw");
3210 if (IFFUNC_ISISR (sym->type))
3213 /* now we need to restore the registers */
3214 /* if this isr has no bank i.e. is going to
3215 run with bank 0 , then we need to save more
3217 if (!FUNC_REGBANK (sym->type))
3220 /* if this function does not call any other
3221 function then we can be economical and
3222 save only those registers that are used */
3223 if (!IFFUNC_HASFCALL(sym->type))
3226 /* if any registers used */
3229 /* save the registers used */
3230 for (i = sym->regsUsed->size; i >= 0; i--)
3232 if (bitVectBitValue (sym->regsUsed, i) ||
3233 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3234 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3241 /* this function has a function call cannot
3242 determines register usage so we will have to pop the
3244 if (options.parms_in_bank1) {
3245 for (i = 7 ; i >= 0 ; i-- ) {
3246 emitcode ("pop","%s",rb1regs[i]);
3249 unsaveRBank (0, ic, FALSE);
3254 /* This ISR uses a non-zero bank.
3256 * Restore any register banks saved by genFunction
3259 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3262 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3264 if (savedBanks & (1 << ix))
3266 unsaveRBank(ix, NULL, FALSE);
3270 if (options.useXstack)
3272 /* Restore bank AFTER calling unsaveRBank,
3273 * since it can trash r0.
3275 emitcode ("pop", "psw");
3279 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3281 if (options.stack10bit)
3283 emitcode ("pop", DP2_RESULT_REG);
3284 emitcode ("pop", "dpx1");
3285 emitcode ("pop", "dph1");
3286 emitcode ("pop", "dpl1");
3288 emitcode ("pop", "dps");
3289 emitcode ("pop", "dpx");
3291 if (!inExcludeList ("dph"))
3292 emitcode ("pop", "dph");
3293 if (!inExcludeList ("dpl"))
3294 emitcode ("pop", "dpl");
3295 if (!inExcludeList ("b"))
3296 emitcode ("pop", "b");
3297 if (!inExcludeList ("acc"))
3298 emitcode ("pop", "acc");
3300 if (IFFUNC_ISCRITICAL (sym->type))
3301 emitcode ("setb", "ea");
3303 /* if debug then send end of function */
3304 if (options.debug && currFunc) {
3306 emitcode ("", "C$%s$%d$%d$%d ==.",
3307 FileBaseName (ic->filename), currFunc->lastLine,
3308 ic->level, ic->block);
3309 if (IS_STATIC (currFunc->etype))
3310 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3312 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3316 emitcode ("reti", "");
3320 if (IFFUNC_ISCRITICAL (sym->type))
3321 emitcode ("setb", "ea");
3323 if (IFFUNC_CALLEESAVES(sym->type))
3327 /* if any registers used */
3330 /* save the registers used */
3331 for (i = sym->regsUsed->size; i >= 0; i--)
3333 if (bitVectBitValue (sym->regsUsed, i) ||
3334 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3335 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3341 /* if debug then send end of function */
3342 if (options.debug && currFunc)
3345 emitcode ("", "C$%s$%d$%d$%d ==.",
3346 FileBaseName (ic->filename), currFunc->lastLine,
3347 ic->level, ic->block);
3348 if (IS_STATIC (currFunc->etype))
3349 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3351 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3355 emitcode ("ret", "");
3360 /*-----------------------------------------------------------------*/
3361 /* genJavaNativeRet - generate code for return JavaNative */
3362 /*-----------------------------------------------------------------*/
3363 static void genJavaNativeRet(iCode *ic)
3367 aopOp (IC_LEFT (ic), ic, FALSE,
3368 AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
3369 size = AOP_SIZE (IC_LEFT (ic));
3373 /* it is assigned to GPR0-R3 then push them */
3374 if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3375 aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3376 for (i = 0 ; i < size ; i++ ) {
3377 emitcode ("push","%s",
3378 aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3380 for (i = (size-1) ; i >= 0 ; i--) {
3381 emitcode ("pop","a%s",javaRet[i]);
3384 for (i = 0 ; i < size ; i++)
3385 emitcode ("mov","%s,%s",javaRet[i],
3386 aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3388 for (i = size ; i < 4 ; i++ )
3389 emitcode ("mov","%s,#0",javaRet[i]);
3393 /*-----------------------------------------------------------------*/
3394 /* genRet - generate code for return statement */
3395 /*-----------------------------------------------------------------*/
3399 int size, offset = 0, pushed = 0;
3401 D (emitcode (";", "genRet "););
3403 /* if we have no return value then
3404 just generate the "ret" */
3408 /* if this is a JavaNative function then return
3409 value in different register */
3410 if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3411 genJavaNativeRet(ic);
3414 /* we have something to return then
3415 move the return value into place */
3416 aopOp (IC_LEFT (ic), ic, FALSE,
3417 (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
3418 size = AOP_SIZE (IC_LEFT (ic));
3420 _startLazyDPSEvaluation ();
3424 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3426 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3428 emitcode ("push", "%s", l);
3433 /* Since A is the last element of fReturn,
3434 * is is OK to clobber it in the aopGet.
3436 l = aopGet (AOP (IC_LEFT (ic)), offset,
3437 FALSE, FALSE, NULL);
3438 if (strcmp (fReturn[offset], l))
3439 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3442 _endLazyDPSEvaluation ();
3449 if (strcmp (fReturn[pushed], "a"))
3450 emitcode ("pop", fReturn[pushed]);
3452 emitcode ("pop", "acc");
3455 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3458 /* generate a jump to the return label
3459 if the next is not the return statement */
3460 if (!(ic->next && ic->next->op == LABEL &&
3461 IC_LABEL (ic->next) == returnLabel))
3463 emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3467 /*-----------------------------------------------------------------*/
3468 /* genLabel - generates a label */
3469 /*-----------------------------------------------------------------*/
3471 genLabel (iCode * ic)
3473 /* special case never generate */
3474 if (IC_LABEL (ic) == entryLabel)
3477 D (emitcode (";", "genLabel ");
3480 emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3483 /*-----------------------------------------------------------------*/
3484 /* genGoto - generates a ljmp */
3485 /*-----------------------------------------------------------------*/
3487 genGoto (iCode * ic)
3489 D (emitcode (";", "genGoto ");
3491 emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3494 /*-----------------------------------------------------------------*/
3495 /* findLabelBackwards: walks back through the iCode chain looking */
3496 /* for the given label. Returns number of iCode instructions */
3497 /* between that label and given ic. */
3498 /* Returns zero if label not found. */
3499 /*-----------------------------------------------------------------*/
3501 findLabelBackwards (iCode * ic, int key)
3510 /* If we have any pushes or pops, we cannot predict the distance.
3511 I don't like this at all, this should be dealt with in the
3513 if (ic->op == IPUSH || ic->op == IPOP) {
3517 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3519 /* printf("findLabelBackwards = %d\n", count); */
3527 /*-----------------------------------------------------------------*/
3528 /* genPlusIncr :- does addition with increment if possible */
3529 /*-----------------------------------------------------------------*/
3531 genPlusIncr (iCode * ic)
3533 unsigned int icount;
3534 unsigned int size = getDataSize (IC_RESULT (ic));
3536 /* will try to generate an increment */
3537 /* if the right side is not a literal
3539 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3542 /* if the literal value of the right hand side
3543 is greater than 4 then it is not worth it */
3544 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3547 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3548 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3550 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
3554 /* if increment 16 bits in register */
3556 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3557 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3558 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3567 /* If the next instruction is a goto and the goto target
3568 * is <= 5 instructions previous to this, we can generate
3569 * jumps straight to that target.
3571 if (ic->next && ic->next->op == GOTO
3572 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3575 D(emitcode (";", "tail increment optimized (range %d)", labelRange););
3576 tlbl = IC_LABEL (ic->next);
3581 tlbl = newiTempLabel (NULL);
3585 l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
3586 emitcode ("inc", "%s", l);
3588 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3589 IS_AOP_PREG (IC_RESULT (ic)))
3591 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3595 emitcode ("clr", "a");
3596 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3599 l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
3600 emitcode ("inc", "%s", l);
3603 if (!strcmp(l, "acc"))
3605 emitcode("jnz", "!tlabel", tlbl->key + 100);
3607 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3608 IS_AOP_PREG (IC_RESULT (ic)))
3610 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3614 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3617 l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
3618 emitcode ("inc", "%s", l);
3622 if (!strcmp(l, "acc"))
3624 emitcode("jnz", "!tlabel", tlbl->key + 100);
3626 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3627 IS_AOP_PREG (IC_RESULT (ic)))
3629 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3633 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3636 l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
3637 emitcode ("inc", "%s", l); }
3641 emitcode ("", "!tlabeldef", tlbl->key + 100);
3646 if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3647 !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 &&
3648 options.model == MODEL_FLAT24 ) {
3652 emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, NULL));
3654 emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, NULL));
3656 emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3659 while (icount--) emitcode ("inc","dptr");
3663 if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3664 AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3666 emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3667 while (icount--) emitcode ("inc","dptr");
3668 emitcode ("mov","dps,#0");
3672 /* if the sizes are greater than 1 then we cannot */
3673 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3674 AOP_SIZE (IC_LEFT (ic)) > 1)
3677 /* we can if the aops of the left & result match or
3678 if they are in registers and the registers are the
3681 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3682 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3683 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3688 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3689 emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3690 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3695 _startLazyDPSEvaluation ();
3698 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3700 _endLazyDPSEvaluation ();
3709 /*-----------------------------------------------------------------*/
3710 /* outBitAcc - output a bit in acc */
3711 /*-----------------------------------------------------------------*/
3713 outBitAcc (operand * result)
3715 symbol *tlbl = newiTempLabel (NULL);
3716 /* if the result is a bit */
3717 if (AOP_TYPE (result) == AOP_CRY)
3719 aopPut (AOP (result), "a", 0);
3723 emitcode ("jz", "!tlabel", tlbl->key + 100);
3724 emitcode ("mov", "a,%s", one);
3725 emitcode ("", "!tlabeldef", tlbl->key + 100);
3730 /*-----------------------------------------------------------------*/
3731 /* genPlusBits - generates code for addition of two bits */
3732 /*-----------------------------------------------------------------*/
3734 genPlusBits (iCode * ic)
3736 D (emitcode (";", "genPlusBits "););
3738 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3740 symbol *lbl = newiTempLabel (NULL);
3741 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3742 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3743 emitcode ("cpl", "c");
3744 emitcode ("", "!tlabeldef", (lbl->key + 100));
3745 outBitC (IC_RESULT (ic));
3749 emitcode ("clr", "a");
3750 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3751 emitcode ("rlc", "a");
3752 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3753 emitcode ("addc", "a,#0");
3754 outAcc (IC_RESULT (ic));
3759 adjustArithmeticResult (iCode * ic)
3761 if (opIsGptr (IC_RESULT (ic)) &&
3762 opIsGptr (IC_LEFT (ic)) &&
3763 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3765 aopPut (AOP (IC_RESULT (ic)),
3766 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3770 if (opIsGptr (IC_RESULT (ic)) &&
3771 opIsGptr (IC_RIGHT (ic)) &&
3772 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3774 aopPut (AOP (IC_RESULT (ic)),
3775 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3779 if (opIsGptr (IC_RESULT (ic)) &&
3780 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3781 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3782 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3783 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3786 SNPRINTF (buff, sizeof(buff),
3787 "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3788 aopPut (AOP (IC_RESULT (ic)), buff, GPTRSIZE - 1);
3792 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
3793 // generates the result if possible. If result is generated, returns TRUE; otherwise
3794 // returns false and caller must deal with fact that result isn't aopOp'd.
3795 bool aopOp3(iCode * ic)
3797 bool dp1InUse, dp2InUse;
3800 // First, generate the right opcode. DPTR may be used if neither left nor result are
3803 // D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
3804 // AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
3805 // AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
3806 // AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
3808 // D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
3809 // AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
3810 // AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
3811 // AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
3815 // Right uses DPTR unless left or result is an AOP_STR.
3816 aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)));
3818 // if the right used DPTR, left MUST use DPTR2.
3819 // if the right used DPTR2, left MUST use DPTR.
3820 // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
3821 // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
3822 // enabling us to assign DPTR to result.
3824 if (AOP_USESDPTR(IC_RIGHT(ic)))
3828 else if (AOP_USESDPTR2(IC_RIGHT(ic)))
3834 if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
3844 aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
3846 // We've op'd the left & right. So, if left or right are the same operand as result,
3847 // we know aopOp will succeed, and we can just do it & bail.
3848 if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)) ||
3849 isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
3851 // D(emitcode(";", "aopOp3: (left | right) & result equal"););
3852 aopOp(IC_RESULT(ic),ic,TRUE, FALSE);
3856 // Note which dptrs are currently in use.
3857 dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
3858 dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
3860 // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot
3862 if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
3867 // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
3868 if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
3873 // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck
3874 if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
3879 aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
3881 // Some sanity checking...
3882 if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
3885 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
3886 __FILE__, __LINE__, ic->filename, ic->lineno);
3887 emitcode(";", ">>> unexpected DPTR here.");
3890 if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
3893 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
3894 __FILE__, __LINE__, ic->filename, ic->lineno);
3895 emitcode(";", ">>> unexpected DPTR2 here.");
3901 // Macro to aopOp all three operands of an ic. If this cannot be done,
3902 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3903 // will be set TRUE. The caller must then handle the case specially, noting
3904 // that the IC_RESULT operand is not aopOp'd.
3906 #define AOP_OP_3_NOFATAL(ic, rc) \
3907 do { rc = !aopOp3(ic); } while (0)
3909 // aopOp the left & right operands of an ic.
3910 #define AOP_OP_2(ic) \
3911 aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
3912 aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
3914 // convienience macro.
3915 #define AOP_SET_LOCALS(ic) \
3916 left = IC_LEFT(ic); \
3917 right = IC_RIGHT(ic); \
3918 result = IC_RESULT(ic);
3921 // Given an integer value of pushedSize bytes on the stack,
3922 // adjust it to be resultSize bytes, either by discarding
3923 // the most significant bytes or by zero-padding.
3925 // On exit from this macro, pushedSize will have been adjusted to
3926 // equal resultSize, and ACC may be trashed.
3927 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3928 /* If the pushed data is bigger than the result, \
3929 * simply discard unused bytes. Icky, but works. \
3931 while (pushedSize > resultSize) \
3933 D (emitcode (";", "discarding unused result byte."););\
3934 emitcode ("pop", "acc"); \
3937 if (pushedSize < resultSize) \
3939 emitcode ("clr", "a"); \
3940 /* Conversly, we haven't pushed enough here. \
3941 * just zero-pad, and all is well. \
3943 while (pushedSize < resultSize) \
3945 emitcode("push", "acc"); \
3949 assert(pushedSize == resultSize);
3951 /*-----------------------------------------------------------------*/
3952 /* genPlus - generates code for addition */
3953 /*-----------------------------------------------------------------*/
3955 genPlus (iCode * ic)
3957 int size, offset = 0;
3961 D (emitcode (";", "genPlus "););
3963 /* special cases :- */
3964 if ( AOP_IS_STR(IC_LEFT(ic)) &&
3965 isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
3966 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
3967 size = floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
3969 while (size--) emitcode ("inc","dptr");
3971 emitcode ("mov","a,dpl");
3972 emitcode ("add","a,#!constbyte",size & 0xff);
3973 emitcode ("mov","dpl,a");
3974 emitcode ("mov","a,dph");
3975 emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
3976 emitcode ("mov","dph,a");
3977 emitcode ("mov","a,dpx");
3978 emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
3979 emitcode ("mov","dpx,a");
3981 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
3984 if ( IS_SYMOP(IC_LEFT(ic)) &&
3985 OP_SYMBOL(IC_LEFT(ic))->remat &&
3986 isOperandInFarSpace(IC_RIGHT(ic))) {
3987 operand *op = IC_RIGHT(ic);
3988 IC_RIGHT(ic) = IC_LEFT(ic);
3992 AOP_OP_3_NOFATAL (ic, pushResult);
3996 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
4001 /* if literal, literal on the right or
4002 if left requires ACC or right is already
4004 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4005 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
4006 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4008 operand *t = IC_RIGHT (ic);
4009 IC_RIGHT (ic) = IC_LEFT (ic);
4011 emitcode (";", "Swapped plus args.");
4014 /* if both left & right are in bit
4016 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4017 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4023 /* if left in bit space & right literal */
4024 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4025 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4027 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4028 /* if result in bit space */
4029 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4031 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4032 emitcode ("cpl", "c");
4033 outBitC (IC_RESULT (ic));
4037 size = getDataSize (IC_RESULT (ic));
4038 _startLazyDPSEvaluation ();
4041 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4042 emitcode ("addc", "a,#0");
4043 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4045 _endLazyDPSEvaluation ();
4050 /* if I can do an increment instead
4051 of add then GOOD for ME */
4052 if (genPlusIncr (ic) == TRUE)
4054 emitcode (";", "did genPlusIncr");
4059 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4061 _startLazyDPSEvaluation ();
4064 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4066 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4068 emitcode ("add", "a,%s",
4069 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4071 emitcode ("addc", "a,%s",
4072 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4076 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4078 /* right is going to use ACC or we would have taken the
4081 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4083 D(emitcode(";", "+ AOP_ACC special case."););
4084 emitcode("xch", "a, %s", DP2_RESULT_REG);
4086 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4089 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4092 emitcode("add", "a, %s", DP2_RESULT_REG);
4096 emitcode ("add", "a,%s",
4097 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE,
4103 emitcode ("addc", "a,%s",
4104 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE,
4110 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4114 emitcode ("push", "acc");
4118 _endLazyDPSEvaluation ();
4122 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4124 size = getDataSize (IC_LEFT (ic));
4125 rSize = getDataSize (IC_RESULT (ic));
4127 ADJUST_PUSHED_RESULT(size, rSize);
4129 _startLazyDPSEvaluation ();
4132 emitcode ("pop", "acc");
4133 aopPut (AOP (IC_RESULT (ic)), "a", size);
4135 _endLazyDPSEvaluation ();
4138 adjustArithmeticResult (ic);
4141 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4142 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4143 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4146 /*-----------------------------------------------------------------*/
4147 /* genMinusDec :- does subtraction with deccrement if possible */
4148 /*-----------------------------------------------------------------*/
4150 genMinusDec (iCode * ic)
4152 unsigned int icount;
4153 unsigned int size = getDataSize (IC_RESULT (ic));
4155 /* will try to generate an increment */
4156 /* if the right side is not a literal
4158 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4161 /* if the literal value of the right hand side
4162 is greater than 4 then it is not worth it */
4163 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4166 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4167 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4169 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
4173 /* if decrement 16 bits in register */
4174 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4175 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4176 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4185 /* If the next instruction is a goto and the goto target
4186 * is <= 5 instructions previous to this, we can generate
4187 * jumps straight to that target.
4189 if (ic->next && ic->next->op == GOTO
4190 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4193 emitcode (";", "tail decrement optimized (range %d)", labelRange);
4194 tlbl = IC_LABEL (ic->next);
4199 tlbl = newiTempLabel (NULL);
4203 l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
4204 emitcode ("dec", "%s", l);
4206 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4207 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4208 IS_AOP_PREG (IC_RESULT (ic)))
4210 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4214 emitcode ("mov", "a,#!constbyte",0xff);
4215 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4217 l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
4218 emitcode ("dec", "%s", l);
4221 if (!strcmp(l, "acc"))
4223 emitcode("jnz", "!tlabel", tlbl->key + 100);
4225 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4226 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4227 IS_AOP_PREG (IC_RESULT (ic)))
4229 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4233 emitcode ("mov", "a,#!constbyte",0xff);
4234 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4236 l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
4237 emitcode ("dec", "%s", l);
4241 if (!strcmp(l, "acc"))
4243 emitcode("jnz", "!tlabel", tlbl->key + 100);
4245 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4246 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4247 IS_AOP_PREG (IC_RESULT (ic)))
4249 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4253 emitcode ("mov", "a,#!constbyte",0xff);
4254 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4256 l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
4257 emitcode ("dec", "%s", l);
4261 emitcode ("", "!tlabeldef", tlbl->key + 100);
4266 /* if the sizes are greater than 1 then we cannot */
4267 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4268 AOP_SIZE (IC_LEFT (ic)) > 1)
4271 /* we can if the aops of the left & result match or
4272 if they are in registers and the registers are the
4275 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4276 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4277 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4280 _startLazyDPSEvaluation ();
4283 emitcode ("dec", "%s",
4284 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
4286 _endLazyDPSEvaluation ();
4294 /*-----------------------------------------------------------------*/
4295 /* addSign - complete with sign */
4296 /*-----------------------------------------------------------------*/
4298 addSign (operand * result, int offset, int sign)
4300 int size = (getDataSize (result) - offset);
4303 _startLazyDPSEvaluation();
4306 emitcode ("rlc", "a");
4307 emitcode ("subb", "a,acc");
4310 aopPut (AOP (result), "a", offset++);
4317 aopPut (AOP (result), zero, offset++);
4320 _endLazyDPSEvaluation();
4324 /*-----------------------------------------------------------------*/
4325 /* genMinusBits - generates code for subtraction of two bits */
4326 /*-----------------------------------------------------------------*/
4328 genMinusBits (iCode * ic)
4330 symbol *lbl = newiTempLabel (NULL);
4332 D (emitcode (";", "genMinusBits "););
4334 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4336 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4337 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4338 emitcode ("cpl", "c");
4339 emitcode ("", "!tlabeldef", (lbl->key + 100));
4340 outBitC (IC_RESULT (ic));
4344 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4345 emitcode ("subb", "a,acc");
4346 emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4347 emitcode ("inc", "a");
4348 emitcode ("", "!tlabeldef", (lbl->key + 100));
4349 aopPut (AOP (IC_RESULT (ic)), "a", 0);
4350 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4354 /*-----------------------------------------------------------------*/
4355 /* genMinus - generates code for subtraction */
4356 /*-----------------------------------------------------------------*/
4358 genMinus (iCode * ic)
4360 int size, offset = 0;
4365 D (emitcode (";", "genMinus "););
4367 AOP_OP_3_NOFATAL(ic, pushResult);
4371 /* special cases :- */
4372 /* if both left & right are in bit space */
4373 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4374 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4380 /* if I can do an decrement instead
4381 of subtract then GOOD for ME */
4382 if (genMinusDec (ic) == TRUE)
4387 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4389 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4395 lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4400 /* if literal, add a,#-lit, else normal subb */
4401 _startLazyDPSEvaluation ();
4403 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4404 if (AOP_USESDPTR(IC_RIGHT(ic))) {
4405 emitcode ("mov","b,%s",
4406 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4407 MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4408 emitcode ("subb","a,b");
4410 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4411 emitcode ("subb", "a,%s",
4412 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE,
4416 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4417 /* first add without previous c */
4419 if (!size && lit==-1) {
4420 emitcode ("dec", "a");
4422 emitcode ("add", "a,#!constbyte",
4423 (unsigned int) (lit & 0x0FFL));
4426 emitcode ("addc", "a,#!constbyte",
4427 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4432 emitcode ("push", "acc");
4434 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4438 _endLazyDPSEvaluation ();
4442 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4444 size = getDataSize (IC_LEFT (ic));
4445 rSize = getDataSize (IC_RESULT (ic));
4447 ADJUST_PUSHED_RESULT(size, rSize);
4449 _startLazyDPSEvaluation ();
4452 emitcode ("pop", "acc");
4453 aopPut (AOP (IC_RESULT (ic)), "a", size);
4455 _endLazyDPSEvaluation ();
4458 adjustArithmeticResult (ic);
4461 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4462 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4463 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4467 /*-----------------------------------------------------------------*/
4468 /* genMultbits :- multiplication of bits */
4469 /*-----------------------------------------------------------------*/
4471 genMultbits (operand * left,
4476 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4477 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4478 aopOp(result, ic, TRUE, FALSE);
4483 /*-----------------------------------------------------------------*/
4484 /* genMultOneByte : 8*8=8/16 bit multiplication */
4485 /*-----------------------------------------------------------------*/
4487 genMultOneByte (operand * left,
4492 sym_link *opetype = operandType (result);
4496 /* (if two literals: the value is computed before) */
4497 /* if one literal, literal on the right */
4498 if (AOP_TYPE (left) == AOP_LIT)
4503 emitcode (";", "swapped left and right");
4506 if (SPEC_USIGN(opetype)
4507 // ignore the sign of left and right, what else can we do?
4508 || (SPEC_USIGN(operandType(left)) &&
4509 SPEC_USIGN(operandType(right)))) {
4510 // just an unsigned 8*8=8/16 multiply
4511 //emitcode (";","unsigned");
4512 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4513 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4514 emitcode ("mul", "ab");
4516 _G.accInUse++; _G.bInUse++;
4517 aopOp(result, ic, TRUE, FALSE);
4519 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4521 // this should never happen
4522 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4523 AOP_SIZE(result), __FILE__, lineno);
4527 aopPut (AOP (result), "a", 0);
4528 _G.accInUse--; _G.bInUse--;
4529 if (AOP_SIZE(result)==2)
4531 aopPut (AOP (result), "b", 1);
4536 // we have to do a signed multiply
4538 emitcode (";", "signed");
4539 emitcode ("clr", "F0"); // reset sign flag
4540 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4542 lbl=newiTempLabel(NULL);
4543 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4544 // left side is negative, 8-bit two's complement, this fails for -128
4545 emitcode ("setb", "F0"); // set sign flag
4546 emitcode ("cpl", "a");
4547 emitcode ("inc", "a");
4549 emitcode ("", "!tlabeldef", lbl->key+100);
4552 if (AOP_TYPE(right)==AOP_LIT) {
4553 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4554 /* AND literal negative */
4555 if ((int) val < 0) {
4556 emitcode ("cpl", "F0"); // complement sign flag
4557 emitcode ("mov", "b,#!constbyte", -val);
4559 emitcode ("mov", "b,#!constbyte", val);
4562 lbl=newiTempLabel(NULL);
4563 emitcode ("mov", "b,a");
4564 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4565 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4566 // right side is negative, 8-bit two's complement
4567 emitcode ("cpl", "F0"); // complement sign flag
4568 emitcode ("cpl", "a");
4569 emitcode ("inc", "a");
4570 emitcode ("", "!tlabeldef", lbl->key+100);
4572 emitcode ("mul", "ab");
4574 _G.accInUse++;_G.bInUse++;
4575 aopOp(result, ic, TRUE, FALSE);
4577 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4579 // this should never happen
4580 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4581 AOP_SIZE(result), __FILE__, lineno);
4585 lbl=newiTempLabel(NULL);
4586 emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4587 // only ONE op was negative, we have to do a 8/16-bit two's complement
4588 emitcode ("cpl", "a"); // lsb
4589 if (AOP_SIZE(result)==1) {
4590 emitcode ("inc", "a");
4592 emitcode ("add", "a,#1");
4593 emitcode ("xch", "a,b");
4594 emitcode ("cpl", "a"); // msb
4595 emitcode ("addc", "a,#0");
4596 emitcode ("xch", "a,b");
4599 emitcode ("", "!tlabeldef", lbl->key+100);
4600 aopPut (AOP (result), "a", 0);
4601 _G.accInUse--;_G.bInUse--;
4602 if (AOP_SIZE(result)==2) {
4603 aopPut (AOP (result), "b", 1);
4607 /*-----------------------------------------------------------------*/
4608 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
4609 /*-----------------------------------------------------------------*/
4610 static void genMultTwoByte (operand *left, operand *right,
4611 operand *result, iCode *ic)
4613 sym_link *retype = getSpec(operandType(right));
4614 sym_link *letype = getSpec(operandType(left));
4615 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4618 if (AOP_TYPE (left) == AOP_LIT) {
4623 /* save EA bit in F1 */
4624 lbl = newiTempLabel(NULL);
4625 emitcode ("setb","F1");
4626 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4627 emitcode ("clr","F1");
4628 emitcode("","!tlabeldef",lbl->key+100);
4630 /* load up MB with right */
4632 emitcode("clr","F0");
4633 if (AOP_TYPE(right) == AOP_LIT) {
4634 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4636 emitcode("setb","F0");
4639 emitcode ("mov","mb,#!constbyte",val & 0xff);
4640 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4642 lbl = newiTempLabel(NULL);
4643 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4644 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4645 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4646 emitcode ("xch", "a,b");
4647 emitcode ("cpl","a");
4648 emitcode ("add", "a,#1");
4649 emitcode ("xch", "a,b");
4650 emitcode ("cpl", "a"); // msb
4651 emitcode ("addc", "a,#0");
4652 emitcode ("setb","F0");
4653 emitcode ("","!tlabeldef",lbl->key+100);
4654 emitcode ("mov","mb,b");
4655 emitcode ("mov","mb,a");
4658 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4659 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4661 /* load up MA with left */
4663 lbl = newiTempLabel(NULL);
4664 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4665 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4666 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4667 emitcode ("xch", "a,b");
4668 emitcode ("cpl","a");
4669 emitcode ("add", "a,#1");
4670 emitcode ("xch", "a,b");
4671 emitcode ("cpl", "a"); // msb
4672 emitcode ("addc","a,#0");
4673 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4674 emitcode ("setb","F0");
4675 emitcode ("","!tlabeldef",lbl->key+100);
4676 emitcode ("mov","ma,b");
4677 emitcode ("mov","ma,a");
4679 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4680 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4682 /* wait for multiplication to finish */
4683 lbl = newiTempLabel(NULL);
4684 emitcode("","!tlabeldef", lbl->key+100);
4685 emitcode("mov","a,mcnt1");
4686 emitcode("anl","a,#!constbyte",0x80);
4687 emitcode("jnz","!tlabel",lbl->key+100);
4689 freeAsmop (left, NULL, ic, TRUE);
4690 freeAsmop (right, NULL, ic,TRUE);
4691 aopOp(result, ic, TRUE, FALSE);
4693 /* if unsigned then simple */
4695 emitcode ("mov","a,ma");
4696 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4697 emitcode ("mov","a,ma");
4698 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4699 aopPut(AOP(result),"ma",1);
4700 aopPut(AOP(result),"ma",0);
4702 emitcode("push","ma");
4703 emitcode("push","ma");
4704 emitcode("push","ma");
4706 /* negate result if needed */
4707 lbl = newiTempLabel(NULL);
4708 emitcode("jnb","F0,!tlabel",lbl->key+100);
4709 emitcode("cpl","a");
4710 emitcode("add","a,#1");
4711 emitcode("","!tlabeldef", lbl->key+100);
4712 if (AOP_TYPE(result) == AOP_ACC)
4714 D(emitcode(";", "ACC special case."););
4715 /* We know result is the only live aop, and
4716 * it's obviously not a DPTR2, so AP is available.
4718 emitcode("mov", "%s,acc", DP2_RESULT_REG);
4722 aopPut(AOP(result),"a",0);
4725 emitcode("pop","acc");
4726 lbl = newiTempLabel(NULL);
4727 emitcode("jnb","F0,!tlabel",lbl->key+100);
4728 emitcode("cpl","a");
4729 emitcode("addc","a,#0");
4730 emitcode("","!tlabeldef", lbl->key+100);
4731 aopPut(AOP(result),"a",1);
4732 emitcode("pop","acc");
4733 if (AOP_SIZE(result) >= 3) {
4734 lbl = newiTempLabel(NULL);
4735 emitcode("jnb","F0,!tlabel",lbl->key+100);
4736 emitcode("cpl","a");
4737 emitcode("addc","a,#0");
4738 emitcode("","!tlabeldef", lbl->key+100);
4739 aopPut(AOP(result),"a",2);
4741 emitcode("pop","acc");
4742 if (AOP_SIZE(result) >= 4) {
4743 lbl = newiTempLabel(NULL);
4744 emitcode("jnb","F0,!tlabel",lbl->key+100);
4745 emitcode("cpl","a");
4746 emitcode("addc","a,#0");
4747 emitcode("","!tlabeldef", lbl->key+100);
4748 aopPut(AOP(result),"a",3);
4750 if (AOP_TYPE(result) == AOP_ACC)
4752 /* We stashed the result away above. */
4753 emitcode("mov", "acc,%s", DP2_RESULT_REG);
4757 freeAsmop (result, NULL, ic, TRUE);
4759 /* restore EA bit in F1 */
4760 lbl = newiTempLabel(NULL);
4761 emitcode ("jnb","F1,!tlabel",lbl->key+100);
4762 emitcode ("setb","EA");
4763 emitcode("","!tlabeldef",lbl->key+100);
4767 /*-----------------------------------------------------------------*/
4768 /* genMult - generates code for multiplication */
4769 /*-----------------------------------------------------------------*/
4771 genMult (iCode * ic)
4773 operand *left = IC_LEFT (ic);
4774 operand *right = IC_RIGHT (ic);
4775 operand *result = IC_RESULT (ic);
4777 D (emitcode (";", "genMult "););
4779 /* assign the amsops */
4782 /* special cases first */
4784 if (AOP_TYPE (left) == AOP_CRY &&
4785 AOP_TYPE (right) == AOP_CRY)
4787 genMultbits (left, right, result, ic);
4791 /* if both are of size == 1 */
4792 if (AOP_SIZE (left) == 1 &&
4793 AOP_SIZE (right) == 1)
4795 genMultOneByte (left, right, result, ic);
4799 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4800 /* use the ds390 ARITHMETIC accel UNIT */
4801 genMultTwoByte (left, right, result, ic);
4804 /* should have been converted to function call */
4808 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4809 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4810 freeAsmop (result, NULL, ic, TRUE);
4813 /*-----------------------------------------------------------------*/
4814 /* genDivbits :- division of bits */
4815 /*-----------------------------------------------------------------*/
4817 genDivbits (operand * left,
4825 /* the result must be bit */
4826 LOAD_AB_FOR_DIV (left, right, l);
4827 emitcode ("div", "ab");
4828 emitcode ("rrc", "a");
4829 aopOp(result, ic, TRUE, FALSE);
4831 aopPut (AOP (result), "c", 0);
4834 /*-----------------------------------------------------------------*/
4835 /* genDivOneByte : 8 bit division */
4836 /*-----------------------------------------------------------------*/
4838 genDivOneByte (operand * left,
4843 sym_link *opetype = operandType (result);
4849 /* signed or unsigned */
4850 if (SPEC_USIGN (opetype))
4852 /* unsigned is easy */
4853 LOAD_AB_FOR_DIV (left, right, l);
4854 emitcode ("div", "ab");
4857 aopOp(result, ic, TRUE, FALSE);
4858 aopPut (AOP (result), "a", 0);
4861 size = AOP_SIZE (result) - 1;
4865 aopPut (AOP (result), zero, offset++);
4870 /* signed is a little bit more difficult */
4872 /* save the signs of the operands */
4873 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4874 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4875 emitcode ("push", "acc"); /* save it on the stack */
4877 /* now sign adjust for both left & right */
4878 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4879 lbl = newiTempLabel (NULL);
4880 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4881 emitcode ("cpl", "a");
4882 emitcode ("inc", "a");
4883 emitcode ("", "!tlabeldef", (lbl->key + 100));
4884 emitcode ("mov", "b,a");
4886 /* sign adjust left side */
4887 MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4889 lbl = newiTempLabel (NULL);
4890 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4891 emitcode ("cpl", "a");
4892 emitcode ("inc", "a");
4893 emitcode ("", "!tlabeldef", (lbl->key + 100));
4895 /* now the division */
4896 emitcode ("nop", "; workaround for DS80C390 div bug.");
4897 emitcode ("div", "ab");
4898 /* we are interested in the lower order
4900 emitcode ("mov", "b,a");
4901 lbl = newiTempLabel (NULL);
4902 emitcode ("pop", "acc");
4903 /* if there was an over flow we don't
4904 adjust the sign of the result */
4905 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4906 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4908 emitcode ("clr", "a");
4909 emitcode ("subb", "a,b");
4910 emitcode ("mov", "b,a");
4911 emitcode ("", "!tlabeldef", (lbl->key + 100));
4913 /* now we are done */
4914 _G.accInUse++; _G.bInUse++;
4915 aopOp(result, ic, TRUE, FALSE);
4917 aopPut (AOP (result), "b", 0);
4919 size = AOP_SIZE (result) - 1;
4923 emitcode ("mov", "c,b.7");
4924 emitcode ("subb", "a,acc");
4928 aopPut (AOP (result), "a", offset++);
4930 _G.accInUse--; _G.bInUse--;
4934 /*-----------------------------------------------------------------*/
4935 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
4936 /*-----------------------------------------------------------------*/
4937 static void genDivTwoByte (operand *left, operand *right,
4938 operand *result, iCode *ic)
4940 sym_link *retype = getSpec(operandType(right));
4941 sym_link *letype = getSpec(operandType(left));
4942 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4945 /* save EA bit in F1 */
4946 lbl = newiTempLabel(NULL);
4947 emitcode ("setb","F1");
4948 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4949 emitcode ("clr","F1");
4950 emitcode("","!tlabeldef",lbl->key+100);
4952 /* load up MA with left */
4954 emitcode("clr","F0");
4955 lbl = newiTempLabel(NULL);
4956 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4957 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4958 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4959 emitcode ("xch", "a,b");
4960 emitcode ("cpl","a");
4961 emitcode ("add", "a,#1");
4962 emitcode ("xch", "a,b");
4963 emitcode ("cpl", "a"); // msb
4964 emitcode ("addc","a,#0");
4965 emitcode ("setb","F0");
4966 emitcode ("","!tlabeldef",lbl->key+100);
4967 emitcode ("mov","ma,b");
4968 emitcode ("mov","ma,a");
4970 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4971 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4974 /* load up MB with right */
4976 if (AOP_TYPE(right) == AOP_LIT) {
4977 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4979 lbl = newiTempLabel(NULL);
4980 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4981 emitcode("setb","F0");
4982 emitcode ("","!tlabeldef",lbl->key+100);
4985 emitcode ("mov","mb,#!constbyte",val & 0xff);
4986 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4988 lbl = newiTempLabel(NULL);
4989 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4990 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4991 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4992 emitcode ("xch", "a,b");
4993 emitcode ("cpl","a");
4994 emitcode ("add", "a,#1");
4995 emitcode ("xch", "a,b");
4996 emitcode ("cpl", "a"); // msb
4997 emitcode ("addc", "a,#0");
4998 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4999 emitcode ("setb","F0");
5000 emitcode ("","!tlabeldef",lbl->key+100);
5001 emitcode ("mov","mb,b");
5002 emitcode ("mov","mb,a");
5005 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5006 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5009 /* wait for multiplication to finish */
5010 lbl = newiTempLabel(NULL);
5011 emitcode("","!tlabeldef", lbl->key+100);
5012 emitcode("mov","a,mcnt1");
5013 emitcode("anl","a,#!constbyte",0x80);
5014 emitcode("jnz","!tlabel",lbl->key+100);
5016 freeAsmop (left, NULL, ic, TRUE);
5017 freeAsmop (right, NULL, ic,TRUE);
5018 aopOp(result, ic, TRUE, FALSE);
5020 /* if unsigned then simple */
5022 aopPut(AOP(result),"ma",1);
5023 aopPut(AOP(result),"ma",0);
5025 emitcode("push","ma");
5027 /* negate result if needed */
5028 lbl = newiTempLabel(NULL);
5029 emitcode("jnb","F0,!tlabel",lbl->key+100);
5030 emitcode("cpl","a");
5031 emitcode("add","a,#1");
5032 emitcode("","!tlabeldef", lbl->key+100);
5033 aopPut(AOP(result),"a",0);
5034 emitcode("pop","acc");
5035 lbl = newiTempLabel(NULL);
5036 emitcode("jnb","F0,!tlabel",lbl->key+100);
5037 emitcode("cpl","a");
5038 emitcode("addc","a,#0");
5039 emitcode("","!tlabeldef", lbl->key+100);
5040 aopPut(AOP(result),"a",1);
5042 freeAsmop (result, NULL, ic, TRUE);
5043 /* restore EA bit in F1 */
5044 lbl = newiTempLabel(NULL);
5045 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5046 emitcode ("setb","EA");
5047 emitcode("","!tlabeldef",lbl->key+100);
5051 /*-----------------------------------------------------------------*/
5052 /* genDiv - generates code for division */
5053 /*-----------------------------------------------------------------*/
5057 operand *left = IC_LEFT (ic);
5058 operand *right = IC_RIGHT (ic);
5059 operand *result = IC_RESULT (ic);
5061 D (emitcode (";", "genDiv "););
5063 /* assign the amsops */
5066 /* special cases first */
5068 if (AOP_TYPE (left) == AOP_CRY &&
5069 AOP_TYPE (right) == AOP_CRY)
5071 genDivbits (left, right, result, ic);
5075 /* if both are of size == 1 */
5076 if (AOP_SIZE (left) == 1 &&
5077 AOP_SIZE (right) == 1)
5079 genDivOneByte (left, right, result, ic);
5083 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5084 /* use the ds390 ARITHMETIC accel UNIT */
5085 genDivTwoByte (left, right, result, ic);
5088 /* should have been converted to function call */
5091 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5092 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5093 freeAsmop (result, NULL, ic, TRUE);
5096 /*-----------------------------------------------------------------*/
5097 /* genModbits :- modulus of bits */
5098 /*-----------------------------------------------------------------*/
5100 genModbits (operand * left,
5108 /* the result must be bit */
5109 LOAD_AB_FOR_DIV (left, right, l);
5110 emitcode ("div", "ab");
5111 emitcode ("mov", "a,b");
5112 emitcode ("rrc", "a");
5113 aopOp(result, ic, TRUE, FALSE);
5114 aopPut (AOP (result), "c", 0);
5117 /*-----------------------------------------------------------------*/
5118 /* genModOneByte : 8 bit modulus */
5119 /*-----------------------------------------------------------------*/
5121 genModOneByte (operand * left,
5126 sym_link *opetype = operandType (result);
5130 /* signed or unsigned */
5131 if (SPEC_USIGN (opetype))
5133 /* unsigned is easy */
5134 LOAD_AB_FOR_DIV (left, right, l);
5135 emitcode ("div", "ab");
5136 aopOp(result, ic, TRUE, FALSE);
5137 aopPut (AOP (result), "b", 0);
5141 /* signed is a little bit more difficult */
5143 /* save the signs of the operands */
5144 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5146 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
5147 emitcode ("push", "acc"); /* save it on the stack */
5149 /* now sign adjust for both left & right */
5150 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5152 lbl = newiTempLabel (NULL);
5153 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5154 emitcode ("cpl", "a");
5155 emitcode ("inc", "a");
5156 emitcode ("", "!tlabeldef", (lbl->key + 100));
5157 emitcode ("mov", "b,a");
5159 /* sign adjust left side */
5160 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5162 lbl = newiTempLabel (NULL);
5163 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5164 emitcode ("cpl", "a");
5165 emitcode ("inc", "a");
5166 emitcode ("", "!tlabeldef", (lbl->key + 100));
5168 /* now the multiplication */
5169 emitcode ("nop", "; workaround for DS80C390 div bug.");
5170 emitcode ("div", "ab");
5171 /* we are interested in the lower order
5173 lbl = newiTempLabel (NULL);
5174 emitcode ("pop", "acc");
5175 /* if there was an over flow we don't
5176 adjust the sign of the result */
5177 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
5178 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5180 emitcode ("clr", "a");
5181 emitcode ("subb", "a,b");
5182 emitcode ("mov", "b,a");
5183 emitcode ("", "!tlabeldef", (lbl->key + 100));
5186 /* now we are done */
5187 aopOp(result, ic, TRUE, FALSE);
5188 aopPut (AOP (result), "b", 0);
5193 /*-----------------------------------------------------------------*/
5194 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
5195 /*-----------------------------------------------------------------*/
5196 static void genModTwoByte (operand *left, operand *right,
5197 operand *result, iCode *ic)
5199 sym_link *retype = getSpec(operandType(right));
5200 sym_link *letype = getSpec(operandType(left));
5201 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5204 /* load up MA with left */
5205 /* save EA bit in F1 */
5206 lbl = newiTempLabel(NULL);
5207 emitcode ("setb","F1");
5208 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5209 emitcode ("clr","F1");
5210 emitcode("","!tlabeldef",lbl->key+100);
5213 lbl = newiTempLabel(NULL);
5214 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5215 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5216 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5217 emitcode ("xch", "a,b");
5218 emitcode ("cpl","a");
5219 emitcode ("add", "a,#1");
5220 emitcode ("xch", "a,b");
5221 emitcode ("cpl", "a"); // msb
5222 emitcode ("addc","a,#0");
5223 emitcode ("","!tlabeldef",lbl->key+100);
5224 emitcode ("mov","ma,b");
5225 emitcode ("mov","ma,a");
5227 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5228 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5231 /* load up MB with right */
5233 if (AOP_TYPE(right) == AOP_LIT) {
5234 int val=floatFromVal (AOP (right)->aopu.aop_lit);
5238 emitcode ("mov","mb,#!constbyte",val & 0xff);
5239 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5241 lbl = newiTempLabel(NULL);
5242 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5243 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5244 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5245 emitcode ("xch", "a,b");
5246 emitcode ("cpl","a");
5247 emitcode ("add", "a,#1");
5248 emitcode ("xch", "a,b");
5249 emitcode ("cpl", "a"); // msb
5250 emitcode ("addc", "a,#0");
5251 emitcode ("","!tlabeldef",lbl->key+100);
5252 emitcode ("mov","mb,b");
5253 emitcode ("mov","mb,a");
5256 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5257 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5260 /* wait for multiplication to finish */
5261 lbl = newiTempLabel(NULL);
5262 emitcode("","!tlabeldef", lbl->key+100);
5263 emitcode("mov","a,mcnt1");
5264 emitcode("anl","a,#!constbyte",0x80);
5265 emitcode("jnz","!tlabel",lbl->key+100);
5267 freeAsmop (left, NULL, ic, TRUE);
5268 freeAsmop (right, NULL, ic,TRUE);
5269 aopOp(result, ic, TRUE, FALSE);
5271 aopPut(AOP(result),"mb",1);
5272 aopPut(AOP(result),"mb",0);
5273 freeAsmop (result, NULL, ic, TRUE);
5275 /* restore EA bit in F1 */
5276 lbl = newiTempLabel(NULL);
5277 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5278 emitcode ("setb","EA");
5279 emitcode("","!tlabeldef",lbl->key+100);
5283 /*-----------------------------------------------------------------*/
5284 /* genMod - generates code for division */
5285 /*-----------------------------------------------------------------*/
5289 operand *left = IC_LEFT (ic);
5290 operand *right = IC_RIGHT (ic);
5291 operand *result = IC_RESULT (ic);
5293 D (emitcode (";", "genMod "); );
5295 /* assign the amsops */
5298 /* special cases first */
5300 if (AOP_TYPE (left) == AOP_CRY &&
5301 AOP_TYPE (right) == AOP_CRY)
5303 genModbits (left, right, result, ic);
5307 /* if both are of size == 1 */
5308 if (AOP_SIZE (left) == 1 &&
5309 AOP_SIZE (right) == 1)
5311 genModOneByte (left, right, result, ic);
5315 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5316 /* use the ds390 ARITHMETIC accel UNIT */
5317 genModTwoByte (left, right, result, ic);
5321 /* should have been converted to function call */
5325 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5326 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5327 freeAsmop (result, NULL, ic, TRUE);
5330 /*-----------------------------------------------------------------*/
5331 /* genIfxJump :- will create a jump depending on the ifx */
5332 /*-----------------------------------------------------------------*/
5334 genIfxJump (iCode * ic, char *jval)
5337 symbol *tlbl = newiTempLabel (NULL);
5340 D (emitcode (";", "genIfxJump"););
5342 /* if true label then we jump if condition
5346 jlbl = IC_TRUE (ic);
5347 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5348 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5352 /* false label is present */
5353 jlbl = IC_FALSE (ic);
5354 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5355 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5357 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5358 emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5360 emitcode (inst, "!tlabel", tlbl->key + 100);
5361 emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5362 emitcode ("", "!tlabeldef", tlbl->key + 100);
5364 /* mark the icode as generated */
5368 /*-----------------------------------------------------------------*/
5369 /* genCmp :- greater or less than comparison */
5370 /*-----------------------------------------------------------------*/
5372 genCmp (operand * left, operand * right,
5373 iCode * ic, iCode * ifx, int sign)
5375 int size, offset = 0;
5376 unsigned long lit = 0L;
5379 D (emitcode (";", "genCmp"););
5381 result = IC_RESULT (ic);
5383 /* if left & right are bit variables */
5384 if (AOP_TYPE (left) == AOP_CRY &&
5385 AOP_TYPE (right) == AOP_CRY)
5387 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5388 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
5392 /* subtract right from left if at the
5393 end the carry flag is set then we know that
5394 left is greater than right */
5395 size = max (AOP_SIZE (left), AOP_SIZE (right));
5397 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5398 if ((size == 1) && !sign
5399 && (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5401 symbol *lbl = newiTempLabel (NULL);
5402 emitcode ("cjne", "%s,%s,!tlabel",
5403 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
5404 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5406 emitcode ("", "!tlabeldef", lbl->key + 100);
5410 if (AOP_TYPE (right) == AOP_LIT)
5412 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5413 /* optimize if(x < 0) or if(x >= 0) */
5422 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
5424 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5425 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5427 aopOp (result, ic, FALSE, FALSE);
5429 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5431 freeAsmop (result, NULL, ic, TRUE);
5432 genIfxJump (ifx, "acc.7");
5437 emitcode ("rlc", "a");
5439 goto release_freedLR;
5447 // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5448 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5449 // emitcode (";", "genCmp #2");
5450 if (sign && (size == 0))
5452 // emitcode (";", "genCmp #3");
5453 emitcode ("xrl", "a,#!constbyte",0x80);
5454 if (AOP_TYPE (right) == AOP_LIT)
5456 unsigned long lit = (unsigned long)
5457 floatFromVal (AOP (right)->aopu.aop_lit);
5458 // emitcode (";", "genCmp #3.1");
5459 emitcode ("subb", "a,#!constbyte",
5460 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5464 // emitcode (";", "genCmp #3.2");
5466 MOVB(aopGet (AOP (right), offset++, FALSE, FALSE, "b"));
5467 saveAccWarn = DEFAULT_ACC_WARNING;
5468 emitcode ("xrl", "b,#!constbyte",0x80);
5469 emitcode ("subb", "a,b");
5476 // emitcode (";", "genCmp #4");
5478 s = aopGet (AOP (right), offset++, FALSE, FALSE, "b");
5479 saveAccWarn = DEFAULT_ACC_WARNING;
5481 emitcode ("subb", "a,%s", s);
5488 /* Don't need the left & right operands any more; do need the result. */
5489 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5490 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5492 aopOp (result, ic, FALSE, FALSE);
5496 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5502 /* if the result is used in the next
5503 ifx conditional branch then generate
5504 code a little differently */
5507 genIfxJump (ifx, "c");
5513 /* leave the result in acc */
5515 freeAsmop (result, NULL, ic, TRUE);
5518 /*-----------------------------------------------------------------*/
5519 /* genCmpGt :- greater than comparison */
5520 /*-----------------------------------------------------------------*/
5522 genCmpGt (iCode * ic, iCode * ifx)
5524 operand *left, *right;
5525 sym_link *letype, *retype;
5528 D (emitcode (";", "genCmpGt ");
5531 left = IC_LEFT (ic);
5532 right = IC_RIGHT (ic);
5534 letype = getSpec (operandType (left));
5535 retype = getSpec (operandType (right));
5536 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5538 /* assign the left & right amsops */
5541 genCmp (right, left, ic, ifx, sign);
5544 /*-----------------------------------------------------------------*/
5545 /* genCmpLt - less than comparisons */
5546 /*-----------------------------------------------------------------*/
5548 genCmpLt (iCode * ic, iCode * ifx)
5550 operand *left, *right;
5551 sym_link *letype, *retype;
5554 D (emitcode (";", "genCmpLt "););
5556 left = IC_LEFT (ic);
5557 right = IC_RIGHT (ic);
5559 letype = getSpec (operandType (left));
5560 retype = getSpec (operandType (right));
5561 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5563 /* assign the left & right amsops */
5566 genCmp (left, right, ic, ifx, sign);
5569 /*-----------------------------------------------------------------*/
5570 /* gencjneshort - compare and jump if not equal */
5571 /*-----------------------------------------------------------------*/
5573 gencjneshort (operand * left, operand * right, symbol * lbl)
5575 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5577 unsigned long lit = 0L;
5579 D (emitcode (";", "gencjneshort");
5582 /* if the left side is a literal or
5583 if the right is in a pointer register and left
5585 if ((AOP_TYPE (left) == AOP_LIT) ||
5586 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5593 if (AOP_TYPE (right) == AOP_LIT)
5594 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5596 if (opIsGptr (left) || opIsGptr (right))
5598 /* We are comparing a generic pointer to something.
5599 * Exclude the generic type byte from the comparison.
5602 D (emitcode (";", "cjneshort: generic ptr special case."););
5606 /* if the right side is a literal then anything goes */
5607 if (AOP_TYPE (right) == AOP_LIT &&
5608 AOP_TYPE (left) != AOP_DIR)
5612 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5613 emitcode ("cjne", "a,%s,!tlabel",
5614 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5620 /* if the right side is in a register or in direct space or
5621 if the left is a pointer register & right is not */
5622 else if (AOP_TYPE (right) == AOP_REG ||
5623 AOP_TYPE (right) == AOP_DIR ||
5624 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5625 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5629 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5630 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5631 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5632 emitcode ("jnz", "!tlabel", lbl->key + 100);
5634 emitcode ("cjne", "a,%s,!tlabel",
5635 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
5642 /* right is a pointer reg need both a & b */
5645 MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5646 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
5647 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5653 /*-----------------------------------------------------------------*/
5654 /* gencjne - compare and jump if not equal */
5655 /*-----------------------------------------------------------------*/
5657 gencjne (operand * left, operand * right, symbol * lbl)
5659 symbol *tlbl = newiTempLabel (NULL);
5661 D (emitcode (";", "gencjne");
5664 gencjneshort (left, right, lbl);
5666 emitcode ("mov", "a,%s", one);
5667 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5668 emitcode ("", "!tlabeldef", lbl->key + 100);
5669 emitcode ("clr", "a");
5670 emitcode ("", "!tlabeldef", tlbl->key + 100);
5673 /*-----------------------------------------------------------------*/
5674 /* genCmpEq - generates code for equal to */
5675 /*-----------------------------------------------------------------*/
5677 genCmpEq (iCode * ic, iCode * ifx)
5679 operand *left, *right, *result;
5681 D (emitcode (";", "genCmpEq ");
5685 AOP_SET_LOCALS (ic);
5687 /* if literal, literal on the right or
5688 if the right is in a pointer register and left
5690 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5691 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5693 operand *t = IC_RIGHT (ic);
5694 IC_RIGHT (ic) = IC_LEFT (ic);
5698 if (ifx && /* !AOP_SIZE(result) */
5699 OP_SYMBOL (result) &&
5700 OP_SYMBOL (result)->regType == REG_CND)
5703 /* if they are both bit variables */
5704 if (AOP_TYPE (left) == AOP_CRY &&
5705 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5707 if (AOP_TYPE (right) == AOP_LIT)
5709 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5712 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5713 emitcode ("cpl", "c");
5717 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5721 emitcode ("clr", "c");
5723 /* AOP_TYPE(right) == AOP_CRY */
5727 symbol *lbl = newiTempLabel (NULL);
5728 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5729 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5730 emitcode ("cpl", "c");
5731 emitcode ("", "!tlabeldef", (lbl->key + 100));
5733 /* if true label then we jump if condition
5735 tlbl = newiTempLabel (NULL);
5738 emitcode ("jnc", "!tlabel", tlbl->key + 100);
5739 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5743 emitcode ("jc", "!tlabel", tlbl->key + 100);
5744 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5746 emitcode ("", "!tlabeldef", tlbl->key + 100);
5750 tlbl = newiTempLabel (NULL);
5751 gencjneshort (left, right, tlbl);
5754 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5755 emitcode ("", "!tlabeldef", tlbl->key + 100);
5759 symbol *lbl = newiTempLabel (NULL);
5760 emitcode ("sjmp", "!tlabel", lbl->key + 100);
5761 emitcode ("", "!tlabeldef", tlbl->key + 100);
5762 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5763 emitcode ("", "!tlabeldef", lbl->key + 100);
5766 /* mark the icode as generated */
5769 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5770 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5774 /* if they are both bit variables */
5775 if (AOP_TYPE (left) == AOP_CRY &&
5776 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5778 if (AOP_TYPE (right) == AOP_LIT)
5780 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5783 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5784 emitcode ("cpl", "c");
5788 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5792 emitcode ("clr", "c");
5794 /* AOP_TYPE(right) == AOP_CRY */
5798 symbol *lbl = newiTempLabel (NULL);
5799 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5800 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5801 emitcode ("cpl", "c");
5802 emitcode ("", "!tlabeldef", (lbl->key + 100));
5805 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5806 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5808 aopOp (result, ic, TRUE, FALSE);
5811 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5818 genIfxJump (ifx, "c");
5821 /* if the result is used in an arithmetic operation
5822 then put the result in place */
5827 gencjne (left, right, newiTempLabel (NULL));
5829 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5830 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5832 aopOp (result, ic, TRUE, FALSE);
5834 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5836 aopPut (AOP (result), "a", 0);
5841 genIfxJump (ifx, "a");
5844 /* if the result is used in an arithmetic operation
5845 then put the result in place */
5846 if (AOP_TYPE (result) != AOP_CRY)
5848 /* leave the result in acc */
5852 freeAsmop (result, NULL, ic, TRUE);
5855 /*-----------------------------------------------------------------*/
5856 /* ifxForOp - returns the icode containing the ifx for operand */
5857 /*-----------------------------------------------------------------*/
5859 ifxForOp (operand * op, iCode * ic)
5861 /* if true symbol then needs to be assigned */
5862 if (IS_TRUE_SYMOP (op))
5865 /* if this has register type condition and
5866 the next instruction is ifx with the same operand
5867 and live to of the operand is upto the ifx only then */
5869 ic->next->op == IFX &&
5870 IC_COND (ic->next)->key == op->key &&
5871 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5876 /*-----------------------------------------------------------------*/
5877 /* hasInc - operand is incremented before any other use */
5878 /*-----------------------------------------------------------------*/
5880 hasInc (operand *op, iCode *ic, int osize)
5882 sym_link *type = operandType(op);
5883 sym_link *retype = getSpec (type);
5884 iCode *lic = ic->next;
5887 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5888 if (!IS_SYMOP(op)) return NULL;
5890 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5891 if (IS_AGGREGATE(type->next)) return NULL;
5892 if (osize != (isize = getSize(type->next))) return NULL;
5895 /* if operand of the form op = op + <sizeof *op> */
5896 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5897 isOperandEqual(IC_RESULT(lic),op) &&
5898 isOperandLiteral(IC_RIGHT(lic)) &&
5899 operandLitValue(IC_RIGHT(lic)) == isize) {
5902 /* if the operand used or deffed */
5903 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5906 /* if GOTO or IFX */
5907 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5913 /*-----------------------------------------------------------------*/
5914 /* genAndOp - for && operation */
5915 /*-----------------------------------------------------------------*/
5917 genAndOp (iCode * ic)
5919 operand *left, *right, *result;
5922 D (emitcode (";", "genAndOp "););
5924 /* note here that && operations that are in an
5925 if statement are taken away by backPatchLabels
5926 only those used in arthmetic operations remain */
5928 AOP_SET_LOCALS (ic);
5930 /* if both are bit variables */
5931 if (AOP_TYPE (left) == AOP_CRY &&
5932 AOP_TYPE (right) == AOP_CRY)
5934 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5935 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5936 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5937 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5939 aopOp (result,ic,FALSE, FALSE);
5944 tlbl = newiTempLabel (NULL);
5946 emitcode ("jz", "!tlabel", tlbl->key + 100);
5948 emitcode ("", "!tlabeldef", tlbl->key + 100);
5949 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5950 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5952 aopOp (result,ic,FALSE, FALSE);
5955 freeAsmop (result, NULL, ic, TRUE);
5959 /*-----------------------------------------------------------------*/
5960 /* genOrOp - for || operation */
5961 /*-----------------------------------------------------------------*/
5963 genOrOp (iCode * ic)
5965 operand *left, *right, *result;
5968 D (emitcode (";", "genOrOp "););
5970 /* note here that || operations that are in an
5971 if statement are taken away by backPatchLabels
5972 only those used in arthmetic operations remain */
5974 AOP_SET_LOCALS (ic);
5976 /* if both are bit variables */
5977 if (AOP_TYPE (left) == AOP_CRY &&
5978 AOP_TYPE (right) == AOP_CRY)
5980 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5981 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5982 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5983 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5985 aopOp (result,ic,FALSE, FALSE);
5991 tlbl = newiTempLabel (NULL);
5993 emitcode ("jnz", "!tlabel", tlbl->key + 100);
5995 emitcode ("", "!tlabeldef", tlbl->key + 100);
5996 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5997 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5999 aopOp (result,ic,FALSE, FALSE);
6004 freeAsmop (result, NULL, ic, TRUE);
6007 /*-----------------------------------------------------------------*/
6008 /* isLiteralBit - test if lit == 2^n */
6009 /*-----------------------------------------------------------------*/
6011 isLiteralBit (unsigned long lit)
6013 unsigned long pw[32] =
6014 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6015 0x100L, 0x200L, 0x400L, 0x800L,
6016 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6017 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6018 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6019 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6020 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6023 for (idx = 0; idx < 32; idx++)
6029 /*-----------------------------------------------------------------*/
6030 /* continueIfTrue - */
6031 /*-----------------------------------------------------------------*/
6033 continueIfTrue (iCode * ic)
6036 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6040 /*-----------------------------------------------------------------*/
6042 /*-----------------------------------------------------------------*/
6044 jumpIfTrue (iCode * ic)
6047 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6051 /*-----------------------------------------------------------------*/
6052 /* jmpTrueOrFalse - */
6053 /*-----------------------------------------------------------------*/
6055 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6057 // ugly but optimized by peephole
6060 symbol *nlbl = newiTempLabel (NULL);
6061 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6062 emitcode ("", "!tlabeldef", tlbl->key + 100);
6063 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6064 emitcode ("", "!tlabeldef", nlbl->key + 100);
6068 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6069 emitcode ("", "!tlabeldef", tlbl->key + 100);
6074 // Generate code to perform a bit-wise logic operation
6075 // on two operands in far space (assumed to already have been
6076 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6077 // in far space. This requires pushing the result on the stack
6078 // then popping it into the result.
6080 genFarFarLogicOp(iCode *ic, char *logicOp)
6082 int size, resultSize, compSize;
6086 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6087 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
6088 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6090 _startLazyDPSEvaluation();
6091 for (size = compSize; (size--); offset++)
6093 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6094 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6095 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6097 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6098 emitcode ("push", "acc");
6100 _endLazyDPSEvaluation();
6102 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6103 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6104 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6106 resultSize = AOP_SIZE(IC_RESULT(ic));
6108 ADJUST_PUSHED_RESULT(compSize, resultSize);
6110 _startLazyDPSEvaluation();
6113 emitcode ("pop", "acc");
6114 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6116 _endLazyDPSEvaluation();
6117 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6121 /*-----------------------------------------------------------------*/
6122 /* genAnd - code for and */
6123 /*-----------------------------------------------------------------*/
6125 genAnd (iCode * ic, iCode * ifx)
6127 operand *left, *right, *result;
6128 int size, offset = 0;
6129 unsigned long lit = 0L;
6134 D (emitcode (";", "genAnd "););
6136 AOP_OP_3_NOFATAL (ic, pushResult);
6137 AOP_SET_LOCALS (ic);
6141 genFarFarLogicOp(ic, "anl");
6146 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6148 AOP_TYPE (left), AOP_TYPE (right));
6149 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6151 AOP_SIZE (left), AOP_SIZE (right));
6154 /* if left is a literal & right is not then exchange them */
6155 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6156 #ifdef LOGIC_OPS_BROKEN
6157 || AOP_NEEDSACC (left)
6161 operand *tmp = right;
6166 /* if result = right then exchange them */
6167 if (sameRegs (AOP (result), AOP (right)))
6169 operand *tmp = right;
6174 /* if right is bit then exchange them */
6175 if (AOP_TYPE (right) == AOP_CRY &&
6176 AOP_TYPE (left) != AOP_CRY)
6178 operand *tmp = right;
6182 if (AOP_TYPE (right) == AOP_LIT)
6183 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6185 size = AOP_SIZE (result);
6188 // result = bit & yy;
6189 if (AOP_TYPE (left) == AOP_CRY)
6191 // c = bit & literal;
6192 if (AOP_TYPE (right) == AOP_LIT)
6196 if (size && sameRegs (AOP (result), AOP (left)))
6199 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6204 if (size && (AOP_TYPE (result) == AOP_CRY))
6206 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6209 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6214 emitcode ("clr", "c");
6219 if (AOP_TYPE (right) == AOP_CRY)
6222 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6223 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6228 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6230 emitcode ("rrc", "a");
6231 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6239 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6240 genIfxJump (ifx, "c");
6244 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6245 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6246 if ((AOP_TYPE (right) == AOP_LIT) &&
6247 (AOP_TYPE (result) == AOP_CRY) &&
6248 (AOP_TYPE (left) != AOP_CRY))
6250 int posbit = isLiteralBit (lit);
6255 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6258 emitcode ("mov", "c,acc.%d", posbit & 0x07);
6264 SNPRINTF (buff, sizeof(buff),
6265 "acc.%d", posbit & 0x07);
6266 genIfxJump (ifx, buff);
6270 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6277 symbol *tlbl = newiTempLabel (NULL);
6278 int sizel = AOP_SIZE (left);
6280 emitcode ("setb", "c");
6283 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6285 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6287 if ((posbit = isLiteralBit (bytelit)) != 0)
6288 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6291 if (bytelit != 0x0FFL)
6292 emitcode ("anl", "a,%s",
6293 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6294 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6299 // bit = left & literal
6302 emitcode ("clr", "c");
6303 emitcode ("", "!tlabeldef", tlbl->key + 100);
6305 // if(left & literal)
6309 jmpTrueOrFalse (ifx, tlbl);
6317 /* if left is same as result */
6318 if (sameRegs (AOP (result), AOP (left)))
6320 for (; size--; offset++)
6322 if (AOP_TYPE (right) == AOP_LIT)
6324 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6326 else if (bytelit == 0)
6327 aopPut (AOP (result), zero, offset);
6328 else if (IS_AOP_PREG (result))
6330 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6331 emitcode ("anl", "a,%s",
6332 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6333 aopPut (AOP (result), "a", offset);
6336 emitcode ("anl", "%s,%s",
6337 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6338 aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6342 if (AOP_TYPE (left) == AOP_ACC)
6343 emitcode ("anl", "a,%s",
6344 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6347 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6348 if (IS_AOP_PREG (result))
6350 emitcode ("anl", "a,%s",
6351 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6352 aopPut (AOP (result), "a", offset);
6355 emitcode ("anl", "%s,a",
6356 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6363 // left & result in different registers
6364 if (AOP_TYPE (result) == AOP_CRY)
6367 // if(size), result in bit
6368 // if(!size && ifx), conditional oper: if(left & right)
6369 symbol *tlbl = newiTempLabel (NULL);
6370 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6372 emitcode ("setb", "c");
6375 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6376 emitcode ("anl", "a,%s",
6377 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6379 if (AOP_TYPE(left)==AOP_ACC) {
6380 emitcode("mov", "b,a");
6381 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6382 emitcode("anl", "a,b");
6384 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6385 emitcode ("anl", "a,%s",
6386 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6389 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6395 emitcode ("", "!tlabeldef", tlbl->key + 100);
6399 jmpTrueOrFalse (ifx, tlbl);
6403 for (; (size--); offset++)
6406 // result = left & right
6407 if (AOP_TYPE (right) == AOP_LIT)
6409 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6411 aopPut (AOP (result),
6412 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6416 else if (bytelit == 0)
6418 aopPut (AOP (result), zero, offset);
6421 D (emitcode (";", "better literal AND."););
6422 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6423 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6424 FALSE, FALSE, DP2_RESULT_REG));
6429 // faster than result <- left, anl result,right
6430 // and better if result is SFR
6431 if (AOP_TYPE (left) == AOP_ACC)
6433 emitcode ("anl", "a,%s",
6434 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6438 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6439 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6441 emitcode("mov", "b,a");
6445 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6446 emitcode ("anl", "a,%s", rOp);
6449 aopPut (AOP (result), "a", offset);
6455 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6456 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6457 freeAsmop (result, NULL, ic, TRUE);
6461 /*-----------------------------------------------------------------*/
6462 /* genOr - code for or */
6463 /*-----------------------------------------------------------------*/
6465 genOr (iCode * ic, iCode * ifx)
6467 operand *left, *right, *result;
6468 int size, offset = 0;
6469 unsigned long lit = 0L;
6472 D (emitcode (";", "genOr "););
6474 AOP_OP_3_NOFATAL (ic, pushResult);
6475 AOP_SET_LOCALS (ic);
6479 genFarFarLogicOp(ic, "orl");
6485 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6487 AOP_TYPE (left), AOP_TYPE (right));
6488 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6490 AOP_SIZE (left), AOP_SIZE (right));
6493 /* if left is a literal & right is not then exchange them */
6494 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6495 #ifdef LOGIC_OPS_BROKEN
6496 || AOP_NEEDSACC (left) // I think this is a net loss now.
6500 operand *tmp = right;
6505 /* if result = right then exchange them */
6506 if (sameRegs (AOP (result), AOP (right)))
6508 operand *tmp = right;
6513 /* if right is bit then exchange them */
6514 if (AOP_TYPE (right) == AOP_CRY &&
6515 AOP_TYPE (left) != AOP_CRY)
6517 operand *tmp = right;
6521 if (AOP_TYPE (right) == AOP_LIT)
6522 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6524 size = AOP_SIZE (result);
6528 if (AOP_TYPE (left) == AOP_CRY)
6530 if (AOP_TYPE (right) == AOP_LIT)
6532 // c = bit & literal;
6535 // lit != 0 => result = 1
6536 if (AOP_TYPE (result) == AOP_CRY)
6539 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6541 continueIfTrue (ifx);
6544 emitcode ("setb", "c");
6548 // lit == 0 => result = left
6549 if (size && sameRegs (AOP (result), AOP (left)))
6551 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6556 if (AOP_TYPE (right) == AOP_CRY)
6559 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6560 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6565 symbol *tlbl = newiTempLabel (NULL);
6566 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6567 emitcode ("setb", "c");
6568 emitcode ("jb", "%s,!tlabel",
6569 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6571 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6572 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6574 jmpTrueOrFalse (ifx, tlbl);
6580 emitcode ("", "!tlabeldef", tlbl->key + 100);
6589 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6590 genIfxJump (ifx, "c");
6594 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6595 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6596 if ((AOP_TYPE (right) == AOP_LIT) &&
6597 (AOP_TYPE (result) == AOP_CRY) &&
6598 (AOP_TYPE (left) != AOP_CRY))
6604 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6606 continueIfTrue (ifx);
6611 // lit = 0, result = boolean(left)
6613 emitcode ("setb", "c");
6617 symbol *tlbl = newiTempLabel (NULL);
6618 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6620 emitcode ("", "!tlabeldef", tlbl->key + 100);
6624 genIfxJump (ifx, "a");
6632 /* if left is same as result */
6633 if (sameRegs (AOP (result), AOP (left)))
6635 for (; size--; offset++)
6637 if (AOP_TYPE (right) == AOP_LIT)
6639 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6645 if (IS_AOP_PREG (left))
6647 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6648 emitcode ("orl", "a,%s",
6649 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6650 aopPut (AOP (result), "a", offset);
6654 emitcode ("orl", "%s,%s",
6655 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6656 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6662 if (AOP_TYPE (left) == AOP_ACC)
6664 emitcode ("orl", "a,%s",
6665 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6669 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6670 if (IS_AOP_PREG (left))
6672 emitcode ("orl", "a,%s",
6673 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6674 aopPut (AOP (result), "a", offset);
6678 emitcode ("orl", "%s,a",
6679 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6687 // left & result in different registers
6688 if (AOP_TYPE (result) == AOP_CRY)
6691 // if(size), result in bit
6692 // if(!size && ifx), conditional oper: if(left | right)
6693 symbol *tlbl = newiTempLabel (NULL);
6694 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6696 emitcode ("setb", "c");
6699 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6700 emitcode ("orl", "a,%s",
6701 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6703 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6704 emitcode ("orl", "a,%s",
6705 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6707 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6713 emitcode ("", "!tlabeldef", tlbl->key + 100);
6717 jmpTrueOrFalse (ifx, tlbl);
6721 _startLazyDPSEvaluation();
6722 for (; (size--); offset++)
6725 // result = left & right
6726 if (AOP_TYPE (right) == AOP_LIT)
6728 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6730 aopPut (AOP (result),
6731 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6735 D (emitcode (";", "better literal OR."););
6736 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6737 emitcode ("orl", "a, %s",
6738 aopGet (AOP (right), offset,
6739 FALSE, FALSE, DP2_RESULT_REG));
6744 // faster than result <- left, anl result,right
6745 // and better if result is SFR
6746 if (AOP_TYPE (left) == AOP_ACC)
6748 emitcode ("orl", "a,%s",
6749 aopGet (AOP (right), offset,
6750 FALSE, FALSE, DP2_RESULT_REG));
6754 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6756 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6758 emitcode("mov", "b,a");
6762 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6763 emitcode ("orl", "a,%s", rOp);
6766 aopPut (AOP (result), "a", offset);
6768 _endLazyDPSEvaluation();
6773 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6774 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6775 freeAsmop (result, NULL, ic, TRUE);
6778 /*-----------------------------------------------------------------*/
6779 /* genXor - code for xclusive or */
6780 /*-----------------------------------------------------------------*/
6782 genXor (iCode * ic, iCode * ifx)
6784 operand *left, *right, *result;
6785 int size, offset = 0;
6786 unsigned long lit = 0L;
6789 D (emitcode (";", "genXor "););
6791 AOP_OP_3_NOFATAL (ic, pushResult);
6792 AOP_SET_LOCALS (ic);
6796 genFarFarLogicOp(ic, "xrl");
6801 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6803 AOP_TYPE (left), AOP_TYPE (right));
6804 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6806 AOP_SIZE (left), AOP_SIZE (right));
6809 /* if left is a literal & right is not ||
6810 if left needs acc & right does not */
6811 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6812 #ifdef LOGIC_OPS_BROKEN
6813 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6817 operand *tmp = right;
6822 /* if result = right then exchange them */
6823 if (sameRegs (AOP (result), AOP (right)))
6825 operand *tmp = right;
6830 /* if right is bit then exchange them */
6831 if (AOP_TYPE (right) == AOP_CRY &&
6832 AOP_TYPE (left) != AOP_CRY)
6834 operand *tmp = right;
6838 if (AOP_TYPE (right) == AOP_LIT)
6839 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6841 size = AOP_SIZE (result);
6845 if (AOP_TYPE (left) == AOP_CRY)
6847 if (AOP_TYPE (right) == AOP_LIT)
6849 // c = bit & literal;
6852 // lit>>1 != 0 => result = 1
6853 if (AOP_TYPE (result) == AOP_CRY)
6856 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6858 continueIfTrue (ifx);
6861 emitcode ("setb", "c");
6868 // lit == 0, result = left
6869 if (size && sameRegs (AOP (result), AOP (left)))
6871 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6875 // lit == 1, result = not(left)
6876 if (size && sameRegs (AOP (result), AOP (left)))
6878 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6883 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6884 emitcode ("cpl", "c");
6893 symbol *tlbl = newiTempLabel (NULL);
6894 if (AOP_TYPE (right) == AOP_CRY)
6897 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6901 int sizer = AOP_SIZE (right);
6903 // if val>>1 != 0, result = 1
6904 emitcode ("setb", "c");
6907 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
6909 // test the msb of the lsb
6910 emitcode ("anl", "a,#!constbyte",0xfe);
6911 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6915 emitcode ("rrc", "a");
6917 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6918 emitcode ("cpl", "c");
6919 emitcode ("", "!tlabeldef", (tlbl->key + 100));
6926 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6927 genIfxJump (ifx, "c");
6931 if (sameRegs (AOP (result), AOP (left)))
6933 /* if left is same as result */
6934 for (; size--; offset++)
6936 if (AOP_TYPE (right) == AOP_LIT)
6938 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6940 else if (IS_AOP_PREG (left))
6942 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6943 emitcode ("xrl", "a,%s",
6944 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6945 aopPut (AOP (result), "a", offset);
6948 emitcode ("xrl", "%s,%s",
6949 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6950 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6954 if (AOP_TYPE (left) == AOP_ACC)
6955 emitcode ("xrl", "a,%s",
6956 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6959 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6960 if (IS_AOP_PREG (left))
6962 emitcode ("xrl", "a,%s",
6963 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6964 aopPut (AOP (result), "a", offset);
6967 emitcode ("xrl", "%s,a",
6968 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6975 // left & result in different registers
6976 if (AOP_TYPE (result) == AOP_CRY)
6979 // if(size), result in bit
6980 // if(!size && ifx), conditional oper: if(left ^ right)
6981 symbol *tlbl = newiTempLabel (NULL);
6982 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6985 emitcode ("setb", "c");
6988 if ((AOP_TYPE (right) == AOP_LIT) &&
6989 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6991 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6995 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6996 emitcode ("xrl", "a,%s",
6997 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6999 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7000 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7002 emitcode("mov", "b,a");
7006 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7007 emitcode ("xrl", "a,%s", rOp);
7010 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7016 emitcode ("", "!tlabeldef", tlbl->key + 100);
7020 jmpTrueOrFalse (ifx, tlbl);
7024 for (; (size--); offset++)
7027 // result = left & right
7028 if (AOP_TYPE (right) == AOP_LIT)
7030 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7032 aopPut (AOP (result),
7033 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7037 D (emitcode (";", "better literal XOR."););
7038 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7039 emitcode ("xrl", "a, %s",
7040 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7044 // faster than result <- left, anl result,right
7045 // and better if result is SFR
7046 if (AOP_TYPE (left) == AOP_ACC)
7048 emitcode ("xrl", "a,%s",
7049 aopGet (AOP (right), offset,
7050 FALSE, FALSE, DP2_RESULT_REG));
7054 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7055 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7057 emitcode("mov", "b,a");
7061 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7062 emitcode ("xrl", "a,%s", rOp);
7065 aopPut (AOP (result), "a", offset);
7072 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7073 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7074 freeAsmop (result, NULL, ic, TRUE);
7077 /*-----------------------------------------------------------------*/
7078 /* genInline - write the inline code out */
7079 /*-----------------------------------------------------------------*/
7081 genInline (iCode * ic)
7083 char *buffer, *bp, *bp1;
7085 D (emitcode (";", "genInline "); );
7087 _G.inLine += (!options.asmpeep);
7089 buffer = Safe_strdup(IC_INLINE(ic));
7093 /* emit each line as a code */
7118 /* emitcode("",buffer); */
7119 _G.inLine -= (!options.asmpeep);
7122 /*-----------------------------------------------------------------*/
7123 /* genRRC - rotate right with carry */
7124 /*-----------------------------------------------------------------*/
7128 operand *left, *result;
7131 D (emitcode (";", "genRRC "););
7133 /* rotate right with carry */
7134 left = IC_LEFT (ic);
7135 result = IC_RESULT (ic);
7136 aopOp (left, ic, FALSE, FALSE);
7137 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7139 /* move it to the result */
7140 size = AOP_SIZE (result);
7144 _startLazyDPSEvaluation ();
7147 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7148 emitcode ("rrc", "a");
7149 if (AOP_SIZE (result) > 1)
7150 aopPut (AOP (result), "a", offset--);
7152 _endLazyDPSEvaluation ();
7154 /* now we need to put the carry into the
7155 highest order byte of the result */
7156 if (AOP_SIZE (result) > 1)
7158 MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7160 emitcode ("mov", "acc.7,c");
7161 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7162 freeAsmop (left, NULL, ic, TRUE);
7163 freeAsmop (result, NULL, ic, TRUE);
7166 /*-----------------------------------------------------------------*/
7167 /* genRLC - generate code for rotate left with carry */
7168 /*-----------------------------------------------------------------*/
7172 operand *left, *result;
7176 D (emitcode (";", "genRLC "););
7178 /* rotate right with carry */
7179 left = IC_LEFT (ic);
7180 result = IC_RESULT (ic);
7181 aopOp (left, ic, FALSE, FALSE);
7182 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7184 /* move it to the result */
7185 size = AOP_SIZE (result);
7189 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7191 emitcode ("add", "a,acc");
7192 if (AOP_SIZE (result) > 1)
7194 aopPut (AOP (result), "a", offset++);
7197 _startLazyDPSEvaluation ();
7200 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7202 emitcode ("rlc", "a");
7203 if (AOP_SIZE (result) > 1)
7204 aopPut (AOP (result), "a", offset++);
7206 _endLazyDPSEvaluation ();
7208 /* now we need to put the carry into the
7209 highest order byte of the result */
7210 if (AOP_SIZE (result) > 1)
7212 l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7215 emitcode ("mov", "acc.0,c");
7216 aopPut (AOP (result), "a", 0);
7217 freeAsmop (left, NULL, ic, TRUE);
7218 freeAsmop (result, NULL, ic, TRUE);
7221 /*-----------------------------------------------------------------*/
7222 /* genGetHbit - generates code get highest order bit */
7223 /*-----------------------------------------------------------------*/
7225 genGetHbit (iCode * ic)
7227 operand *left, *result;
7228 left = IC_LEFT (ic);
7229 result = IC_RESULT (ic);
7230 aopOp (left, ic, FALSE, FALSE);
7231 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7233 D (emitcode (";", "genGetHbit "););
7235 /* get the highest order byte into a */
7236 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7237 if (AOP_TYPE (result) == AOP_CRY)
7239 emitcode ("rlc", "a");
7244 emitcode ("rl", "a");
7245 emitcode ("anl", "a,#1");
7250 freeAsmop (left, NULL, ic, TRUE);
7251 freeAsmop (result, NULL, ic, TRUE);
7254 /*-----------------------------------------------------------------*/
7255 /* AccRol - rotate left accumulator by known count */
7256 /*-----------------------------------------------------------------*/
7258 AccRol (int shCount)
7260 shCount &= 0x0007; // shCount : 0..7
7267 emitcode ("rl", "a");
7270 emitcode ("rl", "a");
7271 emitcode ("rl", "a");
7274 emitcode ("swap", "a");
7275 emitcode ("rr", "a");
7278 emitcode ("swap", "a");
7281 emitcode ("swap", "a");
7282 emitcode ("rl", "a");
7285 emitcode ("rr", "a");
7286 emitcode ("rr", "a");
7289 emitcode ("rr", "a");
7294 /*-----------------------------------------------------------------*/
7295 /* AccLsh - left shift accumulator by known count */
7296 /*-----------------------------------------------------------------*/
7298 AccLsh (int shCount)
7303 emitcode ("add", "a,acc");
7304 else if (shCount == 2)
7306 emitcode ("add", "a,acc");
7307 emitcode ("add", "a,acc");
7311 /* rotate left accumulator */
7313 /* and kill the lower order bits */
7314 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7319 /*-----------------------------------------------------------------*/
7320 /* AccRsh - right shift accumulator by known count */
7321 /*-----------------------------------------------------------------*/
7323 AccRsh (int shCount)
7330 emitcode ("rrc", "a");
7334 /* rotate right accumulator */
7335 AccRol (8 - shCount);
7336 /* and kill the higher order bits */
7337 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7342 #ifdef BETTER_LITERAL_SHIFT
7343 /*-----------------------------------------------------------------*/
7344 /* AccSRsh - signed right shift accumulator by known count */
7345 /*-----------------------------------------------------------------*/
7347 AccSRsh (int shCount)
7354 emitcode ("mov", "c,acc.7");
7355 emitcode ("rrc", "a");
7357 else if (shCount == 2)
7359 emitcode ("mov", "c,acc.7");
7360 emitcode ("rrc", "a");
7361 emitcode ("mov", "c,acc.7");
7362 emitcode ("rrc", "a");
7366 tlbl = newiTempLabel (NULL);
7367 /* rotate right accumulator */
7368 AccRol (8 - shCount);
7369 /* and kill the higher order bits */
7370 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7371 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7372 emitcode ("orl", "a,#!constbyte",
7373 (unsigned char) ~SRMask[shCount]);
7374 emitcode ("", "!tlabeldef", tlbl->key + 100);
7380 #ifdef BETTER_LITERAL_SHIFT
7381 /*-----------------------------------------------------------------*/
7382 /* shiftR1Left2Result - shift right one byte from left to result */
7383 /*-----------------------------------------------------------------*/
7385 shiftR1Left2Result (operand * left, int offl,
7386 operand * result, int offr,
7387 int shCount, int sign)
7389 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7390 /* shift right accumulator */
7395 aopPut (AOP (result), "a", offr);
7399 #ifdef BETTER_LITERAL_SHIFT
7400 /*-----------------------------------------------------------------*/
7401 /* shiftL1Left2Result - shift left one byte from left to result */
7402 /*-----------------------------------------------------------------*/
7404 shiftL1Left2Result (operand * left, int offl,
7405 operand * result, int offr, int shCount)
7407 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7408 /* shift left accumulator */
7410 aopPut (AOP (result), "a", offr);
7414 #ifdef BETTER_LITERAL_SHIFT
7415 /*-----------------------------------------------------------------*/
7416 /* movLeft2Result - move byte from left to result */
7417 /*-----------------------------------------------------------------*/
7419 movLeft2Result (operand * left, int offl,
7420 operand * result, int offr, int sign)
7423 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7425 l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
7427 if (*l == '@' && (IS_AOP_PREG (result)))
7429 emitcode ("mov", "a,%s", l);
7430 aopPut (AOP (result), "a", offr);
7436 aopPut (AOP (result), l, offr);
7440 /* MSB sign in acc.7 ! */
7441 if (getDataSize (left) == offl + 1)
7443 emitcode ("mov", "a,%s", l);
7444 aopPut (AOP (result), "a", offr);
7452 #ifdef BETTER_LITERAL_SHIFT
7453 /*-----------------------------------------------------------------*/
7454 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7455 /*-----------------------------------------------------------------*/
7459 emitcode ("rrc", "a");
7460 emitcode ("xch", "a,%s", x);
7461 emitcode ("rrc", "a");
7462 emitcode ("xch", "a,%s", x);
7466 #ifdef BETTER_LITERAL_SHIFT
7468 /*-----------------------------------------------------------------*/
7469 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7470 /*-----------------------------------------------------------------*/
7474 emitcode ("xch", "a,%s", x);
7475 emitcode ("rlc", "a");
7476 emitcode ("xch", "a,%s", x);
7477 emitcode ("rlc", "a");
7481 #ifdef BETTER_LITERAL_SHIFT
7482 /*-----------------------------------------------------------------*/
7483 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7484 /*-----------------------------------------------------------------*/
7488 emitcode ("xch", "a,%s", x);
7489 emitcode ("add", "a,acc");
7490 emitcode ("xch", "a,%s", x);
7491 emitcode ("rlc", "a");
7495 #ifdef BETTER_LITERAL_SHIFT
7496 /*-----------------------------------------------------------------*/
7497 /* AccAXLsh - left shift a:x by known count (0..7) */
7498 /*-----------------------------------------------------------------*/
7500 AccAXLsh (char *x, int shCount)
7515 case 5: // AAAAABBB:CCCCCDDD
7517 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7519 emitcode ("anl", "a,#!constbyte",
7520 SLMask[shCount]); // BBB00000:CCCCCDDD
7522 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7524 AccRol (shCount); // DDDCCCCC:BBB00000
7526 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7528 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7530 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7532 emitcode ("anl", "a,#!constbyte",
7533 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7535 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7537 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7540 case 6: // AAAAAABB:CCCCCCDD
7541 emitcode ("anl", "a,#!constbyte",
7542 SRMask[shCount]); // 000000BB:CCCCCCDD
7543 emitcode ("mov", "c,acc.0"); // c = B
7544 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7546 AccAXRrl1 (x); // BCCCCCCD:D000000B
7547 AccAXRrl1 (x); // BBCCCCCC:DD000000
7549 emitcode("rrc","a");
7550 emitcode("xch","a,%s", x);
7551 emitcode("rrc","a");
7552 emitcode("mov","c,acc.0"); //<< get correct bit
7553 emitcode("xch","a,%s", x);
7555 emitcode("rrc","a");
7556 emitcode("xch","a,%s", x);
7557 emitcode("rrc","a");
7558 emitcode("xch","a,%s", x);
7561 case 7: // a:x <<= 7
7563 emitcode ("anl", "a,#!constbyte",
7564 SRMask[shCount]); // 0000000B:CCCCCCCD
7566 emitcode ("mov", "c,acc.0"); // c = B
7568 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7570 AccAXRrl1 (x); // BCCCCCCC:D0000000
7579 #ifdef BETTER_LITERAL_SHIFT
7581 /*-----------------------------------------------------------------*/
7582 /* AccAXRsh - right shift a:x known count (0..7) */
7583 /*-----------------------------------------------------------------*/
7585 AccAXRsh (char *x, int shCount)
7593 AccAXRrl1 (x); // 0->a:x
7598 AccAXRrl1 (x); // 0->a:x
7601 AccAXRrl1 (x); // 0->a:x
7606 case 5: // AAAAABBB:CCCCCDDD = a:x
7608 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7610 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7612 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7614 emitcode ("anl", "a,#!constbyte",
7615 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7617 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7619 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7621 emitcode ("anl", "a,#!constbyte",
7622 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7624 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7626 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7628 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7631 case 6: // AABBBBBB:CCDDDDDD
7633 emitcode ("mov", "c,acc.7");
7634 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7636 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7638 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7640 emitcode ("anl", "a,#!constbyte",
7641 SRMask[shCount]); // 000000AA:BBBBBBCC
7644 case 7: // ABBBBBBB:CDDDDDDD
7646 emitcode ("mov", "c,acc.7"); // c = A
7648 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7650 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7652 emitcode ("anl", "a,#!constbyte",
7653 SRMask[shCount]); // 0000000A:BBBBBBBC
7662 #ifdef BETTER_LITERAL_SHIFT
7663 /*-----------------------------------------------------------------*/
7664 /* AccAXRshS - right shift signed a:x known count (0..7) */
7665 /*-----------------------------------------------------------------*/
7667 AccAXRshS (char *x, int shCount)
7675 emitcode ("mov", "c,acc.7");
7676 AccAXRrl1 (x); // s->a:x
7680 emitcode ("mov", "c,acc.7");
7681 AccAXRrl1 (x); // s->a:x
7683 emitcode ("mov", "c,acc.7");
7684 AccAXRrl1 (x); // s->a:x
7689 case 5: // AAAAABBB:CCCCCDDD = a:x
7691 tlbl = newiTempLabel (NULL);
7692 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7694 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7696 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7698 emitcode ("anl", "a,#!constbyte",
7699 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7701 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7703 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7705 emitcode ("anl", "a,#!constbyte",
7706 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7708 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7710 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7712 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7714 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7715 emitcode ("orl", "a,#!constbyte",
7716 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7718 emitcode ("", "!tlabeldef", tlbl->key + 100);
7719 break; // SSSSAAAA:BBBCCCCC
7721 case 6: // AABBBBBB:CCDDDDDD
7723 tlbl = newiTempLabel (NULL);
7724 emitcode ("mov", "c,acc.7");
7725 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7727 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7729 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7731 emitcode ("anl", "a,#!constbyte",
7732 SRMask[shCount]); // 000000AA:BBBBBBCC
7734 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7735 emitcode ("orl", "a,#!constbyte",
7736 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7738 emitcode ("", "!tlabeldef", tlbl->key + 100);
7740 case 7: // ABBBBBBB:CDDDDDDD
7742 tlbl = newiTempLabel (NULL);
7743 emitcode ("mov", "c,acc.7"); // c = A
7745 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7747 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7749 emitcode ("anl", "a,#!constbyte",
7750 SRMask[shCount]); // 0000000A:BBBBBBBC
7752 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7753 emitcode ("orl", "a,#!constbyte",
7754 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7756 emitcode ("", "!tlabeldef", tlbl->key + 100);
7764 #ifdef BETTER_LITERAL_SHIFT
7766 _loadLeftIntoAx(char **lsb,
7772 // Get the initial value from left into a pair of registers.
7773 // MSB must be in A, LSB can be any register.
7775 // If the result is held in registers, it is an optimization
7776 // if the LSB can be held in the register which will hold the,
7777 // result LSB since this saves us from having to copy it into
7778 // the result following AccAXLsh.
7780 // If the result is addressed indirectly, this is not a gain.
7781 if (AOP_NEEDSACC(result))
7785 _startLazyDPSEvaluation();
7786 if (AOP_TYPE(left) == AOP_DPTR2)
7789 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
7790 // get LSB in DP2_RESULT_REG.
7791 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
7792 assert(!strcmp(leftByte, DP2_RESULT_REG));
7796 // get LSB into DP2_RESULT_REG
7797 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
7798 if (strcmp(leftByte, DP2_RESULT_REG))
7801 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7804 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
7805 assert(strcmp(leftByte, DP2_RESULT_REG));
7808 _endLazyDPSEvaluation();
7809 *lsb = DP2_RESULT_REG;
7813 if (sameRegs (AOP (result), AOP (left)) &&
7814 ((offl + MSB16) == offr))
7816 /* don't crash result[offr] */
7817 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
7818 emitcode ("xch", "a,%s",
7819 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
7823 movLeft2Result (left, offl, result, offr, 0);
7824 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
7826 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
7827 assert(strcmp(*lsb,"a"));
7832 _storeAxResults(char *lsb,
7836 _startLazyDPSEvaluation();
7837 if (AOP_NEEDSACC(result))
7839 /* We have to explicitly update the result LSB.
7841 emitcode("xch","a,%s", lsb);
7842 aopPut(AOP(result), "a", offr);
7843 emitcode("mov","a,%s", lsb);
7845 if (getDataSize (result) > 1)
7847 aopPut (AOP (result), "a", offr + MSB16);
7849 _endLazyDPSEvaluation();
7852 /*-----------------------------------------------------------------*/
7853 /* shiftL2Left2Result - shift left two bytes from left to result */
7854 /*-----------------------------------------------------------------*/
7856 shiftL2Left2Result (operand * left, int offl,
7857 operand * result, int offr, int shCount)
7861 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7863 AccAXLsh (lsb, shCount);
7865 _storeAxResults(lsb, result, offr);
7869 #ifdef BETTER_LITERAL_SHIFT
7870 /*-----------------------------------------------------------------*/
7871 /* shiftR2Left2Result - shift right two bytes from left to result */
7872 /*-----------------------------------------------------------------*/
7874 shiftR2Left2Result (operand * left, int offl,
7875 operand * result, int offr,
7876 int shCount, int sign)
7880 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7882 /* a:x >> shCount (x = lsb(result)) */
7885 AccAXRshS(lsb, shCount);
7889 AccAXRsh(lsb, shCount);
7892 _storeAxResults(lsb, result, offr);
7898 /*-----------------------------------------------------------------*/
7899 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7900 /*-----------------------------------------------------------------*/
7902 shiftLLeftOrResult (operand * left, int offl,
7903 operand * result, int offr, int shCount)
7905 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7906 /* shift left accumulator */
7908 /* or with result */
7909 emitcode ("orl", "a,%s",
7910 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7911 /* back to result */
7912 aopPut (AOP (result), "a", offr);
7918 /*-----------------------------------------------------------------*/
7919 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7920 /*-----------------------------------------------------------------*/
7922 shiftRLeftOrResult (operand * left, int offl,
7923 operand * result, int offr, int shCount)
7925 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7926 /* shift right accumulator */
7928 /* or with result */
7929 emitcode ("orl", "a,%s",
7930 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7931 /* back to result */
7932 aopPut (AOP (result), "a", offr);
7936 #ifdef BETTER_LITERAL_SHIFT
7937 /*-----------------------------------------------------------------*/
7938 /* genlshOne - left shift a one byte quantity by known count */
7939 /*-----------------------------------------------------------------*/
7941 genlshOne (operand * result, operand * left, int shCount)
7943 D (emitcode (";", "genlshOne "););
7944 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7948 #ifdef BETTER_LITERAL_SHIFT
7949 /*-----------------------------------------------------------------*/
7950 /* genlshTwo - left shift two bytes by known amount != 0 */
7951 /*-----------------------------------------------------------------*/
7953 genlshTwo (operand * result, operand * left, int shCount)
7957 D (emitcode (";", "genlshTwo "););
7959 size = getDataSize (result);
7961 /* if shCount >= 8 */
7966 _startLazyDPSEvaluation();
7972 _endLazyDPSEvaluation();
7973 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7974 aopPut (AOP (result), zero, LSB);
7978 movLeft2Result (left, LSB, result, MSB16, 0);
7979 aopPut (AOP (result), zero, LSB);
7980 _endLazyDPSEvaluation();
7985 aopPut (AOP (result), zero, LSB);
7986 _endLazyDPSEvaluation();
7990 /* 1 <= shCount <= 7 */
7995 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7999 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8007 /*-----------------------------------------------------------------*/
8008 /* shiftLLong - shift left one long from left to result */
8009 /* offl = LSB or MSB16 */
8010 /*-----------------------------------------------------------------*/
8012 shiftLLong (operand * left, operand * result, int offr)
8015 int size = AOP_SIZE (result);
8017 if (size >= LSB + offr)
8019 l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8021 emitcode ("add", "a,acc");
8022 if (sameRegs (AOP (left), AOP (result)) &&
8023 size >= MSB16 + offr && offr != LSB)
8024 emitcode ("xch", "a,%s",
8025 aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8027 aopPut (AOP (result), "a", LSB + offr);
8030 if (size >= MSB16 + offr)
8032 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8034 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8036 emitcode ("rlc", "a");
8037 if (sameRegs (AOP (left), AOP (result)) &&
8038 size >= MSB24 + offr && offr != LSB)
8039 emitcode ("xch", "a,%s",
8040 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8042 aopPut (AOP (result), "a", MSB16 + offr);
8045 if (size >= MSB24 + offr)
8047 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8049 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8051 emitcode ("rlc", "a");
8052 if (sameRegs (AOP (left), AOP (result)) &&
8053 size >= MSB32 + offr && offr != LSB)
8054 emitcode ("xch", "a,%s",
8055 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8057 aopPut (AOP (result), "a", MSB24 + offr);
8060 if (size > MSB32 + offr)
8062 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8064 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8066 emitcode ("rlc", "a");
8067 aopPut (AOP (result), "a", MSB32 + offr);
8070 aopPut (AOP (result), zero, LSB);
8076 /*-----------------------------------------------------------------*/
8077 /* genlshFour - shift four byte by a known amount != 0 */
8078 /*-----------------------------------------------------------------*/
8080 genlshFour (operand * result, operand * left, int shCount)
8084 D (emitcode (";", "genlshFour ");
8087 size = AOP_SIZE (result);
8089 /* if shifting more that 3 bytes */
8094 /* lowest order of left goes to the highest
8095 order of the destination */
8096 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8098 movLeft2Result (left, LSB, result, MSB32, 0);
8099 aopPut (AOP (result), zero, LSB);
8100 aopPut (AOP (result), zero, MSB16);
8101 aopPut (AOP (result), zero, MSB24);
8105 /* more than two bytes */
8106 else if (shCount >= 16)
8108 /* lower order two bytes goes to higher order two bytes */
8110 /* if some more remaining */
8112 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8115 movLeft2Result (left, MSB16, result, MSB32, 0);
8116 movLeft2Result (left, LSB, result, MSB24, 0);
8118 aopPut (AOP (result), zero, MSB16);
8119 aopPut (AOP (result), zero, LSB);
8123 /* if more than 1 byte */
8124 else if (shCount >= 8)
8126 /* lower order three bytes goes to higher order three bytes */
8131 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8133 movLeft2Result (left, LSB, result, MSB16, 0);
8139 movLeft2Result (left, MSB24, result, MSB32, 0);
8140 movLeft2Result (left, MSB16, result, MSB24, 0);
8141 movLeft2Result (left, LSB, result, MSB16, 0);
8142 aopPut (AOP (result), zero, LSB);
8144 else if (shCount == 1)
8145 shiftLLong (left, result, MSB16);
8148 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8149 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8150 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8151 aopPut (AOP (result), zero, LSB);
8156 /* 1 <= shCount <= 7 */
8157 else if (shCount <= 2)
8159 shiftLLong (left, result, LSB);
8161 shiftLLong (result, result, LSB);
8163 /* 3 <= shCount <= 7, optimize */
8166 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8167 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8168 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8173 #ifdef BETTER_LITERAL_SHIFT
8174 /*-----------------------------------------------------------------*/
8175 /* genLeftShiftLiteral - left shifting by known count */
8176 /*-----------------------------------------------------------------*/
8178 genLeftShiftLiteral (operand * left,
8183 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8186 size = getSize (operandType (result));
8188 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8190 /* We only handle certain easy cases so far. */
8192 && (shCount < (size * 8))
8196 D(emitcode (";", "genLeftShiftLiteral wimping out"););
8200 freeAsmop (right, NULL, ic, TRUE);
8202 aopOp(left, ic, FALSE, FALSE);
8203 aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8206 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8208 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8209 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8211 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8214 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8216 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8217 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8219 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8225 emitcode ("; shift left ", "result %d, left %d", size,
8229 /* I suppose that the left size >= result size */
8232 _startLazyDPSEvaluation();
8235 movLeft2Result (left, size, result, size, 0);
8237 _endLazyDPSEvaluation();
8239 else if (shCount >= (size * 8))
8241 _startLazyDPSEvaluation();
8244 aopPut (AOP (result), zero, size);
8246 _endLazyDPSEvaluation();
8253 genlshOne (result, left, shCount);
8257 genlshTwo (result, left, shCount);
8261 genlshFour (result, left, shCount);
8265 fprintf(stderr, "*** ack! mystery literal shift!\n");
8269 freeAsmop (left, NULL, ic, TRUE);
8270 freeAsmop (result, NULL, ic, TRUE);
8275 /*-----------------------------------------------------------------*/
8276 /* genLeftShift - generates code for left shifting */
8277 /*-----------------------------------------------------------------*/
8279 genLeftShift (iCode * ic)
8281 operand *left, *right, *result;
8284 symbol *tlbl, *tlbl1;
8286 D (emitcode (";", "genLeftShift "););
8288 right = IC_RIGHT (ic);
8289 left = IC_LEFT (ic);
8290 result = IC_RESULT (ic);
8292 aopOp (right, ic, FALSE, FALSE);
8295 #ifdef BETTER_LITERAL_SHIFT
8296 /* if the shift count is known then do it
8297 as efficiently as possible */
8298 if (AOP_TYPE (right) == AOP_LIT)
8300 if (genLeftShiftLiteral (left, right, result, ic))
8307 /* shift count is unknown then we have to form
8308 a loop get the loop count in B : Note: we take
8309 only the lower order byte since shifting
8310 more that 32 bits make no sense anyway, ( the
8311 largest size of an object can be only 32 bits ) */
8313 if (AOP_TYPE (right) == AOP_LIT)
8315 /* Really should be handled by genLeftShiftLiteral,
8316 * but since I'm too lazy to fix that today, at least we can make
8317 * some small improvement.
8319 emitcode("mov", "b,#!constbyte",
8320 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8324 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8325 emitcode ("inc", "b");
8327 freeAsmop (right, NULL, ic, TRUE);
8328 aopOp (left, ic, FALSE, FALSE);
8329 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8331 /* now move the left to the result if they are not the
8333 if (!sameRegs (AOP (left), AOP (result)) &&
8334 AOP_SIZE (result) > 1)
8337 size = AOP_SIZE (result);
8339 _startLazyDPSEvaluation ();
8342 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8343 if (*l == '@' && (IS_AOP_PREG (result)))
8346 emitcode ("mov", "a,%s", l);
8347 aopPut (AOP (result), "a", offset);
8350 aopPut (AOP (result), l, offset);
8353 _endLazyDPSEvaluation ();
8356 tlbl = newiTempLabel (NULL);
8357 size = AOP_SIZE (result);
8359 tlbl1 = newiTempLabel (NULL);
8361 /* if it is only one byte then */
8364 symbol *tlbl1 = newiTempLabel (NULL);
8366 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8367 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8368 emitcode ("", "!tlabeldef", tlbl->key + 100);
8369 emitcode ("add", "a,acc");
8370 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8371 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8372 aopPut (AOP (result), "a", 0);
8376 reAdjustPreg (AOP (result));
8378 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8379 emitcode ("", "!tlabeldef", tlbl->key + 100);
8380 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8381 emitcode ("add", "a,acc");
8382 aopPut (AOP (result), "a", offset++);
8383 _startLazyDPSEvaluation ();
8386 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8387 emitcode ("rlc", "a");
8388 aopPut (AOP (result), "a", offset++);
8390 _endLazyDPSEvaluation ();
8391 reAdjustPreg (AOP (result));
8393 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8394 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8396 freeAsmop (left, NULL, ic, TRUE);
8397 freeAsmop (result, NULL, ic, TRUE);
8400 #ifdef BETTER_LITERAL_SHIFT
8401 /*-----------------------------------------------------------------*/
8402 /* genrshOne - right shift a one byte quantity by known count */
8403 /*-----------------------------------------------------------------*/
8405 genrshOne (operand * result, operand * left,
8406 int shCount, int sign)
8408 D (emitcode (";", "genrshOne"););
8409 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8413 #ifdef BETTER_LITERAL_SHIFT
8414 /*-----------------------------------------------------------------*/
8415 /* genrshTwo - right shift two bytes by known amount != 0 */
8416 /*-----------------------------------------------------------------*/
8418 genrshTwo (operand * result, operand * left,
8419 int shCount, int sign)
8421 D (emitcode (";", "genrshTwo"););
8423 /* if shCount >= 8 */
8427 _startLazyDPSEvaluation();
8430 shiftR1Left2Result (left, MSB16, result, LSB,
8435 movLeft2Result (left, MSB16, result, LSB, sign);
8437 addSign (result, MSB16, sign);
8438 _endLazyDPSEvaluation();
8441 /* 1 <= shCount <= 7 */
8444 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8451 /*-----------------------------------------------------------------*/
8452 /* shiftRLong - shift right one long from left to result */
8453 /* offl = LSB or MSB16 */
8454 /*-----------------------------------------------------------------*/
8456 shiftRLong (operand * left, int offl,
8457 operand * result, int sign)
8459 int isSameRegs=sameRegs(AOP(left),AOP(result));
8461 if (isSameRegs && offl>1) {
8462 // we are in big trouble, but this shouldn't happen
8463 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8466 MOVA (aopGet (AOP (left), MSB32, FALSE, NULL));
8471 emitcode ("rlc", "a");
8472 emitcode ("subb", "a,acc");
8473 emitcode ("xch", "a,%s",
8474 aopGet(AOP(left), MSB32, FALSE, DP2_RESULT_REG));
8476 aopPut (AOP(result), zero, MSB32);
8481 emitcode ("clr", "c");
8483 emitcode ("mov", "c,acc.7");
8486 emitcode ("rrc", "a");
8488 if (isSameRegs && offl==MSB16) {
8490 "a,%s",aopGet (AOP (left), MSB24, FALSE, DP2_RESULT_REG));
8492 aopPut (AOP (result), "a", MSB32);
8493 MOVA (aopGet (AOP (left), MSB24, FALSE, NULL));
8496 emitcode ("rrc", "a");
8497 if (isSameRegs && offl==1) {
8498 emitcode ("xch", "a,%s",
8499 aopGet (AOP (left), MSB16, FALSE, DP2_RESULT_REG));
8501 aopPut (AOP (result), "a", MSB24);
8502 MOVA (aopGet (AOP (left), MSB16, FALSE, NULL));
8504 emitcode ("rrc", "a");
8505 aopPut (AOP (result), "a", MSB16 - offl);
8509 MOVA (aopGet (AOP (left), LSB, FALSE, NULL));
8510 emitcode ("rrc", "a");
8511 aopPut (AOP (result), "a", LSB);
8518 /*-----------------------------------------------------------------*/
8519 /* genrshFour - shift four byte by a known amount != 0 */
8520 /*-----------------------------------------------------------------*/
8522 genrshFour (operand * result, operand * left,
8523 int shCount, int sign)
8525 D (emitcode (";", "genrshFour");
8528 /* if shifting more that 3 bytes */
8533 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8535 movLeft2Result (left, MSB32, result, LSB, sign);
8536 addSign (result, MSB16, sign);
8538 else if (shCount >= 16)
8542 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8545 movLeft2Result (left, MSB24, result, LSB, 0);
8546 movLeft2Result (left, MSB32, result, MSB16, sign);
8548 addSign (result, MSB24, sign);
8550 else if (shCount >= 8)
8554 shiftRLong (left, MSB16, result, sign);
8555 else if (shCount == 0)
8557 movLeft2Result (left, MSB16, result, LSB, 0);
8558 movLeft2Result (left, MSB24, result, MSB16, 0);
8559 movLeft2Result (left, MSB32, result, MSB24, sign);
8560 addSign (result, MSB32, sign);
8564 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8565 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8566 /* the last shift is signed */
8567 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8568 addSign (result, MSB32, sign);
8572 { /* 1 <= shCount <= 7 */
8575 shiftRLong (left, LSB, result, sign);
8577 shiftRLong (result, LSB, result, sign);
8581 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8582 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8583 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8589 #ifdef BETTER_LITERAL_SHIFT
8590 /*-----------------------------------------------------------------*/
8591 /* genRightShiftLiteral - right shifting by known count */
8592 /*-----------------------------------------------------------------*/
8594 genRightShiftLiteral (operand * left,
8600 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8603 size = getSize (operandType (result));
8605 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8607 /* We only handle certain easy cases so far. */
8609 && (shCount < (size * 8))
8613 D(emitcode (";", "genRightShiftLiteral wimping out"););
8617 freeAsmop (right, NULL, ic, TRUE);
8619 aopOp (left, ic, FALSE, FALSE);
8620 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8623 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8627 /* test the LEFT size !!! */
8629 /* I suppose that the left size >= result size */
8632 size = getDataSize (result);
8633 _startLazyDPSEvaluation();
8636 movLeft2Result (left, size, result, size, 0);
8638 _endLazyDPSEvaluation();
8640 else if (shCount >= (size * 8))
8644 /* get sign in acc.7 */
8645 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
8647 addSign (result, LSB, sign);
8654 genrshOne (result, left, shCount, sign);
8658 genrshTwo (result, left, shCount, sign);
8662 genrshFour (result, left, shCount, sign);
8669 freeAsmop (left, NULL, ic, TRUE);
8670 freeAsmop (result, NULL, ic, TRUE);
8676 /*-----------------------------------------------------------------*/
8677 /* genSignedRightShift - right shift of signed number */
8678 /*-----------------------------------------------------------------*/
8680 genSignedRightShift (iCode * ic)
8682 operand *right, *left, *result;
8685 symbol *tlbl, *tlbl1;
8687 D (emitcode (";", "genSignedRightShift "););
8689 /* we do it the hard way put the shift count in b
8690 and loop thru preserving the sign */
8692 right = IC_RIGHT (ic);
8693 left = IC_LEFT (ic);
8694 result = IC_RESULT (ic);
8696 aopOp (right, ic, FALSE, FALSE);
8698 #ifdef BETTER_LITERAL_SHIFT
8699 if (AOP_TYPE (right) == AOP_LIT)
8701 if (genRightShiftLiteral (left, right, result, ic, 1))
8707 /* shift count is unknown then we have to form
8708 a loop get the loop count in B : Note: we take
8709 only the lower order byte since shifting
8710 more that 32 bits make no sense anyway, ( the
8711 largest size of an object can be only 32 bits ) */
8713 if (AOP_TYPE (right) == AOP_LIT)
8715 /* Really should be handled by genRightShiftLiteral,
8716 * but since I'm too lazy to fix that today, at least we can make
8717 * some small improvement.
8719 emitcode("mov", "b,#!constbyte",
8720 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8724 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8725 emitcode ("inc", "b");
8727 freeAsmop (right, NULL, ic, TRUE);
8728 aopOp (left, ic, FALSE, FALSE);
8729 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8731 /* now move the left to the result if they are not the
8733 if (!sameRegs (AOP (left), AOP (result)) &&
8734 AOP_SIZE (result) > 1)
8737 size = AOP_SIZE (result);
8739 _startLazyDPSEvaluation ();
8742 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8743 if (*l == '@' && IS_AOP_PREG (result))
8746 emitcode ("mov", "a,%s", l);
8747 aopPut (AOP (result), "a", offset);
8750 aopPut (AOP (result), l, offset);
8753 _endLazyDPSEvaluation ();
8756 /* mov the highest order bit to OVR */
8757 tlbl = newiTempLabel (NULL);
8758 tlbl1 = newiTempLabel (NULL);
8760 size = AOP_SIZE (result);
8762 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
8763 emitcode ("rlc", "a");
8764 emitcode ("mov", "ov,c");
8765 /* if it is only one byte then */
8768 MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8769 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8770 emitcode ("", "!tlabeldef", tlbl->key + 100);
8771 emitcode ("mov", "c,ov");
8772 emitcode ("rrc", "a");
8773 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8774 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8775 aopPut (AOP (result), "a", 0);
8779 reAdjustPreg (AOP (result));
8780 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8781 emitcode ("", "!tlabeldef", tlbl->key + 100);
8782 emitcode ("mov", "c,ov");
8783 _startLazyDPSEvaluation ();
8786 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8787 emitcode ("rrc", "a");
8788 aopPut (AOP (result), "a", offset--);
8790 _endLazyDPSEvaluation ();
8791 reAdjustPreg (AOP (result));
8792 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8793 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8796 freeAsmop (left, NULL, ic, TRUE);
8797 freeAsmop (result, NULL, ic, TRUE);
8800 /*-----------------------------------------------------------------*/
8801 /* genRightShift - generate code for right shifting */
8802 /*-----------------------------------------------------------------*/
8804 genRightShift (iCode * ic)
8806 operand *right, *left, *result;
8810 symbol *tlbl, *tlbl1;
8812 D (emitcode (";", "genRightShift "););
8814 /* if signed then we do it the hard way preserve the
8815 sign bit moving it inwards */
8816 retype = getSpec (operandType (IC_RESULT (ic)));
8818 if (!SPEC_USIGN (retype))
8820 genSignedRightShift (ic);
8824 /* signed & unsigned types are treated the same : i.e. the
8825 signed is NOT propagated inwards : quoting from the
8826 ANSI - standard : "for E1 >> E2, is equivalent to division
8827 by 2**E2 if unsigned or if it has a non-negative value,
8828 otherwise the result is implementation defined ", MY definition
8829 is that the sign does not get propagated */
8831 right = IC_RIGHT (ic);
8832 left = IC_LEFT (ic);
8833 result = IC_RESULT (ic);
8835 aopOp (right, ic, FALSE, FALSE);
8837 #ifdef BETTER_LITERAL_SHIFT
8838 /* if the shift count is known then do it
8839 as efficiently as possible */
8840 if (AOP_TYPE (right) == AOP_LIT)
8842 if (genRightShiftLiteral (left, right, result, ic, 0))
8849 /* shift count is unknown then we have to form
8850 a loop get the loop count in B : Note: we take
8851 only the lower order byte since shifting
8852 more that 32 bits make no sense anyway, ( the
8853 largest size of an object can be only 32 bits ) */
8855 if (AOP_TYPE (right) == AOP_LIT)
8857 /* Really should be handled by genRightShiftLiteral,
8858 * but since I'm too lazy to fix that today, at least we can make
8859 * some small improvement.
8861 emitcode("mov", "b,#!constbyte",
8862 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8866 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8867 emitcode ("inc", "b");
8869 freeAsmop (right, NULL, ic, TRUE);
8870 aopOp (left, ic, FALSE, FALSE);
8871 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8873 /* now move the left to the result if they are not the
8875 if (!sameRegs (AOP (left), AOP (result)) &&
8876 AOP_SIZE (result) > 1)
8879 size = AOP_SIZE (result);
8881 _startLazyDPSEvaluation ();
8884 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8885 if (*l == '@' && IS_AOP_PREG (result))
8888 emitcode ("mov", "a,%s", l);
8889 aopPut (AOP (result), "a", offset);
8892 aopPut (AOP (result), l, offset);
8895 _endLazyDPSEvaluation ();
8898 tlbl = newiTempLabel (NULL);
8899 tlbl1 = newiTempLabel (NULL);
8900 size = AOP_SIZE (result);
8903 /* if it is only one byte then */
8906 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8907 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8908 emitcode ("", "!tlabeldef", tlbl->key + 100);
8910 emitcode ("rrc", "a");
8911 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8912 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8913 aopPut (AOP (result), "a", 0);
8917 reAdjustPreg (AOP (result));
8918 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8919 emitcode ("", "!tlabeldef", tlbl->key + 100);
8921 _startLazyDPSEvaluation ();
8924 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8925 emitcode ("rrc", "a");
8926 aopPut (AOP (result), "a", offset--);
8928 _endLazyDPSEvaluation ();
8929 reAdjustPreg (AOP (result));
8931 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8932 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8935 freeAsmop (left, NULL, ic, TRUE);
8936 freeAsmop (result, NULL, ic, TRUE);
8939 /*-----------------------------------------------------------------*/
8940 /* genUnpackBits - generates code for unpacking bits */
8941 /*-----------------------------------------------------------------*/
8943 genUnpackBits (operand * result, char *rname, int ptype)
8950 D (emitcode (";", "genUnpackBits "););
8952 etype = getSpec (operandType (result));
8954 /* read the first byte */
8960 emitcode ("mov", "a,@%s", rname);
8964 emitcode ("movx", "a,@%s", rname);
8968 emitcode ("movx", "a,@dptr");
8972 emitcode ("clr", "a");
8973 emitcode ("movc", "a,@a+dptr");
8977 emitcode ("lcall", "__gptrget");
8981 /* if we have bitdisplacement then it fits */
8982 /* into this byte completely or if length is */
8983 /* less than a byte */
8984 if (((shCnt = SPEC_BSTR (etype)) != 0) || (SPEC_BLEN (etype) <= 8))
8987 /* shift right acc */
8990 emitcode ("anl", "a,#!constbyte",
8991 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8992 aopPut (AOP (result), "a", offset);
8996 /* bit field did not fit in a byte */
8997 rlen = SPEC_BLEN (etype) - 8;
8998 aopPut (AOP (result), "a", offset++);
9007 emitcode ("inc", "%s", rname);
9008 emitcode ("mov", "a,@%s", rname);
9012 emitcode ("inc", "%s", rname);
9013 emitcode ("movx", "a,@%s", rname);
9017 emitcode ("inc", "dptr");
9018 emitcode ("movx", "a,@dptr");
9022 emitcode ("clr", "a");
9023 emitcode ("inc", "dptr");
9024 emitcode ("movc", "a,@a+dptr");
9028 emitcode ("inc", "dptr");
9029 emitcode ("lcall", "__gptrget");
9034 /* if we are done */
9038 aopPut (AOP (result), "a", offset++);
9044 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (rlen));
9045 aopPut (AOP (result), "a", offset);
9052 /*-----------------------------------------------------------------*/
9053 /* genDataPointerGet - generates code when ptr offset is known */
9054 /*-----------------------------------------------------------------*/
9056 genDataPointerGet (operand * left,
9062 int size, offset = 0;
9063 aopOp (result, ic, TRUE, FALSE);
9065 /* get the string representation of the name */
9066 l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9067 size = AOP_SIZE (result);
9068 _startLazyDPSEvaluation ();
9073 SNPRINTF (buff, sizeof(buff),
9074 "(%s + %d)", l + 1, offset);
9078 SNPRINTF (buff, sizeof(buff),
9081 aopPut (AOP (result), buff, offset++);
9083 _endLazyDPSEvaluation ();
9085 freeAsmop (left, NULL, ic, TRUE);
9086 freeAsmop (result, NULL, ic, TRUE);
9089 /*-----------------------------------------------------------------*/
9090 /* genNearPointerGet - emitcode for near pointer fetch */
9091 /*-----------------------------------------------------------------*/
9093 genNearPointerGet (operand * left,
9101 sym_link *rtype, *retype, *letype;
9102 sym_link *ltype = operandType (left);
9105 rtype = operandType (result);
9106 retype = getSpec (rtype);
9107 letype = getSpec (ltype);
9109 aopOp (left, ic, FALSE, FALSE);
9111 /* if left is rematerialisable and
9112 result is not bit variable type and
9113 the left is pointer to data space i.e
9114 lower 128 bytes of space */
9115 if (AOP_TYPE (left) == AOP_IMMD &&
9116 !IS_BITVAR (retype) &&
9117 !IS_BITVAR (letype) &&
9118 DCL_TYPE (ltype) == POINTER)
9120 genDataPointerGet (left, result, ic);
9124 /* if the value is already in a pointer register
9125 then don't need anything more */
9126 if (!AOP_INPREG (AOP (left)))
9128 /* otherwise get a free pointer register */
9130 preg = getFreePtr (ic, &aop, FALSE);
9131 emitcode ("mov", "%s,%s",
9133 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9137 rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9139 freeAsmop (left, NULL, ic, TRUE);
9140 aopOp (result, ic, FALSE, FALSE);
9142 /* if bitfield then unpack the bits */
9143 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9144 genUnpackBits (result, rname, POINTER);
9147 /* we have can just get the values */
9148 int size = AOP_SIZE (result);
9153 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9156 emitcode ("mov", "a,@%s", rname);
9157 aopPut (AOP (result), "a", offset);
9161 SNPRINTF (buff, sizeof(buff), "@%s", rname);
9162 aopPut (AOP (result), buff, offset);
9167 emitcode ("inc", "%s", rname);
9172 /* now some housekeeping stuff */
9175 /* we had to allocate for this iCode */
9176 if (pi) { /* post increment present */
9177 aopPut(AOP ( left ),rname,0);
9179 freeAsmop (NULL, aop, ic, TRUE);
9183 /* we did not allocate which means left
9184 already in a pointer register, then
9185 if size > 0 && this could be used again
9186 we have to point it back to where it
9188 if (AOP_SIZE (result) > 1 &&
9189 !OP_SYMBOL (left)->remat &&
9190 (OP_SYMBOL (left)->liveTo > ic->seq ||
9194 int size = AOP_SIZE (result) - 1;
9196 emitcode ("dec", "%s", rname);
9201 freeAsmop (result, NULL, ic, TRUE);
9202 if (pi) pi->generated = 1;
9205 /*-----------------------------------------------------------------*/
9206 /* genPagedPointerGet - emitcode for paged pointer fetch */
9207 /*-----------------------------------------------------------------*/
9209 genPagedPointerGet (operand * left,
9217 sym_link *rtype, *retype, *letype;
9219 rtype = operandType (result);
9220 retype = getSpec (rtype);
9221 letype = getSpec (operandType (left));
9222 aopOp (left, ic, FALSE, FALSE);
9224 /* if the value is already in a pointer register
9225 then don't need anything more */
9226 if (!AOP_INPREG (AOP (left)))
9228 /* otherwise get a free pointer register */
9230 preg = getFreePtr (ic, &aop, FALSE);
9231 emitcode ("mov", "%s,%s",
9233 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9237 rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9239 freeAsmop (left, NULL, ic, TRUE);
9240 aopOp (result, ic, FALSE, FALSE);
9242 /* if bitfield then unpack the bits */
9243 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9244 genUnpackBits (result, rname, PPOINTER);
9247 /* we have can just get the values */
9248 int size = AOP_SIZE (result);
9254 emitcode ("movx", "a,@%s", rname);
9255 aopPut (AOP (result), "a", offset);
9260 emitcode ("inc", "%s", rname);
9264 /* now some housekeeping stuff */
9267 /* we had to allocate for this iCode */
9268 if (pi) aopPut ( AOP (left), rname, 0);
9269 freeAsmop (NULL, aop, ic, TRUE);
9273 /* we did not allocate which means left
9274 already in a pointer register, then
9275 if size > 0 && this could be used again
9276 we have to point it back to where it
9278 if (AOP_SIZE (result) > 1 &&
9279 !OP_SYMBOL (left)->remat &&
9280 (OP_SYMBOL (left)->liveTo > ic->seq ||
9284 int size = AOP_SIZE (result) - 1;
9286 emitcode ("dec", "%s", rname);
9291 freeAsmop (result, NULL, ic, TRUE);
9292 if (pi) pi->generated = 1;
9295 /*-----------------------------------------------------------------*/
9296 /* genFarPointerGet - gget value from far space */
9297 /*-----------------------------------------------------------------*/
9299 genFarPointerGet (operand * left,
9300 operand * result, iCode * ic, iCode *pi)
9302 int size, offset, dopi=1;
9303 sym_link *retype = getSpec (operandType (result));
9304 sym_link *letype = getSpec (operandType (left));
9305 D (emitcode (";", "genFarPointerGet"););
9307 aopOp (left, ic, FALSE, FALSE);
9309 /* if the operand is already in dptr
9310 then we do nothing else we move the value to dptr */
9311 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9313 /* if this is remateriazable */
9314 if (AOP_TYPE (left) == AOP_IMMD)
9316 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9320 /* we need to get it byte by byte */
9321 _startLazyDPSEvaluation ();
9322 if (AOP_TYPE (left) != AOP_DPTR)
9324 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9325 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9326 if (options.model == MODEL_FLAT24)
9327 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9331 /* We need to generate a load to DPTR indirect through DPTR. */
9332 D (emitcode (";", "genFarPointerGet -- indirection special case."););
9333 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9334 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9335 if (options.model == MODEL_FLAT24)
9336 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9337 emitcode ("pop", "dph");
9338 emitcode ("pop", "dpl");
9341 _endLazyDPSEvaluation ();
9344 /* so dptr know contains the address */
9345 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9347 /* if bit then unpack */
9348 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9349 if (AOP_INDPTRn(left)) {
9350 genSetDPTR(AOP(left)->aopu.dptr);
9352 genUnpackBits (result, "dptr", FPOINTER);
9353 if (AOP_INDPTRn(left)) {
9358 size = AOP_SIZE (result);
9361 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9363 genSetDPTR(AOP(left)->aopu.dptr);
9364 emitcode ("movx", "a,@dptr");
9365 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9366 emitcode ("inc", "dptr");
9368 aopPut (AOP (result), "a", offset++);
9371 _startLazyDPSEvaluation ();
9373 if (AOP_INDPTRn(left)) {
9374 genSetDPTR(AOP(left)->aopu.dptr);
9380 emitcode ("movx", "a,@dptr");
9381 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9382 emitcode ("inc", "dptr");
9384 aopPut (AOP (result), "a", offset++);
9386 _endLazyDPSEvaluation ();
9389 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9390 if (!AOP_INDPTRn(left)) {
9391 _startLazyDPSEvaluation ();
9392 aopPut ( AOP (left), "dpl", 0);
9393 aopPut ( AOP (left), "dph", 1);
9394 if (options.model == MODEL_FLAT24)
9395 aopPut ( AOP (left), "dpx", 2);
9396 _endLazyDPSEvaluation ();
9399 } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) &&
9400 AOP_SIZE(result) > 1 &&
9402 (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
9404 size = AOP_SIZE (result) - 1;
9405 if (AOP_INDPTRn(left)) {
9406 genSetDPTR(AOP(left)->aopu.dptr);
9408 while (size--) emitcode ("lcall","__decdptr");
9409 if (AOP_INDPTRn(left)) {
9414 freeAsmop (left, NULL, ic, TRUE);
9415 freeAsmop (result, NULL, ic, TRUE);
9418 /*-----------------------------------------------------------------*/
9419 /* genCodePointerGet - get value from code space */
9420 /*-----------------------------------------------------------------*/
9422 genCodePointerGet (operand * left,
9423 operand * result, iCode * ic, iCode *pi)
9425 int size, offset, dopi=1;
9426 sym_link *retype = getSpec (operandType (result));
9428 aopOp (left, ic, FALSE, FALSE);
9430 /* if the operand is already in dptr
9431 then we do nothing else we move the value to dptr */
9432 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
9434 /* if this is remateriazable */
9435 if (AOP_TYPE (left) == AOP_IMMD)
9437 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9440 { /* we need to get it byte by byte */
9441 _startLazyDPSEvaluation ();
9442 if (AOP_TYPE (left) != AOP_DPTR)
9444 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9445 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9446 if (options.model == MODEL_FLAT24)
9447 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9451 /* We need to generate a load to DPTR indirect through DPTR. */
9452 D (emitcode (";", "gencodePointerGet -- indirection special case."););
9453 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9454 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9455 if (options.model == MODEL_FLAT24)
9456 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9457 emitcode ("pop", "dph");
9458 emitcode ("pop", "dpl");
9461 _endLazyDPSEvaluation ();
9464 /* so dptr know contains the address */
9465 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9467 /* if bit then unpack */
9468 if (IS_BITVAR (retype)) {
9469 if (AOP_INDPTRn(left)) {
9470 genSetDPTR(AOP(left)->aopu.dptr);
9472 genUnpackBits (result, "dptr", CPOINTER);
9473 if (AOP_INDPTRn(left)) {
9478 size = AOP_SIZE (result);
9480 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9482 genSetDPTR(AOP(left)->aopu.dptr);
9483 emitcode ("clr", "a");
9484 emitcode ("movc", "a,@a+dptr");
9485 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9486 emitcode ("inc", "dptr");
9488 aopPut (AOP (result), "a", offset++);
9491 _startLazyDPSEvaluation ();
9494 if (AOP_INDPTRn(left)) {
9495 genSetDPTR(AOP(left)->aopu.dptr);
9501 emitcode ("clr", "a");
9502 emitcode ("movc", "a,@a+dptr");
9503 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9504 emitcode ("inc", "dptr");
9505 aopPut (AOP (result), "a", offset++);
9507 _endLazyDPSEvaluation ();
9510 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9511 if (!AOP_INDPTRn(left)) {
9512 _startLazyDPSEvaluation ();
9514 aopPut ( AOP (left), "dpl", 0);
9515 aopPut ( AOP (left), "dph", 1);
9516 if (options.model == MODEL_FLAT24)
9517 aopPut ( AOP (left), "dpx", 2);
9519 _endLazyDPSEvaluation ();
9522 } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
9523 AOP_SIZE(result) > 1 &&
9524 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9526 size = AOP_SIZE (result) - 1;
9527 if (AOP_INDPTRn(left)) {
9528 genSetDPTR(AOP(left)->aopu.dptr);
9530 while (size--) emitcode ("lcall","__decdptr");
9531 if (AOP_INDPTRn(left)) {
9536 freeAsmop (left, NULL, ic, TRUE);
9537 freeAsmop (result, NULL, ic, TRUE);
9540 /*-----------------------------------------------------------------*/
9541 /* genGenPointerGet - gget value from generic pointer space */
9542 /*-----------------------------------------------------------------*/
9544 genGenPointerGet (operand * left,
9545 operand * result, iCode * ic, iCode * pi)
9548 sym_link *retype = getSpec (operandType (result));
9549 sym_link *letype = getSpec (operandType (left));
9551 D (emitcode (";", "genGenPointerGet "); );
9553 aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
9555 /* if the operand is already in dptr
9556 then we do nothing else we move the value to dptr */
9557 if (AOP_TYPE (left) != AOP_STR)
9559 /* if this is remateriazable */
9560 if (AOP_TYPE (left) == AOP_IMMD)
9562 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9563 if (AOP(left)->aopu.aop_immd.from_cast_remat)
9565 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
9569 emitcode ("mov", "b,#%d", pointerCode (retype));
9573 { /* we need to get it byte by byte */
9574 _startLazyDPSEvaluation ();
9575 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
9576 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
9577 if (options.model == MODEL_FLAT24) {
9578 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9579 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
9581 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9583 _endLazyDPSEvaluation ();
9587 /* so dptr-b now contains the address */
9589 aopOp (result, ic, FALSE, TRUE);
9592 /* if bit then unpack */
9593 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9595 genUnpackBits (result, "dptr", GPOINTER);
9599 size = AOP_SIZE (result);
9606 // Get two bytes at a time, results in _AP & A.
9607 // dptr will be incremented ONCE by __gptrgetWord.
9609 // Note: any change here must be coordinated
9610 // with the implementation of __gptrgetWord
9611 // in device/lib/_gptrget.c
9612 emitcode ("lcall", "__gptrgetWord");
9613 aopPut (AOP (result), DP2_RESULT_REG, offset++);
9614 aopPut (AOP (result), "a", offset++);
9619 // Only one byte to get.
9620 emitcode ("lcall", "__gptrget");
9621 aopPut (AOP (result), "a", offset++);
9624 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9626 emitcode ("inc", "dptr");
9631 if (pi && AOP_TYPE (left) != AOP_IMMD) {
9632 _startLazyDPSEvaluation ();
9634 aopPut ( AOP (left), "dpl", 0);
9635 aopPut ( AOP (left), "dph", 1);
9636 if (options.model == MODEL_FLAT24) {
9637 aopPut ( AOP (left), "dpx", 2);
9638 aopPut ( AOP (left), "b", 3);
9639 } else aopPut ( AOP (left), "b", 2);
9641 _endLazyDPSEvaluation ();
9644 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9645 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9647 size = AOP_SIZE (result) - 1;
9648 while (size--) emitcode ("lcall","__decdptr");
9651 freeAsmop (left, NULL, ic, TRUE);
9652 freeAsmop (result, NULL, ic, TRUE);
9655 /*-----------------------------------------------------------------*/
9656 /* genPointerGet - generate code for pointer get */
9657 /*-----------------------------------------------------------------*/
9659 genPointerGet (iCode * ic, iCode *pi)
9661 operand *left, *result;
9662 sym_link *type, *etype;
9665 D (emitcode (";", "genPointerGet ");
9668 left = IC_LEFT (ic);
9669 result = IC_RESULT (ic);
9671 /* depending on the type of pointer we need to
9672 move it to the correct pointer register */
9673 type = operandType (left);
9674 etype = getSpec (type);
9675 /* if left is of type of pointer then it is simple */
9676 if (IS_PTR (type) && !IS_FUNC (type->next))
9677 p_type = DCL_TYPE (type);
9680 /* we have to go by the storage class */
9681 p_type = PTR_TYPE (SPEC_OCLS (etype));
9683 /* special case when cast remat */
9684 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9685 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9686 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9687 type = operandType (left);
9688 p_type = DCL_TYPE (type);
9690 /* now that we have the pointer type we assign
9691 the pointer values */
9697 genNearPointerGet (left, result, ic, pi);
9701 genPagedPointerGet (left, result, ic, pi);
9705 genFarPointerGet (left, result, ic, pi);
9709 genCodePointerGet (left, result, ic, pi);
9713 genGenPointerGet (left, result, ic, pi);
9719 /*-----------------------------------------------------------------*/
9720 /* genPackBits - generates code for packed bit storage */
9721 /*-----------------------------------------------------------------*/
9723 genPackBits (sym_link * etype,
9725 char *rname, int p_type)
9732 blen = SPEC_BLEN (etype);
9733 bstr = SPEC_BSTR (etype);
9735 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9737 /* if the bit lenth is less than or */
9738 /* it exactly fits a byte then */
9739 if (SPEC_BLEN (etype) <= 8)
9741 /* shift left acc */
9742 AccLsh (SPEC_BSTR (etype));
9744 if (SPEC_BLEN (etype) < 8)
9745 { /* if smaller than a byte */
9751 emitcode ("mov", "b,a");
9752 emitcode ("mov", "a,@%s", rname);
9756 emitcode ("mov", "b,a");
9757 emitcode ("movx", "a,@dptr");
9761 emitcode ("push", "b");
9762 emitcode ("push", "acc");
9763 emitcode ("lcall", "__gptrget");
9764 emitcode ("pop", "b");
9768 emitcode ("anl", "a,#!constbyte", (unsigned char)
9769 ((unsigned char) (0xFF << (blen + bstr)) |
9770 (unsigned char) (0xFF >> (8 - bstr))));
9771 emitcode ("orl", "a,b");
9772 if (p_type == GPOINTER)
9773 emitcode ("pop", "b");
9780 emitcode ("mov", "@%s,a", rname);
9784 emitcode ("movx", "@dptr,a");
9788 emitcode ("lcall", "__gptrput");
9793 if (SPEC_BLEN (etype) <= 8)
9796 emitcode ("inc", "%s", rname);
9797 rLen = SPEC_BLEN (etype);
9799 /* now generate for lengths greater than one byte */
9803 l = aopGet (AOP (right), offset++, FALSE, TRUE, NULL);
9815 emitcode ("mov", "@%s,a", rname);
9818 emitcode ("mov", "@%s,%s", rname, l);
9823 emitcode ("movx", "@dptr,a");
9828 emitcode ("lcall", "__gptrput");
9831 emitcode ("inc", "%s", rname);
9836 /* last last was not complete */
9839 /* save the byte & read byte */
9843 emitcode ("mov", "b,a");
9844 emitcode ("mov", "a,@%s", rname);
9848 emitcode ("mov", "b,a");
9849 emitcode ("movx", "a,@dptr");
9853 emitcode ("push", "b");
9854 emitcode ("push", "acc");
9855 emitcode ("lcall", "__gptrget");
9856 emitcode ("pop", "b");
9860 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1 << rLen));
9861 emitcode ("orl", "a,b");
9864 if (p_type == GPOINTER)
9865 emitcode ("pop", "b");
9871 emitcode ("mov", "@%s,a", rname);
9875 emitcode ("movx", "@dptr,a");
9879 emitcode ("lcall", "__gptrput");
9883 /*-----------------------------------------------------------------*/
9884 /* genDataPointerSet - remat pointer to data space */
9885 /*-----------------------------------------------------------------*/
9887 genDataPointerSet (operand * right,
9891 int size, offset = 0;
9894 aopOp (right, ic, FALSE, FALSE);
9896 l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
9897 size = AOP_SIZE (right);
9902 SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
9906 SNPRINTF (buff, sizeof(buff), "%s", l + 1);
9909 emitcode ("mov", "%s,%s", buff,
9910 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9913 freeAsmop (right, NULL, ic, TRUE);
9914 freeAsmop (result, NULL, ic, TRUE);
9917 /*-----------------------------------------------------------------*/
9918 /* genNearPointerSet - emitcode for near pointer put */
9919 /*-----------------------------------------------------------------*/
9921 genNearPointerSet (operand * right,
9928 sym_link *retype, *letype;
9929 sym_link *ptype = operandType (result);
9931 retype = getSpec (operandType (right));
9932 letype = getSpec (ptype);
9934 aopOp (result, ic, FALSE, FALSE);
9936 /* if the result is rematerializable &
9937 in data space & not a bit variable */
9938 if (AOP_TYPE (result) == AOP_IMMD &&
9939 DCL_TYPE (ptype) == POINTER &&
9940 !IS_BITVAR (retype) &&
9941 !IS_BITVAR (letype))
9943 genDataPointerSet (right, result, ic);
9947 /* if the value is already in a pointer register
9948 then don't need anything more */
9949 if (!AOP_INPREG (AOP (result)))
9951 /* otherwise get a free pointer register */
9955 preg = getFreePtr (ic, &aop, FALSE);
9956 emitcode ("mov", "%s,%s",
9958 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
9962 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
9964 aopOp (right, ic, FALSE, FALSE);
9966 /* if bitfield then unpack the bits */
9967 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9968 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9971 /* we have can just get the values */
9972 int size = AOP_SIZE (right);
9977 l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
9981 emitcode ("mov", "@%s,a", rname);
9984 emitcode ("mov", "@%s,%s", rname, l);
9986 emitcode ("inc", "%s", rname);
9991 /* now some housekeeping stuff */
9994 /* we had to allocate for this iCode */
9995 if (pi) aopPut (AOP (result),rname,0);
9996 freeAsmop (NULL, aop, ic, TRUE);
10000 /* we did not allocate which means left
10001 already in a pointer register, then
10002 if size > 0 && this could be used again
10003 we have to point it back to where it
10005 if (AOP_SIZE (right) > 1 &&
10006 !OP_SYMBOL (result)->remat &&
10007 (OP_SYMBOL (result)->liveTo > ic->seq ||
10011 int size = AOP_SIZE (right) - 1;
10013 emitcode ("dec", "%s", rname);
10018 if (pi) pi->generated = 1;
10019 freeAsmop (result, NULL, ic, TRUE);
10020 freeAsmop (right, NULL, ic, TRUE);
10025 /*-----------------------------------------------------------------*/
10026 /* genPagedPointerSet - emitcode for Paged pointer put */
10027 /*-----------------------------------------------------------------*/
10029 genPagedPointerSet (operand * right,
10036 sym_link *retype, *letype;
10038 retype = getSpec (operandType (right));
10039 letype = getSpec (operandType (result));
10041 aopOp (result, ic, FALSE, FALSE);
10043 /* if the value is already in a pointer register
10044 then don't need anything more */
10045 if (!AOP_INPREG (AOP (result)))
10047 /* otherwise get a free pointer register */
10050 aop = newAsmop (0);
10051 preg = getFreePtr (ic, &aop, FALSE);
10052 emitcode ("mov", "%s,%s",
10054 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10055 rname = preg->name;
10058 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10060 aopOp (right, ic, FALSE, FALSE);
10062 /* if bitfield then unpack the bits */
10063 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10064 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
10067 /* we have can just get the values */
10068 int size = AOP_SIZE (right);
10073 MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10075 emitcode ("movx", "@%s,a", rname);
10078 emitcode ("inc", "%s", rname);
10084 /* now some housekeeping stuff */
10087 if (pi) aopPut (AOP (result),rname,0);
10088 /* we had to allocate for this iCode */
10089 freeAsmop (NULL, aop, ic, TRUE);
10093 /* we did not allocate which means left
10094 already in a pointer register, then
10095 if size > 0 && this could be used again
10096 we have to point it back to where it
10098 if (AOP_SIZE (right) > 1 &&
10099 !OP_SYMBOL (result)->remat &&
10100 (OP_SYMBOL (result)->liveTo > ic->seq ||
10104 int size = AOP_SIZE (right) - 1;
10106 emitcode ("dec", "%s", rname);
10111 if (pi) pi->generated = 1;
10112 freeAsmop (result, NULL, ic, TRUE);
10113 freeAsmop (right, NULL, ic, TRUE);
10118 /*-----------------------------------------------------------------*/
10119 /* genFarPointerSet - set value from far space */
10120 /*-----------------------------------------------------------------*/
10122 genFarPointerSet (operand * right,
10123 operand * result, iCode * ic, iCode *pi)
10125 int size, offset, dopi=1;
10126 sym_link *retype = getSpec (operandType (right));
10127 sym_link *letype = getSpec (operandType (result));
10129 aopOp (result, ic, FALSE, FALSE);
10131 /* if the operand is already in dptr
10132 then we do nothing else we move the value to dptr */
10133 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10135 /* if this is remateriazable */
10136 if (AOP_TYPE (result) == AOP_IMMD)
10137 emitcode ("mov", "dptr,%s",
10138 aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10141 /* we need to get it byte by byte */
10142 _startLazyDPSEvaluation ();
10143 if (AOP_TYPE (result) != AOP_DPTR)
10145 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10146 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10147 if (options.model == MODEL_FLAT24)
10148 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10152 /* We need to generate a load to DPTR indirect through DPTR. */
10153 D (emitcode (";", "genFarPointerSet -- indirection special case."););
10155 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10156 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10157 if (options.model == MODEL_FLAT24)
10158 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10159 emitcode ("pop", "dph");
10160 emitcode ("pop", "dpl");
10163 _endLazyDPSEvaluation ();
10166 /* so dptr know contains the address */
10167 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10169 /* if bit then unpack */
10170 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
10171 if (AOP_INDPTRn(result)) {
10172 genSetDPTR(AOP(result)->aopu.dptr);
10174 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
10175 if (AOP_INDPTRn(result)) {
10179 size = AOP_SIZE (right);
10181 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10183 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10185 genSetDPTR(AOP(result)->aopu.dptr);
10186 emitcode ("movx", "@dptr,a");
10187 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10188 emitcode ("inc", "dptr");
10192 _startLazyDPSEvaluation ();
10194 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10196 if (AOP_INDPTRn(result)) {
10197 genSetDPTR(AOP(result)->aopu.dptr);
10203 emitcode ("movx", "@dptr,a");
10204 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10205 emitcode ("inc", "dptr");
10207 _endLazyDPSEvaluation ();
10211 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10212 if (!AOP_INDPTRn(result)) {
10213 _startLazyDPSEvaluation ();
10215 aopPut (AOP(result),"dpl",0);
10216 aopPut (AOP(result),"dph",1);
10217 if (options.model == MODEL_FLAT24)
10218 aopPut (AOP(result),"dpx",2);
10220 _endLazyDPSEvaluation ();
10223 } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
10224 AOP_SIZE(right) > 1 &&
10225 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10227 size = AOP_SIZE (right) - 1;
10228 if (AOP_INDPTRn(result)) {
10229 genSetDPTR(AOP(result)->aopu.dptr);
10231 while (size--) emitcode ("lcall","__decdptr");
10232 if (AOP_INDPTRn(result)) {
10236 freeAsmop (result, NULL, ic, TRUE);
10237 freeAsmop (right, NULL, ic, TRUE);
10240 /*-----------------------------------------------------------------*/
10241 /* genGenPointerSet - set value from generic pointer space */
10242 /*-----------------------------------------------------------------*/
10244 genGenPointerSet (operand * right,
10245 operand * result, iCode * ic, iCode *pi)
10248 sym_link *retype = getSpec (operandType (right));
10249 sym_link *letype = getSpec (operandType (result));
10251 aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10253 /* if the operand is already in dptr
10254 then we do nothing else we move the value to dptr */
10255 if (AOP_TYPE (result) != AOP_STR)
10257 _startLazyDPSEvaluation ();
10258 /* if this is remateriazable */
10259 if (AOP_TYPE (result) == AOP_IMMD)
10261 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10262 if (AOP(result)->aopu.aop_immd.from_cast_remat)
10264 MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10269 "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10273 { /* we need to get it byte by byte */
10274 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10275 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10276 if (options.model == MODEL_FLAT24) {
10277 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10278 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10280 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10283 _endLazyDPSEvaluation ();
10285 /* so dptr + b now contains the address */
10287 aopOp (right, ic, FALSE, TRUE);
10291 /* if bit then unpack */
10292 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10294 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
10298 size = AOP_SIZE (right);
10301 _startLazyDPSEvaluation ();
10306 // Set two bytes at a time, passed in _AP & A.
10307 // dptr will be incremented ONCE by __gptrputWord.
10309 // Note: any change here must be coordinated
10310 // with the implementation of __gptrputWord
10311 // in device/lib/_gptrput.c
10312 emitcode("mov", "_ap, %s",
10313 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10314 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10318 emitcode ("lcall", "__gptrputWord");
10323 // Only one byte to put.
10324 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10328 emitcode ("lcall", "__gptrput");
10331 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10333 emitcode ("inc", "dptr");
10336 _endLazyDPSEvaluation ();
10339 if (pi && AOP_TYPE (result) != AOP_IMMD) {
10340 _startLazyDPSEvaluation ();
10342 aopPut (AOP(result),"dpl",0);
10343 aopPut (AOP(result),"dph",1);
10344 if (options.model == MODEL_FLAT24) {
10345 aopPut (AOP(result),"dpx",2);
10346 aopPut (AOP(result),"b",3);
10348 aopPut (AOP(result),"b",2);
10350 _endLazyDPSEvaluation ();
10353 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10354 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10356 size = AOP_SIZE (right) - 1;
10357 while (size--) emitcode ("lcall","__decdptr");
10359 freeAsmop (result, NULL, ic, TRUE);
10360 freeAsmop (right, NULL, ic, TRUE);
10363 /*-----------------------------------------------------------------*/
10364 /* genPointerSet - stores the value into a pointer location */
10365 /*-----------------------------------------------------------------*/
10367 genPointerSet (iCode * ic, iCode *pi)
10369 operand *right, *result;
10370 sym_link *type, *etype;
10373 D (emitcode (";", "genPointerSet "););
10375 right = IC_RIGHT (ic);
10376 result = IC_RESULT (ic);
10378 /* depending on the type of pointer we need to
10379 move it to the correct pointer register */
10380 type = operandType (result);
10381 etype = getSpec (type);
10382 /* if left is of type of pointer then it is simple */
10383 if (IS_PTR (type) && !IS_FUNC (type->next))
10385 p_type = DCL_TYPE (type);
10389 /* we have to go by the storage class */
10390 p_type = PTR_TYPE (SPEC_OCLS (etype));
10392 /* special case when cast remat */
10393 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10394 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10395 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10396 type = operandType (result);
10397 p_type = DCL_TYPE (type);
10400 /* now that we have the pointer type we assign
10401 the pointer values */
10407 genNearPointerSet (right, result, ic, pi);
10411 genPagedPointerSet (right, result, ic, pi);
10415 genFarPointerSet (right, result, ic, pi);
10419 genGenPointerSet (right, result, ic, pi);
10423 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10424 "genPointerSet: illegal pointer type");
10429 /*-----------------------------------------------------------------*/
10430 /* genIfx - generate code for Ifx statement */
10431 /*-----------------------------------------------------------------*/
10433 genIfx (iCode * ic, iCode * popIc)
10435 operand *cond = IC_COND (ic);
10438 D (emitcode (";", "genIfx "););
10440 aopOp (cond, ic, FALSE, FALSE);
10442 /* get the value into acc */
10443 if (AOP_TYPE (cond) != AOP_CRY)
10452 /* the result is now in the accumulator */
10453 freeAsmop (cond, NULL, ic, TRUE);
10455 /* if there was something to be popped then do it */
10459 /* if the condition is a bit variable */
10460 if (isbit && IS_ITEMP (cond) &&
10463 genIfxJump (ic, SPIL_LOC (cond)->rname);
10465 else if (isbit && !IS_ITEMP (cond))
10467 genIfxJump (ic, OP_SYMBOL (cond)->rname);
10471 genIfxJump (ic, "a");
10477 /*-----------------------------------------------------------------*/
10478 /* genAddrOf - generates code for address of */
10479 /*-----------------------------------------------------------------*/
10481 genAddrOf (iCode * ic)
10483 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10486 D (emitcode (";", "genAddrOf ");
10489 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10491 /* if the operand is on the stack then we
10492 need to get the stack offset of this
10494 if (sym->onStack) {
10496 /* if 10 bit stack */
10497 if (options.stack10bit) {
10499 tsprintf(buff, sizeof(buff),
10500 "#!constbyte",(options.stack_loc >> 16) & 0xff);
10501 /* if it has an offset then we need to compute it */
10502 /* emitcode ("subb", "a,#!constbyte", */
10503 /* -((sym->stack < 0) ? */
10504 /* ((short) (sym->stack - _G.nRegsSaved)) : */
10505 /* ((short) sym->stack)) & 0xff); */
10506 /* emitcode ("mov","b,a"); */
10507 /* emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
10508 /* ((short) (sym->stack - _G.nRegsSaved)) : */
10509 /* ((short) sym->stack)) >> 8) & 0xff); */
10511 emitcode ("mov", "a,_bpx");
10512 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
10513 ((char) (sym->stack - _G.nRegsSaved)) :
10514 ((char) sym->stack )) & 0xff);
10515 emitcode ("mov", "b,a");
10516 emitcode ("mov", "a,_bpx+1");
10517 emitcode ("addc","a,#!constbyte", (((sym->stack < 0) ?
10518 ((short) (sym->stack - _G.nRegsSaved)) :
10519 ((short) sym->stack )) >> 8) & 0xff);
10520 aopPut (AOP (IC_RESULT (ic)), "b", 0);
10521 aopPut (AOP (IC_RESULT (ic)), "a", 1);
10522 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10524 /* we can just move _bp */
10525 aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10526 aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10527 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10530 /* if it has an offset then we need to compute it */
10532 emitcode ("mov", "a,_bp");
10533 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10534 aopPut (AOP (IC_RESULT (ic)), "a", 0);
10536 /* we can just move _bp */
10537 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10539 /* fill the result with zero */
10540 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10543 if (options.stack10bit && size < (FPTRSIZE - 1)) {
10545 "*** warning: pointer to stack var truncated.\n");
10550 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10556 /* object not on stack then we need the name */
10557 size = AOP_SIZE (IC_RESULT (ic));
10562 char s[SDCC_NAME_MAX];
10566 tsprintf(s, sizeof(s), "#!his",sym->rname);
10569 tsprintf(s, sizeof(s), "#!hihis",sym->rname);
10572 tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
10574 default: /* should not need this (just in case) */
10575 SNPRINTF (s, sizeof(s), "#(%s >> %d)",
10582 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10585 aopPut (AOP (IC_RESULT (ic)), s, offset++);
10589 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10593 /*-----------------------------------------------------------------*/
10594 /* genArrayInit - generates code for address of */
10595 /*-----------------------------------------------------------------*/
10597 genArrayInit (iCode * ic)
10599 literalList *iLoop;
10601 int elementSize = 0, eIndex;
10602 unsigned val, lastVal;
10604 operand *left=IC_LEFT(ic);
10606 D (emitcode (";", "genArrayInit "););
10608 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10610 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10612 // Load immediate value into DPTR.
10613 emitcode("mov", "dptr, %s",
10614 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
10616 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10619 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10620 "Unexpected operand to genArrayInit.\n");
10623 // a regression because of SDCCcse.c:1.52
10624 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10625 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10626 if (options.model == MODEL_FLAT24)
10627 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10631 type = operandType(IC_LEFT(ic));
10633 if (type && type->next)
10635 elementSize = getSize(type->next);
10639 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10640 "can't determine element size in genArrayInit.\n");
10644 iLoop = IC_ARRAYILIST(ic);
10649 bool firstpass = TRUE;
10651 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
10652 iLoop->count, (int)iLoop->literalValue, elementSize);
10658 symbol *tlbl = NULL;
10660 count = ix > 256 ? 256 : ix;
10664 tlbl = newiTempLabel (NULL);
10665 if (firstpass || (count & 0xff))
10667 emitcode("mov", "b, #!constbyte", count & 0xff);
10670 emitcode ("", "!tlabeldef", tlbl->key + 100);
10675 for (eIndex = 0; eIndex < elementSize; eIndex++)
10677 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10678 if (val != lastVal)
10680 emitcode("mov", "a, #!constbyte", val);
10684 emitcode("movx", "@dptr, a");
10685 emitcode("inc", "dptr");
10690 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10696 iLoop = iLoop->next;
10699 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10702 /*-----------------------------------------------------------------*/
10703 /* genFarFarAssign - assignment when both are in far space */
10704 /*-----------------------------------------------------------------*/
10706 genFarFarAssign (operand * result, operand * right, iCode * ic)
10708 int size = AOP_SIZE (right);
10710 symbol *rSym = NULL;
10714 /* quick & easy case. */
10715 D(emitcode(";","genFarFarAssign (1 byte case)"););
10716 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
10717 freeAsmop (right, NULL, ic, FALSE);
10718 /* now assign DPTR to result */
10720 aopOp(result, ic, FALSE, FALSE);
10722 aopPut(AOP(result), "a", 0);
10723 freeAsmop(result, NULL, ic, FALSE);
10727 /* See if we've got an underlying symbol to abuse. */
10728 if (IS_SYMOP(result) && OP_SYMBOL(result))
10730 if (IS_TRUE_SYMOP(result))
10732 rSym = OP_SYMBOL(result);
10734 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10736 rSym = OP_SYMBOL(result)->usl.spillLoc;
10740 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10742 /* We can use the '390 auto-toggle feature to good effect here. */
10744 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10745 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
10746 emitcode ("mov", "dptr,#%s", rSym->rname);
10747 /* DP2 = result, DP1 = right, DP1 is current. */
10750 emitcode("movx", "a,@dptr");
10751 emitcode("movx", "@dptr,a");
10754 emitcode("inc", "dptr");
10755 emitcode("inc", "dptr");
10758 emitcode("mov", "dps,#0");
10759 freeAsmop (right, NULL, ic, FALSE);
10761 some alternative code for processors without auto-toggle
10762 no time to test now, so later well put in...kpb
10763 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10764 emitcode("mov", "dps,#1"); /* Select DPTR2. */
10765 emitcode ("mov", "dptr,#%s", rSym->rname);
10766 /* DP2 = result, DP1 = right, DP1 is current. */
10770 emitcode("movx", "a,@dptr");
10772 emitcode("inc", "dptr");
10773 emitcode("inc", "dps");
10774 emitcode("movx", "@dptr,a");
10776 emitcode("inc", "dptr");
10777 emitcode("inc", "dps");
10779 emitcode("mov", "dps,#0");
10780 freeAsmop (right, NULL, ic, FALSE);
10785 D (emitcode (";", "genFarFarAssign"););
10786 aopOp (result, ic, TRUE, TRUE);
10788 _startLazyDPSEvaluation ();
10792 aopPut (AOP (result),
10793 aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
10796 _endLazyDPSEvaluation ();
10797 freeAsmop (result, NULL, ic, FALSE);
10798 freeAsmop (right, NULL, ic, FALSE);
10802 /*-----------------------------------------------------------------*/
10803 /* genAssign - generate code for assignment */
10804 /*-----------------------------------------------------------------*/
10806 genAssign (iCode * ic)
10808 operand *result, *right;
10810 unsigned long lit = 0L;
10812 D (emitcode (";", "genAssign ");
10815 result = IC_RESULT (ic);
10816 right = IC_RIGHT (ic);
10818 /* if they are the same */
10819 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10822 aopOp (right, ic, FALSE, FALSE);
10824 emitcode (";", "genAssign: resultIsFar = %s",
10825 isOperandInFarSpace (result) ?
10828 /* special case both in far space */
10829 if ((AOP_TYPE (right) == AOP_DPTR ||
10830 AOP_TYPE (right) == AOP_DPTR2) &&
10831 /* IS_TRUE_SYMOP(result) && */
10832 isOperandInFarSpace (result))
10834 genFarFarAssign (result, right, ic);
10838 aopOp (result, ic, TRUE, FALSE);
10840 /* if they are the same registers */
10841 if (sameRegs (AOP (right), AOP (result)))
10844 /* if the result is a bit */
10845 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10847 /* if the right size is a literal then
10848 we know what the value is */
10849 if (AOP_TYPE (right) == AOP_LIT)
10851 if (((int) operandLitValue (right)))
10852 aopPut (AOP (result), one, 0);
10854 aopPut (AOP (result), zero, 0);
10858 /* the right is also a bit variable */
10859 if (AOP_TYPE (right) == AOP_CRY)
10861 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10862 aopPut (AOP (result), "c", 0);
10866 /* we need to or */
10868 aopPut (AOP (result), "a", 0);
10872 /* bit variables done */
10874 size = AOP_SIZE (result);
10876 if (AOP_TYPE (right) == AOP_LIT)
10877 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10880 (AOP_TYPE (result) != AOP_REG) &&
10881 (AOP_TYPE (right) == AOP_LIT) &&
10882 !IS_FLOAT (operandType (right)))
10884 _startLazyDPSEvaluation ();
10885 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10887 aopPut (AOP (result),
10888 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10893 /* And now fill the rest with zeros. */
10896 emitcode ("clr", "a");
10900 aopPut (AOP (result), "a", offset++);
10902 _endLazyDPSEvaluation ();
10906 _startLazyDPSEvaluation ();
10909 aopPut (AOP (result),
10910 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10914 _endLazyDPSEvaluation ();
10918 freeAsmop (right, NULL, ic, FALSE);
10919 freeAsmop (result, NULL, ic, TRUE);
10922 /*-----------------------------------------------------------------*/
10923 /* genJumpTab - generates code for jump table */
10924 /*-----------------------------------------------------------------*/
10926 genJumpTab (iCode * ic)
10931 D (emitcode (";", "genJumpTab ");
10934 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10935 /* get the condition into accumulator */
10936 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
10938 /* multiply by four! */
10939 emitcode ("add", "a,acc");
10940 emitcode ("add", "a,acc");
10941 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10943 jtab = newiTempLabel (NULL);
10944 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
10945 emitcode ("jmp", "@a+dptr");
10946 emitcode ("", "!tlabeldef", jtab->key + 100);
10947 /* now generate the jump labels */
10948 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10949 jtab = setNextItem (IC_JTLABELS (ic)))
10950 emitcode ("ljmp", "!tlabel", jtab->key + 100);
10954 /*-----------------------------------------------------------------*/
10955 /* genCast - gen code for casting */
10956 /*-----------------------------------------------------------------*/
10958 genCast (iCode * ic)
10960 operand *result = IC_RESULT (ic);
10961 sym_link *ctype = operandType (IC_LEFT (ic));
10962 sym_link *rtype = operandType (IC_RIGHT (ic));
10963 operand *right = IC_RIGHT (ic);
10966 D (emitcode (";", "genCast "););
10968 /* if they are equivalent then do nothing */
10969 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10972 aopOp (right, ic, FALSE, FALSE);
10973 aopOp (result, ic, FALSE, AOP_USESDPTR(right));
10975 /* if the result is a bit */
10976 // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10977 if (IS_BITVAR(OP_SYMBOL(result)->type))
10979 /* if the right size is a literal then
10980 we know what the value is */
10981 if (AOP_TYPE (right) == AOP_LIT)
10983 if (((int) operandLitValue (right)))
10984 aopPut (AOP (result), one, 0);
10986 aopPut (AOP (result), zero, 0);
10991 /* the right is also a bit variable */
10992 if (AOP_TYPE (right) == AOP_CRY)
10994 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10995 aopPut (AOP (result), "c", 0);
10999 /* we need to or */
11001 aopPut (AOP (result), "a", 0);
11005 /* if they are the same size : or less */
11006 if (AOP_SIZE (result) <= AOP_SIZE (right))
11009 /* if they are in the same place */
11010 if (sameRegs (AOP (right), AOP (result)))
11013 /* if they in different places then copy */
11014 size = AOP_SIZE (result);
11016 _startLazyDPSEvaluation ();
11019 aopPut (AOP (result),
11020 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11024 _endLazyDPSEvaluation ();
11029 /* if the result is of type pointer */
11030 if (IS_PTR (ctype))
11034 sym_link *type = operandType (right);
11036 /* pointer to generic pointer */
11037 if (IS_GENPTR (ctype))
11041 p_type = DCL_TYPE (type);
11045 #if OLD_CAST_BEHAVIOR
11046 /* KV: we are converting a non-pointer type to
11047 * a generic pointer. This (ifdef'd out) code
11048 * says that the resulting generic pointer
11049 * should have the same class as the storage
11050 * location of the non-pointer variable.
11052 * For example, converting an int (which happens
11053 * to be stored in DATA space) to a pointer results
11054 * in a DATA generic pointer; if the original int
11055 * in XDATA space, so will be the resulting pointer.
11057 * I don't like that behavior, and thus this change:
11058 * all such conversions will be forced to XDATA and
11059 * throw a warning. If you want some non-XDATA
11060 * type, or you want to suppress the warning, you
11061 * must go through an intermediate cast, like so:
11063 * char _generic *gp = (char _xdata *)(intVar);
11065 sym_link *etype = getSpec (type);
11067 /* we have to go by the storage class */
11068 if (SPEC_OCLS (etype) != generic)
11070 p_type = PTR_TYPE (SPEC_OCLS (etype));
11075 /* Converting unknown class (i.e. register variable)
11076 * to generic pointer. This is not good, but
11077 * we'll make a guess (and throw a warning).
11080 werror (W_INT_TO_GEN_PTR_CAST);
11084 /* the first two bytes are known */
11085 size = GPTRSIZE - 1;
11087 _startLazyDPSEvaluation ();
11090 aopPut (AOP (result),
11091 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11095 _endLazyDPSEvaluation ();
11097 /* the last byte depending on type */
11099 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11104 // pointerTypeToGPByte will have bitched.
11108 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11109 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11114 /* just copy the pointers */
11115 size = AOP_SIZE (result);
11117 _startLazyDPSEvaluation ();
11120 aopPut (AOP (result),
11121 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11125 _endLazyDPSEvaluation ();
11129 /* so we now know that the size of destination is greater
11130 than the size of the source */
11131 /* we move to result for the size of source */
11132 size = AOP_SIZE (right);
11134 _startLazyDPSEvaluation ();
11137 aopPut (AOP (result),
11138 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11142 _endLazyDPSEvaluation ();
11144 /* now depending on the sign of the source && destination */
11145 size = AOP_SIZE (result) - AOP_SIZE (right);
11146 /* if unsigned or not an integral type */
11147 /* also, if the source is a bit, we don't need to sign extend, because
11148 * it can't possibly have set the sign bit.
11150 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
11154 aopPut (AOP (result), zero, offset++);
11159 /* we need to extend the sign :{ */
11160 MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11161 FALSE, FALSE, NULL));
11162 emitcode ("rlc", "a");
11163 emitcode ("subb", "a,acc");
11165 aopPut (AOP (result), "a", offset++);
11168 /* we are done hurray !!!! */
11171 freeAsmop (right, NULL, ic, TRUE);
11172 freeAsmop (result, NULL, ic, TRUE);
11176 /*-----------------------------------------------------------------*/
11177 /* genDjnz - generate decrement & jump if not zero instrucion */
11178 /*-----------------------------------------------------------------*/
11180 genDjnz (iCode * ic, iCode * ifx)
11182 symbol *lbl, *lbl1;
11186 /* if the if condition has a false label
11187 then we cannot save */
11188 if (IC_FALSE (ifx))
11191 /* if the minus is not of the form
11193 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11194 !IS_OP_LITERAL (IC_RIGHT (ic)))
11197 if (operandLitValue (IC_RIGHT (ic)) != 1)
11200 /* if the size of this greater than one then no
11202 if (getSize (operandType (IC_RESULT (ic))) > 1)
11205 /* otherwise we can save BIG */
11206 D(emitcode(";", "genDjnz"););
11208 lbl = newiTempLabel (NULL);
11209 lbl1 = newiTempLabel (NULL);
11211 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11213 if (AOP_NEEDSACC(IC_RESULT(ic)))
11215 /* If the result is accessed indirectly via
11216 * the accumulator, we must explicitly write
11217 * it back after the decrement.
11219 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11221 if (strcmp(rByte, "a"))
11223 /* Something is hopelessly wrong */
11224 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11225 __FILE__, __LINE__);
11226 /* We can just give up; the generated code will be inefficient,
11227 * but what the hey.
11229 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11232 emitcode ("dec", "%s", rByte);
11233 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11234 emitcode ("jnz", "!tlabel", lbl->key + 100);
11236 else if (IS_AOP_PREG (IC_RESULT (ic)))
11238 emitcode ("dec", "%s",
11239 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11240 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11241 emitcode ("jnz", "!tlabel", lbl->key + 100);
11245 emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11248 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11249 emitcode ("", "!tlabeldef", lbl->key + 100);
11250 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11251 emitcode ("", "!tlabeldef", lbl1->key + 100);
11253 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11254 ifx->generated = 1;
11258 /*-----------------------------------------------------------------*/
11259 /* genReceive - generate code for a receive iCode */
11260 /*-----------------------------------------------------------------*/
11262 genReceive (iCode * ic)
11264 int size = getSize (operandType (IC_RESULT (ic)));
11268 D (emitcode (";", "genReceive "););
11270 if (ic->argreg == 1)
11272 /* first parameter */
11273 if (AOP_IS_STR(IC_RESULT(ic)))
11275 /* Nothing to do: it's already in the proper place. */
11282 useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11283 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11284 IS_TRUE_SYMOP (IC_RESULT (ic)));
11287 aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11290 /* Sanity checking... */
11291 if (AOP_USESDPTR(IC_RESULT(ic)))
11293 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11294 "genReceive got unexpected DPTR.");
11296 assignResultValue (IC_RESULT (ic));
11301 /* second receive onwards */
11302 /* this gets a little tricky since unused recevies will be
11303 eliminated, we have saved the reg in the type field . and
11304 we use that to figure out which register to use */
11305 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11306 rb1off = ic->argreg;
11309 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11312 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11315 /*-----------------------------------------------------------------*/
11316 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
11317 /*-----------------------------------------------------------------*/
11318 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11320 operand *from , *to , *count;
11325 /* we know it has to be 3 parameters */
11326 assert (nparms == 3);
11328 rsave = newBitVect(16);
11329 /* save DPTR if it needs to be saved */
11330 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11331 if (bitVectBitValue(ic->rMask,i))
11332 rsave = bitVectSetBit(rsave,i);
11334 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11335 ds390_rUmaskForOp (IC_RESULT(ic))));
11342 aopOp (from, ic->next, FALSE, FALSE);
11344 /* get from into DPTR1 */
11345 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11346 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11347 if (options.model == MODEL_FLAT24) {
11348 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11351 freeAsmop (from, NULL, ic, FALSE);
11352 aopOp (to, ic, FALSE, FALSE);
11353 /* get "to" into DPTR */
11354 /* if the operand is already in dptr
11355 then we do nothing else we move the value to dptr */
11356 if (AOP_TYPE (to) != AOP_STR) {
11357 /* if already in DPTR then we need to push */
11358 if (AOP_TYPE(to) == AOP_DPTR) {
11359 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11360 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11361 if (options.model == MODEL_FLAT24)
11362 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11363 emitcode ("pop", "dph");
11364 emitcode ("pop", "dpl");
11366 _startLazyDPSEvaluation ();
11367 /* if this is remateriazable */
11368 if (AOP_TYPE (to) == AOP_IMMD) {
11369 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11370 } else { /* we need to get it byte by byte */
11371 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11372 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11373 if (options.model == MODEL_FLAT24) {
11374 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11377 _endLazyDPSEvaluation ();
11380 freeAsmop (to, NULL, ic, FALSE);
11381 _G.dptrInUse = _G.dptr1InUse = 1;
11382 aopOp (count, ic->next->next, FALSE,FALSE);
11383 lbl =newiTempLabel(NULL);
11385 /* now for the actual copy */
11386 if (AOP_TYPE(count) == AOP_LIT &&
11387 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11388 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11390 emitcode ("lcall","__bi_memcpyc2x_s");
11392 emitcode ("lcall","__bi_memcpyx2x_s");
11394 freeAsmop (count, NULL, ic, FALSE);
11396 symbol *lbl1 = newiTempLabel(NULL);
11398 emitcode (";"," Auto increment but no djnz");
11399 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11400 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11401 freeAsmop (count, NULL, ic, FALSE);
11402 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11403 emitcode ("","!tlabeldef",lbl->key+100);
11405 emitcode ("clr","a");
11406 emitcode ("movc", "a,@a+dptr");
11408 emitcode ("movx", "a,@dptr");
11409 emitcode ("movx", "@dptr,a");
11410 emitcode ("inc", "dptr");
11411 emitcode ("inc", "dptr");
11412 emitcode ("mov","a,b");
11413 emitcode ("orl","a,_ap");
11414 emitcode ("jz","!tlabel",lbl1->key+100);
11415 emitcode ("mov","a,_ap");
11416 emitcode ("add","a,#!constbyte",0xFF);
11417 emitcode ("mov","_ap,a");
11418 emitcode ("mov","a,b");
11419 emitcode ("addc","a,#!constbyte",0xFF);
11420 emitcode ("mov","b,a");
11421 emitcode ("sjmp","!tlabel",lbl->key+100);
11422 emitcode ("","!tlabeldef",lbl1->key+100);
11424 emitcode ("mov", "dps,#0");
11425 _G.dptrInUse = _G.dptr1InUse = 0;
11426 unsavermask(rsave);
11430 /*-----------------------------------------------------------------*/
11431 /* genMemcmpX2X - gen code for memcmp xdata to xdata */
11432 /*-----------------------------------------------------------------*/
11433 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11435 operand *from , *to , *count;
11440 /* we know it has to be 3 parameters */
11441 assert (nparms == 3);
11443 rsave = newBitVect(16);
11444 /* save DPTR if it needs to be saved */
11445 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11446 if (bitVectBitValue(ic->rMask,i))
11447 rsave = bitVectSetBit(rsave,i);
11449 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11450 ds390_rUmaskForOp (IC_RESULT(ic))));
11457 aopOp (from, ic->next, FALSE, FALSE);
11459 /* get from into DPTR1 */
11460 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11461 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11462 if (options.model == MODEL_FLAT24) {
11463 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11466 freeAsmop (from, NULL, ic, FALSE);
11467 aopOp (to, ic, FALSE, FALSE);
11468 /* get "to" into DPTR */
11469 /* if the operand is already in dptr
11470 then we do nothing else we move the value to dptr */
11471 if (AOP_TYPE (to) != AOP_STR) {
11472 /* if already in DPTR then we need to push */
11473 if (AOP_TYPE(to) == AOP_DPTR) {
11474 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11475 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11476 if (options.model == MODEL_FLAT24)
11477 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11478 emitcode ("pop", "dph");
11479 emitcode ("pop", "dpl");
11481 _startLazyDPSEvaluation ();
11482 /* if this is remateriazable */
11483 if (AOP_TYPE (to) == AOP_IMMD) {
11484 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11485 } else { /* we need to get it byte by byte */
11486 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11487 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11488 if (options.model == MODEL_FLAT24) {
11489 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11492 _endLazyDPSEvaluation ();
11495 freeAsmop (to, NULL, ic, FALSE);
11496 _G.dptrInUse = _G.dptr1InUse = 1;
11497 aopOp (count, ic->next->next, FALSE,FALSE);
11498 lbl =newiTempLabel(NULL);
11499 lbl2 =newiTempLabel(NULL);
11501 /* now for the actual compare */
11502 if (AOP_TYPE(count) == AOP_LIT &&
11503 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11504 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11506 emitcode("lcall","__bi_memcmpc2x_s");
11508 emitcode("lcall","__bi_memcmpx2x_s");
11509 freeAsmop (count, NULL, ic, FALSE);
11510 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11511 aopPut(AOP(IC_RESULT(ic)),"a",0);
11512 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11514 symbol *lbl1 = newiTempLabel(NULL);
11516 emitcode("push","ar0");
11517 emitcode (";"," Auto increment but no djnz");
11518 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11519 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11520 freeAsmop (count, NULL, ic, FALSE);
11521 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11522 emitcode ("","!tlabeldef",lbl->key+100);
11524 emitcode ("clr","a");
11525 emitcode ("movc", "a,@a+dptr");
11527 emitcode ("movx", "a,@dptr");
11528 emitcode ("mov","r0,a");
11529 emitcode ("movx", "a,@dptr");
11530 emitcode ("clr","c");
11531 emitcode ("subb","a,r0");
11532 emitcode ("jnz","!tlabel",lbl2->key+100);
11533 emitcode ("inc", "dptr");
11534 emitcode ("inc", "dptr");
11535 emitcode ("mov","a,b");
11536 emitcode ("orl","a,_ap");
11537 emitcode ("jz","!tlabel",lbl1->key+100);
11538 emitcode ("mov","a,_ap");
11539 emitcode ("add","a,#!constbyte",0xFF);
11540 emitcode ("mov","_ap,a");
11541 emitcode ("mov","a,b");
11542 emitcode ("addc","a,#!constbyte",0xFF);
11543 emitcode ("mov","b,a");
11544 emitcode ("sjmp","!tlabel",lbl->key+100);
11545 emitcode ("","!tlabeldef",lbl1->key+100);
11546 emitcode ("clr","a");
11547 emitcode ("","!tlabeldef",lbl2->key+100);
11548 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11549 aopPut(AOP(IC_RESULT(ic)),"a",0);
11550 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11551 emitcode("pop","ar0");
11552 emitcode ("mov", "dps,#0");
11554 _G.dptrInUse = _G.dptr1InUse = 0;
11555 unsavermask(rsave);
11559 /*-----------------------------------------------------------------*/
11560 /* genInp - gen code for __builtin_inp read data from a mem mapped */
11561 /* port, first parameter output area second parameter pointer to */
11562 /* port third parameter count */
11563 /*-----------------------------------------------------------------*/
11564 static void genInp( iCode *ic, int nparms, operand **parms)
11566 operand *from , *to , *count;
11571 /* we know it has to be 3 parameters */
11572 assert (nparms == 3);
11574 rsave = newBitVect(16);
11575 /* save DPTR if it needs to be saved */
11576 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11577 if (bitVectBitValue(ic->rMask,i))
11578 rsave = bitVectSetBit(rsave,i);
11580 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11581 ds390_rUmaskForOp (IC_RESULT(ic))));
11588 aopOp (from, ic->next, FALSE, FALSE);
11590 /* get from into DPTR1 */
11591 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11592 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11593 if (options.model == MODEL_FLAT24) {
11594 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11597 freeAsmop (from, NULL, ic, FALSE);
11598 aopOp (to, ic, FALSE, FALSE);
11599 /* get "to" into DPTR */
11600 /* if the operand is already in dptr
11601 then we do nothing else we move the value to dptr */
11602 if (AOP_TYPE (to) != AOP_STR) {
11603 /* if already in DPTR then we need to push */
11604 if (AOP_TYPE(to) == AOP_DPTR) {
11605 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11606 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11607 if (options.model == MODEL_FLAT24)
11608 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11609 emitcode ("pop", "dph");
11610 emitcode ("pop", "dpl");
11612 _startLazyDPSEvaluation ();
11613 /* if this is remateriazable */
11614 if (AOP_TYPE (to) == AOP_IMMD) {
11615 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11616 } else { /* we need to get it byte by byte */
11617 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11618 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11619 if (options.model == MODEL_FLAT24) {
11620 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11623 _endLazyDPSEvaluation ();
11626 freeAsmop (to, NULL, ic, FALSE);
11628 _G.dptrInUse = _G.dptr1InUse = 1;
11629 aopOp (count, ic->next->next, FALSE,FALSE);
11630 lbl =newiTempLabel(NULL);
11632 /* now for the actual copy */
11633 if (AOP_TYPE(count) == AOP_LIT &&
11634 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11635 emitcode (";","OH JOY auto increment with djnz (very fast)");
11636 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11637 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11638 freeAsmop (count, NULL, ic, FALSE);
11639 emitcode ("","!tlabeldef",lbl->key+100);
11640 emitcode ("movx", "a,@dptr"); /* read data from port */
11641 emitcode ("dec","dps"); /* switch to DPTR */
11642 emitcode ("movx", "@dptr,a"); /* save into location */
11643 emitcode ("inc", "dptr"); /* point to next area */
11644 emitcode ("inc","dps"); /* switch to DPTR2 */
11645 emitcode ("djnz","b,!tlabel",lbl->key+100);
11647 symbol *lbl1 = newiTempLabel(NULL);
11649 emitcode (";"," Auto increment but no djnz");
11650 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11651 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11652 freeAsmop (count, NULL, ic, FALSE);
11653 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11654 emitcode ("","!tlabeldef",lbl->key+100);
11655 emitcode ("movx", "a,@dptr");
11656 emitcode ("dec","dps"); /* switch to DPTR */
11657 emitcode ("movx", "@dptr,a");
11658 emitcode ("inc", "dptr");
11659 emitcode ("inc","dps"); /* switch to DPTR2 */
11660 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
11661 /* emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
11662 emitcode ("mov","a,b");
11663 emitcode ("orl","a,_ap");
11664 emitcode ("jz","!tlabel",lbl1->key+100);
11665 emitcode ("mov","a,_ap");
11666 emitcode ("add","a,#!constbyte",0xFF);
11667 emitcode ("mov","_ap,a");
11668 emitcode ("mov","a,b");
11669 emitcode ("addc","a,#!constbyte",0xFF);
11670 emitcode ("mov","b,a");
11671 emitcode ("sjmp","!tlabel",lbl->key+100);
11672 emitcode ("","!tlabeldef",lbl1->key+100);
11674 emitcode ("mov", "dps,#0");
11675 _G.dptrInUse = _G.dptr1InUse = 0;
11676 unsavermask(rsave);
11680 /*-----------------------------------------------------------------*/
11681 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
11682 /* port, first parameter output area second parameter pointer to */
11683 /* port third parameter count */
11684 /*-----------------------------------------------------------------*/
11685 static void genOutp( iCode *ic, int nparms, operand **parms)
11687 operand *from , *to , *count;
11692 /* we know it has to be 3 parameters */
11693 assert (nparms == 3);
11695 rsave = newBitVect(16);
11696 /* save DPTR if it needs to be saved */
11697 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11698 if (bitVectBitValue(ic->rMask,i))
11699 rsave = bitVectSetBit(rsave,i);
11701 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11702 ds390_rUmaskForOp (IC_RESULT(ic))));
11709 aopOp (from, ic->next, FALSE, FALSE);
11711 /* get from into DPTR1 */
11712 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11713 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11714 if (options.model == MODEL_FLAT24) {
11715 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11718 freeAsmop (from, NULL, ic, FALSE);
11719 aopOp (to, ic, FALSE, FALSE);
11720 /* get "to" into DPTR */
11721 /* if the operand is already in dptr
11722 then we do nothing else we move the value to dptr */
11723 if (AOP_TYPE (to) != AOP_STR) {
11724 /* if already in DPTR then we need to push */
11725 if (AOP_TYPE(to) == AOP_DPTR) {
11726 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11727 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11728 if (options.model == MODEL_FLAT24)
11729 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11730 emitcode ("pop", "dph");
11731 emitcode ("pop", "dpl");
11733 _startLazyDPSEvaluation ();
11734 /* if this is remateriazable */
11735 if (AOP_TYPE (to) == AOP_IMMD) {
11736 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11737 } else { /* we need to get it byte by byte */
11738 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11739 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11740 if (options.model == MODEL_FLAT24) {
11741 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11744 _endLazyDPSEvaluation ();
11747 freeAsmop (to, NULL, ic, FALSE);
11749 _G.dptrInUse = _G.dptr1InUse = 1;
11750 aopOp (count, ic->next->next, FALSE,FALSE);
11751 lbl =newiTempLabel(NULL);
11753 /* now for the actual copy */
11754 if (AOP_TYPE(count) == AOP_LIT &&
11755 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11756 emitcode (";","OH JOY auto increment with djnz (very fast)");
11757 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
11758 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11759 emitcode ("","!tlabeldef",lbl->key+100);
11760 emitcode ("movx", "a,@dptr"); /* read data from port */
11761 emitcode ("inc","dps"); /* switch to DPTR2 */
11762 emitcode ("movx", "@dptr,a"); /* save into location */
11763 emitcode ("inc", "dptr"); /* point to next area */
11764 emitcode ("dec","dps"); /* switch to DPTR */
11765 emitcode ("djnz","b,!tlabel",lbl->key+100);
11766 freeAsmop (count, NULL, ic, FALSE);
11768 symbol *lbl1 = newiTempLabel(NULL);
11770 emitcode (";"," Auto increment but no djnz");
11771 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11772 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11773 freeAsmop (count, NULL, ic, FALSE);
11774 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
11775 emitcode ("","!tlabeldef",lbl->key+100);
11776 emitcode ("movx", "a,@dptr");
11777 emitcode ("inc", "dptr");
11778 emitcode ("inc","dps"); /* switch to DPTR2 */
11779 emitcode ("movx", "@dptr,a");
11780 emitcode ("dec","dps"); /* switch to DPTR */
11781 emitcode ("mov","a,b");
11782 emitcode ("orl","a,_ap");
11783 emitcode ("jz","!tlabel",lbl1->key+100);
11784 emitcode ("mov","a,_ap");
11785 emitcode ("add","a,#!constbyte",0xFF);
11786 emitcode ("mov","_ap,a");
11787 emitcode ("mov","a,b");
11788 emitcode ("addc","a,#!constbyte",0xFF);
11789 emitcode ("mov","b,a");
11790 emitcode ("sjmp","!tlabel",lbl->key+100);
11791 emitcode ("","!tlabeldef",lbl1->key+100);
11793 emitcode ("mov", "dps,#0");
11794 _G.dptrInUse = _G.dptr1InUse = 0;
11795 unsavermask(rsave);
11799 /*-----------------------------------------------------------------*/
11800 /* genSwapW - swap lower & high order bytes */
11801 /*-----------------------------------------------------------------*/
11802 static void genSwapW(iCode *ic, int nparms, operand **parms)
11806 assert (nparms==1);
11809 dest=IC_RESULT(ic);
11811 assert(getSize(operandType(src))==2);
11813 aopOp (src, ic, FALSE, FALSE);
11814 emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
11816 MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
11818 freeAsmop (src, NULL, ic, FALSE);
11820 aopOp (dest,ic, FALSE, FALSE);
11821 aopPut(AOP(dest),"b",0);
11822 aopPut(AOP(dest),"a",1);
11823 freeAsmop (dest, NULL, ic, FALSE);
11826 /*-----------------------------------------------------------------*/
11827 /* genMemsetX - gencode for memSetX data */
11828 /*-----------------------------------------------------------------*/
11829 static void genMemsetX(iCode *ic, int nparms, operand **parms)
11831 operand *to , *val , *count;
11837 /* we know it has to be 3 parameters */
11838 assert (nparms == 3);
11844 /* save DPTR if it needs to be saved */
11845 rsave = newBitVect(16);
11846 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11847 if (bitVectBitValue(ic->rMask,i))
11848 rsave = bitVectSetBit(rsave,i);
11850 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11851 ds390_rUmaskForOp (IC_RESULT(ic))));
11854 aopOp (to, ic, FALSE, FALSE);
11855 /* get "to" into DPTR */
11856 /* if the operand is already in dptr
11857 then we do nothing else we move the value to dptr */
11858 if (AOP_TYPE (to) != AOP_STR) {
11859 /* if already in DPTR then we need to push */
11860 if (AOP_TYPE(to) == AOP_DPTR) {
11861 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11862 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11863 if (options.model == MODEL_FLAT24)
11864 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11865 emitcode ("pop", "dph");
11866 emitcode ("pop", "dpl");
11868 _startLazyDPSEvaluation ();
11869 /* if this is remateriazable */
11870 if (AOP_TYPE (to) == AOP_IMMD) {
11871 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11872 } else { /* we need to get it byte by byte */
11873 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11874 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11875 if (options.model == MODEL_FLAT24) {
11876 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11879 _endLazyDPSEvaluation ();
11882 freeAsmop (to, NULL, ic, FALSE);
11884 aopOp (val, ic->next->next, FALSE,FALSE);
11885 aopOp (count, ic->next->next, FALSE,FALSE);
11886 lbl =newiTempLabel(NULL);
11887 /* now for the actual copy */
11888 if (AOP_TYPE(count) == AOP_LIT &&
11889 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11890 l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
11891 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11893 emitcode ("","!tlabeldef",lbl->key+100);
11894 emitcode ("movx", "@dptr,a");
11895 emitcode ("inc", "dptr");
11896 emitcode ("djnz","b,!tlabel",lbl->key+100);
11898 symbol *lbl1 = newiTempLabel(NULL);
11900 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11901 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11902 emitcode ("","!tlabeldef",lbl->key+100);
11903 MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
11904 emitcode ("movx", "@dptr,a");
11905 emitcode ("inc", "dptr");
11906 emitcode ("mov","a,b");
11907 emitcode ("orl","a,_ap");
11908 emitcode ("jz","!tlabel",lbl1->key+100);
11909 emitcode ("mov","a,_ap");
11910 emitcode ("add","a,#!constbyte",0xFF);
11911 emitcode ("mov","_ap,a");
11912 emitcode ("mov","a,b");
11913 emitcode ("addc","a,#!constbyte",0xFF);
11914 emitcode ("mov","b,a");
11915 emitcode ("sjmp","!tlabel",lbl->key+100);
11916 emitcode ("","!tlabeldef",lbl1->key+100);
11918 freeAsmop (count, NULL, ic, FALSE);
11919 unsavermask(rsave);
11922 /*-----------------------------------------------------------------*/
11923 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
11924 /*-----------------------------------------------------------------*/
11925 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
11928 operand *pnum, *result;
11931 assert (nparms==1);
11932 /* save registers that need to be saved */
11933 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11934 ds390_rUmaskForOp (IC_RESULT(ic))));
11937 aopOp (pnum, ic, FALSE, FALSE);
11938 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
11939 freeAsmop (pnum, NULL, ic, FALSE);
11940 emitcode ("lcall","NatLib_LoadPrimitive");
11941 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11942 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
11943 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
11944 for (i = (size-1) ; i >= 0 ; i-- ) {
11945 emitcode ("push","a%s",javaRet[i]);
11947 for (i=0; i < size ; i++ ) {
11948 emitcode ("pop","a%s",
11949 aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
11952 for (i = 0 ; i < size ; i++ ) {
11953 aopPut(AOP(result),javaRet[i],i);
11956 freeAsmop (result, NULL, ic, FALSE);
11957 unsavermask(rsave);
11960 /*-----------------------------------------------------------------*/
11961 /* genNatLibLoadPointer - calls TINI api function to load pointer */
11962 /*-----------------------------------------------------------------*/
11963 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
11966 operand *pnum, *result;
11970 assert (nparms==1);
11971 /* save registers that need to be saved */
11972 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11973 ds390_rUmaskForOp (IC_RESULT(ic))));
11976 aopOp (pnum, ic, FALSE, FALSE);
11977 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
11978 freeAsmop (pnum, NULL, ic, FALSE);
11979 emitcode ("lcall","NatLib_LoadPointer");
11980 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11981 if (AOP_TYPE(result)!=AOP_STR) {
11982 for (i = 0 ; i < size ; i++ ) {
11983 aopPut(AOP(result),fReturn[i],i);
11986 freeAsmop (result, NULL, ic, FALSE);
11987 unsavermask(rsave);
11990 /*-----------------------------------------------------------------*/
11991 /* genNatLibInstallStateBlock - */
11992 /*-----------------------------------------------------------------*/
11993 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
11994 operand **parms, const char *name)
11997 operand *psb, *handle;
11998 assert (nparms==2);
12000 /* save registers that need to be saved */
12001 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12002 ds390_rUmaskForOp (IC_RESULT(ic))));
12006 /* put pointer to state block into DPTR1 */
12007 aopOp (psb, ic, FALSE, FALSE);
12008 if (AOP_TYPE (psb) == AOP_IMMD) {
12009 emitcode ("mov","dps,#1");
12010 emitcode ("mov", "dptr,%s",
12011 aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12012 emitcode ("mov","dps,#0");
12014 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12015 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12016 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12018 freeAsmop (psb, NULL, ic, FALSE);
12020 /* put libraryID into DPTR */
12021 emitcode ("mov","dptr,#LibraryID");
12023 /* put handle into r3:r2 */
12024 aopOp (handle, ic, FALSE, FALSE);
12025 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12026 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12027 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12028 emitcode ("pop","ar3");
12029 emitcode ("pop","ar2");
12031 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12032 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12034 freeAsmop (psb, NULL, ic, FALSE);
12036 /* make the call */
12037 emitcode ("lcall","NatLib_Install%sStateBlock",name);
12039 /* put return value into place*/
12041 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12043 aopPut(AOP(IC_RESULT(ic)),"a",0);
12044 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12045 unsavermask(rsave);
12048 /*-----------------------------------------------------------------*/
12049 /* genNatLibRemoveStateBlock - */
12050 /*-----------------------------------------------------------------*/
12051 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12057 /* save registers that need to be saved */
12058 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12059 ds390_rUmaskForOp (IC_RESULT(ic))));
12061 /* put libraryID into DPTR */
12062 emitcode ("mov","dptr,#LibraryID");
12063 /* make the call */
12064 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12065 unsavermask(rsave);
12068 /*-----------------------------------------------------------------*/
12069 /* genNatLibGetStateBlock - */
12070 /*-----------------------------------------------------------------*/
12071 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12072 operand **parms,const char *name)
12075 symbol *lbl = newiTempLabel(NULL);
12078 /* save registers that need to be saved */
12079 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12080 ds390_rUmaskForOp (IC_RESULT(ic))));
12082 /* put libraryID into DPTR */
12083 emitcode ("mov","dptr,#LibraryID");
12084 /* make the call */
12085 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12086 emitcode ("jnz","!tlabel",lbl->key+100);
12088 /* put return value into place */
12089 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12090 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12091 emitcode ("push","ar3");
12092 emitcode ("push","ar2");
12093 emitcode ("pop","%s",
12094 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12095 emitcode ("pop","%s",
12096 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12098 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12099 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12101 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12102 emitcode ("","!tlabeldef",lbl->key+100);
12103 unsavermask(rsave);
12106 /*-----------------------------------------------------------------*/
12107 /* genMMMalloc - */
12108 /*-----------------------------------------------------------------*/
12109 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12110 int size, const char *name)
12115 symbol *lbl = newiTempLabel(NULL);
12117 assert (nparms == 1);
12118 /* save registers that need to be saved */
12119 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12120 ds390_rUmaskForOp (IC_RESULT(ic))));
12123 aopOp (bsize,ic,FALSE,FALSE);
12125 /* put the size in R4-R2 */
12126 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12127 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12128 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12130 emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12131 emitcode("pop","ar4");
12133 emitcode("pop","ar3");
12134 emitcode("pop","ar2");
12136 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12137 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12139 emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12142 freeAsmop (bsize, NULL, ic, FALSE);
12144 /* make the call */
12145 emitcode ("lcall","MM_%s",name);
12146 emitcode ("jz","!tlabel",lbl->key+100);
12147 emitcode ("mov","r2,#!constbyte",0xff);
12148 emitcode ("mov","r3,#!constbyte",0xff);
12149 emitcode ("","!tlabeldef",lbl->key+100);
12150 /* we don't care about the pointer : we just save the handle */
12151 rsym = OP_SYMBOL(IC_RESULT(ic));
12152 if (rsym->liveFrom != rsym->liveTo) {
12153 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12154 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12155 emitcode ("push","ar3");
12156 emitcode ("push","ar2");
12157 emitcode ("pop","%s",
12158 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12159 emitcode ("pop","%s",
12160 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12162 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12163 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12165 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12167 unsavermask(rsave);
12170 /*-----------------------------------------------------------------*/
12172 /*-----------------------------------------------------------------*/
12173 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12178 assert (nparms == 1);
12179 /* save registers that need to be saved */
12180 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12181 ds390_rUmaskForOp (IC_RESULT(ic))));
12184 aopOp (handle,ic,FALSE,FALSE);
12186 /* put the size in R4-R2 */
12187 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12188 emitcode("push","%s",
12189 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12190 emitcode("push","%s",
12191 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12192 emitcode("pop","ar3");
12193 emitcode("pop","ar2");
12195 emitcode ("mov","r2,%s",
12196 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12197 emitcode ("mov","r3,%s",
12198 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12200 freeAsmop (handle, NULL, ic, FALSE);
12202 /* make the call */
12203 emitcode ("lcall","MM_Deref");
12206 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12207 if (rsym->liveFrom != rsym->liveTo) {
12208 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12209 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12210 _startLazyDPSEvaluation ();
12212 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12213 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12214 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12216 _endLazyDPSEvaluation ();
12221 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12222 unsavermask(rsave);
12225 /*-----------------------------------------------------------------*/
12226 /* genMMUnrestrictedPersist - */
12227 /*-----------------------------------------------------------------*/
12228 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12233 assert (nparms == 1);
12234 /* save registers that need to be saved */
12235 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12236 ds390_rUmaskForOp (IC_RESULT(ic))));
12239 aopOp (handle,ic,FALSE,FALSE);
12241 /* put the size in R3-R2 */
12242 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12243 emitcode("push","%s",
12244 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12245 emitcode("push","%s",
12246 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12247 emitcode("pop","ar3");
12248 emitcode("pop","ar2");
12250 emitcode ("mov","r2,%s",
12251 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12252 emitcode ("mov","r3,%s",
12253 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12255 freeAsmop (handle, NULL, ic, FALSE);
12257 /* make the call */
12258 emitcode ("lcall","MM_UnrestrictedPersist");
12261 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12262 if (rsym->liveFrom != rsym->liveTo) {
12263 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12264 aopPut(AOP(IC_RESULT(ic)),"a",0);
12265 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12268 unsavermask(rsave);
12271 /*-----------------------------------------------------------------*/
12272 /* genSystemExecJavaProcess - */
12273 /*-----------------------------------------------------------------*/
12274 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12277 operand *handle, *pp;
12279 assert (nparms==2);
12280 /* save registers that need to be saved */
12281 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12282 ds390_rUmaskForOp (IC_RESULT(ic))));
12287 /* put the handle in R3-R2 */
12288 aopOp (handle,ic,FALSE,FALSE);
12289 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12290 emitcode("push","%s",
12291 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12292 emitcode("push","%s",
12293 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12294 emitcode("pop","ar3");
12295 emitcode("pop","ar2");
12297 emitcode ("mov","r2,%s",
12298 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12299 emitcode ("mov","r3,%s",
12300 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12302 freeAsmop (handle, NULL, ic, FALSE);
12304 /* put pointer in DPTR */
12305 aopOp (pp,ic,FALSE,FALSE);
12306 if (AOP_TYPE(pp) == AOP_IMMD) {
12307 emitcode ("mov", "dptr,%s",
12308 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12309 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12310 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12311 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12312 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12314 freeAsmop (handle, NULL, ic, FALSE);
12316 /* make the call */
12317 emitcode ("lcall","System_ExecJavaProcess");
12319 /* put result in place */
12321 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12322 if (rsym->liveFrom != rsym->liveTo) {
12323 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12324 aopPut(AOP(IC_RESULT(ic)),"a",0);
12325 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12329 unsavermask(rsave);
12332 /*-----------------------------------------------------------------*/
12333 /* genSystemRTCRegisters - */
12334 /*-----------------------------------------------------------------*/
12335 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12341 assert (nparms==1);
12342 /* save registers that need to be saved */
12343 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12344 ds390_rUmaskForOp (IC_RESULT(ic))));
12347 /* put pointer in DPTR */
12348 aopOp (pp,ic,FALSE,FALSE);
12349 if (AOP_TYPE (pp) == AOP_IMMD) {
12350 emitcode ("mov","dps,#1");
12351 emitcode ("mov", "dptr,%s",
12352 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12353 emitcode ("mov","dps,#0");
12355 emitcode ("mov","dpl1,%s",
12356 aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12357 emitcode ("mov","dph1,%s",
12358 aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12359 emitcode ("mov","dpx1,%s",
12360 aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12362 freeAsmop (pp, NULL, ic, FALSE);
12364 /* make the call */
12365 emitcode ("lcall","System_%sRTCRegisters",name);
12367 unsavermask(rsave);
12370 /*-----------------------------------------------------------------*/
12371 /* genSystemThreadSleep - */
12372 /*-----------------------------------------------------------------*/
12373 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12378 assert (nparms==1);
12379 /* save registers that need to be saved */
12380 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12381 ds390_rUmaskForOp (IC_RESULT(ic))));
12384 aopOp(to,ic,FALSE,FALSE);
12385 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12386 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12387 emitcode ("push","%s",
12388 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12389 emitcode ("push","%s",
12390 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12391 emitcode ("push","%s",
12392 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12393 emitcode ("push","%s",
12394 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12395 emitcode ("pop","ar3");
12396 emitcode ("pop","ar2");
12397 emitcode ("pop","ar1");
12398 emitcode ("pop","ar0");
12400 emitcode ("mov","r0,%s",
12401 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12402 emitcode ("mov","r1,%s",
12403 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12404 emitcode ("mov","r2,%s",
12405 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12406 emitcode ("mov","r3,%s",
12407 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12409 freeAsmop (to, NULL, ic, FALSE);
12411 /* suspend in acc */
12413 aopOp(s,ic,FALSE,FALSE);
12414 emitcode ("mov","a,%s",
12415 aopGet(AOP(s),0,FALSE,TRUE,NULL));
12416 freeAsmop (s, NULL, ic, FALSE);
12418 /* make the call */
12419 emitcode ("lcall","System_%s",name);
12421 unsavermask(rsave);
12424 /*-----------------------------------------------------------------*/
12425 /* genSystemThreadResume - */
12426 /*-----------------------------------------------------------------*/
12427 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12432 assert (nparms==2);
12433 /* save registers that need to be saved */
12434 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12435 ds390_rUmaskForOp (IC_RESULT(ic))));
12441 aopOp(pid,ic,FALSE,FALSE);
12442 emitcode ("mov","r0,%s",
12443 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12444 freeAsmop (pid, NULL, ic, FALSE);
12447 aopOp(tid,ic,FALSE,FALSE);
12448 emitcode ("mov","a,%s",
12449 aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
12450 freeAsmop (tid, NULL, ic, FALSE);
12452 emitcode ("lcall","System_ThreadResume");
12454 /* put result into place */
12456 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12457 if (rsym->liveFrom != rsym->liveTo) {
12458 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12459 aopPut(AOP(IC_RESULT(ic)),"a",0);
12460 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12463 unsavermask(rsave);
12466 /*-----------------------------------------------------------------*/
12467 /* genSystemProcessResume - */
12468 /*-----------------------------------------------------------------*/
12469 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
12474 assert (nparms==1);
12475 /* save registers that need to be saved */
12476 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12477 ds390_rUmaskForOp (IC_RESULT(ic))));
12482 aopOp(pid,ic,FALSE,FALSE);
12483 emitcode ("mov","a,%s",
12484 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12485 freeAsmop (pid, NULL, ic, FALSE);
12487 emitcode ("lcall","System_ProcessResume");
12489 unsavermask(rsave);
12492 /*-----------------------------------------------------------------*/
12494 /*-----------------------------------------------------------------*/
12495 static void genSystem (iCode *ic,int nparms,char *name)
12497 assert(nparms == 0);
12499 emitcode ("lcall","System_%s",name);
12502 /*-----------------------------------------------------------------*/
12503 /* genSystemPoll - */
12504 /*-----------------------------------------------------------------*/
12505 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
12510 assert (nparms==1);
12511 /* save registers that need to be saved */
12512 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12513 ds390_rUmaskForOp (IC_RESULT(ic))));
12516 aopOp (fp,ic,FALSE,FALSE);
12517 if (AOP_TYPE (fp) == AOP_IMMD) {
12518 emitcode ("mov", "dptr,%s",
12519 aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
12520 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
12521 emitcode ("mov","dpl,%s",
12522 aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
12523 emitcode ("mov","dph,%s",
12524 aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
12525 emitcode ("mov","dpx,%s",
12526 aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
12528 freeAsmop (fp, NULL, ic, FALSE);
12530 emitcode ("lcall","System_%sPoll",name);
12532 /* put result into place */
12534 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12535 if (rsym->liveFrom != rsym->liveTo) {
12536 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12537 aopPut(AOP(IC_RESULT(ic)),"a",0);
12538 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12541 unsavermask(rsave);
12544 /*-----------------------------------------------------------------*/
12545 /* genSystemGetCurrentID - */
12546 /*-----------------------------------------------------------------*/
12547 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
12549 assert (nparms==0);
12551 emitcode ("lcall","System_GetCurrent%sId",name);
12552 /* put result into place */
12554 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12555 if (rsym->liveFrom != rsym->liveTo) {
12556 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12557 aopPut(AOP(IC_RESULT(ic)),"a",0);
12558 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12563 /*-----------------------------------------------------------------*/
12564 /* genBuiltIn - calls the appropriate function to generating code */
12565 /* for a built in function */
12566 /*-----------------------------------------------------------------*/
12567 static void genBuiltIn (iCode *ic)
12569 operand *bi_parms[MAX_BUILTIN_ARGS];
12574 /* get all the arguments for a built in function */
12575 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
12577 /* which function is it */
12578 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
12579 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
12580 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
12581 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
12582 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
12583 } else if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
12584 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
12585 } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
12586 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
12587 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
12588 genMemsetX(bi_iCode,nbi_parms,bi_parms);
12589 } else if (strcmp(bif->name,"__builtin_inp")==0) {
12590 genInp(bi_iCode,nbi_parms,bi_parms);
12591 } else if (strcmp(bif->name,"__builtin_outp")==0) {
12592 genOutp(bi_iCode,nbi_parms,bi_parms);
12593 } else if (strcmp(bif->name,"__builtin_swapw")==0) {
12594 genSwapW(bi_iCode,nbi_parms,bi_parms);
12595 /* JavaNative builtIns */
12596 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
12597 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
12598 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
12599 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
12600 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
12601 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
12602 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
12603 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
12604 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
12605 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12606 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
12607 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12608 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
12609 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
12610 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
12611 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
12612 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
12613 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12614 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
12615 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12616 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
12617 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
12618 } else if (strcmp(bif->name,"MM_Malloc")==0) {
12619 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
12620 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
12621 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
12622 } else if (strcmp(bif->name,"MM_Free")==0) {
12623 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
12624 } else if (strcmp(bif->name,"MM_Deref")==0) {
12625 genMMDeref(bi_iCode,nbi_parms,bi_parms);
12626 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
12627 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
12628 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
12629 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
12630 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
12631 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
12632 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
12633 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
12634 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
12635 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
12636 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
12637 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
12638 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
12639 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
12640 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
12641 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
12642 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12643 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12644 } else if (strcmp(bif->name,"System_SaveThread")==0) {
12645 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12646 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12647 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12648 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
12649 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
12650 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
12651 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
12652 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
12653 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
12654 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
12655 genSystem(bi_iCode,nbi_parms,"ProcessYield");
12656 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
12657 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
12658 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
12659 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
12660 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
12661 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
12662 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
12663 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
12664 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
12665 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
12667 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
12673 /*-----------------------------------------------------------------*/
12674 /* gen390Code - generate code for Dallas 390 based controllers */
12675 /*-----------------------------------------------------------------*/
12677 gen390Code (iCode * lic)
12682 lineHead = lineCurr = NULL;
12683 dptrn[1][0] = "dpl1";
12684 dptrn[1][1] = "dph1";
12685 dptrn[1][2] = "dpx1";
12687 if (options.model == MODEL_FLAT24) {
12688 fReturnSizeDS390 = 5;
12689 fReturn = fReturn24;
12691 fReturnSizeDS390 = 4;
12692 fReturn = fReturn16;
12693 options.stack10bit=0;
12696 /* print the allocation information */
12698 printAllocInfo (currFunc, codeOutFile);
12700 /* if debug information required */
12701 if (options.debug && currFunc)
12703 debugFile->writeFunction(currFunc);
12705 if (IS_STATIC (currFunc->etype))
12706 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
12708 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
12711 /* stack pointer name */
12712 if (options.useXstack)
12718 for (ic = lic; ic; ic = ic->next)
12721 if (ic->lineno && cln != ic->lineno)
12726 emitcode ("", "C$%s$%d$%d$%d ==.",
12727 FileBaseName (ic->filename), ic->lineno,
12728 ic->level, ic->block);
12731 if (!options.noCcodeInAsm) {
12732 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
12733 printCLine(ic->filename, ic->lineno));
12737 if (options.iCodeInAsm) {
12738 emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
12740 /* if the result is marked as
12741 spilt and rematerializable or code for
12742 this has already been generated then
12744 if (resultRemat (ic) || ic->generated)
12747 /* depending on the operation */
12767 /* IPOP happens only when trying to restore a
12768 spilt live range, if there is an ifx statement
12769 following this pop then the if statement might
12770 be using some of the registers being popped which
12771 would destory the contents of the register so
12772 we need to check for this condition and handle it */
12774 ic->next->op == IFX &&
12775 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
12776 genIfx (ic->next, ic);
12794 genEndFunction (ic);
12814 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
12831 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
12835 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
12842 /* note these two are xlated by algebraic equivalence
12843 during parsing SDCC.y */
12844 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12845 "got '>=' or '<=' shouldn't have come here");
12849 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
12861 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
12865 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
12869 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
12893 genRightShift (ic);
12896 case GET_VALUE_AT_ADDRESS:
12897 genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
12901 if (POINTER_SET (ic))
12902 genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
12928 if (ic->builtinSEND) genBuiltIn(ic);
12929 else addSet (&_G.sendSet, ic);
12942 /* now we are ready to call the
12943 peep hole optimizer */
12944 if (!options.nopeep)
12945 peepHole (&lineHead);
12947 /* now do the actual printing */
12948 printLine (lineHead, codeOutFile);