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 // jwk: 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 // jwk: this needs a closer look
3260 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3263 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3265 if (savedBanks & (1 << ix))
3267 unsaveRBank(ix, NULL, FALSE);
3271 if (options.useXstack)
3273 /* Restore bank AFTER calling unsaveRBank,
3274 * since it can trash r0.
3276 emitcode ("pop", "psw");
3280 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3282 if (options.stack10bit)
3284 emitcode ("pop", DP2_RESULT_REG);
3285 emitcode ("pop", "dpx1");
3286 emitcode ("pop", "dph1");
3287 emitcode ("pop", "dpl1");
3289 emitcode ("pop", "dps");
3290 emitcode ("pop", "dpx");
3292 if (!inExcludeList ("dph"))
3293 emitcode ("pop", "dph");
3294 if (!inExcludeList ("dpl"))
3295 emitcode ("pop", "dpl");
3296 if (!inExcludeList ("b"))
3297 emitcode ("pop", "b");
3298 if (!inExcludeList ("acc"))
3299 emitcode ("pop", "acc");
3301 if (IFFUNC_ISCRITICAL (sym->type))
3302 emitcode ("setb", "ea");
3304 /* if debug then send end of function */
3305 if (options.debug && currFunc) {
3307 emitcode ("", "C$%s$%d$%d$%d ==.",
3308 FileBaseName (ic->filename), currFunc->lastLine,
3309 ic->level, ic->block);
3310 if (IS_STATIC (currFunc->etype))
3311 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3313 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3317 emitcode ("reti", "");
3321 if (IFFUNC_ISCRITICAL (sym->type))
3322 emitcode ("setb", "ea");
3324 if (IFFUNC_CALLEESAVES(sym->type))
3328 /* if any registers used */
3331 /* save the registers used */
3332 for (i = sym->regsUsed->size; i >= 0; i--)
3334 if (bitVectBitValue (sym->regsUsed, i) ||
3335 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3336 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3342 /* if debug then send end of function */
3343 if (options.debug && currFunc)
3346 emitcode ("", "C$%s$%d$%d$%d ==.",
3347 FileBaseName (ic->filename), currFunc->lastLine,
3348 ic->level, ic->block);
3349 if (IS_STATIC (currFunc->etype))
3350 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3352 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3356 emitcode ("ret", "");
3361 /*-----------------------------------------------------------------*/
3362 /* genJavaNativeRet - generate code for return JavaNative */
3363 /*-----------------------------------------------------------------*/
3364 static void genJavaNativeRet(iCode *ic)
3368 aopOp (IC_LEFT (ic), ic, FALSE,
3369 AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
3370 size = AOP_SIZE (IC_LEFT (ic));
3374 /* it is assigned to GPR0-R3 then push them */
3375 if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3376 aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3377 for (i = 0 ; i < size ; i++ ) {
3378 emitcode ("push","%s",
3379 aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3381 for (i = (size-1) ; i >= 0 ; i--) {
3382 emitcode ("pop","a%s",javaRet[i]);
3385 for (i = 0 ; i < size ; i++)
3386 emitcode ("mov","%s,%s",javaRet[i],
3387 aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3389 for (i = size ; i < 4 ; i++ )
3390 emitcode ("mov","%s,#0",javaRet[i]);
3394 /*-----------------------------------------------------------------*/
3395 /* genRet - generate code for return statement */
3396 /*-----------------------------------------------------------------*/
3400 int size, offset = 0, pushed = 0;
3402 D (emitcode (";", "genRet "););
3404 /* if we have no return value then
3405 just generate the "ret" */
3409 /* if this is a JavaNative function then return
3410 value in different register */
3411 if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3412 genJavaNativeRet(ic);
3415 /* we have something to return then
3416 move the return value into place */
3417 aopOp (IC_LEFT (ic), ic, FALSE,
3418 (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
3419 size = AOP_SIZE (IC_LEFT (ic));
3421 _startLazyDPSEvaluation ();
3425 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3427 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3429 emitcode ("push", "%s", l);
3434 /* Since A is the last element of fReturn,
3435 * is is OK to clobber it in the aopGet.
3437 l = aopGet (AOP (IC_LEFT (ic)), offset,
3438 FALSE, FALSE, NULL);
3439 if (strcmp (fReturn[offset], l))
3440 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3443 _endLazyDPSEvaluation ();
3450 if (strcmp (fReturn[pushed], "a"))
3451 emitcode ("pop", fReturn[pushed]);
3453 emitcode ("pop", "acc");
3456 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3459 /* generate a jump to the return label
3460 if the next is not the return statement */
3461 if (!(ic->next && ic->next->op == LABEL &&
3462 IC_LABEL (ic->next) == returnLabel))
3464 emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3468 /*-----------------------------------------------------------------*/
3469 /* genLabel - generates a label */
3470 /*-----------------------------------------------------------------*/
3472 genLabel (iCode * ic)
3474 /* special case never generate */
3475 if (IC_LABEL (ic) == entryLabel)
3478 D (emitcode (";", "genLabel ");
3481 emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3484 /*-----------------------------------------------------------------*/
3485 /* genGoto - generates a ljmp */
3486 /*-----------------------------------------------------------------*/
3488 genGoto (iCode * ic)
3490 D (emitcode (";", "genGoto ");
3492 emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3495 /*-----------------------------------------------------------------*/
3496 /* findLabelBackwards: walks back through the iCode chain looking */
3497 /* for the given label. Returns number of iCode instructions */
3498 /* between that label and given ic. */
3499 /* Returns zero if label not found. */
3500 /*-----------------------------------------------------------------*/
3502 findLabelBackwards (iCode * ic, int key)
3511 /* If we have any pushes or pops, we cannot predict the distance.
3512 I don't like this at all, this should be dealt with in the
3514 if (ic->op == IPUSH || ic->op == IPOP) {
3518 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3520 /* printf("findLabelBackwards = %d\n", count); */
3528 /*-----------------------------------------------------------------*/
3529 /* genPlusIncr :- does addition with increment if possible */
3530 /*-----------------------------------------------------------------*/
3532 genPlusIncr (iCode * ic)
3534 unsigned int icount;
3535 unsigned int size = getDataSize (IC_RESULT (ic));
3537 /* will try to generate an increment */
3538 /* if the right side is not a literal
3540 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3543 /* if the literal value of the right hand side
3544 is greater than 4 then it is not worth it */
3545 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3548 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3549 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3551 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
3555 /* if increment 16 bits in register */
3557 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3558 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3559 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3568 /* If the next instruction is a goto and the goto target
3569 * is <= 5 instructions previous to this, we can generate
3570 * jumps straight to that target.
3572 if (ic->next && ic->next->op == GOTO
3573 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3576 D(emitcode (";", "tail increment optimized (range %d)", labelRange););
3577 tlbl = IC_LABEL (ic->next);
3582 tlbl = newiTempLabel (NULL);
3586 l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
3587 emitcode ("inc", "%s", l);
3589 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3590 IS_AOP_PREG (IC_RESULT (ic)))
3592 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3596 emitcode ("clr", "a");
3597 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3600 l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
3601 emitcode ("inc", "%s", l);
3604 if (!strcmp(l, "acc"))
3606 emitcode("jnz", "!tlabel", tlbl->key + 100);
3608 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3609 IS_AOP_PREG (IC_RESULT (ic)))
3611 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3615 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3618 l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
3619 emitcode ("inc", "%s", l);
3623 if (!strcmp(l, "acc"))
3625 emitcode("jnz", "!tlabel", tlbl->key + 100);
3627 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3628 IS_AOP_PREG (IC_RESULT (ic)))
3630 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3634 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3637 l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
3638 emitcode ("inc", "%s", l); }
3642 emitcode ("", "!tlabeldef", tlbl->key + 100);
3647 if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3648 !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 &&
3649 options.model == MODEL_FLAT24 ) {
3653 emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, NULL));
3655 emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, NULL));
3657 emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3660 while (icount--) emitcode ("inc","dptr");
3664 if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3665 AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3667 emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3668 while (icount--) emitcode ("inc","dptr");
3669 emitcode ("mov","dps,#0");
3673 /* if the sizes are greater than 1 then we cannot */
3674 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3675 AOP_SIZE (IC_LEFT (ic)) > 1)
3678 /* we can if the aops of the left & result match or
3679 if they are in registers and the registers are the
3682 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3683 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3684 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3689 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3690 emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3691 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3696 _startLazyDPSEvaluation ();
3699 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3701 _endLazyDPSEvaluation ();
3710 /*-----------------------------------------------------------------*/
3711 /* outBitAcc - output a bit in acc */
3712 /*-----------------------------------------------------------------*/
3714 outBitAcc (operand * result)
3716 symbol *tlbl = newiTempLabel (NULL);
3717 /* if the result is a bit */
3718 if (AOP_TYPE (result) == AOP_CRY)
3720 aopPut (AOP (result), "a", 0);
3724 emitcode ("jz", "!tlabel", tlbl->key + 100);
3725 emitcode ("mov", "a,%s", one);
3726 emitcode ("", "!tlabeldef", tlbl->key + 100);
3731 /*-----------------------------------------------------------------*/
3732 /* genPlusBits - generates code for addition of two bits */
3733 /*-----------------------------------------------------------------*/
3735 genPlusBits (iCode * ic)
3737 D (emitcode (";", "genPlusBits "););
3739 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3741 symbol *lbl = newiTempLabel (NULL);
3742 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3743 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3744 emitcode ("cpl", "c");
3745 emitcode ("", "!tlabeldef", (lbl->key + 100));
3746 outBitC (IC_RESULT (ic));
3750 emitcode ("clr", "a");
3751 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3752 emitcode ("rlc", "a");
3753 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3754 emitcode ("addc", "a,#0");
3755 outAcc (IC_RESULT (ic));
3760 adjustArithmeticResult (iCode * ic)
3762 if (opIsGptr (IC_RESULT (ic)) &&
3763 opIsGptr (IC_LEFT (ic)) &&
3764 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3766 aopPut (AOP (IC_RESULT (ic)),
3767 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3771 if (opIsGptr (IC_RESULT (ic)) &&
3772 opIsGptr (IC_RIGHT (ic)) &&
3773 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3775 aopPut (AOP (IC_RESULT (ic)),
3776 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3780 if (opIsGptr (IC_RESULT (ic)) &&
3781 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3782 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3783 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3784 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3787 SNPRINTF (buff, sizeof(buff),
3788 "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3789 aopPut (AOP (IC_RESULT (ic)), buff, GPTRSIZE - 1);
3793 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
3794 // generates the result if possible. If result is generated, returns TRUE; otherwise
3795 // returns false and caller must deal with fact that result isn't aopOp'd.
3796 bool aopOp3(iCode * ic)
3798 bool dp1InUse, dp2InUse;
3801 // First, generate the right opcode. DPTR may be used if neither left nor result are
3804 // D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
3805 // AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
3806 // AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
3807 // AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
3809 // D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
3810 // AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
3811 // AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
3812 // AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
3816 // Right uses DPTR unless left or result is an AOP_STR.
3817 aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)));
3819 // if the right used DPTR, left MUST use DPTR2.
3820 // if the right used DPTR2, left MUST use DPTR.
3821 // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
3822 // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
3823 // enabling us to assign DPTR to result.
3825 if (AOP_USESDPTR(IC_RIGHT(ic)))
3829 else if (AOP_USESDPTR2(IC_RIGHT(ic)))
3835 if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
3845 aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
3847 // We've op'd the left & right. So, if left or right are the same operand as result,
3848 // we know aopOp will succeed, and we can just do it & bail.
3849 if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)) ||
3850 isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
3852 // D(emitcode(";", "aopOp3: (left | right) & result equal"););
3853 aopOp(IC_RESULT(ic),ic,TRUE, FALSE);
3857 // Note which dptrs are currently in use.
3858 dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
3859 dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
3861 // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot
3863 if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
3868 // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
3869 if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
3874 // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck
3875 if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
3880 aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
3882 // Some sanity checking...
3883 if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
3886 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
3887 __FILE__, __LINE__, ic->filename, ic->lineno);
3888 emitcode(";", ">>> unexpected DPTR here.");
3891 if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
3894 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
3895 __FILE__, __LINE__, ic->filename, ic->lineno);
3896 emitcode(";", ">>> unexpected DPTR2 here.");
3902 // Macro to aopOp all three operands of an ic. If this cannot be done,
3903 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3904 // will be set TRUE. The caller must then handle the case specially, noting
3905 // that the IC_RESULT operand is not aopOp'd.
3907 #define AOP_OP_3_NOFATAL(ic, rc) \
3908 do { rc = !aopOp3(ic); } while (0)
3910 // aopOp the left & right operands of an ic.
3911 #define AOP_OP_2(ic) \
3912 aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
3913 aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
3915 // convienience macro.
3916 #define AOP_SET_LOCALS(ic) \
3917 left = IC_LEFT(ic); \
3918 right = IC_RIGHT(ic); \
3919 result = IC_RESULT(ic);
3922 // Given an integer value of pushedSize bytes on the stack,
3923 // adjust it to be resultSize bytes, either by discarding
3924 // the most significant bytes or by zero-padding.
3926 // On exit from this macro, pushedSize will have been adjusted to
3927 // equal resultSize, and ACC may be trashed.
3928 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3929 /* If the pushed data is bigger than the result, \
3930 * simply discard unused bytes. Icky, but works. \
3932 while (pushedSize > resultSize) \
3934 D (emitcode (";", "discarding unused result byte."););\
3935 emitcode ("pop", "acc"); \
3938 if (pushedSize < resultSize) \
3940 emitcode ("clr", "a"); \
3941 /* Conversly, we haven't pushed enough here. \
3942 * just zero-pad, and all is well. \
3944 while (pushedSize < resultSize) \
3946 emitcode("push", "acc"); \
3950 assert(pushedSize == resultSize);
3952 /*-----------------------------------------------------------------*/
3953 /* genPlus - generates code for addition */
3954 /*-----------------------------------------------------------------*/
3956 genPlus (iCode * ic)
3958 int size, offset = 0;
3962 D (emitcode (";", "genPlus "););
3964 /* special cases :- */
3965 if ( AOP_IS_STR(IC_LEFT(ic)) &&
3966 isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
3967 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
3968 size = floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
3970 while (size--) emitcode ("inc","dptr");
3972 emitcode ("mov","a,dpl");
3973 emitcode ("add","a,#!constbyte",size & 0xff);
3974 emitcode ("mov","dpl,a");
3975 emitcode ("mov","a,dph");
3976 emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
3977 emitcode ("mov","dph,a");
3978 emitcode ("mov","a,dpx");
3979 emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
3980 emitcode ("mov","dpx,a");
3982 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
3985 if ( IS_SYMOP(IC_LEFT(ic)) &&
3986 OP_SYMBOL(IC_LEFT(ic))->remat &&
3987 isOperandInFarSpace(IC_RIGHT(ic))) {
3988 operand *op = IC_RIGHT(ic);
3989 IC_RIGHT(ic) = IC_LEFT(ic);
3993 AOP_OP_3_NOFATAL (ic, pushResult);
3997 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
4002 /* if literal, literal on the right or
4003 if left requires ACC or right is already
4005 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4006 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
4007 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4009 operand *t = IC_RIGHT (ic);
4010 IC_RIGHT (ic) = IC_LEFT (ic);
4012 emitcode (";", "Swapped plus args.");
4015 /* if both left & right are in bit
4017 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4018 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4024 /* if left in bit space & right literal */
4025 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4026 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4028 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4029 /* if result in bit space */
4030 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4032 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4033 emitcode ("cpl", "c");
4034 outBitC (IC_RESULT (ic));
4038 size = getDataSize (IC_RESULT (ic));
4039 _startLazyDPSEvaluation ();
4042 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4043 emitcode ("addc", "a,#0");
4044 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4046 _endLazyDPSEvaluation ();
4051 /* if I can do an increment instead
4052 of add then GOOD for ME */
4053 if (genPlusIncr (ic) == TRUE)
4055 emitcode (";", "did genPlusIncr");
4060 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4062 _startLazyDPSEvaluation ();
4065 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4067 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4069 emitcode ("add", "a,%s",
4070 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4072 emitcode ("addc", "a,%s",
4073 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4077 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4079 /* right is going to use ACC or we would have taken the
4082 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4084 D(emitcode(";", "+ AOP_ACC special case."););
4085 emitcode("xch", "a, %s", DP2_RESULT_REG);
4087 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4090 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4093 emitcode("add", "a, %s", DP2_RESULT_REG);
4097 emitcode ("add", "a,%s",
4098 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE,
4104 emitcode ("addc", "a,%s",
4105 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE,
4111 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4115 emitcode ("push", "acc");
4119 _endLazyDPSEvaluation ();
4123 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4125 size = getDataSize (IC_LEFT (ic));
4126 rSize = getDataSize (IC_RESULT (ic));
4128 ADJUST_PUSHED_RESULT(size, rSize);
4130 _startLazyDPSEvaluation ();
4133 emitcode ("pop", "acc");
4134 aopPut (AOP (IC_RESULT (ic)), "a", size);
4136 _endLazyDPSEvaluation ();
4139 adjustArithmeticResult (ic);
4142 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4143 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4144 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4147 /*-----------------------------------------------------------------*/
4148 /* genMinusDec :- does subtraction with deccrement if possible */
4149 /*-----------------------------------------------------------------*/
4151 genMinusDec (iCode * ic)
4153 unsigned int icount;
4154 unsigned int size = getDataSize (IC_RESULT (ic));
4156 /* will try to generate an increment */
4157 /* if the right side is not a literal
4159 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4162 /* if the literal value of the right hand side
4163 is greater than 4 then it is not worth it */
4164 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4167 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4168 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4170 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
4174 /* if decrement 16 bits in register */
4175 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4176 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4177 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4186 /* If the next instruction is a goto and the goto target
4187 * is <= 5 instructions previous to this, we can generate
4188 * jumps straight to that target.
4190 if (ic->next && ic->next->op == GOTO
4191 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4194 emitcode (";", "tail decrement optimized (range %d)", labelRange);
4195 tlbl = IC_LABEL (ic->next);
4200 tlbl = newiTempLabel (NULL);
4204 l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
4205 emitcode ("dec", "%s", l);
4207 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4208 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4209 IS_AOP_PREG (IC_RESULT (ic)))
4211 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4215 emitcode ("mov", "a,#!constbyte",0xff);
4216 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4218 l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
4219 emitcode ("dec", "%s", l);
4222 if (!strcmp(l, "acc"))
4224 emitcode("jnz", "!tlabel", tlbl->key + 100);
4226 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4227 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4228 IS_AOP_PREG (IC_RESULT (ic)))
4230 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4234 emitcode ("mov", "a,#!constbyte",0xff);
4235 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4237 l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
4238 emitcode ("dec", "%s", l);
4242 if (!strcmp(l, "acc"))
4244 emitcode("jnz", "!tlabel", tlbl->key + 100);
4246 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4247 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4248 IS_AOP_PREG (IC_RESULT (ic)))
4250 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4254 emitcode ("mov", "a,#!constbyte",0xff);
4255 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4257 l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
4258 emitcode ("dec", "%s", l);
4262 emitcode ("", "!tlabeldef", tlbl->key + 100);
4267 /* if the sizes are greater than 1 then we cannot */
4268 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4269 AOP_SIZE (IC_LEFT (ic)) > 1)
4272 /* we can if the aops of the left & result match or
4273 if they are in registers and the registers are the
4276 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4277 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4278 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4281 _startLazyDPSEvaluation ();
4284 emitcode ("dec", "%s",
4285 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
4287 _endLazyDPSEvaluation ();
4295 /*-----------------------------------------------------------------*/
4296 /* addSign - complete with sign */
4297 /*-----------------------------------------------------------------*/
4299 addSign (operand * result, int offset, int sign)
4301 int size = (getDataSize (result) - offset);
4304 _startLazyDPSEvaluation();
4307 emitcode ("rlc", "a");
4308 emitcode ("subb", "a,acc");
4311 aopPut (AOP (result), "a", offset++);
4318 aopPut (AOP (result), zero, offset++);
4321 _endLazyDPSEvaluation();
4325 /*-----------------------------------------------------------------*/
4326 /* genMinusBits - generates code for subtraction of two bits */
4327 /*-----------------------------------------------------------------*/
4329 genMinusBits (iCode * ic)
4331 symbol *lbl = newiTempLabel (NULL);
4333 D (emitcode (";", "genMinusBits "););
4335 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4337 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4338 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4339 emitcode ("cpl", "c");
4340 emitcode ("", "!tlabeldef", (lbl->key + 100));
4341 outBitC (IC_RESULT (ic));
4345 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4346 emitcode ("subb", "a,acc");
4347 emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4348 emitcode ("inc", "a");
4349 emitcode ("", "!tlabeldef", (lbl->key + 100));
4350 aopPut (AOP (IC_RESULT (ic)), "a", 0);
4351 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4355 /*-----------------------------------------------------------------*/
4356 /* genMinus - generates code for subtraction */
4357 /*-----------------------------------------------------------------*/
4359 genMinus (iCode * ic)
4361 int size, offset = 0;
4366 D (emitcode (";", "genMinus "););
4368 AOP_OP_3_NOFATAL(ic, pushResult);
4372 /* special cases :- */
4373 /* if both left & right are in bit space */
4374 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4375 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4381 /* if I can do an decrement instead
4382 of subtract then GOOD for ME */
4383 if (genMinusDec (ic) == TRUE)
4388 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4390 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4396 lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4401 /* if literal, add a,#-lit, else normal subb */
4402 _startLazyDPSEvaluation ();
4404 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4405 if (AOP_USESDPTR(IC_RIGHT(ic))) {
4406 emitcode ("mov","b,%s",
4407 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4408 MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4409 emitcode ("subb","a,b");
4411 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4412 emitcode ("subb", "a,%s",
4413 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE,
4417 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4418 /* first add without previous c */
4420 if (!size && lit==-1) {
4421 emitcode ("dec", "a");
4423 emitcode ("add", "a,#!constbyte",
4424 (unsigned int) (lit & 0x0FFL));
4427 emitcode ("addc", "a,#!constbyte",
4428 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4433 emitcode ("push", "acc");
4435 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4439 _endLazyDPSEvaluation ();
4443 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4445 size = getDataSize (IC_LEFT (ic));
4446 rSize = getDataSize (IC_RESULT (ic));
4448 ADJUST_PUSHED_RESULT(size, rSize);
4450 _startLazyDPSEvaluation ();
4453 emitcode ("pop", "acc");
4454 aopPut (AOP (IC_RESULT (ic)), "a", size);
4456 _endLazyDPSEvaluation ();
4459 adjustArithmeticResult (ic);
4462 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4463 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4464 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4468 /*-----------------------------------------------------------------*/
4469 /* genMultbits :- multiplication of bits */
4470 /*-----------------------------------------------------------------*/
4472 genMultbits (operand * left,
4477 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4478 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4479 aopOp(result, ic, TRUE, FALSE);
4484 /*-----------------------------------------------------------------*/
4485 /* genMultOneByte : 8*8=8/16 bit multiplication */
4486 /*-----------------------------------------------------------------*/
4488 genMultOneByte (operand * left,
4493 sym_link *opetype = operandType (result);
4497 /* (if two literals: the value is computed before) */
4498 /* if one literal, literal on the right */
4499 if (AOP_TYPE (left) == AOP_LIT)
4504 emitcode (";", "swapped left and right");
4507 if (SPEC_USIGN(opetype)
4508 // ignore the sign of left and right, what else can we do?
4509 || (SPEC_USIGN(operandType(left)) &&
4510 SPEC_USIGN(operandType(right)))) {
4511 // just an unsigned 8*8=8/16 multiply
4512 //emitcode (";","unsigned");
4513 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4514 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4515 emitcode ("mul", "ab");
4517 _G.accInUse++; _G.bInUse++;
4518 aopOp(result, ic, TRUE, FALSE);
4520 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4522 // this should never happen
4523 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4524 AOP_SIZE(result), __FILE__, lineno);
4528 aopPut (AOP (result), "a", 0);
4529 _G.accInUse--; _G.bInUse--;
4530 if (AOP_SIZE(result)==2)
4532 aopPut (AOP (result), "b", 1);
4537 // we have to do a signed multiply
4539 emitcode (";", "signed");
4540 emitcode ("clr", "F0"); // reset sign flag
4541 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4543 lbl=newiTempLabel(NULL);
4544 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4545 // left side is negative, 8-bit two's complement, this fails for -128
4546 emitcode ("setb", "F0"); // set sign flag
4547 emitcode ("cpl", "a");
4548 emitcode ("inc", "a");
4550 emitcode ("", "!tlabeldef", lbl->key+100);
4553 if (AOP_TYPE(right)==AOP_LIT) {
4554 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4555 /* AND literal negative */
4556 if ((int) val < 0) {
4557 emitcode ("cpl", "F0"); // complement sign flag
4558 emitcode ("mov", "b,#!constbyte", -val);
4560 emitcode ("mov", "b,#!constbyte", val);
4563 lbl=newiTempLabel(NULL);
4564 emitcode ("mov", "b,a");
4565 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4566 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4567 // right side is negative, 8-bit two's complement
4568 emitcode ("cpl", "F0"); // complement sign flag
4569 emitcode ("cpl", "a");
4570 emitcode ("inc", "a");
4571 emitcode ("", "!tlabeldef", lbl->key+100);
4573 emitcode ("mul", "ab");
4575 _G.accInUse++;_G.bInUse++;
4576 aopOp(result, ic, TRUE, FALSE);
4578 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4580 // this should never happen
4581 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4582 AOP_SIZE(result), __FILE__, lineno);
4586 lbl=newiTempLabel(NULL);
4587 emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4588 // only ONE op was negative, we have to do a 8/16-bit two's complement
4589 emitcode ("cpl", "a"); // lsb
4590 if (AOP_SIZE(result)==1) {
4591 emitcode ("inc", "a");
4593 emitcode ("add", "a,#1");
4594 emitcode ("xch", "a,b");
4595 emitcode ("cpl", "a"); // msb
4596 emitcode ("addc", "a,#0");
4597 emitcode ("xch", "a,b");
4600 emitcode ("", "!tlabeldef", lbl->key+100);
4601 aopPut (AOP (result), "a", 0);
4602 _G.accInUse--;_G.bInUse--;
4603 if (AOP_SIZE(result)==2) {
4604 aopPut (AOP (result), "b", 1);
4608 /*-----------------------------------------------------------------*/
4609 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
4610 /*-----------------------------------------------------------------*/
4611 static void genMultTwoByte (operand *left, operand *right,
4612 operand *result, iCode *ic)
4614 sym_link *retype = getSpec(operandType(right));
4615 sym_link *letype = getSpec(operandType(left));
4616 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4619 if (AOP_TYPE (left) == AOP_LIT) {
4624 /* save EA bit in F1 */
4625 lbl = newiTempLabel(NULL);
4626 emitcode ("setb","F1");
4627 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4628 emitcode ("clr","F1");
4629 emitcode("","!tlabeldef",lbl->key+100);
4631 /* load up MB with right */
4633 emitcode("clr","F0");
4634 if (AOP_TYPE(right) == AOP_LIT) {
4635 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4637 emitcode("setb","F0");
4640 emitcode ("mov","mb,#!constbyte",val & 0xff);
4641 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4643 lbl = newiTempLabel(NULL);
4644 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4645 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4646 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4647 emitcode ("xch", "a,b");
4648 emitcode ("cpl","a");
4649 emitcode ("add", "a,#1");
4650 emitcode ("xch", "a,b");
4651 emitcode ("cpl", "a"); // msb
4652 emitcode ("addc", "a,#0");
4653 emitcode ("setb","F0");
4654 emitcode ("","!tlabeldef",lbl->key+100);
4655 emitcode ("mov","mb,b");
4656 emitcode ("mov","mb,a");
4659 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4660 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4662 /* load up MA with left */
4664 lbl = newiTempLabel(NULL);
4665 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4666 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4667 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4668 emitcode ("xch", "a,b");
4669 emitcode ("cpl","a");
4670 emitcode ("add", "a,#1");
4671 emitcode ("xch", "a,b");
4672 emitcode ("cpl", "a"); // msb
4673 emitcode ("addc","a,#0");
4674 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4675 emitcode ("setb","F0");
4676 emitcode ("","!tlabeldef",lbl->key+100);
4677 emitcode ("mov","ma,b");
4678 emitcode ("mov","ma,a");
4680 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4681 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4683 /* wait for multiplication to finish */
4684 lbl = newiTempLabel(NULL);
4685 emitcode("","!tlabeldef", lbl->key+100);
4686 emitcode("mov","a,mcnt1");
4687 emitcode("anl","a,#!constbyte",0x80);
4688 emitcode("jnz","!tlabel",lbl->key+100);
4690 freeAsmop (left, NULL, ic, TRUE);
4691 freeAsmop (right, NULL, ic,TRUE);
4692 aopOp(result, ic, TRUE, FALSE);
4694 /* if unsigned then simple */
4696 emitcode ("mov","a,ma");
4697 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4698 emitcode ("mov","a,ma");
4699 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4700 aopPut(AOP(result),"ma",1);
4701 aopPut(AOP(result),"ma",0);
4703 emitcode("push","ma");
4704 emitcode("push","ma");
4705 emitcode("push","ma");
4707 /* negate result if needed */
4708 lbl = newiTempLabel(NULL);
4709 emitcode("jnb","F0,!tlabel",lbl->key+100);
4710 emitcode("cpl","a");
4711 emitcode("add","a,#1");
4712 emitcode("","!tlabeldef", lbl->key+100);
4713 if (AOP_TYPE(result) == AOP_ACC)
4715 D(emitcode(";", "ACC special case."););
4716 /* We know result is the only live aop, and
4717 * it's obviously not a DPTR2, so AP is available.
4719 emitcode("mov", "%s,acc", DP2_RESULT_REG);
4723 aopPut(AOP(result),"a",0);
4726 emitcode("pop","acc");
4727 lbl = newiTempLabel(NULL);
4728 emitcode("jnb","F0,!tlabel",lbl->key+100);
4729 emitcode("cpl","a");
4730 emitcode("addc","a,#0");
4731 emitcode("","!tlabeldef", lbl->key+100);
4732 aopPut(AOP(result),"a",1);
4733 emitcode("pop","acc");
4734 if (AOP_SIZE(result) >= 3) {
4735 lbl = newiTempLabel(NULL);
4736 emitcode("jnb","F0,!tlabel",lbl->key+100);
4737 emitcode("cpl","a");
4738 emitcode("addc","a,#0");
4739 emitcode("","!tlabeldef", lbl->key+100);
4740 aopPut(AOP(result),"a",2);
4742 emitcode("pop","acc");
4743 if (AOP_SIZE(result) >= 4) {
4744 lbl = newiTempLabel(NULL);
4745 emitcode("jnb","F0,!tlabel",lbl->key+100);
4746 emitcode("cpl","a");
4747 emitcode("addc","a,#0");
4748 emitcode("","!tlabeldef", lbl->key+100);
4749 aopPut(AOP(result),"a",3);
4751 if (AOP_TYPE(result) == AOP_ACC)
4753 /* We stashed the result away above. */
4754 emitcode("mov", "acc,%s", DP2_RESULT_REG);
4758 freeAsmop (result, NULL, ic, TRUE);
4760 /* restore EA bit in F1 */
4761 lbl = newiTempLabel(NULL);
4762 emitcode ("jnb","F1,!tlabel",lbl->key+100);
4763 emitcode ("setb","EA");
4764 emitcode("","!tlabeldef",lbl->key+100);
4768 /*-----------------------------------------------------------------*/
4769 /* genMult - generates code for multiplication */
4770 /*-----------------------------------------------------------------*/
4772 genMult (iCode * ic)
4774 operand *left = IC_LEFT (ic);
4775 operand *right = IC_RIGHT (ic);
4776 operand *result = IC_RESULT (ic);
4778 D (emitcode (";", "genMult "););
4780 /* assign the amsops */
4783 /* special cases first */
4785 if (AOP_TYPE (left) == AOP_CRY &&
4786 AOP_TYPE (right) == AOP_CRY)
4788 genMultbits (left, right, result, ic);
4792 /* if both are of size == 1 */
4793 if (AOP_SIZE (left) == 1 &&
4794 AOP_SIZE (right) == 1)
4796 genMultOneByte (left, right, result, ic);
4800 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4801 /* use the ds390 ARITHMETIC accel UNIT */
4802 genMultTwoByte (left, right, result, ic);
4805 /* should have been converted to function call */
4809 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4810 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4811 freeAsmop (result, NULL, ic, TRUE);
4814 /*-----------------------------------------------------------------*/
4815 /* genDivbits :- division of bits */
4816 /*-----------------------------------------------------------------*/
4818 genDivbits (operand * left,
4826 /* the result must be bit */
4827 LOAD_AB_FOR_DIV (left, right, l);
4828 emitcode ("div", "ab");
4829 emitcode ("rrc", "a");
4830 aopOp(result, ic, TRUE, FALSE);
4832 aopPut (AOP (result), "c", 0);
4835 /*-----------------------------------------------------------------*/
4836 /* genDivOneByte : 8 bit division */
4837 /*-----------------------------------------------------------------*/
4839 genDivOneByte (operand * left,
4844 sym_link *opetype = operandType (result);
4850 /* signed or unsigned */
4851 if (SPEC_USIGN (opetype))
4853 /* unsigned is easy */
4854 LOAD_AB_FOR_DIV (left, right, l);
4855 emitcode ("div", "ab");
4858 aopOp(result, ic, TRUE, FALSE);
4859 aopPut (AOP (result), "a", 0);
4862 size = AOP_SIZE (result) - 1;
4866 aopPut (AOP (result), zero, offset++);
4871 /* signed is a little bit more difficult */
4873 /* save the signs of the operands */
4874 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4875 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4876 emitcode ("push", "acc"); /* save it on the stack */
4878 /* now sign adjust for both left & right */
4879 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4880 lbl = newiTempLabel (NULL);
4881 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4882 emitcode ("cpl", "a");
4883 emitcode ("inc", "a");
4884 emitcode ("", "!tlabeldef", (lbl->key + 100));
4885 emitcode ("mov", "b,a");
4887 /* sign adjust left side */
4888 MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4890 lbl = newiTempLabel (NULL);
4891 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4892 emitcode ("cpl", "a");
4893 emitcode ("inc", "a");
4894 emitcode ("", "!tlabeldef", (lbl->key + 100));
4896 /* now the division */
4897 emitcode ("nop", "; workaround for DS80C390 div bug.");
4898 emitcode ("div", "ab");
4899 /* we are interested in the lower order
4901 emitcode ("mov", "b,a");
4902 lbl = newiTempLabel (NULL);
4903 emitcode ("pop", "acc");
4904 /* if there was an over flow we don't
4905 adjust the sign of the result */
4906 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4907 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4909 emitcode ("clr", "a");
4910 emitcode ("subb", "a,b");
4911 emitcode ("mov", "b,a");
4912 emitcode ("", "!tlabeldef", (lbl->key + 100));
4914 /* now we are done */
4915 _G.accInUse++; _G.bInUse++;
4916 aopOp(result, ic, TRUE, FALSE);
4918 aopPut (AOP (result), "b", 0);
4920 size = AOP_SIZE (result) - 1;
4924 emitcode ("mov", "c,b.7");
4925 emitcode ("subb", "a,acc");
4929 aopPut (AOP (result), "a", offset++);
4931 _G.accInUse--; _G.bInUse--;
4935 /*-----------------------------------------------------------------*/
4936 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
4937 /*-----------------------------------------------------------------*/
4938 static void genDivTwoByte (operand *left, operand *right,
4939 operand *result, iCode *ic)
4941 sym_link *retype = getSpec(operandType(right));
4942 sym_link *letype = getSpec(operandType(left));
4943 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4946 /* save EA bit in F1 */
4947 lbl = newiTempLabel(NULL);
4948 emitcode ("setb","F1");
4949 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4950 emitcode ("clr","F1");
4951 emitcode("","!tlabeldef",lbl->key+100);
4953 /* load up MA with left */
4955 emitcode("clr","F0");
4956 lbl = newiTempLabel(NULL);
4957 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4958 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4959 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4960 emitcode ("xch", "a,b");
4961 emitcode ("cpl","a");
4962 emitcode ("add", "a,#1");
4963 emitcode ("xch", "a,b");
4964 emitcode ("cpl", "a"); // msb
4965 emitcode ("addc","a,#0");
4966 emitcode ("setb","F0");
4967 emitcode ("","!tlabeldef",lbl->key+100);
4968 emitcode ("mov","ma,b");
4969 emitcode ("mov","ma,a");
4971 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4972 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4975 /* load up MB with right */
4977 if (AOP_TYPE(right) == AOP_LIT) {
4978 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4980 lbl = newiTempLabel(NULL);
4981 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4982 emitcode("setb","F0");
4983 emitcode ("","!tlabeldef",lbl->key+100);
4986 emitcode ("mov","mb,#!constbyte",val & 0xff);
4987 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4989 lbl = newiTempLabel(NULL);
4990 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4991 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4992 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4993 emitcode ("xch", "a,b");
4994 emitcode ("cpl","a");
4995 emitcode ("add", "a,#1");
4996 emitcode ("xch", "a,b");
4997 emitcode ("cpl", "a"); // msb
4998 emitcode ("addc", "a,#0");
4999 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5000 emitcode ("setb","F0");
5001 emitcode ("","!tlabeldef",lbl->key+100);
5002 emitcode ("mov","mb,b");
5003 emitcode ("mov","mb,a");
5006 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5007 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5010 /* wait for multiplication to finish */
5011 lbl = newiTempLabel(NULL);
5012 emitcode("","!tlabeldef", lbl->key+100);
5013 emitcode("mov","a,mcnt1");
5014 emitcode("anl","a,#!constbyte",0x80);
5015 emitcode("jnz","!tlabel",lbl->key+100);
5017 freeAsmop (left, NULL, ic, TRUE);
5018 freeAsmop (right, NULL, ic,TRUE);
5019 aopOp(result, ic, TRUE, FALSE);
5021 /* if unsigned then simple */
5023 aopPut(AOP(result),"ma",1);
5024 aopPut(AOP(result),"ma",0);
5026 emitcode("push","ma");
5028 /* negate result if needed */
5029 lbl = newiTempLabel(NULL);
5030 emitcode("jnb","F0,!tlabel",lbl->key+100);
5031 emitcode("cpl","a");
5032 emitcode("add","a,#1");
5033 emitcode("","!tlabeldef", lbl->key+100);
5034 aopPut(AOP(result),"a",0);
5035 emitcode("pop","acc");
5036 lbl = newiTempLabel(NULL);
5037 emitcode("jnb","F0,!tlabel",lbl->key+100);
5038 emitcode("cpl","a");
5039 emitcode("addc","a,#0");
5040 emitcode("","!tlabeldef", lbl->key+100);
5041 aopPut(AOP(result),"a",1);
5043 freeAsmop (result, NULL, ic, TRUE);
5044 /* restore EA bit in F1 */
5045 lbl = newiTempLabel(NULL);
5046 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5047 emitcode ("setb","EA");
5048 emitcode("","!tlabeldef",lbl->key+100);
5052 /*-----------------------------------------------------------------*/
5053 /* genDiv - generates code for division */
5054 /*-----------------------------------------------------------------*/
5058 operand *left = IC_LEFT (ic);
5059 operand *right = IC_RIGHT (ic);
5060 operand *result = IC_RESULT (ic);
5062 D (emitcode (";", "genDiv "););
5064 /* assign the amsops */
5067 /* special cases first */
5069 if (AOP_TYPE (left) == AOP_CRY &&
5070 AOP_TYPE (right) == AOP_CRY)
5072 genDivbits (left, right, result, ic);
5076 /* if both are of size == 1 */
5077 if (AOP_SIZE (left) == 1 &&
5078 AOP_SIZE (right) == 1)
5080 genDivOneByte (left, right, result, ic);
5084 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5085 /* use the ds390 ARITHMETIC accel UNIT */
5086 genDivTwoByte (left, right, result, ic);
5089 /* should have been converted to function call */
5092 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5093 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5094 freeAsmop (result, NULL, ic, TRUE);
5097 /*-----------------------------------------------------------------*/
5098 /* genModbits :- modulus of bits */
5099 /*-----------------------------------------------------------------*/
5101 genModbits (operand * left,
5109 /* the result must be bit */
5110 LOAD_AB_FOR_DIV (left, right, l);
5111 emitcode ("div", "ab");
5112 emitcode ("mov", "a,b");
5113 emitcode ("rrc", "a");
5114 aopOp(result, ic, TRUE, FALSE);
5115 aopPut (AOP (result), "c", 0);
5118 /*-----------------------------------------------------------------*/
5119 /* genModOneByte : 8 bit modulus */
5120 /*-----------------------------------------------------------------*/
5122 genModOneByte (operand * left,
5127 sym_link *opetype = operandType (result);
5131 /* signed or unsigned */
5132 if (SPEC_USIGN (opetype))
5134 /* unsigned is easy */
5135 LOAD_AB_FOR_DIV (left, right, l);
5136 emitcode ("div", "ab");
5137 aopOp(result, ic, TRUE, FALSE);
5138 aopPut (AOP (result), "b", 0);
5142 /* signed is a little bit more difficult */
5144 /* save the signs of the operands */
5145 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5147 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
5148 emitcode ("push", "acc"); /* save it on the stack */
5150 /* now sign adjust for both left & right */
5151 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5153 lbl = newiTempLabel (NULL);
5154 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5155 emitcode ("cpl", "a");
5156 emitcode ("inc", "a");
5157 emitcode ("", "!tlabeldef", (lbl->key + 100));
5158 emitcode ("mov", "b,a");
5160 /* sign adjust left side */
5161 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5163 lbl = newiTempLabel (NULL);
5164 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5165 emitcode ("cpl", "a");
5166 emitcode ("inc", "a");
5167 emitcode ("", "!tlabeldef", (lbl->key + 100));
5169 /* now the multiplication */
5170 emitcode ("nop", "; workaround for DS80C390 div bug.");
5171 emitcode ("div", "ab");
5172 /* we are interested in the lower order
5174 lbl = newiTempLabel (NULL);
5175 emitcode ("pop", "acc");
5176 /* if there was an over flow we don't
5177 adjust the sign of the result */
5178 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
5179 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5181 emitcode ("clr", "a");
5182 emitcode ("subb", "a,b");
5183 emitcode ("mov", "b,a");
5184 emitcode ("", "!tlabeldef", (lbl->key + 100));
5187 /* now we are done */
5188 aopOp(result, ic, TRUE, FALSE);
5189 aopPut (AOP (result), "b", 0);
5194 /*-----------------------------------------------------------------*/
5195 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
5196 /*-----------------------------------------------------------------*/
5197 static void genModTwoByte (operand *left, operand *right,
5198 operand *result, iCode *ic)
5200 sym_link *retype = getSpec(operandType(right));
5201 sym_link *letype = getSpec(operandType(left));
5202 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5205 /* load up MA with left */
5206 /* save EA bit in F1 */
5207 lbl = newiTempLabel(NULL);
5208 emitcode ("setb","F1");
5209 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5210 emitcode ("clr","F1");
5211 emitcode("","!tlabeldef",lbl->key+100);
5214 lbl = newiTempLabel(NULL);
5215 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5216 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5217 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5218 emitcode ("xch", "a,b");
5219 emitcode ("cpl","a");
5220 emitcode ("add", "a,#1");
5221 emitcode ("xch", "a,b");
5222 emitcode ("cpl", "a"); // msb
5223 emitcode ("addc","a,#0");
5224 emitcode ("","!tlabeldef",lbl->key+100);
5225 emitcode ("mov","ma,b");
5226 emitcode ("mov","ma,a");
5228 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5229 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5232 /* load up MB with right */
5234 if (AOP_TYPE(right) == AOP_LIT) {
5235 int val=floatFromVal (AOP (right)->aopu.aop_lit);
5239 emitcode ("mov","mb,#!constbyte",val & 0xff);
5240 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5242 lbl = newiTempLabel(NULL);
5243 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5244 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5245 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5246 emitcode ("xch", "a,b");
5247 emitcode ("cpl","a");
5248 emitcode ("add", "a,#1");
5249 emitcode ("xch", "a,b");
5250 emitcode ("cpl", "a"); // msb
5251 emitcode ("addc", "a,#0");
5252 emitcode ("","!tlabeldef",lbl->key+100);
5253 emitcode ("mov","mb,b");
5254 emitcode ("mov","mb,a");
5257 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5258 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5261 /* wait for multiplication to finish */
5262 lbl = newiTempLabel(NULL);
5263 emitcode("","!tlabeldef", lbl->key+100);
5264 emitcode("mov","a,mcnt1");
5265 emitcode("anl","a,#!constbyte",0x80);
5266 emitcode("jnz","!tlabel",lbl->key+100);
5268 freeAsmop (left, NULL, ic, TRUE);
5269 freeAsmop (right, NULL, ic,TRUE);
5270 aopOp(result, ic, TRUE, FALSE);
5272 aopPut(AOP(result),"mb",1);
5273 aopPut(AOP(result),"mb",0);
5274 freeAsmop (result, NULL, ic, TRUE);
5276 /* restore EA bit in F1 */
5277 lbl = newiTempLabel(NULL);
5278 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5279 emitcode ("setb","EA");
5280 emitcode("","!tlabeldef",lbl->key+100);
5284 /*-----------------------------------------------------------------*/
5285 /* genMod - generates code for division */
5286 /*-----------------------------------------------------------------*/
5290 operand *left = IC_LEFT (ic);
5291 operand *right = IC_RIGHT (ic);
5292 operand *result = IC_RESULT (ic);
5294 D (emitcode (";", "genMod "); );
5296 /* assign the amsops */
5299 /* special cases first */
5301 if (AOP_TYPE (left) == AOP_CRY &&
5302 AOP_TYPE (right) == AOP_CRY)
5304 genModbits (left, right, result, ic);
5308 /* if both are of size == 1 */
5309 if (AOP_SIZE (left) == 1 &&
5310 AOP_SIZE (right) == 1)
5312 genModOneByte (left, right, result, ic);
5316 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5317 /* use the ds390 ARITHMETIC accel UNIT */
5318 genModTwoByte (left, right, result, ic);
5322 /* should have been converted to function call */
5326 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5327 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5328 freeAsmop (result, NULL, ic, TRUE);
5331 /*-----------------------------------------------------------------*/
5332 /* genIfxJump :- will create a jump depending on the ifx */
5333 /*-----------------------------------------------------------------*/
5335 genIfxJump (iCode * ic, char *jval)
5338 symbol *tlbl = newiTempLabel (NULL);
5341 D (emitcode (";", "genIfxJump"););
5343 /* if true label then we jump if condition
5347 jlbl = IC_TRUE (ic);
5348 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5349 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5353 /* false label is present */
5354 jlbl = IC_FALSE (ic);
5355 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5356 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5358 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5359 emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5361 emitcode (inst, "!tlabel", tlbl->key + 100);
5362 emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5363 emitcode ("", "!tlabeldef", tlbl->key + 100);
5365 /* mark the icode as generated */
5369 /*-----------------------------------------------------------------*/
5370 /* genCmp :- greater or less than comparison */
5371 /*-----------------------------------------------------------------*/
5373 genCmp (operand * left, operand * right,
5374 iCode * ic, iCode * ifx, int sign)
5376 int size, offset = 0;
5377 unsigned long lit = 0L;
5380 D (emitcode (";", "genCmp"););
5382 result = IC_RESULT (ic);
5384 /* if left & right are bit variables */
5385 if (AOP_TYPE (left) == AOP_CRY &&
5386 AOP_TYPE (right) == AOP_CRY)
5388 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5389 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
5393 /* subtract right from left if at the
5394 end the carry flag is set then we know that
5395 left is greater than right */
5396 size = max (AOP_SIZE (left), AOP_SIZE (right));
5398 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5399 if ((size == 1) && !sign
5400 && (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5402 symbol *lbl = newiTempLabel (NULL);
5403 emitcode ("cjne", "%s,%s,!tlabel",
5404 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
5405 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5407 emitcode ("", "!tlabeldef", lbl->key + 100);
5411 if (AOP_TYPE (right) == AOP_LIT)
5413 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5414 /* optimize if(x < 0) or if(x >= 0) */
5423 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
5425 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5426 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5428 aopOp (result, ic, FALSE, FALSE);
5430 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5432 freeAsmop (result, NULL, ic, TRUE);
5433 genIfxJump (ifx, "acc.7");
5438 emitcode ("rlc", "a");
5440 goto release_freedLR;
5448 // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5449 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5450 // emitcode (";", "genCmp #2");
5451 if (sign && (size == 0))
5453 // emitcode (";", "genCmp #3");
5454 emitcode ("xrl", "a,#!constbyte",0x80);
5455 if (AOP_TYPE (right) == AOP_LIT)
5457 unsigned long lit = (unsigned long)
5458 floatFromVal (AOP (right)->aopu.aop_lit);
5459 // emitcode (";", "genCmp #3.1");
5460 emitcode ("subb", "a,#!constbyte",
5461 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5465 // emitcode (";", "genCmp #3.2");
5467 MOVB(aopGet (AOP (right), offset++, FALSE, FALSE, "b"));
5468 saveAccWarn = DEFAULT_ACC_WARNING;
5469 emitcode ("xrl", "b,#!constbyte",0x80);
5470 emitcode ("subb", "a,b");
5477 // emitcode (";", "genCmp #4");
5479 s = aopGet (AOP (right), offset++, FALSE, FALSE, "b");
5480 saveAccWarn = DEFAULT_ACC_WARNING;
5482 emitcode ("subb", "a,%s", s);
5489 /* Don't need the left & right operands any more; do need the result. */
5490 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5491 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5493 aopOp (result, ic, FALSE, FALSE);
5497 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5503 /* if the result is used in the next
5504 ifx conditional branch then generate
5505 code a little differently */
5508 genIfxJump (ifx, "c");
5514 /* leave the result in acc */
5516 freeAsmop (result, NULL, ic, TRUE);
5519 /*-----------------------------------------------------------------*/
5520 /* genCmpGt :- greater than comparison */
5521 /*-----------------------------------------------------------------*/
5523 genCmpGt (iCode * ic, iCode * ifx)
5525 operand *left, *right;
5526 sym_link *letype, *retype;
5529 D (emitcode (";", "genCmpGt ");
5532 left = IC_LEFT (ic);
5533 right = IC_RIGHT (ic);
5535 letype = getSpec (operandType (left));
5536 retype = getSpec (operandType (right));
5537 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5539 /* assign the left & right amsops */
5542 genCmp (right, left, ic, ifx, sign);
5545 /*-----------------------------------------------------------------*/
5546 /* genCmpLt - less than comparisons */
5547 /*-----------------------------------------------------------------*/
5549 genCmpLt (iCode * ic, iCode * ifx)
5551 operand *left, *right;
5552 sym_link *letype, *retype;
5555 D (emitcode (";", "genCmpLt "););
5557 left = IC_LEFT (ic);
5558 right = IC_RIGHT (ic);
5560 letype = getSpec (operandType (left));
5561 retype = getSpec (operandType (right));
5562 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5564 /* assign the left & right amsops */
5567 genCmp (left, right, ic, ifx, sign);
5570 /*-----------------------------------------------------------------*/
5571 /* gencjneshort - compare and jump if not equal */
5572 /*-----------------------------------------------------------------*/
5574 gencjneshort (operand * left, operand * right, symbol * lbl)
5576 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5578 unsigned long lit = 0L;
5580 D (emitcode (";", "gencjneshort");
5583 /* if the left side is a literal or
5584 if the right is in a pointer register and left
5586 if ((AOP_TYPE (left) == AOP_LIT) ||
5587 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5594 if (AOP_TYPE (right) == AOP_LIT)
5595 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5597 if (opIsGptr (left) || opIsGptr (right))
5599 /* We are comparing a generic pointer to something.
5600 * Exclude the generic type byte from the comparison.
5603 D (emitcode (";", "cjneshort: generic ptr special case."););
5607 /* if the right side is a literal then anything goes */
5608 if (AOP_TYPE (right) == AOP_LIT &&
5609 AOP_TYPE (left) != AOP_DIR)
5613 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5614 emitcode ("cjne", "a,%s,!tlabel",
5615 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5621 /* if the right side is in a register or in direct space or
5622 if the left is a pointer register & right is not */
5623 else if (AOP_TYPE (right) == AOP_REG ||
5624 AOP_TYPE (right) == AOP_DIR ||
5625 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5626 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5630 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5631 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5632 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5633 emitcode ("jnz", "!tlabel", lbl->key + 100);
5635 emitcode ("cjne", "a,%s,!tlabel",
5636 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
5643 /* right is a pointer reg need both a & b */
5646 MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5647 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
5648 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5654 /*-----------------------------------------------------------------*/
5655 /* gencjne - compare and jump if not equal */
5656 /*-----------------------------------------------------------------*/
5658 gencjne (operand * left, operand * right, symbol * lbl)
5660 symbol *tlbl = newiTempLabel (NULL);
5662 D (emitcode (";", "gencjne");
5665 gencjneshort (left, right, lbl);
5667 emitcode ("mov", "a,%s", one);
5668 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5669 emitcode ("", "!tlabeldef", lbl->key + 100);
5670 emitcode ("clr", "a");
5671 emitcode ("", "!tlabeldef", tlbl->key + 100);
5674 /*-----------------------------------------------------------------*/
5675 /* genCmpEq - generates code for equal to */
5676 /*-----------------------------------------------------------------*/
5678 genCmpEq (iCode * ic, iCode * ifx)
5680 operand *left, *right, *result;
5682 D (emitcode (";", "genCmpEq ");
5686 AOP_SET_LOCALS (ic);
5688 /* if literal, literal on the right or
5689 if the right is in a pointer register and left
5691 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5692 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5694 operand *t = IC_RIGHT (ic);
5695 IC_RIGHT (ic) = IC_LEFT (ic);
5699 if (ifx && /* !AOP_SIZE(result) */
5700 OP_SYMBOL (result) &&
5701 OP_SYMBOL (result)->regType == REG_CND)
5704 /* if they are both bit variables */
5705 if (AOP_TYPE (left) == AOP_CRY &&
5706 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5708 if (AOP_TYPE (right) == AOP_LIT)
5710 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5713 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5714 emitcode ("cpl", "c");
5718 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5722 emitcode ("clr", "c");
5724 /* AOP_TYPE(right) == AOP_CRY */
5728 symbol *lbl = newiTempLabel (NULL);
5729 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5730 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5731 emitcode ("cpl", "c");
5732 emitcode ("", "!tlabeldef", (lbl->key + 100));
5734 /* if true label then we jump if condition
5736 tlbl = newiTempLabel (NULL);
5739 emitcode ("jnc", "!tlabel", tlbl->key + 100);
5740 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5744 emitcode ("jc", "!tlabel", tlbl->key + 100);
5745 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5747 emitcode ("", "!tlabeldef", tlbl->key + 100);
5751 tlbl = newiTempLabel (NULL);
5752 gencjneshort (left, right, tlbl);
5755 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5756 emitcode ("", "!tlabeldef", tlbl->key + 100);
5760 symbol *lbl = newiTempLabel (NULL);
5761 emitcode ("sjmp", "!tlabel", lbl->key + 100);
5762 emitcode ("", "!tlabeldef", tlbl->key + 100);
5763 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5764 emitcode ("", "!tlabeldef", lbl->key + 100);
5767 /* mark the icode as generated */
5770 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5771 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5775 /* if they are both bit variables */
5776 if (AOP_TYPE (left) == AOP_CRY &&
5777 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5779 if (AOP_TYPE (right) == AOP_LIT)
5781 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5784 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5785 emitcode ("cpl", "c");
5789 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5793 emitcode ("clr", "c");
5795 /* AOP_TYPE(right) == AOP_CRY */
5799 symbol *lbl = newiTempLabel (NULL);
5800 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5801 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5802 emitcode ("cpl", "c");
5803 emitcode ("", "!tlabeldef", (lbl->key + 100));
5806 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5807 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5809 aopOp (result, ic, TRUE, FALSE);
5812 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5819 genIfxJump (ifx, "c");
5822 /* if the result is used in an arithmetic operation
5823 then put the result in place */
5828 gencjne (left, right, newiTempLabel (NULL));
5830 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5831 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5833 aopOp (result, ic, TRUE, FALSE);
5835 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5837 aopPut (AOP (result), "a", 0);
5842 genIfxJump (ifx, "a");
5845 /* if the result is used in an arithmetic operation
5846 then put the result in place */
5847 if (AOP_TYPE (result) != AOP_CRY)
5849 /* leave the result in acc */
5853 freeAsmop (result, NULL, ic, TRUE);
5856 /*-----------------------------------------------------------------*/
5857 /* ifxForOp - returns the icode containing the ifx for operand */
5858 /*-----------------------------------------------------------------*/
5860 ifxForOp (operand * op, iCode * ic)
5862 /* if true symbol then needs to be assigned */
5863 if (IS_TRUE_SYMOP (op))
5866 /* if this has register type condition and
5867 the next instruction is ifx with the same operand
5868 and live to of the operand is upto the ifx only then */
5870 ic->next->op == IFX &&
5871 IC_COND (ic->next)->key == op->key &&
5872 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5877 /*-----------------------------------------------------------------*/
5878 /* hasInc - operand is incremented before any other use */
5879 /*-----------------------------------------------------------------*/
5881 hasInc (operand *op, iCode *ic, int osize)
5883 sym_link *type = operandType(op);
5884 sym_link *retype = getSpec (type);
5885 iCode *lic = ic->next;
5888 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5889 if (!IS_SYMOP(op)) return NULL;
5891 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5892 if (IS_AGGREGATE(type->next)) return NULL;
5893 if (osize != (isize = getSize(type->next))) return NULL;
5896 /* if operand of the form op = op + <sizeof *op> */
5897 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5898 isOperandEqual(IC_RESULT(lic),op) &&
5899 isOperandLiteral(IC_RIGHT(lic)) &&
5900 operandLitValue(IC_RIGHT(lic)) == isize) {
5903 /* if the operand used or deffed */
5904 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5907 /* if GOTO or IFX */
5908 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5914 /*-----------------------------------------------------------------*/
5915 /* genAndOp - for && operation */
5916 /*-----------------------------------------------------------------*/
5918 genAndOp (iCode * ic)
5920 operand *left, *right, *result;
5923 D (emitcode (";", "genAndOp "););
5925 /* note here that && operations that are in an
5926 if statement are taken away by backPatchLabels
5927 only those used in arthmetic operations remain */
5929 AOP_SET_LOCALS (ic);
5931 /* if both are bit variables */
5932 if (AOP_TYPE (left) == AOP_CRY &&
5933 AOP_TYPE (right) == AOP_CRY)
5935 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5936 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5937 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5938 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5940 aopOp (result,ic,FALSE, FALSE);
5945 tlbl = newiTempLabel (NULL);
5947 emitcode ("jz", "!tlabel", tlbl->key + 100);
5949 emitcode ("", "!tlabeldef", tlbl->key + 100);
5950 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5951 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5953 aopOp (result,ic,FALSE, FALSE);
5956 freeAsmop (result, NULL, ic, TRUE);
5960 /*-----------------------------------------------------------------*/
5961 /* genOrOp - for || operation */
5962 /*-----------------------------------------------------------------*/
5964 genOrOp (iCode * ic)
5966 operand *left, *right, *result;
5969 D (emitcode (";", "genOrOp "););
5971 /* note here that || operations that are in an
5972 if statement are taken away by backPatchLabels
5973 only those used in arthmetic operations remain */
5975 AOP_SET_LOCALS (ic);
5977 /* if both are bit variables */
5978 if (AOP_TYPE (left) == AOP_CRY &&
5979 AOP_TYPE (right) == AOP_CRY)
5981 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5982 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5983 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5984 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5986 aopOp (result,ic,FALSE, FALSE);
5992 tlbl = newiTempLabel (NULL);
5994 emitcode ("jnz", "!tlabel", tlbl->key + 100);
5996 emitcode ("", "!tlabeldef", tlbl->key + 100);
5997 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5998 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6000 aopOp (result,ic,FALSE, FALSE);
6005 freeAsmop (result, NULL, ic, TRUE);
6008 /*-----------------------------------------------------------------*/
6009 /* isLiteralBit - test if lit == 2^n */
6010 /*-----------------------------------------------------------------*/
6012 isLiteralBit (unsigned long lit)
6014 unsigned long pw[32] =
6015 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6016 0x100L, 0x200L, 0x400L, 0x800L,
6017 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6018 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6019 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6020 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6021 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6024 for (idx = 0; idx < 32; idx++)
6030 /*-----------------------------------------------------------------*/
6031 /* continueIfTrue - */
6032 /*-----------------------------------------------------------------*/
6034 continueIfTrue (iCode * ic)
6037 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6041 /*-----------------------------------------------------------------*/
6043 /*-----------------------------------------------------------------*/
6045 jumpIfTrue (iCode * ic)
6048 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6052 /*-----------------------------------------------------------------*/
6053 /* jmpTrueOrFalse - */
6054 /*-----------------------------------------------------------------*/
6056 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6058 // ugly but optimized by peephole
6061 symbol *nlbl = newiTempLabel (NULL);
6062 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6063 emitcode ("", "!tlabeldef", tlbl->key + 100);
6064 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6065 emitcode ("", "!tlabeldef", nlbl->key + 100);
6069 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6070 emitcode ("", "!tlabeldef", tlbl->key + 100);
6075 // Generate code to perform a bit-wise logic operation
6076 // on two operands in far space (assumed to already have been
6077 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6078 // in far space. This requires pushing the result on the stack
6079 // then popping it into the result.
6081 genFarFarLogicOp(iCode *ic, char *logicOp)
6083 int size, resultSize, compSize;
6087 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6088 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
6089 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6091 _startLazyDPSEvaluation();
6092 for (size = compSize; (size--); offset++)
6094 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6095 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6096 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6098 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6099 emitcode ("push", "acc");
6101 _endLazyDPSEvaluation();
6103 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6104 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6105 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6107 resultSize = AOP_SIZE(IC_RESULT(ic));
6109 ADJUST_PUSHED_RESULT(compSize, resultSize);
6111 _startLazyDPSEvaluation();
6114 emitcode ("pop", "acc");
6115 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6117 _endLazyDPSEvaluation();
6118 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6122 /*-----------------------------------------------------------------*/
6123 /* genAnd - code for and */
6124 /*-----------------------------------------------------------------*/
6126 genAnd (iCode * ic, iCode * ifx)
6128 operand *left, *right, *result;
6129 int size, offset = 0;
6130 unsigned long lit = 0L;
6135 D (emitcode (";", "genAnd "););
6137 AOP_OP_3_NOFATAL (ic, pushResult);
6138 AOP_SET_LOCALS (ic);
6142 genFarFarLogicOp(ic, "anl");
6147 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6149 AOP_TYPE (left), AOP_TYPE (right));
6150 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6152 AOP_SIZE (left), AOP_SIZE (right));
6155 /* if left is a literal & right is not then exchange them */
6156 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6157 #ifdef LOGIC_OPS_BROKEN
6158 || AOP_NEEDSACC (left)
6162 operand *tmp = right;
6167 /* if result = right then exchange them */
6168 if (sameRegs (AOP (result), AOP (right)))
6170 operand *tmp = right;
6175 /* if right is bit then exchange them */
6176 if (AOP_TYPE (right) == AOP_CRY &&
6177 AOP_TYPE (left) != AOP_CRY)
6179 operand *tmp = right;
6183 if (AOP_TYPE (right) == AOP_LIT)
6184 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6186 size = AOP_SIZE (result);
6189 // result = bit & yy;
6190 if (AOP_TYPE (left) == AOP_CRY)
6192 // c = bit & literal;
6193 if (AOP_TYPE (right) == AOP_LIT)
6197 if (size && sameRegs (AOP (result), AOP (left)))
6200 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6205 if (size && (AOP_TYPE (result) == AOP_CRY))
6207 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6210 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6215 emitcode ("clr", "c");
6220 if (AOP_TYPE (right) == AOP_CRY)
6223 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6224 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6229 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6231 emitcode ("rrc", "a");
6232 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6240 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6241 genIfxJump (ifx, "c");
6245 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6246 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6247 if ((AOP_TYPE (right) == AOP_LIT) &&
6248 (AOP_TYPE (result) == AOP_CRY) &&
6249 (AOP_TYPE (left) != AOP_CRY))
6251 int posbit = isLiteralBit (lit);
6256 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6259 emitcode ("mov", "c,acc.%d", posbit & 0x07);
6265 SNPRINTF (buff, sizeof(buff),
6266 "acc.%d", posbit & 0x07);
6267 genIfxJump (ifx, buff);
6271 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6278 symbol *tlbl = newiTempLabel (NULL);
6279 int sizel = AOP_SIZE (left);
6281 emitcode ("setb", "c");
6284 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6286 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6288 if ((posbit = isLiteralBit (bytelit)) != 0)
6289 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6292 if (bytelit != 0x0FFL)
6293 emitcode ("anl", "a,%s",
6294 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6295 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6300 // bit = left & literal
6303 emitcode ("clr", "c");
6304 emitcode ("", "!tlabeldef", tlbl->key + 100);
6306 // if(left & literal)
6310 jmpTrueOrFalse (ifx, tlbl);
6318 /* if left is same as result */
6319 if (sameRegs (AOP (result), AOP (left)))
6321 for (; size--; offset++)
6323 if (AOP_TYPE (right) == AOP_LIT)
6325 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6327 else if (bytelit == 0)
6328 aopPut (AOP (result), zero, offset);
6329 else if (IS_AOP_PREG (result))
6331 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6332 emitcode ("anl", "a,%s",
6333 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6334 aopPut (AOP (result), "a", offset);
6337 emitcode ("anl", "%s,%s",
6338 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6339 aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6343 if (AOP_TYPE (left) == AOP_ACC)
6344 emitcode ("anl", "a,%s",
6345 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6348 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6349 if (IS_AOP_PREG (result))
6351 emitcode ("anl", "a,%s",
6352 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6353 aopPut (AOP (result), "a", offset);
6356 emitcode ("anl", "%s,a",
6357 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6364 // left & result in different registers
6365 if (AOP_TYPE (result) == AOP_CRY)
6368 // if(size), result in bit
6369 // if(!size && ifx), conditional oper: if(left & right)
6370 symbol *tlbl = newiTempLabel (NULL);
6371 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6373 emitcode ("setb", "c");
6376 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6377 emitcode ("anl", "a,%s",
6378 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6380 if (AOP_TYPE(left)==AOP_ACC) {
6381 emitcode("mov", "b,a");
6382 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6383 emitcode("anl", "a,b");
6385 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6386 emitcode ("anl", "a,%s",
6387 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6390 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6396 emitcode ("", "!tlabeldef", tlbl->key + 100);
6400 jmpTrueOrFalse (ifx, tlbl);
6404 for (; (size--); offset++)
6407 // result = left & right
6408 if (AOP_TYPE (right) == AOP_LIT)
6410 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6412 aopPut (AOP (result),
6413 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6417 else if (bytelit == 0)
6419 aopPut (AOP (result), zero, offset);
6422 D (emitcode (";", "better literal AND."););
6423 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6424 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6425 FALSE, FALSE, DP2_RESULT_REG));
6430 // faster than result <- left, anl result,right
6431 // and better if result is SFR
6432 if (AOP_TYPE (left) == AOP_ACC)
6434 emitcode ("anl", "a,%s",
6435 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6439 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6440 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6442 emitcode("mov", "b,a");
6446 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6447 emitcode ("anl", "a,%s", rOp);
6450 aopPut (AOP (result), "a", offset);
6456 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6457 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6458 freeAsmop (result, NULL, ic, TRUE);
6462 /*-----------------------------------------------------------------*/
6463 /* genOr - code for or */
6464 /*-----------------------------------------------------------------*/
6466 genOr (iCode * ic, iCode * ifx)
6468 operand *left, *right, *result;
6469 int size, offset = 0;
6470 unsigned long lit = 0L;
6473 D (emitcode (";", "genOr "););
6475 AOP_OP_3_NOFATAL (ic, pushResult);
6476 AOP_SET_LOCALS (ic);
6480 genFarFarLogicOp(ic, "orl");
6486 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6488 AOP_TYPE (left), AOP_TYPE (right));
6489 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6491 AOP_SIZE (left), AOP_SIZE (right));
6494 /* if left is a literal & right is not then exchange them */
6495 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6496 #ifdef LOGIC_OPS_BROKEN
6497 || AOP_NEEDSACC (left) // I think this is a net loss now.
6501 operand *tmp = right;
6506 /* if result = right then exchange them */
6507 if (sameRegs (AOP (result), AOP (right)))
6509 operand *tmp = right;
6514 /* if right is bit then exchange them */
6515 if (AOP_TYPE (right) == AOP_CRY &&
6516 AOP_TYPE (left) != AOP_CRY)
6518 operand *tmp = right;
6522 if (AOP_TYPE (right) == AOP_LIT)
6523 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6525 size = AOP_SIZE (result);
6529 if (AOP_TYPE (left) == AOP_CRY)
6531 if (AOP_TYPE (right) == AOP_LIT)
6533 // c = bit & literal;
6536 // lit != 0 => result = 1
6537 if (AOP_TYPE (result) == AOP_CRY)
6540 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6542 continueIfTrue (ifx);
6545 emitcode ("setb", "c");
6549 // lit == 0 => result = left
6550 if (size && sameRegs (AOP (result), AOP (left)))
6552 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6557 if (AOP_TYPE (right) == AOP_CRY)
6560 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6561 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6566 symbol *tlbl = newiTempLabel (NULL);
6567 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6568 emitcode ("setb", "c");
6569 emitcode ("jb", "%s,!tlabel",
6570 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6572 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6573 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6575 jmpTrueOrFalse (ifx, tlbl);
6581 emitcode ("", "!tlabeldef", tlbl->key + 100);
6590 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6591 genIfxJump (ifx, "c");
6595 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6596 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6597 if ((AOP_TYPE (right) == AOP_LIT) &&
6598 (AOP_TYPE (result) == AOP_CRY) &&
6599 (AOP_TYPE (left) != AOP_CRY))
6605 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6607 continueIfTrue (ifx);
6612 // lit = 0, result = boolean(left)
6614 emitcode ("setb", "c");
6618 symbol *tlbl = newiTempLabel (NULL);
6619 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6621 emitcode ("", "!tlabeldef", tlbl->key + 100);
6625 genIfxJump (ifx, "a");
6633 /* if left is same as result */
6634 if (sameRegs (AOP (result), AOP (left)))
6636 for (; size--; offset++)
6638 if (AOP_TYPE (right) == AOP_LIT)
6640 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6646 if (IS_AOP_PREG (left))
6648 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6649 emitcode ("orl", "a,%s",
6650 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6651 aopPut (AOP (result), "a", offset);
6655 emitcode ("orl", "%s,%s",
6656 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6657 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6663 if (AOP_TYPE (left) == AOP_ACC)
6665 emitcode ("orl", "a,%s",
6666 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6670 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6671 if (IS_AOP_PREG (left))
6673 emitcode ("orl", "a,%s",
6674 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6675 aopPut (AOP (result), "a", offset);
6679 emitcode ("orl", "%s,a",
6680 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6688 // left & result in different registers
6689 if (AOP_TYPE (result) == AOP_CRY)
6692 // if(size), result in bit
6693 // if(!size && ifx), conditional oper: if(left | right)
6694 symbol *tlbl = newiTempLabel (NULL);
6695 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6697 emitcode ("setb", "c");
6700 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6701 emitcode ("orl", "a,%s",
6702 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6704 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6705 emitcode ("orl", "a,%s",
6706 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6708 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6714 emitcode ("", "!tlabeldef", tlbl->key + 100);
6718 jmpTrueOrFalse (ifx, tlbl);
6722 _startLazyDPSEvaluation();
6723 for (; (size--); offset++)
6726 // result = left & right
6727 if (AOP_TYPE (right) == AOP_LIT)
6729 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6731 aopPut (AOP (result),
6732 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6736 D (emitcode (";", "better literal OR."););
6737 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6738 emitcode ("orl", "a, %s",
6739 aopGet (AOP (right), offset,
6740 FALSE, FALSE, DP2_RESULT_REG));
6745 // faster than result <- left, anl result,right
6746 // and better if result is SFR
6747 if (AOP_TYPE (left) == AOP_ACC)
6749 emitcode ("orl", "a,%s",
6750 aopGet (AOP (right), offset,
6751 FALSE, FALSE, DP2_RESULT_REG));
6755 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6757 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6759 emitcode("mov", "b,a");
6763 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6764 emitcode ("orl", "a,%s", rOp);
6767 aopPut (AOP (result), "a", offset);
6769 _endLazyDPSEvaluation();
6774 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6775 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6776 freeAsmop (result, NULL, ic, TRUE);
6779 /*-----------------------------------------------------------------*/
6780 /* genXor - code for xclusive or */
6781 /*-----------------------------------------------------------------*/
6783 genXor (iCode * ic, iCode * ifx)
6785 operand *left, *right, *result;
6786 int size, offset = 0;
6787 unsigned long lit = 0L;
6790 D (emitcode (";", "genXor "););
6792 AOP_OP_3_NOFATAL (ic, pushResult);
6793 AOP_SET_LOCALS (ic);
6797 genFarFarLogicOp(ic, "xrl");
6802 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6804 AOP_TYPE (left), AOP_TYPE (right));
6805 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6807 AOP_SIZE (left), AOP_SIZE (right));
6810 /* if left is a literal & right is not ||
6811 if left needs acc & right does not */
6812 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6813 #ifdef LOGIC_OPS_BROKEN
6814 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6818 operand *tmp = right;
6823 /* if result = right then exchange them */
6824 if (sameRegs (AOP (result), AOP (right)))
6826 operand *tmp = right;
6831 /* if right is bit then exchange them */
6832 if (AOP_TYPE (right) == AOP_CRY &&
6833 AOP_TYPE (left) != AOP_CRY)
6835 operand *tmp = right;
6839 if (AOP_TYPE (right) == AOP_LIT)
6840 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6842 size = AOP_SIZE (result);
6846 if (AOP_TYPE (left) == AOP_CRY)
6848 if (AOP_TYPE (right) == AOP_LIT)
6850 // c = bit & literal;
6853 // lit>>1 != 0 => result = 1
6854 if (AOP_TYPE (result) == AOP_CRY)
6857 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6859 continueIfTrue (ifx);
6862 emitcode ("setb", "c");
6869 // lit == 0, result = left
6870 if (size && sameRegs (AOP (result), AOP (left)))
6872 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6876 // lit == 1, result = not(left)
6877 if (size && sameRegs (AOP (result), AOP (left)))
6879 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6884 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6885 emitcode ("cpl", "c");
6894 symbol *tlbl = newiTempLabel (NULL);
6895 if (AOP_TYPE (right) == AOP_CRY)
6898 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6902 int sizer = AOP_SIZE (right);
6904 // if val>>1 != 0, result = 1
6905 emitcode ("setb", "c");
6908 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
6910 // test the msb of the lsb
6911 emitcode ("anl", "a,#!constbyte",0xfe);
6912 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6916 emitcode ("rrc", "a");
6918 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6919 emitcode ("cpl", "c");
6920 emitcode ("", "!tlabeldef", (tlbl->key + 100));
6927 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6928 genIfxJump (ifx, "c");
6932 if (sameRegs (AOP (result), AOP (left)))
6934 /* if left is same as result */
6935 for (; size--; offset++)
6937 if (AOP_TYPE (right) == AOP_LIT)
6939 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6941 else if (IS_AOP_PREG (left))
6943 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6944 emitcode ("xrl", "a,%s",
6945 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6946 aopPut (AOP (result), "a", offset);
6949 emitcode ("xrl", "%s,%s",
6950 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6951 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6955 if (AOP_TYPE (left) == AOP_ACC)
6956 emitcode ("xrl", "a,%s",
6957 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6960 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6961 if (IS_AOP_PREG (left))
6963 emitcode ("xrl", "a,%s",
6964 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6965 aopPut (AOP (result), "a", offset);
6968 emitcode ("xrl", "%s,a",
6969 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6976 // left & result in different registers
6977 if (AOP_TYPE (result) == AOP_CRY)
6980 // if(size), result in bit
6981 // if(!size && ifx), conditional oper: if(left ^ right)
6982 symbol *tlbl = newiTempLabel (NULL);
6983 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6986 emitcode ("setb", "c");
6989 if ((AOP_TYPE (right) == AOP_LIT) &&
6990 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6992 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6996 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6997 emitcode ("xrl", "a,%s",
6998 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7000 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7001 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7003 emitcode("mov", "b,a");
7007 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7008 emitcode ("xrl", "a,%s", rOp);
7011 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7017 emitcode ("", "!tlabeldef", tlbl->key + 100);
7021 jmpTrueOrFalse (ifx, tlbl);
7025 for (; (size--); offset++)
7028 // result = left & right
7029 if (AOP_TYPE (right) == AOP_LIT)
7031 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7033 aopPut (AOP (result),
7034 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7038 D (emitcode (";", "better literal XOR."););
7039 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7040 emitcode ("xrl", "a, %s",
7041 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7045 // faster than result <- left, anl result,right
7046 // and better if result is SFR
7047 if (AOP_TYPE (left) == AOP_ACC)
7049 emitcode ("xrl", "a,%s",
7050 aopGet (AOP (right), offset,
7051 FALSE, FALSE, DP2_RESULT_REG));
7055 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7056 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7058 emitcode("mov", "b,a");
7062 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7063 emitcode ("xrl", "a,%s", rOp);
7066 aopPut (AOP (result), "a", offset);
7073 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7074 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7075 freeAsmop (result, NULL, ic, TRUE);
7078 /*-----------------------------------------------------------------*/
7079 /* genInline - write the inline code out */
7080 /*-----------------------------------------------------------------*/
7082 genInline (iCode * ic)
7084 char *buffer, *bp, *bp1;
7086 D (emitcode (";", "genInline "); );
7088 _G.inLine += (!options.asmpeep);
7090 buffer = Safe_strdup(IC_INLINE(ic));
7094 /* emit each line as a code */
7119 /* emitcode("",buffer); */
7120 _G.inLine -= (!options.asmpeep);
7123 /*-----------------------------------------------------------------*/
7124 /* genRRC - rotate right with carry */
7125 /*-----------------------------------------------------------------*/
7129 operand *left, *result;
7132 D (emitcode (";", "genRRC "););
7134 /* rotate right with carry */
7135 left = IC_LEFT (ic);
7136 result = IC_RESULT (ic);
7137 aopOp (left, ic, FALSE, FALSE);
7138 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7140 /* move it to the result */
7141 size = AOP_SIZE (result);
7145 _startLazyDPSEvaluation ();
7148 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7149 emitcode ("rrc", "a");
7150 if (AOP_SIZE (result) > 1)
7151 aopPut (AOP (result), "a", offset--);
7153 _endLazyDPSEvaluation ();
7155 /* now we need to put the carry into the
7156 highest order byte of the result */
7157 if (AOP_SIZE (result) > 1)
7159 MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7161 emitcode ("mov", "acc.7,c");
7162 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7163 freeAsmop (left, NULL, ic, TRUE);
7164 freeAsmop (result, NULL, ic, TRUE);
7167 /*-----------------------------------------------------------------*/
7168 /* genRLC - generate code for rotate left with carry */
7169 /*-----------------------------------------------------------------*/
7173 operand *left, *result;
7177 D (emitcode (";", "genRLC "););
7179 /* rotate right with carry */
7180 left = IC_LEFT (ic);
7181 result = IC_RESULT (ic);
7182 aopOp (left, ic, FALSE, FALSE);
7183 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7185 /* move it to the result */
7186 size = AOP_SIZE (result);
7190 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7192 emitcode ("add", "a,acc");
7193 if (AOP_SIZE (result) > 1)
7195 aopPut (AOP (result), "a", offset++);
7198 _startLazyDPSEvaluation ();
7201 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7203 emitcode ("rlc", "a");
7204 if (AOP_SIZE (result) > 1)
7205 aopPut (AOP (result), "a", offset++);
7207 _endLazyDPSEvaluation ();
7209 /* now we need to put the carry into the
7210 highest order byte of the result */
7211 if (AOP_SIZE (result) > 1)
7213 l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7216 emitcode ("mov", "acc.0,c");
7217 aopPut (AOP (result), "a", 0);
7218 freeAsmop (left, NULL, ic, TRUE);
7219 freeAsmop (result, NULL, ic, TRUE);
7222 /*-----------------------------------------------------------------*/
7223 /* genGetHbit - generates code get highest order bit */
7224 /*-----------------------------------------------------------------*/
7226 genGetHbit (iCode * ic)
7228 operand *left, *result;
7229 left = IC_LEFT (ic);
7230 result = IC_RESULT (ic);
7231 aopOp (left, ic, FALSE, FALSE);
7232 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7234 D (emitcode (";", "genGetHbit "););
7236 /* get the highest order byte into a */
7237 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7238 if (AOP_TYPE (result) == AOP_CRY)
7240 emitcode ("rlc", "a");
7245 emitcode ("rl", "a");
7246 emitcode ("anl", "a,#1");
7251 freeAsmop (left, NULL, ic, TRUE);
7252 freeAsmop (result, NULL, ic, TRUE);
7255 /*-----------------------------------------------------------------*/
7256 /* AccRol - rotate left accumulator by known count */
7257 /*-----------------------------------------------------------------*/
7259 AccRol (int shCount)
7261 shCount &= 0x0007; // shCount : 0..7
7268 emitcode ("rl", "a");
7271 emitcode ("rl", "a");
7272 emitcode ("rl", "a");
7275 emitcode ("swap", "a");
7276 emitcode ("rr", "a");
7279 emitcode ("swap", "a");
7282 emitcode ("swap", "a");
7283 emitcode ("rl", "a");
7286 emitcode ("rr", "a");
7287 emitcode ("rr", "a");
7290 emitcode ("rr", "a");
7295 /*-----------------------------------------------------------------*/
7296 /* AccLsh - left shift accumulator by known count */
7297 /*-----------------------------------------------------------------*/
7299 AccLsh (int shCount)
7304 emitcode ("add", "a,acc");
7305 else if (shCount == 2)
7307 emitcode ("add", "a,acc");
7308 emitcode ("add", "a,acc");
7312 /* rotate left accumulator */
7314 /* and kill the lower order bits */
7315 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7320 /*-----------------------------------------------------------------*/
7321 /* AccRsh - right shift accumulator by known count */
7322 /*-----------------------------------------------------------------*/
7324 AccRsh (int shCount)
7331 emitcode ("rrc", "a");
7335 /* rotate right accumulator */
7336 AccRol (8 - shCount);
7337 /* and kill the higher order bits */
7338 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7343 #ifdef BETTER_LITERAL_SHIFT
7344 /*-----------------------------------------------------------------*/
7345 /* AccSRsh - signed right shift accumulator by known count */
7346 /*-----------------------------------------------------------------*/
7348 AccSRsh (int shCount)
7355 emitcode ("mov", "c,acc.7");
7356 emitcode ("rrc", "a");
7358 else if (shCount == 2)
7360 emitcode ("mov", "c,acc.7");
7361 emitcode ("rrc", "a");
7362 emitcode ("mov", "c,acc.7");
7363 emitcode ("rrc", "a");
7367 tlbl = newiTempLabel (NULL);
7368 /* rotate right accumulator */
7369 AccRol (8 - shCount);
7370 /* and kill the higher order bits */
7371 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7372 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7373 emitcode ("orl", "a,#!constbyte",
7374 (unsigned char) ~SRMask[shCount]);
7375 emitcode ("", "!tlabeldef", tlbl->key + 100);
7381 #ifdef BETTER_LITERAL_SHIFT
7382 /*-----------------------------------------------------------------*/
7383 /* shiftR1Left2Result - shift right one byte from left to result */
7384 /*-----------------------------------------------------------------*/
7386 shiftR1Left2Result (operand * left, int offl,
7387 operand * result, int offr,
7388 int shCount, int sign)
7390 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7391 /* shift right accumulator */
7396 aopPut (AOP (result), "a", offr);
7400 #ifdef BETTER_LITERAL_SHIFT
7401 /*-----------------------------------------------------------------*/
7402 /* shiftL1Left2Result - shift left one byte from left to result */
7403 /*-----------------------------------------------------------------*/
7405 shiftL1Left2Result (operand * left, int offl,
7406 operand * result, int offr, int shCount)
7408 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7409 /* shift left accumulator */
7411 aopPut (AOP (result), "a", offr);
7415 #ifdef BETTER_LITERAL_SHIFT
7416 /*-----------------------------------------------------------------*/
7417 /* movLeft2Result - move byte from left to result */
7418 /*-----------------------------------------------------------------*/
7420 movLeft2Result (operand * left, int offl,
7421 operand * result, int offr, int sign)
7424 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7426 l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
7428 if (*l == '@' && (IS_AOP_PREG (result)))
7430 emitcode ("mov", "a,%s", l);
7431 aopPut (AOP (result), "a", offr);
7437 aopPut (AOP (result), l, offr);
7441 /* MSB sign in acc.7 ! */
7442 if (getDataSize (left) == offl + 1)
7444 emitcode ("mov", "a,%s", l);
7445 aopPut (AOP (result), "a", offr);
7453 #ifdef BETTER_LITERAL_SHIFT
7454 /*-----------------------------------------------------------------*/
7455 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7456 /*-----------------------------------------------------------------*/
7460 emitcode ("rrc", "a");
7461 emitcode ("xch", "a,%s", x);
7462 emitcode ("rrc", "a");
7463 emitcode ("xch", "a,%s", x);
7467 #ifdef BETTER_LITERAL_SHIFT
7469 /*-----------------------------------------------------------------*/
7470 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7471 /*-----------------------------------------------------------------*/
7475 emitcode ("xch", "a,%s", x);
7476 emitcode ("rlc", "a");
7477 emitcode ("xch", "a,%s", x);
7478 emitcode ("rlc", "a");
7482 #ifdef BETTER_LITERAL_SHIFT
7483 /*-----------------------------------------------------------------*/
7484 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7485 /*-----------------------------------------------------------------*/
7489 emitcode ("xch", "a,%s", x);
7490 emitcode ("add", "a,acc");
7491 emitcode ("xch", "a,%s", x);
7492 emitcode ("rlc", "a");
7496 #ifdef BETTER_LITERAL_SHIFT
7497 /*-----------------------------------------------------------------*/
7498 /* AccAXLsh - left shift a:x by known count (0..7) */
7499 /*-----------------------------------------------------------------*/
7501 AccAXLsh (char *x, int shCount)
7516 case 5: // AAAAABBB:CCCCCDDD
7518 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7520 emitcode ("anl", "a,#!constbyte",
7521 SLMask[shCount]); // BBB00000:CCCCCDDD
7523 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7525 AccRol (shCount); // DDDCCCCC:BBB00000
7527 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7529 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7531 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7533 emitcode ("anl", "a,#!constbyte",
7534 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7536 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7538 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7541 case 6: // AAAAAABB:CCCCCCDD
7542 emitcode ("anl", "a,#!constbyte",
7543 SRMask[shCount]); // 000000BB:CCCCCCDD
7544 emitcode ("mov", "c,acc.0"); // c = B
7545 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7547 AccAXRrl1 (x); // BCCCCCCD:D000000B
7548 AccAXRrl1 (x); // BBCCCCCC:DD000000
7550 emitcode("rrc","a");
7551 emitcode("xch","a,%s", x);
7552 emitcode("rrc","a");
7553 emitcode("mov","c,acc.0"); //<< get correct bit
7554 emitcode("xch","a,%s", x);
7556 emitcode("rrc","a");
7557 emitcode("xch","a,%s", x);
7558 emitcode("rrc","a");
7559 emitcode("xch","a,%s", x);
7562 case 7: // a:x <<= 7
7564 emitcode ("anl", "a,#!constbyte",
7565 SRMask[shCount]); // 0000000B:CCCCCCCD
7567 emitcode ("mov", "c,acc.0"); // c = B
7569 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7571 AccAXRrl1 (x); // BCCCCCCC:D0000000
7580 #ifdef BETTER_LITERAL_SHIFT
7582 /*-----------------------------------------------------------------*/
7583 /* AccAXRsh - right shift a:x known count (0..7) */
7584 /*-----------------------------------------------------------------*/
7586 AccAXRsh (char *x, int shCount)
7594 AccAXRrl1 (x); // 0->a:x
7599 AccAXRrl1 (x); // 0->a:x
7602 AccAXRrl1 (x); // 0->a:x
7607 case 5: // AAAAABBB:CCCCCDDD = a:x
7609 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7611 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7613 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7615 emitcode ("anl", "a,#!constbyte",
7616 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7618 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7620 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7622 emitcode ("anl", "a,#!constbyte",
7623 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7625 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7627 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7629 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7632 case 6: // AABBBBBB:CCDDDDDD
7634 emitcode ("mov", "c,acc.7");
7635 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7637 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7639 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7641 emitcode ("anl", "a,#!constbyte",
7642 SRMask[shCount]); // 000000AA:BBBBBBCC
7645 case 7: // ABBBBBBB:CDDDDDDD
7647 emitcode ("mov", "c,acc.7"); // c = A
7649 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7651 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7653 emitcode ("anl", "a,#!constbyte",
7654 SRMask[shCount]); // 0000000A:BBBBBBBC
7663 #ifdef BETTER_LITERAL_SHIFT
7664 /*-----------------------------------------------------------------*/
7665 /* AccAXRshS - right shift signed a:x known count (0..7) */
7666 /*-----------------------------------------------------------------*/
7668 AccAXRshS (char *x, int shCount)
7676 emitcode ("mov", "c,acc.7");
7677 AccAXRrl1 (x); // s->a:x
7681 emitcode ("mov", "c,acc.7");
7682 AccAXRrl1 (x); // s->a:x
7684 emitcode ("mov", "c,acc.7");
7685 AccAXRrl1 (x); // s->a:x
7690 case 5: // AAAAABBB:CCCCCDDD = a:x
7692 tlbl = newiTempLabel (NULL);
7693 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7695 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7697 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7699 emitcode ("anl", "a,#!constbyte",
7700 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7702 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7704 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7706 emitcode ("anl", "a,#!constbyte",
7707 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7709 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7711 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7713 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7715 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7716 emitcode ("orl", "a,#!constbyte",
7717 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7719 emitcode ("", "!tlabeldef", tlbl->key + 100);
7720 break; // SSSSAAAA:BBBCCCCC
7722 case 6: // AABBBBBB:CCDDDDDD
7724 tlbl = newiTempLabel (NULL);
7725 emitcode ("mov", "c,acc.7");
7726 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7728 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7730 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7732 emitcode ("anl", "a,#!constbyte",
7733 SRMask[shCount]); // 000000AA:BBBBBBCC
7735 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7736 emitcode ("orl", "a,#!constbyte",
7737 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7739 emitcode ("", "!tlabeldef", tlbl->key + 100);
7741 case 7: // ABBBBBBB:CDDDDDDD
7743 tlbl = newiTempLabel (NULL);
7744 emitcode ("mov", "c,acc.7"); // c = A
7746 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7748 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7750 emitcode ("anl", "a,#!constbyte",
7751 SRMask[shCount]); // 0000000A:BBBBBBBC
7753 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7754 emitcode ("orl", "a,#!constbyte",
7755 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7757 emitcode ("", "!tlabeldef", tlbl->key + 100);
7765 #ifdef BETTER_LITERAL_SHIFT
7767 _loadLeftIntoAx(char **lsb,
7773 // Get the initial value from left into a pair of registers.
7774 // MSB must be in A, LSB can be any register.
7776 // If the result is held in registers, it is an optimization
7777 // if the LSB can be held in the register which will hold the,
7778 // result LSB since this saves us from having to copy it into
7779 // the result following AccAXLsh.
7781 // If the result is addressed indirectly, this is not a gain.
7782 if (AOP_NEEDSACC(result))
7786 _startLazyDPSEvaluation();
7787 if (AOP_TYPE(left) == AOP_DPTR2)
7790 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
7791 // get LSB in DP2_RESULT_REG.
7792 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
7793 assert(!strcmp(leftByte, DP2_RESULT_REG));
7797 // get LSB into DP2_RESULT_REG
7798 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
7799 if (strcmp(leftByte, DP2_RESULT_REG))
7802 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7805 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
7806 assert(strcmp(leftByte, DP2_RESULT_REG));
7809 _endLazyDPSEvaluation();
7810 *lsb = DP2_RESULT_REG;
7814 if (sameRegs (AOP (result), AOP (left)) &&
7815 ((offl + MSB16) == offr))
7817 /* don't crash result[offr] */
7818 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
7819 emitcode ("xch", "a,%s",
7820 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
7824 movLeft2Result (left, offl, result, offr, 0);
7825 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
7827 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
7828 assert(strcmp(*lsb,"a"));
7833 _storeAxResults(char *lsb,
7837 _startLazyDPSEvaluation();
7838 if (AOP_NEEDSACC(result))
7840 /* We have to explicitly update the result LSB.
7842 emitcode("xch","a,%s", lsb);
7843 aopPut(AOP(result), "a", offr);
7844 emitcode("mov","a,%s", lsb);
7846 if (getDataSize (result) > 1)
7848 aopPut (AOP (result), "a", offr + MSB16);
7850 _endLazyDPSEvaluation();
7853 /*-----------------------------------------------------------------*/
7854 /* shiftL2Left2Result - shift left two bytes from left to result */
7855 /*-----------------------------------------------------------------*/
7857 shiftL2Left2Result (operand * left, int offl,
7858 operand * result, int offr, int shCount)
7862 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7864 AccAXLsh (lsb, shCount);
7866 _storeAxResults(lsb, result, offr);
7870 #ifdef BETTER_LITERAL_SHIFT
7871 /*-----------------------------------------------------------------*/
7872 /* shiftR2Left2Result - shift right two bytes from left to result */
7873 /*-----------------------------------------------------------------*/
7875 shiftR2Left2Result (operand * left, int offl,
7876 operand * result, int offr,
7877 int shCount, int sign)
7881 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7883 /* a:x >> shCount (x = lsb(result)) */
7886 AccAXRshS(lsb, shCount);
7890 AccAXRsh(lsb, shCount);
7893 _storeAxResults(lsb, result, offr);
7899 /*-----------------------------------------------------------------*/
7900 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7901 /*-----------------------------------------------------------------*/
7903 shiftLLeftOrResult (operand * left, int offl,
7904 operand * result, int offr, int shCount)
7906 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7907 /* shift left accumulator */
7909 /* or with result */
7910 emitcode ("orl", "a,%s",
7911 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7912 /* back to result */
7913 aopPut (AOP (result), "a", offr);
7919 /*-----------------------------------------------------------------*/
7920 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7921 /*-----------------------------------------------------------------*/
7923 shiftRLeftOrResult (operand * left, int offl,
7924 operand * result, int offr, int shCount)
7926 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7927 /* shift right accumulator */
7929 /* or with result */
7930 emitcode ("orl", "a,%s",
7931 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7932 /* back to result */
7933 aopPut (AOP (result), "a", offr);
7937 #ifdef BETTER_LITERAL_SHIFT
7938 /*-----------------------------------------------------------------*/
7939 /* genlshOne - left shift a one byte quantity by known count */
7940 /*-----------------------------------------------------------------*/
7942 genlshOne (operand * result, operand * left, int shCount)
7944 D (emitcode (";", "genlshOne "););
7945 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7949 #ifdef BETTER_LITERAL_SHIFT
7950 /*-----------------------------------------------------------------*/
7951 /* genlshTwo - left shift two bytes by known amount != 0 */
7952 /*-----------------------------------------------------------------*/
7954 genlshTwo (operand * result, operand * left, int shCount)
7958 D (emitcode (";", "genlshTwo "););
7960 size = getDataSize (result);
7962 /* if shCount >= 8 */
7967 _startLazyDPSEvaluation();
7973 _endLazyDPSEvaluation();
7974 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7975 aopPut (AOP (result), zero, LSB);
7979 movLeft2Result (left, LSB, result, MSB16, 0);
7980 aopPut (AOP (result), zero, LSB);
7981 _endLazyDPSEvaluation();
7986 aopPut (AOP (result), zero, LSB);
7987 _endLazyDPSEvaluation();
7991 /* 1 <= shCount <= 7 */
7996 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8000 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8008 /*-----------------------------------------------------------------*/
8009 /* shiftLLong - shift left one long from left to result */
8010 /* offl = LSB or MSB16 */
8011 /*-----------------------------------------------------------------*/
8013 shiftLLong (operand * left, operand * result, int offr)
8016 int size = AOP_SIZE (result);
8018 if (size >= LSB + offr)
8020 l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8022 emitcode ("add", "a,acc");
8023 if (sameRegs (AOP (left), AOP (result)) &&
8024 size >= MSB16 + offr && offr != LSB)
8025 emitcode ("xch", "a,%s",
8026 aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8028 aopPut (AOP (result), "a", LSB + offr);
8031 if (size >= MSB16 + offr)
8033 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8035 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8037 emitcode ("rlc", "a");
8038 if (sameRegs (AOP (left), AOP (result)) &&
8039 size >= MSB24 + offr && offr != LSB)
8040 emitcode ("xch", "a,%s",
8041 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8043 aopPut (AOP (result), "a", MSB16 + offr);
8046 if (size >= MSB24 + offr)
8048 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8050 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8052 emitcode ("rlc", "a");
8053 if (sameRegs (AOP (left), AOP (result)) &&
8054 size >= MSB32 + offr && offr != LSB)
8055 emitcode ("xch", "a,%s",
8056 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8058 aopPut (AOP (result), "a", MSB24 + offr);
8061 if (size > MSB32 + offr)
8063 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8065 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8067 emitcode ("rlc", "a");
8068 aopPut (AOP (result), "a", MSB32 + offr);
8071 aopPut (AOP (result), zero, LSB);
8077 /*-----------------------------------------------------------------*/
8078 /* genlshFour - shift four byte by a known amount != 0 */
8079 /*-----------------------------------------------------------------*/
8081 genlshFour (operand * result, operand * left, int shCount)
8085 D (emitcode (";", "genlshFour ");
8088 size = AOP_SIZE (result);
8090 /* if shifting more that 3 bytes */
8095 /* lowest order of left goes to the highest
8096 order of the destination */
8097 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8099 movLeft2Result (left, LSB, result, MSB32, 0);
8100 aopPut (AOP (result), zero, LSB);
8101 aopPut (AOP (result), zero, MSB16);
8102 aopPut (AOP (result), zero, MSB24);
8106 /* more than two bytes */
8107 else if (shCount >= 16)
8109 /* lower order two bytes goes to higher order two bytes */
8111 /* if some more remaining */
8113 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8116 movLeft2Result (left, MSB16, result, MSB32, 0);
8117 movLeft2Result (left, LSB, result, MSB24, 0);
8119 aopPut (AOP (result), zero, MSB16);
8120 aopPut (AOP (result), zero, LSB);
8124 /* if more than 1 byte */
8125 else if (shCount >= 8)
8127 /* lower order three bytes goes to higher order three bytes */
8132 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8134 movLeft2Result (left, LSB, result, MSB16, 0);
8140 movLeft2Result (left, MSB24, result, MSB32, 0);
8141 movLeft2Result (left, MSB16, result, MSB24, 0);
8142 movLeft2Result (left, LSB, result, MSB16, 0);
8143 aopPut (AOP (result), zero, LSB);
8145 else if (shCount == 1)
8146 shiftLLong (left, result, MSB16);
8149 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8150 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8151 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8152 aopPut (AOP (result), zero, LSB);
8157 /* 1 <= shCount <= 7 */
8158 else if (shCount <= 2)
8160 shiftLLong (left, result, LSB);
8162 shiftLLong (result, result, LSB);
8164 /* 3 <= shCount <= 7, optimize */
8167 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8168 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8169 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8174 #ifdef BETTER_LITERAL_SHIFT
8175 /*-----------------------------------------------------------------*/
8176 /* genLeftShiftLiteral - left shifting by known count */
8177 /*-----------------------------------------------------------------*/
8179 genLeftShiftLiteral (operand * left,
8184 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8187 size = getSize (operandType (result));
8189 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8191 /* We only handle certain easy cases so far. */
8193 && (shCount < (size * 8))
8197 D(emitcode (";", "genLeftShiftLiteral wimping out"););
8201 freeAsmop (right, NULL, ic, TRUE);
8203 aopOp(left, ic, FALSE, FALSE);
8204 aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8207 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8209 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8210 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8212 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8215 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8217 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8218 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8220 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8226 emitcode ("; shift left ", "result %d, left %d", size,
8230 /* I suppose that the left size >= result size */
8233 _startLazyDPSEvaluation();
8236 movLeft2Result (left, size, result, size, 0);
8238 _endLazyDPSEvaluation();
8240 else if (shCount >= (size * 8))
8242 _startLazyDPSEvaluation();
8245 aopPut (AOP (result), zero, size);
8247 _endLazyDPSEvaluation();
8254 genlshOne (result, left, shCount);
8258 genlshTwo (result, left, shCount);
8262 genlshFour (result, left, shCount);
8266 fprintf(stderr, "*** ack! mystery literal shift!\n");
8270 freeAsmop (left, NULL, ic, TRUE);
8271 freeAsmop (result, NULL, ic, TRUE);
8276 /*-----------------------------------------------------------------*/
8277 /* genLeftShift - generates code for left shifting */
8278 /*-----------------------------------------------------------------*/
8280 genLeftShift (iCode * ic)
8282 operand *left, *right, *result;
8285 symbol *tlbl, *tlbl1;
8287 D (emitcode (";", "genLeftShift "););
8289 right = IC_RIGHT (ic);
8290 left = IC_LEFT (ic);
8291 result = IC_RESULT (ic);
8293 aopOp (right, ic, FALSE, FALSE);
8296 #ifdef BETTER_LITERAL_SHIFT
8297 /* if the shift count is known then do it
8298 as efficiently as possible */
8299 if (AOP_TYPE (right) == AOP_LIT)
8301 if (genLeftShiftLiteral (left, right, result, ic))
8308 /* shift count is unknown then we have to form
8309 a loop get the loop count in B : Note: we take
8310 only the lower order byte since shifting
8311 more that 32 bits make no sense anyway, ( the
8312 largest size of an object can be only 32 bits ) */
8314 if (AOP_TYPE (right) == AOP_LIT)
8316 /* Really should be handled by genLeftShiftLiteral,
8317 * but since I'm too lazy to fix that today, at least we can make
8318 * some small improvement.
8320 emitcode("mov", "b,#!constbyte",
8321 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8325 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8326 emitcode ("inc", "b");
8328 freeAsmop (right, NULL, ic, TRUE);
8329 aopOp (left, ic, FALSE, FALSE);
8330 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8332 /* now move the left to the result if they are not the
8334 if (!sameRegs (AOP (left), AOP (result)) &&
8335 AOP_SIZE (result) > 1)
8338 size = AOP_SIZE (result);
8340 _startLazyDPSEvaluation ();
8343 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8344 if (*l == '@' && (IS_AOP_PREG (result)))
8347 emitcode ("mov", "a,%s", l);
8348 aopPut (AOP (result), "a", offset);
8351 aopPut (AOP (result), l, offset);
8354 _endLazyDPSEvaluation ();
8357 tlbl = newiTempLabel (NULL);
8358 size = AOP_SIZE (result);
8360 tlbl1 = newiTempLabel (NULL);
8362 /* if it is only one byte then */
8365 symbol *tlbl1 = newiTempLabel (NULL);
8367 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8368 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8369 emitcode ("", "!tlabeldef", tlbl->key + 100);
8370 emitcode ("add", "a,acc");
8371 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8372 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8373 aopPut (AOP (result), "a", 0);
8377 reAdjustPreg (AOP (result));
8379 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8380 emitcode ("", "!tlabeldef", tlbl->key + 100);
8381 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8382 emitcode ("add", "a,acc");
8383 aopPut (AOP (result), "a", offset++);
8384 _startLazyDPSEvaluation ();
8387 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8388 emitcode ("rlc", "a");
8389 aopPut (AOP (result), "a", offset++);
8391 _endLazyDPSEvaluation ();
8392 reAdjustPreg (AOP (result));
8394 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8395 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8397 freeAsmop (left, NULL, ic, TRUE);
8398 freeAsmop (result, NULL, ic, TRUE);
8401 #ifdef BETTER_LITERAL_SHIFT
8402 /*-----------------------------------------------------------------*/
8403 /* genrshOne - right shift a one byte quantity by known count */
8404 /*-----------------------------------------------------------------*/
8406 genrshOne (operand * result, operand * left,
8407 int shCount, int sign)
8409 D (emitcode (";", "genrshOne"););
8410 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8414 #ifdef BETTER_LITERAL_SHIFT
8415 /*-----------------------------------------------------------------*/
8416 /* genrshTwo - right shift two bytes by known amount != 0 */
8417 /*-----------------------------------------------------------------*/
8419 genrshTwo (operand * result, operand * left,
8420 int shCount, int sign)
8422 D (emitcode (";", "genrshTwo"););
8424 /* if shCount >= 8 */
8428 _startLazyDPSEvaluation();
8431 shiftR1Left2Result (left, MSB16, result, LSB,
8436 movLeft2Result (left, MSB16, result, LSB, sign);
8438 addSign (result, MSB16, sign);
8439 _endLazyDPSEvaluation();
8442 /* 1 <= shCount <= 7 */
8445 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8452 /*-----------------------------------------------------------------*/
8453 /* shiftRLong - shift right one long from left to result */
8454 /* offl = LSB or MSB16 */
8455 /*-----------------------------------------------------------------*/
8457 shiftRLong (operand * left, int offl,
8458 operand * result, int sign)
8460 int isSameRegs=sameRegs(AOP(left),AOP(result));
8462 if (isSameRegs && offl>1) {
8463 // we are in big trouble, but this shouldn't happen
8464 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8467 MOVA (aopGet (AOP (left), MSB32, FALSE, NULL));
8472 emitcode ("rlc", "a");
8473 emitcode ("subb", "a,acc");
8474 emitcode ("xch", "a,%s",
8475 aopGet(AOP(left), MSB32, FALSE, DP2_RESULT_REG));
8477 aopPut (AOP(result), zero, MSB32);
8482 emitcode ("clr", "c");
8484 emitcode ("mov", "c,acc.7");
8487 emitcode ("rrc", "a");
8489 if (isSameRegs && offl==MSB16) {
8491 "a,%s",aopGet (AOP (left), MSB24, FALSE, DP2_RESULT_REG));
8493 aopPut (AOP (result), "a", MSB32);
8494 MOVA (aopGet (AOP (left), MSB24, FALSE, NULL));
8497 emitcode ("rrc", "a");
8498 if (isSameRegs && offl==1) {
8499 emitcode ("xch", "a,%s",
8500 aopGet (AOP (left), MSB16, FALSE, DP2_RESULT_REG));
8502 aopPut (AOP (result), "a", MSB24);
8503 MOVA (aopGet (AOP (left), MSB16, FALSE, NULL));
8505 emitcode ("rrc", "a");
8506 aopPut (AOP (result), "a", MSB16 - offl);
8510 MOVA (aopGet (AOP (left), LSB, FALSE, NULL));
8511 emitcode ("rrc", "a");
8512 aopPut (AOP (result), "a", LSB);
8519 /*-----------------------------------------------------------------*/
8520 /* genrshFour - shift four byte by a known amount != 0 */
8521 /*-----------------------------------------------------------------*/
8523 genrshFour (operand * result, operand * left,
8524 int shCount, int sign)
8526 D (emitcode (";", "genrshFour");
8529 /* if shifting more that 3 bytes */
8534 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8536 movLeft2Result (left, MSB32, result, LSB, sign);
8537 addSign (result, MSB16, sign);
8539 else if (shCount >= 16)
8543 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8546 movLeft2Result (left, MSB24, result, LSB, 0);
8547 movLeft2Result (left, MSB32, result, MSB16, sign);
8549 addSign (result, MSB24, sign);
8551 else if (shCount >= 8)
8555 shiftRLong (left, MSB16, result, sign);
8556 else if (shCount == 0)
8558 movLeft2Result (left, MSB16, result, LSB, 0);
8559 movLeft2Result (left, MSB24, result, MSB16, 0);
8560 movLeft2Result (left, MSB32, result, MSB24, sign);
8561 addSign (result, MSB32, sign);
8565 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8566 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8567 /* the last shift is signed */
8568 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8569 addSign (result, MSB32, sign);
8573 { /* 1 <= shCount <= 7 */
8576 shiftRLong (left, LSB, result, sign);
8578 shiftRLong (result, LSB, result, sign);
8582 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8583 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8584 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8590 #ifdef BETTER_LITERAL_SHIFT
8591 /*-----------------------------------------------------------------*/
8592 /* genRightShiftLiteral - right shifting by known count */
8593 /*-----------------------------------------------------------------*/
8595 genRightShiftLiteral (operand * left,
8601 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8604 size = getSize (operandType (result));
8606 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8608 /* We only handle certain easy cases so far. */
8610 && (shCount < (size * 8))
8614 D(emitcode (";", "genRightShiftLiteral wimping out"););
8618 freeAsmop (right, NULL, ic, TRUE);
8620 aopOp (left, ic, FALSE, FALSE);
8621 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8624 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8628 /* test the LEFT size !!! */
8630 /* I suppose that the left size >= result size */
8633 size = getDataSize (result);
8634 _startLazyDPSEvaluation();
8637 movLeft2Result (left, size, result, size, 0);
8639 _endLazyDPSEvaluation();
8641 else if (shCount >= (size * 8))
8645 /* get sign in acc.7 */
8646 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
8648 addSign (result, LSB, sign);
8655 genrshOne (result, left, shCount, sign);
8659 genrshTwo (result, left, shCount, sign);
8663 genrshFour (result, left, shCount, sign);
8670 freeAsmop (left, NULL, ic, TRUE);
8671 freeAsmop (result, NULL, ic, TRUE);
8677 /*-----------------------------------------------------------------*/
8678 /* genSignedRightShift - right shift of signed number */
8679 /*-----------------------------------------------------------------*/
8681 genSignedRightShift (iCode * ic)
8683 operand *right, *left, *result;
8686 symbol *tlbl, *tlbl1;
8688 D (emitcode (";", "genSignedRightShift "););
8690 /* we do it the hard way put the shift count in b
8691 and loop thru preserving the sign */
8693 right = IC_RIGHT (ic);
8694 left = IC_LEFT (ic);
8695 result = IC_RESULT (ic);
8697 aopOp (right, ic, FALSE, FALSE);
8699 #ifdef BETTER_LITERAL_SHIFT
8700 if (AOP_TYPE (right) == AOP_LIT)
8702 if (genRightShiftLiteral (left, right, result, ic, 1))
8708 /* shift count is unknown then we have to form
8709 a loop get the loop count in B : Note: we take
8710 only the lower order byte since shifting
8711 more that 32 bits make no sense anyway, ( the
8712 largest size of an object can be only 32 bits ) */
8714 if (AOP_TYPE (right) == AOP_LIT)
8716 /* Really should be handled by genRightShiftLiteral,
8717 * but since I'm too lazy to fix that today, at least we can make
8718 * some small improvement.
8720 emitcode("mov", "b,#!constbyte",
8721 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8725 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8726 emitcode ("inc", "b");
8728 freeAsmop (right, NULL, ic, TRUE);
8729 aopOp (left, ic, FALSE, FALSE);
8730 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8732 /* now move the left to the result if they are not the
8734 if (!sameRegs (AOP (left), AOP (result)) &&
8735 AOP_SIZE (result) > 1)
8738 size = AOP_SIZE (result);
8740 _startLazyDPSEvaluation ();
8743 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8744 if (*l == '@' && IS_AOP_PREG (result))
8747 emitcode ("mov", "a,%s", l);
8748 aopPut (AOP (result), "a", offset);
8751 aopPut (AOP (result), l, offset);
8754 _endLazyDPSEvaluation ();
8757 /* mov the highest order bit to OVR */
8758 tlbl = newiTempLabel (NULL);
8759 tlbl1 = newiTempLabel (NULL);
8761 size = AOP_SIZE (result);
8763 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
8764 emitcode ("rlc", "a");
8765 emitcode ("mov", "ov,c");
8766 /* if it is only one byte then */
8769 MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8770 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8771 emitcode ("", "!tlabeldef", tlbl->key + 100);
8772 emitcode ("mov", "c,ov");
8773 emitcode ("rrc", "a");
8774 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8775 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8776 aopPut (AOP (result), "a", 0);
8780 reAdjustPreg (AOP (result));
8781 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8782 emitcode ("", "!tlabeldef", tlbl->key + 100);
8783 emitcode ("mov", "c,ov");
8784 _startLazyDPSEvaluation ();
8787 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8788 emitcode ("rrc", "a");
8789 aopPut (AOP (result), "a", offset--);
8791 _endLazyDPSEvaluation ();
8792 reAdjustPreg (AOP (result));
8793 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8794 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8797 freeAsmop (left, NULL, ic, TRUE);
8798 freeAsmop (result, NULL, ic, TRUE);
8801 /*-----------------------------------------------------------------*/
8802 /* genRightShift - generate code for right shifting */
8803 /*-----------------------------------------------------------------*/
8805 genRightShift (iCode * ic)
8807 operand *right, *left, *result;
8811 symbol *tlbl, *tlbl1;
8813 D (emitcode (";", "genRightShift "););
8815 /* if signed then we do it the hard way preserve the
8816 sign bit moving it inwards */
8817 retype = getSpec (operandType (IC_RESULT (ic)));
8819 if (!SPEC_USIGN (retype))
8821 genSignedRightShift (ic);
8825 /* signed & unsigned types are treated the same : i.e. the
8826 signed is NOT propagated inwards : quoting from the
8827 ANSI - standard : "for E1 >> E2, is equivalent to division
8828 by 2**E2 if unsigned or if it has a non-negative value,
8829 otherwise the result is implementation defined ", MY definition
8830 is that the sign does not get propagated */
8832 right = IC_RIGHT (ic);
8833 left = IC_LEFT (ic);
8834 result = IC_RESULT (ic);
8836 aopOp (right, ic, FALSE, FALSE);
8838 #ifdef BETTER_LITERAL_SHIFT
8839 /* if the shift count is known then do it
8840 as efficiently as possible */
8841 if (AOP_TYPE (right) == AOP_LIT)
8843 if (genRightShiftLiteral (left, right, result, ic, 0))
8850 /* shift count is unknown then we have to form
8851 a loop get the loop count in B : Note: we take
8852 only the lower order byte since shifting
8853 more that 32 bits make no sense anyway, ( the
8854 largest size of an object can be only 32 bits ) */
8856 if (AOP_TYPE (right) == AOP_LIT)
8858 /* Really should be handled by genRightShiftLiteral,
8859 * but since I'm too lazy to fix that today, at least we can make
8860 * some small improvement.
8862 emitcode("mov", "b,#!constbyte",
8863 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8867 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8868 emitcode ("inc", "b");
8870 freeAsmop (right, NULL, ic, TRUE);
8871 aopOp (left, ic, FALSE, FALSE);
8872 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8874 /* now move the left to the result if they are not the
8876 if (!sameRegs (AOP (left), AOP (result)) &&
8877 AOP_SIZE (result) > 1)
8880 size = AOP_SIZE (result);
8882 _startLazyDPSEvaluation ();
8885 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8886 if (*l == '@' && IS_AOP_PREG (result))
8889 emitcode ("mov", "a,%s", l);
8890 aopPut (AOP (result), "a", offset);
8893 aopPut (AOP (result), l, offset);
8896 _endLazyDPSEvaluation ();
8899 tlbl = newiTempLabel (NULL);
8900 tlbl1 = newiTempLabel (NULL);
8901 size = AOP_SIZE (result);
8904 /* if it is only one byte then */
8907 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8908 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8909 emitcode ("", "!tlabeldef", tlbl->key + 100);
8911 emitcode ("rrc", "a");
8912 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8913 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8914 aopPut (AOP (result), "a", 0);
8918 reAdjustPreg (AOP (result));
8919 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8920 emitcode ("", "!tlabeldef", tlbl->key + 100);
8922 _startLazyDPSEvaluation ();
8925 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8926 emitcode ("rrc", "a");
8927 aopPut (AOP (result), "a", offset--);
8929 _endLazyDPSEvaluation ();
8930 reAdjustPreg (AOP (result));
8932 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8933 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8936 freeAsmop (left, NULL, ic, TRUE);
8937 freeAsmop (result, NULL, ic, TRUE);
8940 /*-----------------------------------------------------------------*/
8941 /* genUnpackBits - generates code for unpacking bits */
8942 /*-----------------------------------------------------------------*/
8944 genUnpackBits (operand * result, char *rname, int ptype)
8951 D (emitcode (";", "genUnpackBits "););
8953 etype = getSpec (operandType (result));
8955 /* read the first byte */
8961 emitcode ("mov", "a,@%s", rname);
8965 emitcode ("movx", "a,@%s", rname);
8969 emitcode ("movx", "a,@dptr");
8973 emitcode ("clr", "a");
8974 emitcode ("movc", "a,@a+dptr");
8978 emitcode ("lcall", "__gptrget");
8982 /* if we have bitdisplacement then it fits */
8983 /* into this byte completely or if length is */
8984 /* less than a byte */
8985 if (((shCnt = SPEC_BSTR (etype)) != 0) || (SPEC_BLEN (etype) <= 8))
8988 /* shift right acc */
8991 emitcode ("anl", "a,#!constbyte",
8992 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8993 aopPut (AOP (result), "a", offset);
8997 /* bit field did not fit in a byte */
8998 rlen = SPEC_BLEN (etype) - 8;
8999 aopPut (AOP (result), "a", offset++);
9008 emitcode ("inc", "%s", rname);
9009 emitcode ("mov", "a,@%s", rname);
9013 emitcode ("inc", "%s", rname);
9014 emitcode ("movx", "a,@%s", rname);
9018 emitcode ("inc", "dptr");
9019 emitcode ("movx", "a,@dptr");
9023 emitcode ("clr", "a");
9024 emitcode ("inc", "dptr");
9025 emitcode ("movc", "a,@a+dptr");
9029 emitcode ("inc", "dptr");
9030 emitcode ("lcall", "__gptrget");
9035 /* if we are done */
9039 aopPut (AOP (result), "a", offset++);
9045 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (rlen));
9046 aopPut (AOP (result), "a", offset);
9053 /*-----------------------------------------------------------------*/
9054 /* genDataPointerGet - generates code when ptr offset is known */
9055 /*-----------------------------------------------------------------*/
9057 genDataPointerGet (operand * left,
9063 int size, offset = 0;
9064 aopOp (result, ic, TRUE, FALSE);
9066 /* get the string representation of the name */
9067 l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9068 size = AOP_SIZE (result);
9069 _startLazyDPSEvaluation ();
9074 SNPRINTF (buff, sizeof(buff),
9075 "(%s + %d)", l + 1, offset);
9079 SNPRINTF (buff, sizeof(buff),
9082 aopPut (AOP (result), buff, offset++);
9084 _endLazyDPSEvaluation ();
9086 freeAsmop (left, NULL, ic, TRUE);
9087 freeAsmop (result, NULL, ic, TRUE);
9090 /*-----------------------------------------------------------------*/
9091 /* genNearPointerGet - emitcode for near pointer fetch */
9092 /*-----------------------------------------------------------------*/
9094 genNearPointerGet (operand * left,
9102 sym_link *rtype, *retype, *letype;
9103 sym_link *ltype = operandType (left);
9106 rtype = operandType (result);
9107 retype = getSpec (rtype);
9108 letype = getSpec (ltype);
9110 aopOp (left, ic, FALSE, FALSE);
9112 /* if left is rematerialisable and
9113 result is not bit variable type and
9114 the left is pointer to data space i.e
9115 lower 128 bytes of space */
9116 if (AOP_TYPE (left) == AOP_IMMD &&
9117 !IS_BITVAR (retype) &&
9118 !IS_BITVAR (letype) &&
9119 DCL_TYPE (ltype) == POINTER)
9121 genDataPointerGet (left, result, ic);
9125 /* if the value is already in a pointer register
9126 then don't need anything more */
9127 if (!AOP_INPREG (AOP (left)))
9129 /* otherwise get a free pointer register */
9131 preg = getFreePtr (ic, &aop, FALSE);
9132 emitcode ("mov", "%s,%s",
9134 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9138 rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9140 freeAsmop (left, NULL, ic, TRUE);
9141 aopOp (result, ic, FALSE, FALSE);
9143 /* if bitfield then unpack the bits */
9144 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9145 genUnpackBits (result, rname, POINTER);
9148 /* we have can just get the values */
9149 int size = AOP_SIZE (result);
9154 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9157 emitcode ("mov", "a,@%s", rname);
9158 aopPut (AOP (result), "a", offset);
9162 SNPRINTF (buff, sizeof(buff), "@%s", rname);
9163 aopPut (AOP (result), buff, offset);
9168 emitcode ("inc", "%s", rname);
9173 /* now some housekeeping stuff */
9176 /* we had to allocate for this iCode */
9177 if (pi) { /* post increment present */
9178 aopPut(AOP ( left ),rname,0);
9180 freeAsmop (NULL, aop, ic, TRUE);
9184 /* we did not allocate which means left
9185 already in a pointer register, then
9186 if size > 0 && this could be used again
9187 we have to point it back to where it
9189 if (AOP_SIZE (result) > 1 &&
9190 !OP_SYMBOL (left)->remat &&
9191 (OP_SYMBOL (left)->liveTo > ic->seq ||
9195 int size = AOP_SIZE (result) - 1;
9197 emitcode ("dec", "%s", rname);
9202 freeAsmop (result, NULL, ic, TRUE);
9203 if (pi) pi->generated = 1;
9206 /*-----------------------------------------------------------------*/
9207 /* genPagedPointerGet - emitcode for paged pointer fetch */
9208 /*-----------------------------------------------------------------*/
9210 genPagedPointerGet (operand * left,
9218 sym_link *rtype, *retype, *letype;
9220 rtype = operandType (result);
9221 retype = getSpec (rtype);
9222 letype = getSpec (operandType (left));
9223 aopOp (left, ic, FALSE, FALSE);
9225 /* if the value is already in a pointer register
9226 then don't need anything more */
9227 if (!AOP_INPREG (AOP (left)))
9229 /* otherwise get a free pointer register */
9231 preg = getFreePtr (ic, &aop, FALSE);
9232 emitcode ("mov", "%s,%s",
9234 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9238 rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9240 freeAsmop (left, NULL, ic, TRUE);
9241 aopOp (result, ic, FALSE, FALSE);
9243 /* if bitfield then unpack the bits */
9244 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9245 genUnpackBits (result, rname, PPOINTER);
9248 /* we have can just get the values */
9249 int size = AOP_SIZE (result);
9255 emitcode ("movx", "a,@%s", rname);
9256 aopPut (AOP (result), "a", offset);
9261 emitcode ("inc", "%s", rname);
9265 /* now some housekeeping stuff */
9268 /* we had to allocate for this iCode */
9269 if (pi) aopPut ( AOP (left), rname, 0);
9270 freeAsmop (NULL, aop, ic, TRUE);
9274 /* we did not allocate which means left
9275 already in a pointer register, then
9276 if size > 0 && this could be used again
9277 we have to point it back to where it
9279 if (AOP_SIZE (result) > 1 &&
9280 !OP_SYMBOL (left)->remat &&
9281 (OP_SYMBOL (left)->liveTo > ic->seq ||
9285 int size = AOP_SIZE (result) - 1;
9287 emitcode ("dec", "%s", rname);
9292 freeAsmop (result, NULL, ic, TRUE);
9293 if (pi) pi->generated = 1;
9296 /*-----------------------------------------------------------------*/
9297 /* genFarPointerGet - gget value from far space */
9298 /*-----------------------------------------------------------------*/
9300 genFarPointerGet (operand * left,
9301 operand * result, iCode * ic, iCode *pi)
9303 int size, offset, dopi=1;
9304 sym_link *retype = getSpec (operandType (result));
9305 sym_link *letype = getSpec (operandType (left));
9306 D (emitcode (";", "genFarPointerGet"););
9308 aopOp (left, ic, FALSE, FALSE);
9310 /* if the operand is already in dptr
9311 then we do nothing else we move the value to dptr */
9312 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9314 /* if this is remateriazable */
9315 if (AOP_TYPE (left) == AOP_IMMD)
9317 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9321 /* we need to get it byte by byte */
9322 _startLazyDPSEvaluation ();
9323 if (AOP_TYPE (left) != AOP_DPTR)
9325 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9326 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9327 if (options.model == MODEL_FLAT24)
9328 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9332 /* We need to generate a load to DPTR indirect through DPTR. */
9333 D (emitcode (";", "genFarPointerGet -- indirection special case."););
9334 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9335 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9336 if (options.model == MODEL_FLAT24)
9337 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9338 emitcode ("pop", "dph");
9339 emitcode ("pop", "dpl");
9342 _endLazyDPSEvaluation ();
9345 /* so dptr know contains the address */
9346 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9348 /* if bit then unpack */
9349 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9350 if (AOP_INDPTRn(left)) {
9351 genSetDPTR(AOP(left)->aopu.dptr);
9353 genUnpackBits (result, "dptr", FPOINTER);
9354 if (AOP_INDPTRn(left)) {
9359 size = AOP_SIZE (result);
9362 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9364 genSetDPTR(AOP(left)->aopu.dptr);
9365 emitcode ("movx", "a,@dptr");
9366 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9367 emitcode ("inc", "dptr");
9369 aopPut (AOP (result), "a", offset++);
9372 _startLazyDPSEvaluation ();
9374 if (AOP_INDPTRn(left)) {
9375 genSetDPTR(AOP(left)->aopu.dptr);
9381 emitcode ("movx", "a,@dptr");
9382 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9383 emitcode ("inc", "dptr");
9385 aopPut (AOP (result), "a", offset++);
9387 _endLazyDPSEvaluation ();
9390 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9391 if (!AOP_INDPTRn(left)) {
9392 _startLazyDPSEvaluation ();
9393 aopPut ( AOP (left), "dpl", 0);
9394 aopPut ( AOP (left), "dph", 1);
9395 if (options.model == MODEL_FLAT24)
9396 aopPut ( AOP (left), "dpx", 2);
9397 _endLazyDPSEvaluation ();
9400 } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) &&
9401 AOP_SIZE(result) > 1 &&
9403 (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
9405 size = AOP_SIZE (result) - 1;
9406 if (AOP_INDPTRn(left)) {
9407 genSetDPTR(AOP(left)->aopu.dptr);
9409 while (size--) emitcode ("lcall","__decdptr");
9410 if (AOP_INDPTRn(left)) {
9415 freeAsmop (left, NULL, ic, TRUE);
9416 freeAsmop (result, NULL, ic, TRUE);
9419 /*-----------------------------------------------------------------*/
9420 /* genCodePointerGet - get value from code space */
9421 /*-----------------------------------------------------------------*/
9423 genCodePointerGet (operand * left,
9424 operand * result, iCode * ic, iCode *pi)
9426 int size, offset, dopi=1;
9427 sym_link *retype = getSpec (operandType (result));
9429 aopOp (left, ic, FALSE, FALSE);
9431 /* if the operand is already in dptr
9432 then we do nothing else we move the value to dptr */
9433 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
9435 /* if this is remateriazable */
9436 if (AOP_TYPE (left) == AOP_IMMD)
9438 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9441 { /* we need to get it byte by byte */
9442 _startLazyDPSEvaluation ();
9443 if (AOP_TYPE (left) != AOP_DPTR)
9445 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9446 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9447 if (options.model == MODEL_FLAT24)
9448 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9452 /* We need to generate a load to DPTR indirect through DPTR. */
9453 D (emitcode (";", "gencodePointerGet -- indirection special case."););
9454 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9455 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9456 if (options.model == MODEL_FLAT24)
9457 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9458 emitcode ("pop", "dph");
9459 emitcode ("pop", "dpl");
9462 _endLazyDPSEvaluation ();
9465 /* so dptr know contains the address */
9466 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9468 /* if bit then unpack */
9469 if (IS_BITVAR (retype)) {
9470 if (AOP_INDPTRn(left)) {
9471 genSetDPTR(AOP(left)->aopu.dptr);
9473 genUnpackBits (result, "dptr", CPOINTER);
9474 if (AOP_INDPTRn(left)) {
9479 size = AOP_SIZE (result);
9481 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9483 genSetDPTR(AOP(left)->aopu.dptr);
9484 emitcode ("clr", "a");
9485 emitcode ("movc", "a,@a+dptr");
9486 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9487 emitcode ("inc", "dptr");
9489 aopPut (AOP (result), "a", offset++);
9492 _startLazyDPSEvaluation ();
9495 if (AOP_INDPTRn(left)) {
9496 genSetDPTR(AOP(left)->aopu.dptr);
9502 emitcode ("clr", "a");
9503 emitcode ("movc", "a,@a+dptr");
9504 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9505 emitcode ("inc", "dptr");
9506 aopPut (AOP (result), "a", offset++);
9508 _endLazyDPSEvaluation ();
9511 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9512 if (!AOP_INDPTRn(left)) {
9513 _startLazyDPSEvaluation ();
9515 aopPut ( AOP (left), "dpl", 0);
9516 aopPut ( AOP (left), "dph", 1);
9517 if (options.model == MODEL_FLAT24)
9518 aopPut ( AOP (left), "dpx", 2);
9520 _endLazyDPSEvaluation ();
9523 } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
9524 AOP_SIZE(result) > 1 &&
9525 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9527 size = AOP_SIZE (result) - 1;
9528 if (AOP_INDPTRn(left)) {
9529 genSetDPTR(AOP(left)->aopu.dptr);
9531 while (size--) emitcode ("lcall","__decdptr");
9532 if (AOP_INDPTRn(left)) {
9537 freeAsmop (left, NULL, ic, TRUE);
9538 freeAsmop (result, NULL, ic, TRUE);
9541 /*-----------------------------------------------------------------*/
9542 /* genGenPointerGet - gget value from generic pointer space */
9543 /*-----------------------------------------------------------------*/
9545 genGenPointerGet (operand * left,
9546 operand * result, iCode * ic, iCode * pi)
9549 sym_link *retype = getSpec (operandType (result));
9550 sym_link *letype = getSpec (operandType (left));
9552 D (emitcode (";", "genGenPointerGet "); );
9554 aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
9556 /* if the operand is already in dptr
9557 then we do nothing else we move the value to dptr */
9558 if (AOP_TYPE (left) != AOP_STR)
9560 /* if this is remateriazable */
9561 if (AOP_TYPE (left) == AOP_IMMD)
9563 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9564 if (AOP(left)->aopu.aop_immd.from_cast_remat)
9566 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
9570 emitcode ("mov", "b,#%d", pointerCode (retype));
9574 { /* we need to get it byte by byte */
9575 _startLazyDPSEvaluation ();
9576 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
9577 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
9578 if (options.model == MODEL_FLAT24) {
9579 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9580 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
9582 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9584 _endLazyDPSEvaluation ();
9588 /* so dptr-b now contains the address */
9590 aopOp (result, ic, FALSE, TRUE);
9593 /* if bit then unpack */
9594 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9596 genUnpackBits (result, "dptr", GPOINTER);
9600 size = AOP_SIZE (result);
9607 // Get two bytes at a time, results in _AP & A.
9608 // dptr will be incremented ONCE by __gptrgetWord.
9610 // Note: any change here must be coordinated
9611 // with the implementation of __gptrgetWord
9612 // in device/lib/_gptrget.c
9613 emitcode ("lcall", "__gptrgetWord");
9614 aopPut (AOP (result), DP2_RESULT_REG, offset++);
9615 aopPut (AOP (result), "a", offset++);
9620 // Only one byte to get.
9621 emitcode ("lcall", "__gptrget");
9622 aopPut (AOP (result), "a", offset++);
9625 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9627 emitcode ("inc", "dptr");
9632 if (pi && AOP_TYPE (left) != AOP_IMMD) {
9633 _startLazyDPSEvaluation ();
9635 aopPut ( AOP (left), "dpl", 0);
9636 aopPut ( AOP (left), "dph", 1);
9637 if (options.model == MODEL_FLAT24) {
9638 aopPut ( AOP (left), "dpx", 2);
9639 aopPut ( AOP (left), "b", 3);
9640 } else aopPut ( AOP (left), "b", 2);
9642 _endLazyDPSEvaluation ();
9645 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9646 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9648 size = AOP_SIZE (result) - 1;
9649 while (size--) emitcode ("lcall","__decdptr");
9652 freeAsmop (left, NULL, ic, TRUE);
9653 freeAsmop (result, NULL, ic, TRUE);
9656 /*-----------------------------------------------------------------*/
9657 /* genPointerGet - generate code for pointer get */
9658 /*-----------------------------------------------------------------*/
9660 genPointerGet (iCode * ic, iCode *pi)
9662 operand *left, *result;
9663 sym_link *type, *etype;
9666 D (emitcode (";", "genPointerGet ");
9669 left = IC_LEFT (ic);
9670 result = IC_RESULT (ic);
9672 /* depending on the type of pointer we need to
9673 move it to the correct pointer register */
9674 type = operandType (left);
9675 etype = getSpec (type);
9676 /* if left is of type of pointer then it is simple */
9677 if (IS_PTR (type) && !IS_FUNC (type->next))
9678 p_type = DCL_TYPE (type);
9681 /* we have to go by the storage class */
9682 p_type = PTR_TYPE (SPEC_OCLS (etype));
9684 /* special case when cast remat */
9685 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9686 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9687 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9688 type = operandType (left);
9689 p_type = DCL_TYPE (type);
9691 /* now that we have the pointer type we assign
9692 the pointer values */
9698 genNearPointerGet (left, result, ic, pi);
9702 genPagedPointerGet (left, result, ic, pi);
9706 genFarPointerGet (left, result, ic, pi);
9710 genCodePointerGet (left, result, ic, pi);
9714 genGenPointerGet (left, result, ic, pi);
9720 /*-----------------------------------------------------------------*/
9721 /* genPackBits - generates code for packed bit storage */
9722 /*-----------------------------------------------------------------*/
9724 genPackBits (sym_link * etype,
9726 char *rname, int p_type)
9733 blen = SPEC_BLEN (etype);
9734 bstr = SPEC_BSTR (etype);
9736 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9738 /* if the bit lenth is less than or */
9739 /* it exactly fits a byte then */
9740 if (SPEC_BLEN (etype) <= 8)
9742 /* shift left acc */
9743 AccLsh (SPEC_BSTR (etype));
9745 if (SPEC_BLEN (etype) < 8)
9746 { /* if smaller than a byte */
9752 emitcode ("mov", "b,a");
9753 emitcode ("mov", "a,@%s", rname);
9757 emitcode ("mov", "b,a");
9758 emitcode ("movx", "a,@dptr");
9762 emitcode ("push", "b");
9763 emitcode ("push", "acc");
9764 emitcode ("lcall", "__gptrget");
9765 emitcode ("pop", "b");
9769 emitcode ("anl", "a,#!constbyte", (unsigned char)
9770 ((unsigned char) (0xFF << (blen + bstr)) |
9771 (unsigned char) (0xFF >> (8 - bstr))));
9772 emitcode ("orl", "a,b");
9773 if (p_type == GPOINTER)
9774 emitcode ("pop", "b");
9781 emitcode ("mov", "@%s,a", rname);
9785 emitcode ("movx", "@dptr,a");
9789 emitcode ("lcall", "__gptrput");
9794 if (SPEC_BLEN (etype) <= 8)
9797 emitcode ("inc", "%s", rname);
9798 rLen = SPEC_BLEN (etype);
9800 /* now generate for lengths greater than one byte */
9804 l = aopGet (AOP (right), offset++, FALSE, TRUE, NULL);
9816 emitcode ("mov", "@%s,a", rname);
9819 emitcode ("mov", "@%s,%s", rname, l);
9824 emitcode ("movx", "@dptr,a");
9829 emitcode ("lcall", "__gptrput");
9832 emitcode ("inc", "%s", rname);
9837 /* last last was not complete */
9840 /* save the byte & read byte */
9844 emitcode ("mov", "b,a");
9845 emitcode ("mov", "a,@%s", rname);
9849 emitcode ("mov", "b,a");
9850 emitcode ("movx", "a,@dptr");
9854 emitcode ("push", "b");
9855 emitcode ("push", "acc");
9856 emitcode ("lcall", "__gptrget");
9857 emitcode ("pop", "b");
9861 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1 << rLen));
9862 emitcode ("orl", "a,b");
9865 if (p_type == GPOINTER)
9866 emitcode ("pop", "b");
9872 emitcode ("mov", "@%s,a", rname);
9876 emitcode ("movx", "@dptr,a");
9880 emitcode ("lcall", "__gptrput");
9884 /*-----------------------------------------------------------------*/
9885 /* genDataPointerSet - remat pointer to data space */
9886 /*-----------------------------------------------------------------*/
9888 genDataPointerSet (operand * right,
9892 int size, offset = 0;
9895 aopOp (right, ic, FALSE, FALSE);
9897 l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
9898 size = AOP_SIZE (right);
9903 SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
9907 SNPRINTF (buff, sizeof(buff), "%s", l + 1);
9910 emitcode ("mov", "%s,%s", buff,
9911 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9914 freeAsmop (right, NULL, ic, TRUE);
9915 freeAsmop (result, NULL, ic, TRUE);
9918 /*-----------------------------------------------------------------*/
9919 /* genNearPointerSet - emitcode for near pointer put */
9920 /*-----------------------------------------------------------------*/
9922 genNearPointerSet (operand * right,
9929 sym_link *retype, *letype;
9930 sym_link *ptype = operandType (result);
9932 retype = getSpec (operandType (right));
9933 letype = getSpec (ptype);
9935 aopOp (result, ic, FALSE, FALSE);
9937 /* if the result is rematerializable &
9938 in data space & not a bit variable */
9939 if (AOP_TYPE (result) == AOP_IMMD &&
9940 DCL_TYPE (ptype) == POINTER &&
9941 !IS_BITVAR (retype) &&
9942 !IS_BITVAR (letype))
9944 genDataPointerSet (right, result, ic);
9948 /* if the value is already in a pointer register
9949 then don't need anything more */
9950 if (!AOP_INPREG (AOP (result)))
9952 /* otherwise get a free pointer register */
9956 preg = getFreePtr (ic, &aop, FALSE);
9957 emitcode ("mov", "%s,%s",
9959 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
9963 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
9965 aopOp (right, ic, FALSE, FALSE);
9967 /* if bitfield then unpack the bits */
9968 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9969 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9972 /* we have can just get the values */
9973 int size = AOP_SIZE (right);
9978 l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
9982 emitcode ("mov", "@%s,a", rname);
9985 emitcode ("mov", "@%s,%s", rname, l);
9987 emitcode ("inc", "%s", rname);
9992 /* now some housekeeping stuff */
9995 /* we had to allocate for this iCode */
9996 if (pi) aopPut (AOP (result),rname,0);
9997 freeAsmop (NULL, aop, ic, TRUE);
10001 /* we did not allocate which means left
10002 already in a pointer register, then
10003 if size > 0 && this could be used again
10004 we have to point it back to where it
10006 if (AOP_SIZE (right) > 1 &&
10007 !OP_SYMBOL (result)->remat &&
10008 (OP_SYMBOL (result)->liveTo > ic->seq ||
10012 int size = AOP_SIZE (right) - 1;
10014 emitcode ("dec", "%s", rname);
10019 if (pi) pi->generated = 1;
10020 freeAsmop (result, NULL, ic, TRUE);
10021 freeAsmop (right, NULL, ic, TRUE);
10026 /*-----------------------------------------------------------------*/
10027 /* genPagedPointerSet - emitcode for Paged pointer put */
10028 /*-----------------------------------------------------------------*/
10030 genPagedPointerSet (operand * right,
10037 sym_link *retype, *letype;
10039 retype = getSpec (operandType (right));
10040 letype = getSpec (operandType (result));
10042 aopOp (result, ic, FALSE, FALSE);
10044 /* if the value is already in a pointer register
10045 then don't need anything more */
10046 if (!AOP_INPREG (AOP (result)))
10048 /* otherwise get a free pointer register */
10051 aop = newAsmop (0);
10052 preg = getFreePtr (ic, &aop, FALSE);
10053 emitcode ("mov", "%s,%s",
10055 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10056 rname = preg->name;
10059 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10061 aopOp (right, ic, FALSE, FALSE);
10063 /* if bitfield then unpack the bits */
10064 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10065 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
10068 /* we have can just get the values */
10069 int size = AOP_SIZE (right);
10074 MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10076 emitcode ("movx", "@%s,a", rname);
10079 emitcode ("inc", "%s", rname);
10085 /* now some housekeeping stuff */
10088 if (pi) aopPut (AOP (result),rname,0);
10089 /* we had to allocate for this iCode */
10090 freeAsmop (NULL, aop, ic, TRUE);
10094 /* we did not allocate which means left
10095 already in a pointer register, then
10096 if size > 0 && this could be used again
10097 we have to point it back to where it
10099 if (AOP_SIZE (right) > 1 &&
10100 !OP_SYMBOL (result)->remat &&
10101 (OP_SYMBOL (result)->liveTo > ic->seq ||
10105 int size = AOP_SIZE (right) - 1;
10107 emitcode ("dec", "%s", rname);
10112 if (pi) pi->generated = 1;
10113 freeAsmop (result, NULL, ic, TRUE);
10114 freeAsmop (right, NULL, ic, TRUE);
10119 /*-----------------------------------------------------------------*/
10120 /* genFarPointerSet - set value from far space */
10121 /*-----------------------------------------------------------------*/
10123 genFarPointerSet (operand * right,
10124 operand * result, iCode * ic, iCode *pi)
10126 int size, offset, dopi=1;
10127 sym_link *retype = getSpec (operandType (right));
10128 sym_link *letype = getSpec (operandType (result));
10130 aopOp (result, ic, FALSE, FALSE);
10132 /* if the operand is already in dptr
10133 then we do nothing else we move the value to dptr */
10134 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10136 /* if this is remateriazable */
10137 if (AOP_TYPE (result) == AOP_IMMD)
10138 emitcode ("mov", "dptr,%s",
10139 aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10142 /* we need to get it byte by byte */
10143 _startLazyDPSEvaluation ();
10144 if (AOP_TYPE (result) != AOP_DPTR)
10146 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10147 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10148 if (options.model == MODEL_FLAT24)
10149 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10153 /* We need to generate a load to DPTR indirect through DPTR. */
10154 D (emitcode (";", "genFarPointerSet -- indirection special case."););
10156 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10157 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10158 if (options.model == MODEL_FLAT24)
10159 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10160 emitcode ("pop", "dph");
10161 emitcode ("pop", "dpl");
10164 _endLazyDPSEvaluation ();
10167 /* so dptr know contains the address */
10168 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10170 /* if bit then unpack */
10171 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
10172 if (AOP_INDPTRn(result)) {
10173 genSetDPTR(AOP(result)->aopu.dptr);
10175 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
10176 if (AOP_INDPTRn(result)) {
10180 size = AOP_SIZE (right);
10182 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10184 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10186 genSetDPTR(AOP(result)->aopu.dptr);
10187 emitcode ("movx", "@dptr,a");
10188 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10189 emitcode ("inc", "dptr");
10193 _startLazyDPSEvaluation ();
10195 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10197 if (AOP_INDPTRn(result)) {
10198 genSetDPTR(AOP(result)->aopu.dptr);
10204 emitcode ("movx", "@dptr,a");
10205 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10206 emitcode ("inc", "dptr");
10208 _endLazyDPSEvaluation ();
10212 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10213 if (!AOP_INDPTRn(result)) {
10214 _startLazyDPSEvaluation ();
10216 aopPut (AOP(result),"dpl",0);
10217 aopPut (AOP(result),"dph",1);
10218 if (options.model == MODEL_FLAT24)
10219 aopPut (AOP(result),"dpx",2);
10221 _endLazyDPSEvaluation ();
10224 } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
10225 AOP_SIZE(right) > 1 &&
10226 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10228 size = AOP_SIZE (right) - 1;
10229 if (AOP_INDPTRn(result)) {
10230 genSetDPTR(AOP(result)->aopu.dptr);
10232 while (size--) emitcode ("lcall","__decdptr");
10233 if (AOP_INDPTRn(result)) {
10237 freeAsmop (result, NULL, ic, TRUE);
10238 freeAsmop (right, NULL, ic, TRUE);
10241 /*-----------------------------------------------------------------*/
10242 /* genGenPointerSet - set value from generic pointer space */
10243 /*-----------------------------------------------------------------*/
10245 genGenPointerSet (operand * right,
10246 operand * result, iCode * ic, iCode *pi)
10249 sym_link *retype = getSpec (operandType (right));
10250 sym_link *letype = getSpec (operandType (result));
10252 aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10254 /* if the operand is already in dptr
10255 then we do nothing else we move the value to dptr */
10256 if (AOP_TYPE (result) != AOP_STR)
10258 _startLazyDPSEvaluation ();
10259 /* if this is remateriazable */
10260 if (AOP_TYPE (result) == AOP_IMMD)
10262 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10263 if (AOP(result)->aopu.aop_immd.from_cast_remat)
10265 MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10270 "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10274 { /* we need to get it byte by byte */
10275 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10276 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10277 if (options.model == MODEL_FLAT24) {
10278 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10279 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10281 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10284 _endLazyDPSEvaluation ();
10286 /* so dptr + b now contains the address */
10288 aopOp (right, ic, FALSE, TRUE);
10292 /* if bit then unpack */
10293 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10295 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
10299 size = AOP_SIZE (right);
10302 _startLazyDPSEvaluation ();
10307 // Set two bytes at a time, passed in _AP & A.
10308 // dptr will be incremented ONCE by __gptrputWord.
10310 // Note: any change here must be coordinated
10311 // with the implementation of __gptrputWord
10312 // in device/lib/_gptrput.c
10313 emitcode("mov", "_ap, %s",
10314 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10315 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10319 emitcode ("lcall", "__gptrputWord");
10324 // Only one byte to put.
10325 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10329 emitcode ("lcall", "__gptrput");
10332 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10334 emitcode ("inc", "dptr");
10337 _endLazyDPSEvaluation ();
10340 if (pi && AOP_TYPE (result) != AOP_IMMD) {
10341 _startLazyDPSEvaluation ();
10343 aopPut (AOP(result),"dpl",0);
10344 aopPut (AOP(result),"dph",1);
10345 if (options.model == MODEL_FLAT24) {
10346 aopPut (AOP(result),"dpx",2);
10347 aopPut (AOP(result),"b",3);
10349 aopPut (AOP(result),"b",2);
10351 _endLazyDPSEvaluation ();
10354 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10355 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10357 size = AOP_SIZE (right) - 1;
10358 while (size--) emitcode ("lcall","__decdptr");
10360 freeAsmop (result, NULL, ic, TRUE);
10361 freeAsmop (right, NULL, ic, TRUE);
10364 /*-----------------------------------------------------------------*/
10365 /* genPointerSet - stores the value into a pointer location */
10366 /*-----------------------------------------------------------------*/
10368 genPointerSet (iCode * ic, iCode *pi)
10370 operand *right, *result;
10371 sym_link *type, *etype;
10374 D (emitcode (";", "genPointerSet "););
10376 right = IC_RIGHT (ic);
10377 result = IC_RESULT (ic);
10379 /* depending on the type of pointer we need to
10380 move it to the correct pointer register */
10381 type = operandType (result);
10382 etype = getSpec (type);
10383 /* if left is of type of pointer then it is simple */
10384 if (IS_PTR (type) && !IS_FUNC (type->next))
10386 p_type = DCL_TYPE (type);
10390 /* we have to go by the storage class */
10391 p_type = PTR_TYPE (SPEC_OCLS (etype));
10393 /* special case when cast remat */
10394 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10395 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10396 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10397 type = operandType (result);
10398 p_type = DCL_TYPE (type);
10401 /* now that we have the pointer type we assign
10402 the pointer values */
10408 genNearPointerSet (right, result, ic, pi);
10412 genPagedPointerSet (right, result, ic, pi);
10416 genFarPointerSet (right, result, ic, pi);
10420 genGenPointerSet (right, result, ic, pi);
10424 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10425 "genPointerSet: illegal pointer type");
10430 /*-----------------------------------------------------------------*/
10431 /* genIfx - generate code for Ifx statement */
10432 /*-----------------------------------------------------------------*/
10434 genIfx (iCode * ic, iCode * popIc)
10436 operand *cond = IC_COND (ic);
10439 D (emitcode (";", "genIfx "););
10441 aopOp (cond, ic, FALSE, FALSE);
10443 /* get the value into acc */
10444 if (AOP_TYPE (cond) != AOP_CRY)
10453 /* the result is now in the accumulator */
10454 freeAsmop (cond, NULL, ic, TRUE);
10456 /* if there was something to be popped then do it */
10460 /* if the condition is a bit variable */
10461 if (isbit && IS_ITEMP (cond) &&
10464 genIfxJump (ic, SPIL_LOC (cond)->rname);
10466 else if (isbit && !IS_ITEMP (cond))
10468 genIfxJump (ic, OP_SYMBOL (cond)->rname);
10472 genIfxJump (ic, "a");
10478 /*-----------------------------------------------------------------*/
10479 /* genAddrOf - generates code for address of */
10480 /*-----------------------------------------------------------------*/
10482 genAddrOf (iCode * ic)
10484 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10487 D (emitcode (";", "genAddrOf ");
10490 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10492 /* if the operand is on the stack then we
10493 need to get the stack offset of this
10495 if (sym->onStack) {
10497 /* if 10 bit stack */
10498 if (options.stack10bit) {
10500 tsprintf(buff, sizeof(buff),
10501 "#!constbyte",(options.stack_loc >> 16) & 0xff);
10502 /* if it has an offset then we need to compute it */
10503 /* emitcode ("subb", "a,#!constbyte", */
10504 /* -((sym->stack < 0) ? */
10505 /* ((short) (sym->stack - _G.nRegsSaved)) : */
10506 /* ((short) sym->stack)) & 0xff); */
10507 /* emitcode ("mov","b,a"); */
10508 /* emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
10509 /* ((short) (sym->stack - _G.nRegsSaved)) : */
10510 /* ((short) sym->stack)) >> 8) & 0xff); */
10512 emitcode ("mov", "a,_bpx");
10513 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
10514 ((char) (sym->stack - _G.nRegsSaved)) :
10515 ((char) sym->stack )) & 0xff);
10516 emitcode ("mov", "b,a");
10517 emitcode ("mov", "a,_bpx+1");
10518 emitcode ("addc","a,#!constbyte", (((sym->stack < 0) ?
10519 ((short) (sym->stack - _G.nRegsSaved)) :
10520 ((short) sym->stack )) >> 8) & 0xff);
10521 aopPut (AOP (IC_RESULT (ic)), "b", 0);
10522 aopPut (AOP (IC_RESULT (ic)), "a", 1);
10523 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10525 /* we can just move _bp */
10526 aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10527 aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10528 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10531 /* if it has an offset then we need to compute it */
10533 emitcode ("mov", "a,_bp");
10534 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10535 aopPut (AOP (IC_RESULT (ic)), "a", 0);
10537 /* we can just move _bp */
10538 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10540 /* fill the result with zero */
10541 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10544 if (options.stack10bit && size < (FPTRSIZE - 1)) {
10546 "*** warning: pointer to stack var truncated.\n");
10551 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10557 /* object not on stack then we need the name */
10558 size = AOP_SIZE (IC_RESULT (ic));
10563 char s[SDCC_NAME_MAX];
10567 tsprintf(s, sizeof(s), "!his",sym->rname);
10570 tsprintf(s, sizeof(s), "!hihis",sym->rname);
10573 tsprintf(s, sizeof(s), "!hihihis",sym->rname);
10575 default: /* should not need this (just in case) */
10576 SNPRINTF (s, sizeof(s), "#(%s >> %d)",
10583 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10586 aopPut (AOP (IC_RESULT (ic)), s, offset++);
10590 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10594 /*-----------------------------------------------------------------*/
10595 /* genArrayInit - generates code for address of */
10596 /*-----------------------------------------------------------------*/
10598 genArrayInit (iCode * ic)
10600 literalList *iLoop;
10602 int elementSize = 0, eIndex;
10603 unsigned val, lastVal;
10605 operand *left=IC_LEFT(ic);
10607 D (emitcode (";", "genArrayInit "););
10609 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10611 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10613 // Load immediate value into DPTR.
10614 emitcode("mov", "dptr, %s",
10615 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
10617 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10620 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10621 "Unexpected operand to genArrayInit.\n");
10624 // a regression because of SDCCcse.c:1.52
10625 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10626 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10627 if (options.model == MODEL_FLAT24)
10628 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10632 type = operandType(IC_LEFT(ic));
10634 if (type && type->next)
10636 elementSize = getSize(type->next);
10640 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10641 "can't determine element size in genArrayInit.\n");
10645 iLoop = IC_ARRAYILIST(ic);
10650 bool firstpass = TRUE;
10652 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
10653 iLoop->count, (int)iLoop->literalValue, elementSize);
10659 symbol *tlbl = NULL;
10661 count = ix > 256 ? 256 : ix;
10665 tlbl = newiTempLabel (NULL);
10666 if (firstpass || (count & 0xff))
10668 emitcode("mov", "b, #!constbyte", count & 0xff);
10671 emitcode ("", "!tlabeldef", tlbl->key + 100);
10676 for (eIndex = 0; eIndex < elementSize; eIndex++)
10678 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10679 if (val != lastVal)
10681 emitcode("mov", "a, #!constbyte", val);
10685 emitcode("movx", "@dptr, a");
10686 emitcode("inc", "dptr");
10691 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10697 iLoop = iLoop->next;
10700 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10703 /*-----------------------------------------------------------------*/
10704 /* genFarFarAssign - assignment when both are in far space */
10705 /*-----------------------------------------------------------------*/
10707 genFarFarAssign (operand * result, operand * right, iCode * ic)
10709 int size = AOP_SIZE (right);
10711 symbol *rSym = NULL;
10715 /* quick & easy case. */
10716 D(emitcode(";","genFarFarAssign (1 byte case)"););
10717 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
10718 freeAsmop (right, NULL, ic, FALSE);
10719 /* now assign DPTR to result */
10721 aopOp(result, ic, FALSE, FALSE);
10723 aopPut(AOP(result), "a", 0);
10724 freeAsmop(result, NULL, ic, FALSE);
10728 /* See if we've got an underlying symbol to abuse. */
10729 if (IS_SYMOP(result) && OP_SYMBOL(result))
10731 if (IS_TRUE_SYMOP(result))
10733 rSym = OP_SYMBOL(result);
10735 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10737 rSym = OP_SYMBOL(result)->usl.spillLoc;
10741 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10743 /* We can use the '390 auto-toggle feature to good effect here. */
10745 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10746 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
10747 emitcode ("mov", "dptr,#%s", rSym->rname);
10748 /* DP2 = result, DP1 = right, DP1 is current. */
10751 emitcode("movx", "a,@dptr");
10752 emitcode("movx", "@dptr,a");
10755 emitcode("inc", "dptr");
10756 emitcode("inc", "dptr");
10759 emitcode("mov", "dps,#0");
10760 freeAsmop (right, NULL, ic, FALSE);
10762 some alternative code for processors without auto-toggle
10763 no time to test now, so later well put in...kpb
10764 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10765 emitcode("mov", "dps,#1"); /* Select DPTR2. */
10766 emitcode ("mov", "dptr,#%s", rSym->rname);
10767 /* DP2 = result, DP1 = right, DP1 is current. */
10771 emitcode("movx", "a,@dptr");
10773 emitcode("inc", "dptr");
10774 emitcode("inc", "dps");
10775 emitcode("movx", "@dptr,a");
10777 emitcode("inc", "dptr");
10778 emitcode("inc", "dps");
10780 emitcode("mov", "dps,#0");
10781 freeAsmop (right, NULL, ic, FALSE);
10786 D (emitcode (";", "genFarFarAssign"););
10787 aopOp (result, ic, TRUE, TRUE);
10789 _startLazyDPSEvaluation ();
10793 aopPut (AOP (result),
10794 aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
10797 _endLazyDPSEvaluation ();
10798 freeAsmop (result, NULL, ic, FALSE);
10799 freeAsmop (right, NULL, ic, FALSE);
10803 /*-----------------------------------------------------------------*/
10804 /* genAssign - generate code for assignment */
10805 /*-----------------------------------------------------------------*/
10807 genAssign (iCode * ic)
10809 operand *result, *right;
10811 unsigned long lit = 0L;
10813 D (emitcode (";", "genAssign ");
10816 result = IC_RESULT (ic);
10817 right = IC_RIGHT (ic);
10819 /* if they are the same */
10820 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10823 aopOp (right, ic, FALSE, FALSE);
10825 emitcode (";", "genAssign: resultIsFar = %s",
10826 isOperandInFarSpace (result) ?
10829 /* special case both in far space */
10830 if ((AOP_TYPE (right) == AOP_DPTR ||
10831 AOP_TYPE (right) == AOP_DPTR2) &&
10832 /* IS_TRUE_SYMOP(result) && */
10833 isOperandInFarSpace (result))
10835 genFarFarAssign (result, right, ic);
10839 aopOp (result, ic, TRUE, FALSE);
10841 /* if they are the same registers */
10842 if (sameRegs (AOP (right), AOP (result)))
10845 /* if the result is a bit */
10846 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10848 /* if the right size is a literal then
10849 we know what the value is */
10850 if (AOP_TYPE (right) == AOP_LIT)
10852 if (((int) operandLitValue (right)))
10853 aopPut (AOP (result), one, 0);
10855 aopPut (AOP (result), zero, 0);
10859 /* the right is also a bit variable */
10860 if (AOP_TYPE (right) == AOP_CRY)
10862 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10863 aopPut (AOP (result), "c", 0);
10867 /* we need to or */
10869 aopPut (AOP (result), "a", 0);
10873 /* bit variables done */
10875 size = AOP_SIZE (result);
10877 if (AOP_TYPE (right) == AOP_LIT)
10878 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10881 (AOP_TYPE (result) != AOP_REG) &&
10882 (AOP_TYPE (right) == AOP_LIT) &&
10883 !IS_FLOAT (operandType (right)))
10885 _startLazyDPSEvaluation ();
10886 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10888 aopPut (AOP (result),
10889 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10894 /* And now fill the rest with zeros. */
10897 emitcode ("clr", "a");
10901 aopPut (AOP (result), "a", offset++);
10903 _endLazyDPSEvaluation ();
10907 _startLazyDPSEvaluation ();
10910 aopPut (AOP (result),
10911 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10915 _endLazyDPSEvaluation ();
10919 freeAsmop (right, NULL, ic, FALSE);
10920 freeAsmop (result, NULL, ic, TRUE);
10923 /*-----------------------------------------------------------------*/
10924 /* genJumpTab - generates code for jump table */
10925 /*-----------------------------------------------------------------*/
10927 genJumpTab (iCode * ic)
10932 D (emitcode (";", "genJumpTab ");
10935 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10936 /* get the condition into accumulator */
10937 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
10939 /* multiply by four! */
10940 emitcode ("add", "a,acc");
10941 emitcode ("add", "a,acc");
10942 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10944 jtab = newiTempLabel (NULL);
10945 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
10946 emitcode ("jmp", "@a+dptr");
10947 emitcode ("", "!tlabeldef", jtab->key + 100);
10948 /* now generate the jump labels */
10949 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10950 jtab = setNextItem (IC_JTLABELS (ic)))
10951 emitcode ("ljmp", "!tlabel", jtab->key + 100);
10955 /*-----------------------------------------------------------------*/
10956 /* genCast - gen code for casting */
10957 /*-----------------------------------------------------------------*/
10959 genCast (iCode * ic)
10961 operand *result = IC_RESULT (ic);
10962 sym_link *ctype = operandType (IC_LEFT (ic));
10963 sym_link *rtype = operandType (IC_RIGHT (ic));
10964 operand *right = IC_RIGHT (ic);
10967 D (emitcode (";", "genCast "););
10969 /* if they are equivalent then do nothing */
10970 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10973 aopOp (right, ic, FALSE, FALSE);
10974 aopOp (result, ic, FALSE, AOP_USESDPTR(right));
10976 /* if the result is a bit */
10977 // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10978 if (IS_BITVAR(OP_SYMBOL(result)->type))
10980 /* if the right size is a literal then
10981 we know what the value is */
10982 if (AOP_TYPE (right) == AOP_LIT)
10984 if (((int) operandLitValue (right)))
10985 aopPut (AOP (result), one, 0);
10987 aopPut (AOP (result), zero, 0);
10992 /* the right is also a bit variable */
10993 if (AOP_TYPE (right) == AOP_CRY)
10995 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10996 aopPut (AOP (result), "c", 0);
11000 /* we need to or */
11002 aopPut (AOP (result), "a", 0);
11006 /* if they are the same size : or less */
11007 if (AOP_SIZE (result) <= AOP_SIZE (right))
11010 /* if they are in the same place */
11011 if (sameRegs (AOP (right), AOP (result)))
11014 /* if they in different places then copy */
11015 size = AOP_SIZE (result);
11017 _startLazyDPSEvaluation ();
11020 aopPut (AOP (result),
11021 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11025 _endLazyDPSEvaluation ();
11030 /* if the result is of type pointer */
11031 if (IS_PTR (ctype))
11035 sym_link *type = operandType (right);
11037 /* pointer to generic pointer */
11038 if (IS_GENPTR (ctype))
11042 p_type = DCL_TYPE (type);
11046 #if OLD_CAST_BEHAVIOR
11047 /* KV: we are converting a non-pointer type to
11048 * a generic pointer. This (ifdef'd out) code
11049 * says that the resulting generic pointer
11050 * should have the same class as the storage
11051 * location of the non-pointer variable.
11053 * For example, converting an int (which happens
11054 * to be stored in DATA space) to a pointer results
11055 * in a DATA generic pointer; if the original int
11056 * in XDATA space, so will be the resulting pointer.
11058 * I don't like that behavior, and thus this change:
11059 * all such conversions will be forced to XDATA and
11060 * throw a warning. If you want some non-XDATA
11061 * type, or you want to suppress the warning, you
11062 * must go through an intermediate cast, like so:
11064 * char _generic *gp = (char _xdata *)(intVar);
11066 sym_link *etype = getSpec (type);
11068 /* we have to go by the storage class */
11069 if (SPEC_OCLS (etype) != generic)
11071 p_type = PTR_TYPE (SPEC_OCLS (etype));
11076 /* Converting unknown class (i.e. register variable)
11077 * to generic pointer. This is not good, but
11078 * we'll make a guess (and throw a warning).
11081 werror (W_INT_TO_GEN_PTR_CAST);
11085 /* the first two bytes are known */
11086 size = GPTRSIZE - 1;
11088 _startLazyDPSEvaluation ();
11091 aopPut (AOP (result),
11092 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11096 _endLazyDPSEvaluation ();
11098 /* the last byte depending on type */
11100 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11105 // pointerTypeToGPByte will have bitched.
11109 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11110 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11115 /* just copy the pointers */
11116 size = AOP_SIZE (result);
11118 _startLazyDPSEvaluation ();
11121 aopPut (AOP (result),
11122 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11126 _endLazyDPSEvaluation ();
11130 /* so we now know that the size of destination is greater
11131 than the size of the source */
11132 /* we move to result for the size of source */
11133 size = AOP_SIZE (right);
11135 _startLazyDPSEvaluation ();
11138 aopPut (AOP (result),
11139 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11143 _endLazyDPSEvaluation ();
11145 /* now depending on the sign of the source && destination */
11146 size = AOP_SIZE (result) - AOP_SIZE (right);
11147 /* if unsigned or not an integral type */
11148 /* also, if the source is a bit, we don't need to sign extend, because
11149 * it can't possibly have set the sign bit.
11151 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
11155 aopPut (AOP (result), zero, offset++);
11160 /* we need to extend the sign :{ */
11161 MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11162 FALSE, FALSE, NULL));
11163 emitcode ("rlc", "a");
11164 emitcode ("subb", "a,acc");
11166 aopPut (AOP (result), "a", offset++);
11169 /* we are done hurray !!!! */
11172 freeAsmop (right, NULL, ic, TRUE);
11173 freeAsmop (result, NULL, ic, TRUE);
11177 /*-----------------------------------------------------------------*/
11178 /* genDjnz - generate decrement & jump if not zero instrucion */
11179 /*-----------------------------------------------------------------*/
11181 genDjnz (iCode * ic, iCode * ifx)
11183 symbol *lbl, *lbl1;
11187 /* if the if condition has a false label
11188 then we cannot save */
11189 if (IC_FALSE (ifx))
11192 /* if the minus is not of the form
11194 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11195 !IS_OP_LITERAL (IC_RIGHT (ic)))
11198 if (operandLitValue (IC_RIGHT (ic)) != 1)
11201 /* if the size of this greater than one then no
11203 if (getSize (operandType (IC_RESULT (ic))) > 1)
11206 /* otherwise we can save BIG */
11207 D(emitcode(";", "genDjnz"););
11209 lbl = newiTempLabel (NULL);
11210 lbl1 = newiTempLabel (NULL);
11212 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11214 if (AOP_NEEDSACC(IC_RESULT(ic)))
11216 /* If the result is accessed indirectly via
11217 * the accumulator, we must explicitly write
11218 * it back after the decrement.
11220 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11222 if (strcmp(rByte, "a"))
11224 /* Something is hopelessly wrong */
11225 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11226 __FILE__, __LINE__);
11227 /* We can just give up; the generated code will be inefficient,
11228 * but what the hey.
11230 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11233 emitcode ("dec", "%s", rByte);
11234 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11235 emitcode ("jnz", "!tlabel", lbl->key + 100);
11237 else if (IS_AOP_PREG (IC_RESULT (ic)))
11239 emitcode ("dec", "%s",
11240 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11241 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11242 emitcode ("jnz", "!tlabel", lbl->key + 100);
11246 emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11249 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11250 emitcode ("", "!tlabeldef", lbl->key + 100);
11251 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11252 emitcode ("", "!tlabeldef", lbl1->key + 100);
11254 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11255 ifx->generated = 1;
11259 /*-----------------------------------------------------------------*/
11260 /* genReceive - generate code for a receive iCode */
11261 /*-----------------------------------------------------------------*/
11263 genReceive (iCode * ic)
11265 int size = getSize (operandType (IC_RESULT (ic)));
11269 D (emitcode (";", "genReceive "););
11271 if (ic->argreg == 1)
11273 /* first parameter */
11274 if (AOP_IS_STR(IC_RESULT(ic)))
11276 /* Nothing to do: it's already in the proper place. */
11283 useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11284 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11285 IS_TRUE_SYMOP (IC_RESULT (ic)));
11288 aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11291 /* Sanity checking... */
11292 if (AOP_USESDPTR(IC_RESULT(ic)))
11294 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11295 "genReceive got unexpected DPTR.");
11297 assignResultValue (IC_RESULT (ic));
11302 /* second receive onwards */
11303 /* this gets a little tricky since unused recevies will be
11304 eliminated, we have saved the reg in the type field . and
11305 we use that to figure out which register to use */
11306 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11307 rb1off = ic->argreg;
11310 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11313 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11316 /*-----------------------------------------------------------------*/
11317 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
11318 /*-----------------------------------------------------------------*/
11319 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11321 operand *from , *to , *count;
11326 /* we know it has to be 3 parameters */
11327 assert (nparms == 3);
11329 rsave = newBitVect(16);
11330 /* save DPTR if it needs to be saved */
11331 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11332 if (bitVectBitValue(ic->rMask,i))
11333 rsave = bitVectSetBit(rsave,i);
11335 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11336 ds390_rUmaskForOp (IC_RESULT(ic))));
11343 aopOp (from, ic->next, FALSE, FALSE);
11345 /* get from into DPTR1 */
11346 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11347 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11348 if (options.model == MODEL_FLAT24) {
11349 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11352 freeAsmop (from, NULL, ic, FALSE);
11353 aopOp (to, ic, FALSE, FALSE);
11354 /* get "to" into DPTR */
11355 /* if the operand is already in dptr
11356 then we do nothing else we move the value to dptr */
11357 if (AOP_TYPE (to) != AOP_STR) {
11358 /* if already in DPTR then we need to push */
11359 if (AOP_TYPE(to) == AOP_DPTR) {
11360 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11361 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11362 if (options.model == MODEL_FLAT24)
11363 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11364 emitcode ("pop", "dph");
11365 emitcode ("pop", "dpl");
11367 _startLazyDPSEvaluation ();
11368 /* if this is remateriazable */
11369 if (AOP_TYPE (to) == AOP_IMMD) {
11370 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11371 } else { /* we need to get it byte by byte */
11372 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11373 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11374 if (options.model == MODEL_FLAT24) {
11375 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11378 _endLazyDPSEvaluation ();
11381 freeAsmop (to, NULL, ic, FALSE);
11382 _G.dptrInUse = _G.dptr1InUse = 1;
11383 aopOp (count, ic->next->next, FALSE,FALSE);
11384 lbl =newiTempLabel(NULL);
11386 /* now for the actual copy */
11387 if (AOP_TYPE(count) == AOP_LIT &&
11388 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11389 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11391 emitcode ("lcall","__bi_memcpyc2x_s");
11393 emitcode ("lcall","__bi_memcpyx2x_s");
11395 freeAsmop (count, NULL, ic, FALSE);
11397 symbol *lbl1 = newiTempLabel(NULL);
11399 emitcode (";"," Auto increment but no djnz");
11400 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11401 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11402 freeAsmop (count, NULL, ic, FALSE);
11403 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11404 emitcode ("","!tlabeldef",lbl->key+100);
11406 emitcode ("clr","a");
11407 emitcode ("movc", "a,@a+dptr");
11409 emitcode ("movx", "a,@dptr");
11410 emitcode ("movx", "@dptr,a");
11411 emitcode ("inc", "dptr");
11412 emitcode ("inc", "dptr");
11413 emitcode ("mov","a,b");
11414 emitcode ("orl","a,_ap");
11415 emitcode ("jz","!tlabel",lbl1->key+100);
11416 emitcode ("mov","a,_ap");
11417 emitcode ("add","a,#!constbyte",0xFF);
11418 emitcode ("mov","_ap,a");
11419 emitcode ("mov","a,b");
11420 emitcode ("addc","a,#!constbyte",0xFF);
11421 emitcode ("mov","b,a");
11422 emitcode ("sjmp","!tlabel",lbl->key+100);
11423 emitcode ("","!tlabeldef",lbl1->key+100);
11425 emitcode ("mov", "dps,#0");
11426 _G.dptrInUse = _G.dptr1InUse = 0;
11427 unsavermask(rsave);
11431 /*-----------------------------------------------------------------*/
11432 /* genMemcmpX2X - gen code for memcmp xdata to xdata */
11433 /*-----------------------------------------------------------------*/
11434 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11436 operand *from , *to , *count;
11441 /* we know it has to be 3 parameters */
11442 assert (nparms == 3);
11444 rsave = newBitVect(16);
11445 /* save DPTR if it needs to be saved */
11446 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11447 if (bitVectBitValue(ic->rMask,i))
11448 rsave = bitVectSetBit(rsave,i);
11450 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11451 ds390_rUmaskForOp (IC_RESULT(ic))));
11458 aopOp (from, ic->next, FALSE, FALSE);
11460 /* get from into DPTR1 */
11461 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11462 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11463 if (options.model == MODEL_FLAT24) {
11464 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11467 freeAsmop (from, NULL, ic, FALSE);
11468 aopOp (to, ic, FALSE, FALSE);
11469 /* get "to" into DPTR */
11470 /* if the operand is already in dptr
11471 then we do nothing else we move the value to dptr */
11472 if (AOP_TYPE (to) != AOP_STR) {
11473 /* if already in DPTR then we need to push */
11474 if (AOP_TYPE(to) == AOP_DPTR) {
11475 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11476 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11477 if (options.model == MODEL_FLAT24)
11478 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11479 emitcode ("pop", "dph");
11480 emitcode ("pop", "dpl");
11482 _startLazyDPSEvaluation ();
11483 /* if this is remateriazable */
11484 if (AOP_TYPE (to) == AOP_IMMD) {
11485 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11486 } else { /* we need to get it byte by byte */
11487 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11488 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11489 if (options.model == MODEL_FLAT24) {
11490 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11493 _endLazyDPSEvaluation ();
11496 freeAsmop (to, NULL, ic, FALSE);
11497 _G.dptrInUse = _G.dptr1InUse = 1;
11498 aopOp (count, ic->next->next, FALSE,FALSE);
11499 lbl =newiTempLabel(NULL);
11500 lbl2 =newiTempLabel(NULL);
11502 /* now for the actual compare */
11503 if (AOP_TYPE(count) == AOP_LIT &&
11504 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11505 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11507 emitcode("lcall","__bi_memcmpc2x_s");
11509 emitcode("lcall","__bi_memcmpx2x_s");
11510 freeAsmop (count, NULL, ic, FALSE);
11511 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11512 aopPut(AOP(IC_RESULT(ic)),"a",0);
11513 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11515 symbol *lbl1 = newiTempLabel(NULL);
11517 emitcode("push","ar0");
11518 emitcode (";"," Auto increment but no djnz");
11519 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11520 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11521 freeAsmop (count, NULL, ic, FALSE);
11522 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11523 emitcode ("","!tlabeldef",lbl->key+100);
11525 emitcode ("clr","a");
11526 emitcode ("movc", "a,@a+dptr");
11528 emitcode ("movx", "a,@dptr");
11529 emitcode ("mov","r0,a");
11530 emitcode ("movx", "a,@dptr");
11531 emitcode ("clr","c");
11532 emitcode ("subb","a,r0");
11533 emitcode ("jnz","!tlabel",lbl2->key+100);
11534 emitcode ("inc", "dptr");
11535 emitcode ("inc", "dptr");
11536 emitcode ("mov","a,b");
11537 emitcode ("orl","a,_ap");
11538 emitcode ("jz","!tlabel",lbl1->key+100);
11539 emitcode ("mov","a,_ap");
11540 emitcode ("add","a,#!constbyte",0xFF);
11541 emitcode ("mov","_ap,a");
11542 emitcode ("mov","a,b");
11543 emitcode ("addc","a,#!constbyte",0xFF);
11544 emitcode ("mov","b,a");
11545 emitcode ("sjmp","!tlabel",lbl->key+100);
11546 emitcode ("","!tlabeldef",lbl1->key+100);
11547 emitcode ("clr","a");
11548 emitcode ("","!tlabeldef",lbl2->key+100);
11549 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11550 aopPut(AOP(IC_RESULT(ic)),"a",0);
11551 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11552 emitcode("pop","ar0");
11553 emitcode ("mov", "dps,#0");
11555 _G.dptrInUse = _G.dptr1InUse = 0;
11556 unsavermask(rsave);
11560 /*-----------------------------------------------------------------*/
11561 /* genInp - gen code for __builtin_inp read data from a mem mapped */
11562 /* port, first parameter output area second parameter pointer to */
11563 /* port third parameter count */
11564 /*-----------------------------------------------------------------*/
11565 static void genInp( iCode *ic, int nparms, operand **parms)
11567 operand *from , *to , *count;
11572 /* we know it has to be 3 parameters */
11573 assert (nparms == 3);
11575 rsave = newBitVect(16);
11576 /* save DPTR if it needs to be saved */
11577 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11578 if (bitVectBitValue(ic->rMask,i))
11579 rsave = bitVectSetBit(rsave,i);
11581 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11582 ds390_rUmaskForOp (IC_RESULT(ic))));
11589 aopOp (from, ic->next, FALSE, FALSE);
11591 /* get from into DPTR1 */
11592 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11593 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11594 if (options.model == MODEL_FLAT24) {
11595 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11598 freeAsmop (from, NULL, ic, FALSE);
11599 aopOp (to, ic, FALSE, FALSE);
11600 /* get "to" into DPTR */
11601 /* if the operand is already in dptr
11602 then we do nothing else we move the value to dptr */
11603 if (AOP_TYPE (to) != AOP_STR) {
11604 /* if already in DPTR then we need to push */
11605 if (AOP_TYPE(to) == AOP_DPTR) {
11606 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11607 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11608 if (options.model == MODEL_FLAT24)
11609 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11610 emitcode ("pop", "dph");
11611 emitcode ("pop", "dpl");
11613 _startLazyDPSEvaluation ();
11614 /* if this is remateriazable */
11615 if (AOP_TYPE (to) == AOP_IMMD) {
11616 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11617 } else { /* we need to get it byte by byte */
11618 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11619 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11620 if (options.model == MODEL_FLAT24) {
11621 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11624 _endLazyDPSEvaluation ();
11627 freeAsmop (to, NULL, ic, FALSE);
11629 _G.dptrInUse = _G.dptr1InUse = 1;
11630 aopOp (count, ic->next->next, FALSE,FALSE);
11631 lbl =newiTempLabel(NULL);
11633 /* now for the actual copy */
11634 if (AOP_TYPE(count) == AOP_LIT &&
11635 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11636 emitcode (";","OH JOY auto increment with djnz (very fast)");
11637 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11638 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11639 freeAsmop (count, NULL, ic, FALSE);
11640 emitcode ("","!tlabeldef",lbl->key+100);
11641 emitcode ("movx", "a,@dptr"); /* read data from port */
11642 emitcode ("dec","dps"); /* switch to DPTR */
11643 emitcode ("movx", "@dptr,a"); /* save into location */
11644 emitcode ("inc", "dptr"); /* point to next area */
11645 emitcode ("inc","dps"); /* switch to DPTR2 */
11646 emitcode ("djnz","b,!tlabel",lbl->key+100);
11648 symbol *lbl1 = newiTempLabel(NULL);
11650 emitcode (";"," Auto increment but no djnz");
11651 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11652 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11653 freeAsmop (count, NULL, ic, FALSE);
11654 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11655 emitcode ("","!tlabeldef",lbl->key+100);
11656 emitcode ("movx", "a,@dptr");
11657 emitcode ("dec","dps"); /* switch to DPTR */
11658 emitcode ("movx", "@dptr,a");
11659 emitcode ("inc", "dptr");
11660 emitcode ("inc","dps"); /* switch to DPTR2 */
11661 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
11662 /* emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
11663 emitcode ("mov","a,b");
11664 emitcode ("orl","a,_ap");
11665 emitcode ("jz","!tlabel",lbl1->key+100);
11666 emitcode ("mov","a,_ap");
11667 emitcode ("add","a,#!constbyte",0xFF);
11668 emitcode ("mov","_ap,a");
11669 emitcode ("mov","a,b");
11670 emitcode ("addc","a,#!constbyte",0xFF);
11671 emitcode ("mov","b,a");
11672 emitcode ("sjmp","!tlabel",lbl->key+100);
11673 emitcode ("","!tlabeldef",lbl1->key+100);
11675 emitcode ("mov", "dps,#0");
11676 _G.dptrInUse = _G.dptr1InUse = 0;
11677 unsavermask(rsave);
11681 /*-----------------------------------------------------------------*/
11682 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
11683 /* port, first parameter output area second parameter pointer to */
11684 /* port third parameter count */
11685 /*-----------------------------------------------------------------*/
11686 static void genOutp( iCode *ic, int nparms, operand **parms)
11688 operand *from , *to , *count;
11693 /* we know it has to be 3 parameters */
11694 assert (nparms == 3);
11696 rsave = newBitVect(16);
11697 /* save DPTR if it needs to be saved */
11698 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11699 if (bitVectBitValue(ic->rMask,i))
11700 rsave = bitVectSetBit(rsave,i);
11702 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11703 ds390_rUmaskForOp (IC_RESULT(ic))));
11710 aopOp (from, ic->next, FALSE, FALSE);
11712 /* get from into DPTR1 */
11713 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11714 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11715 if (options.model == MODEL_FLAT24) {
11716 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11719 freeAsmop (from, NULL, ic, FALSE);
11720 aopOp (to, ic, FALSE, FALSE);
11721 /* get "to" into DPTR */
11722 /* if the operand is already in dptr
11723 then we do nothing else we move the value to dptr */
11724 if (AOP_TYPE (to) != AOP_STR) {
11725 /* if already in DPTR then we need to push */
11726 if (AOP_TYPE(to) == AOP_DPTR) {
11727 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11728 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11729 if (options.model == MODEL_FLAT24)
11730 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11731 emitcode ("pop", "dph");
11732 emitcode ("pop", "dpl");
11734 _startLazyDPSEvaluation ();
11735 /* if this is remateriazable */
11736 if (AOP_TYPE (to) == AOP_IMMD) {
11737 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11738 } else { /* we need to get it byte by byte */
11739 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11740 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11741 if (options.model == MODEL_FLAT24) {
11742 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11745 _endLazyDPSEvaluation ();
11748 freeAsmop (to, NULL, ic, FALSE);
11750 _G.dptrInUse = _G.dptr1InUse = 1;
11751 aopOp (count, ic->next->next, FALSE,FALSE);
11752 lbl =newiTempLabel(NULL);
11754 /* now for the actual copy */
11755 if (AOP_TYPE(count) == AOP_LIT &&
11756 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11757 emitcode (";","OH JOY auto increment with djnz (very fast)");
11758 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
11759 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11760 emitcode ("","!tlabeldef",lbl->key+100);
11761 emitcode ("movx", "a,@dptr"); /* read data from port */
11762 emitcode ("inc","dps"); /* switch to DPTR2 */
11763 emitcode ("movx", "@dptr,a"); /* save into location */
11764 emitcode ("inc", "dptr"); /* point to next area */
11765 emitcode ("dec","dps"); /* switch to DPTR */
11766 emitcode ("djnz","b,!tlabel",lbl->key+100);
11767 freeAsmop (count, NULL, ic, FALSE);
11769 symbol *lbl1 = newiTempLabel(NULL);
11771 emitcode (";"," Auto increment but no djnz");
11772 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11773 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11774 freeAsmop (count, NULL, ic, FALSE);
11775 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
11776 emitcode ("","!tlabeldef",lbl->key+100);
11777 emitcode ("movx", "a,@dptr");
11778 emitcode ("inc", "dptr");
11779 emitcode ("inc","dps"); /* switch to DPTR2 */
11780 emitcode ("movx", "@dptr,a");
11781 emitcode ("dec","dps"); /* switch to DPTR */
11782 emitcode ("mov","a,b");
11783 emitcode ("orl","a,_ap");
11784 emitcode ("jz","!tlabel",lbl1->key+100);
11785 emitcode ("mov","a,_ap");
11786 emitcode ("add","a,#!constbyte",0xFF);
11787 emitcode ("mov","_ap,a");
11788 emitcode ("mov","a,b");
11789 emitcode ("addc","a,#!constbyte",0xFF);
11790 emitcode ("mov","b,a");
11791 emitcode ("sjmp","!tlabel",lbl->key+100);
11792 emitcode ("","!tlabeldef",lbl1->key+100);
11794 emitcode ("mov", "dps,#0");
11795 _G.dptrInUse = _G.dptr1InUse = 0;
11796 unsavermask(rsave);
11800 /*-----------------------------------------------------------------*/
11801 /* genSwapW - swap lower & high order bytes */
11802 /*-----------------------------------------------------------------*/
11803 static void genSwapW(iCode *ic, int nparms, operand **parms)
11807 assert (nparms==1);
11810 dest=IC_RESULT(ic);
11812 assert(getSize(operandType(src))==2);
11814 aopOp (src, ic, FALSE, FALSE);
11815 emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
11817 MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
11819 freeAsmop (src, NULL, ic, FALSE);
11821 aopOp (dest,ic, FALSE, FALSE);
11822 aopPut(AOP(dest),"b",0);
11823 aopPut(AOP(dest),"a",1);
11824 freeAsmop (dest, NULL, ic, FALSE);
11827 /*-----------------------------------------------------------------*/
11828 /* genMemsetX - gencode for memSetX data */
11829 /*-----------------------------------------------------------------*/
11830 static void genMemsetX(iCode *ic, int nparms, operand **parms)
11832 operand *to , *val , *count;
11838 /* we know it has to be 3 parameters */
11839 assert (nparms == 3);
11845 /* save DPTR if it needs to be saved */
11846 rsave = newBitVect(16);
11847 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11848 if (bitVectBitValue(ic->rMask,i))
11849 rsave = bitVectSetBit(rsave,i);
11851 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11852 ds390_rUmaskForOp (IC_RESULT(ic))));
11855 aopOp (to, ic, FALSE, FALSE);
11856 /* get "to" into DPTR */
11857 /* if the operand is already in dptr
11858 then we do nothing else we move the value to dptr */
11859 if (AOP_TYPE (to) != AOP_STR) {
11860 /* if already in DPTR then we need to push */
11861 if (AOP_TYPE(to) == AOP_DPTR) {
11862 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11863 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11864 if (options.model == MODEL_FLAT24)
11865 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11866 emitcode ("pop", "dph");
11867 emitcode ("pop", "dpl");
11869 _startLazyDPSEvaluation ();
11870 /* if this is remateriazable */
11871 if (AOP_TYPE (to) == AOP_IMMD) {
11872 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11873 } else { /* we need to get it byte by byte */
11874 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11875 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11876 if (options.model == MODEL_FLAT24) {
11877 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11880 _endLazyDPSEvaluation ();
11883 freeAsmop (to, NULL, ic, FALSE);
11885 aopOp (val, ic->next->next, FALSE,FALSE);
11886 aopOp (count, ic->next->next, FALSE,FALSE);
11887 lbl =newiTempLabel(NULL);
11888 /* now for the actual copy */
11889 if (AOP_TYPE(count) == AOP_LIT &&
11890 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11891 l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
11892 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11894 emitcode ("","!tlabeldef",lbl->key+100);
11895 emitcode ("movx", "@dptr,a");
11896 emitcode ("inc", "dptr");
11897 emitcode ("djnz","b,!tlabel",lbl->key+100);
11899 symbol *lbl1 = newiTempLabel(NULL);
11901 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11902 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11903 emitcode ("","!tlabeldef",lbl->key+100);
11904 MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
11905 emitcode ("movx", "@dptr,a");
11906 emitcode ("inc", "dptr");
11907 emitcode ("mov","a,b");
11908 emitcode ("orl","a,_ap");
11909 emitcode ("jz","!tlabel",lbl1->key+100);
11910 emitcode ("mov","a,_ap");
11911 emitcode ("add","a,#!constbyte",0xFF);
11912 emitcode ("mov","_ap,a");
11913 emitcode ("mov","a,b");
11914 emitcode ("addc","a,#!constbyte",0xFF);
11915 emitcode ("mov","b,a");
11916 emitcode ("sjmp","!tlabel",lbl->key+100);
11917 emitcode ("","!tlabeldef",lbl1->key+100);
11919 freeAsmop (count, NULL, ic, FALSE);
11920 unsavermask(rsave);
11923 /*-----------------------------------------------------------------*/
11924 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
11925 /*-----------------------------------------------------------------*/
11926 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
11929 operand *pnum, *result;
11932 assert (nparms==1);
11933 /* save registers that need to be saved */
11934 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11935 ds390_rUmaskForOp (IC_RESULT(ic))));
11938 aopOp (pnum, ic, FALSE, FALSE);
11939 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
11940 freeAsmop (pnum, NULL, ic, FALSE);
11941 emitcode ("lcall","NatLib_LoadPrimitive");
11942 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11943 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
11944 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
11945 for (i = (size-1) ; i >= 0 ; i-- ) {
11946 emitcode ("push","a%s",javaRet[i]);
11948 for (i=0; i < size ; i++ ) {
11949 emitcode ("pop","a%s",
11950 aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
11953 for (i = 0 ; i < size ; i++ ) {
11954 aopPut(AOP(result),javaRet[i],i);
11957 freeAsmop (result, NULL, ic, FALSE);
11958 unsavermask(rsave);
11961 /*-----------------------------------------------------------------*/
11962 /* genNatLibLoadPointer - calls TINI api function to load pointer */
11963 /*-----------------------------------------------------------------*/
11964 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
11967 operand *pnum, *result;
11971 assert (nparms==1);
11972 /* save registers that need to be saved */
11973 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11974 ds390_rUmaskForOp (IC_RESULT(ic))));
11977 aopOp (pnum, ic, FALSE, FALSE);
11978 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
11979 freeAsmop (pnum, NULL, ic, FALSE);
11980 emitcode ("lcall","NatLib_LoadPointer");
11981 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11982 if (AOP_TYPE(result)!=AOP_STR) {
11983 for (i = 0 ; i < size ; i++ ) {
11984 aopPut(AOP(result),fReturn[i],i);
11987 freeAsmop (result, NULL, ic, FALSE);
11988 unsavermask(rsave);
11991 /*-----------------------------------------------------------------*/
11992 /* genNatLibInstallStateBlock - */
11993 /*-----------------------------------------------------------------*/
11994 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
11995 operand **parms, const char *name)
11998 operand *psb, *handle;
11999 assert (nparms==2);
12001 /* save registers that need to be saved */
12002 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12003 ds390_rUmaskForOp (IC_RESULT(ic))));
12007 /* put pointer to state block into DPTR1 */
12008 aopOp (psb, ic, FALSE, FALSE);
12009 if (AOP_TYPE (psb) == AOP_IMMD) {
12010 emitcode ("mov","dps,#1");
12011 emitcode ("mov", "dptr,%s",
12012 aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12013 emitcode ("mov","dps,#0");
12015 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12016 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12017 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12019 freeAsmop (psb, NULL, ic, FALSE);
12021 /* put libraryID into DPTR */
12022 emitcode ("mov","dptr,#LibraryID");
12024 /* put handle into r3:r2 */
12025 aopOp (handle, ic, FALSE, FALSE);
12026 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12027 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12028 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12029 emitcode ("pop","ar3");
12030 emitcode ("pop","ar2");
12032 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12033 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12035 freeAsmop (psb, NULL, ic, FALSE);
12037 /* make the call */
12038 emitcode ("lcall","NatLib_Install%sStateBlock",name);
12040 /* put return value into place*/
12042 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12044 aopPut(AOP(IC_RESULT(ic)),"a",0);
12045 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12046 unsavermask(rsave);
12049 /*-----------------------------------------------------------------*/
12050 /* genNatLibRemoveStateBlock - */
12051 /*-----------------------------------------------------------------*/
12052 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12058 /* save registers that need to be saved */
12059 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12060 ds390_rUmaskForOp (IC_RESULT(ic))));
12062 /* put libraryID into DPTR */
12063 emitcode ("mov","dptr,#LibraryID");
12064 /* make the call */
12065 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12066 unsavermask(rsave);
12069 /*-----------------------------------------------------------------*/
12070 /* genNatLibGetStateBlock - */
12071 /*-----------------------------------------------------------------*/
12072 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12073 operand **parms,const char *name)
12076 symbol *lbl = newiTempLabel(NULL);
12079 /* save registers that need to be saved */
12080 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12081 ds390_rUmaskForOp (IC_RESULT(ic))));
12083 /* put libraryID into DPTR */
12084 emitcode ("mov","dptr,#LibraryID");
12085 /* make the call */
12086 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12087 emitcode ("jnz","!tlabel",lbl->key+100);
12089 /* put return value into place */
12090 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12091 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12092 emitcode ("push","ar3");
12093 emitcode ("push","ar2");
12094 emitcode ("pop","%s",
12095 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12096 emitcode ("pop","%s",
12097 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12099 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12100 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12102 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12103 emitcode ("","!tlabeldef",lbl->key+100);
12104 unsavermask(rsave);
12107 /*-----------------------------------------------------------------*/
12108 /* genMMMalloc - */
12109 /*-----------------------------------------------------------------*/
12110 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12111 int size, const char *name)
12116 symbol *lbl = newiTempLabel(NULL);
12118 assert (nparms == 1);
12119 /* save registers that need to be saved */
12120 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12121 ds390_rUmaskForOp (IC_RESULT(ic))));
12124 aopOp (bsize,ic,FALSE,FALSE);
12126 /* put the size in R4-R2 */
12127 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12128 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12129 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12131 emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12132 emitcode("pop","ar4");
12134 emitcode("pop","ar3");
12135 emitcode("pop","ar2");
12137 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12138 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12140 emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12143 freeAsmop (bsize, NULL, ic, FALSE);
12145 /* make the call */
12146 emitcode ("lcall","MM_%s",name);
12147 emitcode ("jz","!tlabel",lbl->key+100);
12148 emitcode ("mov","r2,#!constbyte",0xff);
12149 emitcode ("mov","r3,#!constbyte",0xff);
12150 emitcode ("","!tlabeldef",lbl->key+100);
12151 /* we don't care about the pointer : we just save the handle */
12152 rsym = OP_SYMBOL(IC_RESULT(ic));
12153 if (rsym->liveFrom != rsym->liveTo) {
12154 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12155 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12156 emitcode ("push","ar3");
12157 emitcode ("push","ar2");
12158 emitcode ("pop","%s",
12159 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12160 emitcode ("pop","%s",
12161 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12163 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12164 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12166 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12168 unsavermask(rsave);
12171 /*-----------------------------------------------------------------*/
12173 /*-----------------------------------------------------------------*/
12174 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12179 assert (nparms == 1);
12180 /* save registers that need to be saved */
12181 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12182 ds390_rUmaskForOp (IC_RESULT(ic))));
12185 aopOp (handle,ic,FALSE,FALSE);
12187 /* put the size in R4-R2 */
12188 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12189 emitcode("push","%s",
12190 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12191 emitcode("push","%s",
12192 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12193 emitcode("pop","ar3");
12194 emitcode("pop","ar2");
12196 emitcode ("mov","r2,%s",
12197 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12198 emitcode ("mov","r3,%s",
12199 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12201 freeAsmop (handle, NULL, ic, FALSE);
12203 /* make the call */
12204 emitcode ("lcall","MM_Deref");
12207 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12208 if (rsym->liveFrom != rsym->liveTo) {
12209 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12210 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12211 _startLazyDPSEvaluation ();
12213 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12214 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12215 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12217 _endLazyDPSEvaluation ();
12222 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12223 unsavermask(rsave);
12226 /*-----------------------------------------------------------------*/
12227 /* genMMUnrestrictedPersist - */
12228 /*-----------------------------------------------------------------*/
12229 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12234 assert (nparms == 1);
12235 /* save registers that need to be saved */
12236 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12237 ds390_rUmaskForOp (IC_RESULT(ic))));
12240 aopOp (handle,ic,FALSE,FALSE);
12242 /* put the size in R3-R2 */
12243 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12244 emitcode("push","%s",
12245 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12246 emitcode("push","%s",
12247 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12248 emitcode("pop","ar3");
12249 emitcode("pop","ar2");
12251 emitcode ("mov","r2,%s",
12252 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12253 emitcode ("mov","r3,%s",
12254 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12256 freeAsmop (handle, NULL, ic, FALSE);
12258 /* make the call */
12259 emitcode ("lcall","MM_UnrestrictedPersist");
12262 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12263 if (rsym->liveFrom != rsym->liveTo) {
12264 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12265 aopPut(AOP(IC_RESULT(ic)),"a",0);
12266 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12269 unsavermask(rsave);
12272 /*-----------------------------------------------------------------*/
12273 /* genSystemExecJavaProcess - */
12274 /*-----------------------------------------------------------------*/
12275 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12278 operand *handle, *pp;
12280 assert (nparms==2);
12281 /* save registers that need to be saved */
12282 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12283 ds390_rUmaskForOp (IC_RESULT(ic))));
12288 /* put the handle in R3-R2 */
12289 aopOp (handle,ic,FALSE,FALSE);
12290 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12291 emitcode("push","%s",
12292 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12293 emitcode("push","%s",
12294 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12295 emitcode("pop","ar3");
12296 emitcode("pop","ar2");
12298 emitcode ("mov","r2,%s",
12299 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12300 emitcode ("mov","r3,%s",
12301 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12303 freeAsmop (handle, NULL, ic, FALSE);
12305 /* put pointer in DPTR */
12306 aopOp (pp,ic,FALSE,FALSE);
12307 if (AOP_TYPE(pp) == AOP_IMMD) {
12308 emitcode ("mov", "dptr,%s",
12309 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12310 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12311 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12312 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12313 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12315 freeAsmop (handle, NULL, ic, FALSE);
12317 /* make the call */
12318 emitcode ("lcall","System_ExecJavaProcess");
12320 /* put result in place */
12322 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12323 if (rsym->liveFrom != rsym->liveTo) {
12324 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12325 aopPut(AOP(IC_RESULT(ic)),"a",0);
12326 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12330 unsavermask(rsave);
12333 /*-----------------------------------------------------------------*/
12334 /* genSystemRTCRegisters - */
12335 /*-----------------------------------------------------------------*/
12336 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12342 assert (nparms==1);
12343 /* save registers that need to be saved */
12344 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12345 ds390_rUmaskForOp (IC_RESULT(ic))));
12348 /* put pointer in DPTR */
12349 aopOp (pp,ic,FALSE,FALSE);
12350 if (AOP_TYPE (pp) == AOP_IMMD) {
12351 emitcode ("mov","dps,#1");
12352 emitcode ("mov", "dptr,%s",
12353 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12354 emitcode ("mov","dps,#0");
12356 emitcode ("mov","dpl1,%s",
12357 aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12358 emitcode ("mov","dph1,%s",
12359 aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12360 emitcode ("mov","dpx1,%s",
12361 aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12363 freeAsmop (pp, NULL, ic, FALSE);
12365 /* make the call */
12366 emitcode ("lcall","System_%sRTCRegisters",name);
12368 unsavermask(rsave);
12371 /*-----------------------------------------------------------------*/
12372 /* genSystemThreadSleep - */
12373 /*-----------------------------------------------------------------*/
12374 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12379 assert (nparms==1);
12380 /* save registers that need to be saved */
12381 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12382 ds390_rUmaskForOp (IC_RESULT(ic))));
12385 aopOp(to,ic,FALSE,FALSE);
12386 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12387 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12388 emitcode ("push","%s",
12389 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12390 emitcode ("push","%s",
12391 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12392 emitcode ("push","%s",
12393 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12394 emitcode ("push","%s",
12395 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12396 emitcode ("pop","ar3");
12397 emitcode ("pop","ar2");
12398 emitcode ("pop","ar1");
12399 emitcode ("pop","ar0");
12401 emitcode ("mov","r0,%s",
12402 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12403 emitcode ("mov","r1,%s",
12404 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12405 emitcode ("mov","r2,%s",
12406 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12407 emitcode ("mov","r3,%s",
12408 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12410 freeAsmop (to, NULL, ic, FALSE);
12412 /* suspend in acc */
12414 aopOp(s,ic,FALSE,FALSE);
12415 emitcode ("mov","a,%s",
12416 aopGet(AOP(s),0,FALSE,TRUE,NULL));
12417 freeAsmop (s, NULL, ic, FALSE);
12419 /* make the call */
12420 emitcode ("lcall","System_%s",name);
12422 unsavermask(rsave);
12425 /*-----------------------------------------------------------------*/
12426 /* genSystemThreadResume - */
12427 /*-----------------------------------------------------------------*/
12428 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12433 assert (nparms==2);
12434 /* save registers that need to be saved */
12435 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12436 ds390_rUmaskForOp (IC_RESULT(ic))));
12442 aopOp(pid,ic,FALSE,FALSE);
12443 emitcode ("mov","r0,%s",
12444 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12445 freeAsmop (pid, NULL, ic, FALSE);
12448 aopOp(tid,ic,FALSE,FALSE);
12449 emitcode ("mov","a,%s",
12450 aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
12451 freeAsmop (tid, NULL, ic, FALSE);
12453 emitcode ("lcall","System_ThreadResume");
12455 /* put result into place */
12457 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12458 if (rsym->liveFrom != rsym->liveTo) {
12459 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12460 aopPut(AOP(IC_RESULT(ic)),"a",0);
12461 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12464 unsavermask(rsave);
12467 /*-----------------------------------------------------------------*/
12468 /* genSystemProcessResume - */
12469 /*-----------------------------------------------------------------*/
12470 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
12475 assert (nparms==1);
12476 /* save registers that need to be saved */
12477 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12478 ds390_rUmaskForOp (IC_RESULT(ic))));
12483 aopOp(pid,ic,FALSE,FALSE);
12484 emitcode ("mov","a,%s",
12485 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12486 freeAsmop (pid, NULL, ic, FALSE);
12488 emitcode ("lcall","System_ProcessResume");
12490 unsavermask(rsave);
12493 /*-----------------------------------------------------------------*/
12495 /*-----------------------------------------------------------------*/
12496 static void genSystem (iCode *ic,int nparms,char *name)
12498 assert(nparms == 0);
12500 emitcode ("lcall","System_%s",name);
12503 /*-----------------------------------------------------------------*/
12504 /* genSystemPoll - */
12505 /*-----------------------------------------------------------------*/
12506 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
12511 assert (nparms==1);
12512 /* save registers that need to be saved */
12513 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12514 ds390_rUmaskForOp (IC_RESULT(ic))));
12517 aopOp (fp,ic,FALSE,FALSE);
12518 if (AOP_TYPE (fp) == AOP_IMMD) {
12519 emitcode ("mov", "dptr,%s",
12520 aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
12521 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
12522 emitcode ("mov","dpl,%s",
12523 aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
12524 emitcode ("mov","dph,%s",
12525 aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
12526 emitcode ("mov","dpx,%s",
12527 aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
12529 freeAsmop (fp, NULL, ic, FALSE);
12531 emitcode ("lcall","System_%sPoll",name);
12533 /* put result into place */
12535 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12536 if (rsym->liveFrom != rsym->liveTo) {
12537 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12538 aopPut(AOP(IC_RESULT(ic)),"a",0);
12539 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12542 unsavermask(rsave);
12545 /*-----------------------------------------------------------------*/
12546 /* genSystemGetCurrentID - */
12547 /*-----------------------------------------------------------------*/
12548 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
12550 assert (nparms==0);
12552 emitcode ("lcall","System_GetCurrent%sId",name);
12553 /* put result into place */
12555 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12556 if (rsym->liveFrom != rsym->liveTo) {
12557 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12558 aopPut(AOP(IC_RESULT(ic)),"a",0);
12559 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12564 /*-----------------------------------------------------------------*/
12565 /* genBuiltIn - calls the appropriate function to generating code */
12566 /* for a built in function */
12567 /*-----------------------------------------------------------------*/
12568 static void genBuiltIn (iCode *ic)
12570 operand *bi_parms[MAX_BUILTIN_ARGS];
12575 /* get all the arguments for a built in function */
12576 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
12578 /* which function is it */
12579 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
12580 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
12581 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
12582 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
12583 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
12584 } else if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
12585 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
12586 } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
12587 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
12588 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
12589 genMemsetX(bi_iCode,nbi_parms,bi_parms);
12590 } else if (strcmp(bif->name,"__builtin_inp")==0) {
12591 genInp(bi_iCode,nbi_parms,bi_parms);
12592 } else if (strcmp(bif->name,"__builtin_outp")==0) {
12593 genOutp(bi_iCode,nbi_parms,bi_parms);
12594 } else if (strcmp(bif->name,"__builtin_swapw")==0) {
12595 genSwapW(bi_iCode,nbi_parms,bi_parms);
12596 /* JavaNative builtIns */
12597 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
12598 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
12599 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
12600 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
12601 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
12602 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
12603 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
12604 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
12605 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
12606 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12607 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
12608 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12609 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
12610 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
12611 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
12612 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
12613 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
12614 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12615 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
12616 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12617 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
12618 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
12619 } else if (strcmp(bif->name,"MM_Malloc")==0) {
12620 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
12621 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
12622 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
12623 } else if (strcmp(bif->name,"MM_Free")==0) {
12624 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
12625 } else if (strcmp(bif->name,"MM_Deref")==0) {
12626 genMMDeref(bi_iCode,nbi_parms,bi_parms);
12627 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
12628 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
12629 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
12630 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
12631 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
12632 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
12633 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
12634 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
12635 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
12636 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
12637 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
12638 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
12639 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
12640 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
12641 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
12642 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
12643 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12644 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12645 } else if (strcmp(bif->name,"System_SaveThread")==0) {
12646 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12647 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12648 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12649 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
12650 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
12651 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
12652 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
12653 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
12654 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
12655 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
12656 genSystem(bi_iCode,nbi_parms,"ProcessYield");
12657 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
12658 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
12659 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
12660 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
12661 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
12662 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
12663 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
12664 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
12665 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
12666 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
12668 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
12674 /*-----------------------------------------------------------------*/
12675 /* gen390Code - generate code for Dallas 390 based controllers */
12676 /*-----------------------------------------------------------------*/
12678 gen390Code (iCode * lic)
12683 lineHead = lineCurr = NULL;
12684 dptrn[1][0] = "dpl1";
12685 dptrn[1][1] = "dph1";
12686 dptrn[1][2] = "dpx1";
12688 if (options.model == MODEL_FLAT24) {
12689 fReturnSizeDS390 = 5;
12690 fReturn = fReturn24;
12692 fReturnSizeDS390 = 4;
12693 fReturn = fReturn16;
12694 options.stack10bit=0;
12697 /* print the allocation information */
12699 printAllocInfo (currFunc, codeOutFile);
12701 /* if debug information required */
12702 if (options.debug && currFunc)
12704 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
12706 if (IS_STATIC (currFunc->etype))
12707 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
12709 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
12712 /* stack pointer name */
12713 if (options.useXstack)
12719 for (ic = lic; ic; ic = ic->next)
12722 if (ic->lineno && cln != ic->lineno)
12727 emitcode ("", "C$%s$%d$%d$%d ==.",
12728 FileBaseName (ic->filename), ic->lineno,
12729 ic->level, ic->block);
12732 if (!options.noCcodeInAsm) {
12733 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
12734 printCLine(ic->filename, ic->lineno));
12738 if (options.iCodeInAsm) {
12739 emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
12741 /* if the result is marked as
12742 spilt and rematerializable or code for
12743 this has already been generated then
12745 if (resultRemat (ic) || ic->generated)
12748 /* depending on the operation */
12768 /* IPOP happens only when trying to restore a
12769 spilt live range, if there is an ifx statement
12770 following this pop then the if statement might
12771 be using some of the registers being popped which
12772 would destory the contents of the register so
12773 we need to check for this condition and handle it */
12775 ic->next->op == IFX &&
12776 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
12777 genIfx (ic->next, ic);
12795 genEndFunction (ic);
12815 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
12832 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
12836 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
12843 /* note these two are xlated by algebraic equivalence
12844 during parsing SDCC.y */
12845 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12846 "got '>=' or '<=' shouldn't have come here");
12850 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
12862 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
12866 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
12870 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
12894 genRightShift (ic);
12897 case GET_VALUE_AT_ADDRESS:
12898 genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
12902 if (POINTER_SET (ic))
12903 genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
12929 if (ic->builtinSEND) genBuiltIn(ic);
12930 else addSet (&_G.sendSet, ic);
12943 /* now we are ready to call the
12944 peep hole optimizer */
12945 if (!options.nopeep)
12946 peepHole (&lineHead);
12948 /* now do the actual printing */
12949 printLine (lineHead, codeOutFile);