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)
522 emitcode ("mov", "dpx1,#!constbyte",
523 (options.stack_loc >> 16) & 0xff);
525 emitcode ("mov", "dph1,_bpx+1");
527 emitcode ("mov", "dpl1,_bpx");
528 emitcode ("mov","dps,#1");
530 if (options.model == MODEL_FLAT24)
532 emitcode ("mov", "dpx,#!constbyte",
533 (options.stack_loc >> 16) & 0xff);
535 emitcode ("mov", "dph,_bpx+1");
536 emitcode ("mov", "dpl,_bpx");
538 stack_val = -stack_val;
539 while (stack_val--) {
540 emitcode ("inc","dptr");
543 emitcode("mov","dps,#0");
547 emitcode ("push", "acc");
550 emitcode ("push", "b");
552 emitcode ("mov", "a,_bpx");
553 emitcode ("clr","c");
554 emitcode ("subb", "a,#!constbyte", stack_val & 0xff);
555 emitcode ("mov","b,a");
556 emitcode ("mov","a,_bpx+1");
557 emitcode ("subb","a,#!constbyte",(stack_val >> 8) & 0xff);
559 if (options.model == MODEL_FLAT24)
561 emitcode ("mov", "dpx1,#!constbyte",
562 (options.stack_loc >> 16) & 0xff);
564 emitcode ("mov", "dph1,a");
565 emitcode ("mov", "dpl1,b");
567 if (options.model == MODEL_FLAT24)
569 emitcode ("mov", "dpx,#!constbyte",
570 (options.stack_loc >> 16) & 0xff);
572 emitcode ("mov", "dph,a");
573 emitcode ("mov", "dpl,b");
577 emitcode ("pop", "b");
580 emitcode ("pop", "acc");
582 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
583 aop->size = getSize (sym->type);
587 /* if in bit space */
588 if (IN_BITSPACE (space))
590 sym->aop = aop = newAsmop (AOP_CRY);
591 aop->aopu.aop_dir = sym->rname;
592 aop->size = getSize (sym->type);
595 /* if it is in direct space */
596 if (IN_DIRSPACE (space))
598 sym->aop = aop = newAsmop (AOP_DIR);
599 aop->aopu.aop_dir = sym->rname;
600 aop->size = getSize (sym->type);
604 /* special case for a function */
605 if (IS_FUNC (sym->type))
607 sym->aop = aop = newAsmop (AOP_IMMD);
608 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
609 aop->size = FPTRSIZE;
613 /* only remaining is far space */
614 /* in which case DPTR gets the address */
615 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
620 emitcode ("mov", "dptr,#%s", sym->rname);
625 emitcode ("mov", "dptr,#%s", sym->rname);
627 aop->size = getSize (sym->type);
629 /* if it is in code space */
630 if (IN_CODESPACE (space))
636 /*-----------------------------------------------------------------*/
637 /* aopForRemat - rematerialzes an object */
638 /*-----------------------------------------------------------------*/
640 aopForRemat (symbol * sym)
642 iCode *ic = sym->rematiCode;
643 asmop *aop = newAsmop (AOP_IMMD);
650 val += (int) operandLitValue (IC_RIGHT (ic));
651 else if (ic->op == '-')
652 val -= (int) operandLitValue (IC_RIGHT (ic));
653 else if (IS_CAST_ICODE(ic)) {
654 sym_link *from_type = operandType(IC_RIGHT(ic));
655 aop->aopu.aop_immd.from_cast_remat = 1;
656 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
657 ptr_type = DCL_TYPE(from_type);
658 if (ptr_type == IPOINTER) {
665 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
670 SNPRINTF (buffer, sizeof(buffer),
672 OP_SYMBOL (IC_LEFT (ic))->rname,
673 val >= 0 ? '+' : '-',
674 abs (val) & 0xffffff);
678 if (IS_ASSIGN_ICODE(ic) && isOperandLiteral(IC_RIGHT(ic)))
680 SNPRINTF(buffer, sizeof(buffer),
681 "0x%x",(int) operandLitValue (IC_RIGHT (ic)));
685 strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
689 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);
690 /* set immd2 field if required */
691 if (aop->aopu.aop_immd.from_cast_remat)
693 tsprintf(buffer, sizeof(buffer), "#!constbyte",ptr_type);
694 aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
700 /*-----------------------------------------------------------------*/
701 /* aopHasRegs - returns true if aop has regs between from-to */
702 /*-----------------------------------------------------------------*/
703 static int aopHasRegs(asmop *aop, int from, int to)
707 if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
709 for (; size < aop->size ; size++) {
711 for (reg = from ; reg <= to ; reg++)
712 if (aop->aopu.aop_reg[size] == ds390_regWithIdx(reg)) return 1;
717 /*-----------------------------------------------------------------*/
718 /* regsInCommon - two operands have some registers in common */
719 /*-----------------------------------------------------------------*/
721 regsInCommon (operand * op1, operand * op2)
726 /* if they have registers in common */
727 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
730 sym1 = OP_SYMBOL (op1);
731 sym2 = OP_SYMBOL (op2);
733 if (sym1->nRegs == 0 || sym2->nRegs == 0)
736 for (i = 0; i < sym1->nRegs; i++)
742 for (j = 0; j < sym2->nRegs; j++)
747 if (sym2->regs[j] == sym1->regs[i])
755 /*-----------------------------------------------------------------*/
756 /* operandsEqu - equivalent */
757 /*-----------------------------------------------------------------*/
759 operandsEqu (operand * op1, operand * op2)
763 /* if they not symbols */
764 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
767 sym1 = OP_SYMBOL (op1);
768 sym2 = OP_SYMBOL (op2);
770 /* if both are itemps & one is spilt
771 and the other is not then false */
772 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
773 sym1->isspilt != sym2->isspilt)
776 /* if they are the same */
780 if (strcmp (sym1->rname, sym2->rname) == 0)
784 /* if left is a tmp & right is not */
785 if (IS_ITEMP (op1) &&
788 (sym1->usl.spillLoc == sym2))
791 if (IS_ITEMP (op2) &&
795 (sym2->usl.spillLoc == sym1))
801 /*-----------------------------------------------------------------*/
802 /* sameRegs - two asmops have the same registers */
803 /*-----------------------------------------------------------------*/
805 sameRegs (asmop * aop1, asmop * aop2)
811 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
818 if (aop1->type != AOP_REG ||
819 aop2->type != AOP_REG)
822 if (aop1->size != aop2->size)
825 for (i = 0; i < aop1->size; i++)
826 if (aop1->aopu.aop_reg[i] !=
827 aop2->aopu.aop_reg[i])
833 /*-----------------------------------------------------------------*/
834 /* aopOp - allocates an asmop for an operand : */
835 /*-----------------------------------------------------------------*/
837 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
846 /* if this a literal */
847 if (IS_OP_LITERAL (op))
849 op->aop = aop = newAsmop (AOP_LIT);
850 aop->aopu.aop_lit = op->operand.valOperand;
851 aop->size = getSize (operandType (op));
855 /* if already has a asmop then continue */
859 /* if the underlying symbol has a aop */
860 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
862 op->aop = OP_SYMBOL (op)->aop;
866 /* if this is a true symbol */
867 if (IS_TRUE_SYMOP (op))
869 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
873 /* this is a temporary : this has
879 e) can be a return use only */
881 sym = OP_SYMBOL (op);
884 /* if the type is a conditional */
885 if (sym->regType == REG_CND)
887 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
892 /* if it is spilt then two situations
894 b) has a spill location */
895 if (sym->isspilt || sym->nRegs == 0)
898 /* rematerialize it NOW */
901 sym->aop = op->aop = aop =
903 aop->size = getSize (sym->type);
910 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
911 aop->size = getSize (sym->type);
912 for (i = 0; i < 2; i++)
913 aop->aopu.aop_str[i] = accUse[i];
923 /* a AOP_STR uses DPTR, but DPTR is already in use;
926 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"AOP_STR with DPTR in use!");
929 aop = op->aop = sym->aop = newAsmop (AOP_STR);
930 aop->size = getSize (sym->type);
931 for (i = 0; i < (int) fReturnSizeDS390; i++)
932 aop->aopu.aop_str[i] = fReturn[i];
936 if (sym->dptr) { /* has been allocated to a DPTRn */
937 aop = op->aop = sym->aop = newAsmop (AOP_DPTRn);
938 aop->size = getSize (sym->type);
939 aop->aopu.dptr = sym->dptr;
942 /* else spill location */
943 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
944 /* force a new aop if sizes differ */
945 sym->usl.spillLoc->aop = NULL;
947 sym->aop = op->aop = aop =
948 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
949 aop->size = getSize (sym->type);
953 /* must be in a register */
954 sym->aop = op->aop = aop = newAsmop (AOP_REG);
955 aop->size = sym->nRegs;
956 for (i = 0; i < sym->nRegs; i++)
957 aop->aopu.aop_reg[i] = sym->regs[i];
960 /*-----------------------------------------------------------------*/
961 /* freeAsmop - free up the asmop given to an operand */
962 /*----------------------------------------------------------------*/
964 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
981 /* depending on the asmop type only three cases need work AOP_RO
982 , AOP_R1 && AOP_STK */
990 emitcode ("pop", "ar0");
994 bitVectUnSetBit (ic->rUsed, R0_IDX);
1002 emitcode ("pop", "ar1");
1006 bitVectUnSetBit (ic->rUsed, R1_IDX);
1012 int stk = aop->aopu.aop_stk + aop->size;
1013 bitVectUnSetBit (ic->rUsed, R0_IDX);
1014 bitVectUnSetBit (ic->rUsed, R1_IDX);
1016 getFreePtr (ic, &aop, FALSE);
1018 if (options.stack10bit)
1020 /* I'm not sure what to do here yet... */
1023 "*** Warning: probably generating bad code for "
1024 "10 bit stack mode.\n");
1029 emitcode ("mov", "a,_bp");
1030 emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
1031 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1035 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1040 emitcode ("pop", "acc");
1041 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1044 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1047 freeAsmop (op, NULL, ic, TRUE);
1050 emitcode ("pop", "ar0");
1056 emitcode ("pop", "ar1");
1061 if (_G.dptr1InUse) {
1062 emitcode ("pop","dpx1");
1063 emitcode ("pop","dph1");
1064 emitcode ("pop","dpl1");
1069 emitcode ("pop","dpx");
1070 emitcode ("pop","dph");
1071 emitcode ("pop","dpl");
1076 /* all other cases just dealloc */
1082 OP_SYMBOL (op)->aop = NULL;
1083 /* if the symbol has a spill */
1085 SPIL_LOC (op)->aop = NULL;
1090 #define DEFAULT_ACC_WARNING 0
1091 static int saveAccWarn = DEFAULT_ACC_WARNING;
1093 /*-------------------------------------------------------------------*/
1094 /* aopGet - for fetching value of the aop */
1096 /* Set saveAcc to NULL if you are sure it is OK to clobber the value */
1097 /* in the accumulator. Set it to the name of a free register */
1098 /* if acc must be preserved; the register will be used to preserve */
1099 /* acc temporarily and to return the result byte. */
1100 /*-------------------------------------------------------------------*/
1109 /* offset is greater than
1111 if (offset > (aop->size - 1) &&
1112 aop->type != AOP_LIT)
1115 /* depending on type */
1121 /* if we need to increment it */
1122 while (offset > aop->coff)
1124 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1128 while (offset < aop->coff)
1130 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1137 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1138 return (dname ? "acc" : "a");
1140 SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1141 return Safe_strdup(buffer);
1144 assert(offset <= 3);
1145 return dptrn[aop->aopu.dptr][offset];
1150 if (aop->type == AOP_DPTR2)
1158 // if (aop->type != AOP_DPTR2)
1160 // if (saveAccWarn) { fprintf(stderr, "saveAcc for DPTR...\n"); }
1161 // emitcode(";", "spanky: saveAcc for DPTR");
1164 emitcode ("xch", "a, %s", saveAcc);
1169 while (offset > aop->coff)
1171 emitcode ("inc", "dptr");
1175 while (offset < aop->coff)
1177 emitcode ("lcall", "__decdptr");
1184 emitcode ("clr", "a");
1185 emitcode ("movc", "a,@a+dptr");
1189 emitcode ("movx", "a,@dptr");
1192 if (aop->type == AOP_DPTR2)
1200 emitcode ("xch", "a, %s", saveAcc);
1201 // if (strcmp(saveAcc, "_ap"))
1203 // emitcode(";", "spiffy: non _ap return from aopGet.");
1208 return (dname ? "acc" : "a");
1211 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1213 SNPRINTF(buffer, sizeof(buffer),
1214 "%s",aop->aopu.aop_immd.aop_immd2);
1218 SNPRINTF(buffer, sizeof(buffer),
1219 "#%s", aop->aopu.aop_immd.aop_immd1);
1225 tsprintf(buffer, sizeof(buffer),
1226 "#!his",aop->aopu.aop_immd.aop_immd1);
1229 tsprintf(buffer, sizeof(buffer),
1230 "#!hihis",aop->aopu.aop_immd.aop_immd1);
1233 tsprintf(buffer, sizeof(buffer),
1234 "#!hihihis",aop->aopu.aop_immd.aop_immd1);
1236 default: /* should not need this (just in case) */
1237 SNPRINTF (buffer, sizeof(buffer),
1239 aop->aopu.aop_immd.aop_immd1,
1245 SNPRINTF (buffer, sizeof(buffer),
1246 "#%s", aop->aopu.aop_immd.aop_immd1);
1248 return Safe_strdup(buffer);
1253 SNPRINTF (buffer, sizeof(buffer),
1260 SNPRINTF(buffer, sizeof(buffer),
1261 "%s", aop->aopu.aop_dir);
1264 return Safe_strdup(buffer);
1268 return aop->aopu.aop_reg[offset]->dname;
1270 return aop->aopu.aop_reg[offset]->name;
1273 emitcode ("clr", "a");
1274 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1275 emitcode ("rlc", "a");
1276 return (dname ? "acc" : "a");
1279 if (!offset && dname)
1281 return aop->aopu.aop_str[offset];
1284 return aopLiteral (aop->aopu.aop_lit, offset);
1288 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1292 return aop->aopu.aop_str[offset];
1296 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1297 "aopget got unsupported aop->type");
1300 return NULL; // not reached, but makes compiler happy.
1302 /*-----------------------------------------------------------------*/
1303 /* aopPut - puts a string for a aop */
1304 /*-----------------------------------------------------------------*/
1306 aopPut (asmop * aop, char *s, int offset)
1308 if (aop->size && offset > (aop->size - 1))
1310 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1311 "aopPut got offset > aop->size");
1315 /* will assign value to value */
1316 /* depending on where it is ofcourse */
1322 SNPRINTF (buffer, sizeof(buffer),
1324 aop->aopu.aop_dir, offset);
1328 SNPRINTF (buffer, sizeof(buffer),
1329 "%s", aop->aopu.aop_dir);
1333 if (strcmp (buffer, s))
1335 emitcode ("mov", "%s,%s", buffer, s);
1340 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1341 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1344 strcmp (s, "r0") == 0 ||
1345 strcmp (s, "r1") == 0 ||
1346 strcmp (s, "r2") == 0 ||
1347 strcmp (s, "r3") == 0 ||
1348 strcmp (s, "r4") == 0 ||
1349 strcmp (s, "r5") == 0 ||
1350 strcmp (s, "r6") == 0 ||
1351 strcmp (s, "r7") == 0)
1353 emitcode ("mov", "%s,%s",
1354 aop->aopu.aop_reg[offset]->dname, s);
1358 emitcode ("mov", "%s,%s",
1359 aop->aopu.aop_reg[offset]->name, s);
1365 emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1371 if (aop->type == AOP_DPTR2)
1379 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1380 "aopPut writting to code space");
1384 while (offset > aop->coff)
1387 emitcode ("inc", "dptr");
1390 while (offset < aop->coff)
1393 emitcode ("lcall", "__decdptr");
1398 /* if not in accumulater */
1401 emitcode ("movx", "@dptr,a");
1403 if (aop->type == AOP_DPTR2)
1411 while (offset > aop->coff)
1414 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1416 while (offset < aop->coff)
1419 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1426 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1432 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1434 else if (strcmp (s, "r0") == 0 ||
1435 strcmp (s, "r1") == 0 ||
1436 strcmp (s, "r2") == 0 ||
1437 strcmp (s, "r3") == 0 ||
1438 strcmp (s, "r4") == 0 ||
1439 strcmp (s, "r5") == 0 ||
1440 strcmp (s, "r6") == 0 ||
1441 strcmp (s, "r7") == 0)
1444 SNPRINTF(buff, sizeof(buff),
1446 emitcode ("mov", "@%s,%s",
1447 aop->aopu.aop_ptr->name, buff);
1451 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1456 if (strcmp (s, "a") == 0)
1457 emitcode ("push", "acc");
1461 emitcode ("push", "acc");
1463 emitcode ("push", s);
1469 /* if bit variable */
1470 if (!aop->aopu.aop_dir)
1472 emitcode ("clr", "a");
1473 emitcode ("rlc", "a");
1478 emitcode ("clr", "%s", aop->aopu.aop_dir);
1480 emitcode ("setb", "%s", aop->aopu.aop_dir);
1481 else if (!strcmp (s, "c"))
1482 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1485 if (strcmp (s, "a"))
1490 /* set C, if a >= 1 */
1491 emitcode ("add", "a,#!constbyte",0xff);
1492 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1500 if (strcmp (aop->aopu.aop_str[offset], s))
1501 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1506 if (!offset && (strcmp (s, "acc") == 0))
1509 if (strcmp (aop->aopu.aop_str[offset], s))
1510 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1514 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1515 "aopPut got unsupported aop->type");
1522 /*--------------------------------------------------------------------*/
1523 /* reAdjustPreg - points a register back to where it should (coff==0) */
1524 /*--------------------------------------------------------------------*/
1526 reAdjustPreg (asmop * aop)
1528 if ((aop->coff==0) || (aop->size <= 1)) {
1537 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1541 if (aop->type == AOP_DPTR2)
1548 emitcode ("lcall", "__decdptr");
1551 if (aop->type == AOP_DPTR2)
1561 #define AOP(op) op->aop
1562 #define AOP_TYPE(op) AOP(op)->type
1563 #define AOP_SIZE(op) AOP(op)->size
1564 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1565 AOP_TYPE(x) == AOP_R0))
1567 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1568 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1571 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1572 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1573 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1574 #define AOP_INDPTRn(x) (AOP_TYPE(x) == AOP_DPTRn)
1575 #define AOP_USESDPTR(x) ((AOP_TYPE(x) == AOP_DPTR) || (AOP_TYPE(x) == AOP_STR))
1576 #define AOP_USESDPTR2(x) ((AOP_TYPE(x) == AOP_DPTR2) || (AOP_TYPE(x) == AOP_DPTRn))
1578 // The following two macros can be used even if the aop has not yet been aopOp'd.
1579 #define AOP_IS_STR(x) (IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
1580 #define AOP_IS_DPTRn(x) (IS_SYMOP(x) && OP_SYMBOL(x)->dptr)
1582 /* Workaround for DS80C390 bug: div ab may return bogus results
1583 * if A is accessed in instruction immediately before the div.
1585 * Will be fixed in B4 rev of processor, Dallas claims.
1588 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1589 if (!AOP_NEEDSACC(RIGHT)) \
1591 /* We can load A first, then B, since \
1592 * B (the RIGHT operand) won't clobber A, \
1593 * thus avoiding touching A right before the div. \
1595 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1596 L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL); \
1598 L = aopGet(AOP(RIGHT),0,FALSE,FALSE,"b"); \
1603 /* Just stuff in a nop after loading A. */ \
1604 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,NULL));\
1605 L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL); \
1607 emitcode("nop", "; workaround for DS80C390 div bug."); \
1610 /*-----------------------------------------------------------------*/
1611 /* genNotFloat - generates not for float operations */
1612 /*-----------------------------------------------------------------*/
1614 genNotFloat (operand * op, operand * res)
1619 D (emitcode (";", "genNotFloat "););
1621 /* we will put 127 in the first byte of
1623 aopPut (AOP (res), "#127", 0);
1624 size = AOP_SIZE (op) - 1;
1627 _startLazyDPSEvaluation ();
1628 MOVA(aopGet(op->aop, offset++, FALSE, FALSE, NULL));
1632 emitcode ("orl", "a,%s",
1634 offset++, FALSE, FALSE,
1637 _endLazyDPSEvaluation ();
1639 tlbl = newiTempLabel (NULL);
1640 aopPut (res->aop, one, 1);
1641 emitcode ("jz", "!tlabel", (tlbl->key + 100));
1642 aopPut (res->aop, zero, 1);
1643 emitcode ("", "!tlabeldef", (tlbl->key + 100));
1645 size = res->aop->size - 2;
1647 /* put zeros in the rest */
1649 aopPut (res->aop, zero, offset++);
1652 /*-----------------------------------------------------------------*/
1653 /* opIsGptr: returns non-zero if the passed operand is */
1654 /* a generic pointer type. */
1655 /*-----------------------------------------------------------------*/
1657 opIsGptr (operand * op)
1659 sym_link *type = operandType (op);
1661 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1668 /*-----------------------------------------------------------------*/
1669 /* getDataSize - get the operand data size */
1670 /*-----------------------------------------------------------------*/
1672 getDataSize (operand * op)
1675 size = AOP_SIZE (op);
1676 if (size == GPTRSIZE)
1678 sym_link *type = operandType (op);
1679 if (IS_GENPTR (type))
1681 /* generic pointer; arithmetic operations
1682 * should ignore the high byte (pointer type).
1690 /*-----------------------------------------------------------------*/
1691 /* outAcc - output Acc */
1692 /*-----------------------------------------------------------------*/
1694 outAcc (operand * result)
1697 size = getDataSize (result);
1700 aopPut (AOP (result), "a", 0);
1703 /* unsigned or positive */
1706 aopPut (AOP (result), zero, offset++);
1711 /*-----------------------------------------------------------------*/
1712 /* outBitC - output a bit C */
1713 /*-----------------------------------------------------------------*/
1715 outBitC (operand * result)
1717 /* if the result is bit */
1718 if (AOP_TYPE (result) == AOP_CRY)
1720 aopPut (AOP (result), "c", 0);
1724 emitcode ("clr", "a");
1725 emitcode ("rlc", "a");
1730 /*-----------------------------------------------------------------*/
1731 /* toBoolean - emit code for orl a,operator(sizeop) */
1732 /*-----------------------------------------------------------------*/
1734 toBoolean (operand * oper)
1736 int size = AOP_SIZE (oper) - 1;
1740 /* The generic part of a generic pointer should
1741 * not participate in it's truth value.
1743 * i.e. 0x10000000 is zero.
1745 if (opIsGptr (oper))
1747 D (emitcode (";", "toBoolean: generic ptr special case."););
1751 _startLazyDPSEvaluation ();
1752 if (AOP_NEEDSACC (oper) && size)
1757 emitcode ("push", "b");
1759 MOVB (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1763 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1770 emitcode ("orl", "b,%s",
1771 aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1775 emitcode ("orl", "a,%s",
1776 aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1779 _endLazyDPSEvaluation ();
1783 emitcode ("mov", "a,b");
1786 emitcode ("pop", "b");
1793 /*-----------------------------------------------------------------*/
1794 /* genNot - generate code for ! operation */
1795 /*-----------------------------------------------------------------*/
1800 sym_link *optype = operandType (IC_LEFT (ic));
1802 D (emitcode (";", "genNot "););
1804 /* assign asmOps to operand & result */
1805 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1806 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1808 /* if in bit space then a special case */
1809 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1811 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1812 emitcode ("cpl", "c");
1813 outBitC (IC_RESULT (ic));
1817 /* if type float then do float */
1818 if (IS_FLOAT (optype))
1820 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1824 toBoolean (IC_LEFT (ic));
1826 tlbl = newiTempLabel (NULL);
1827 emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1828 emitcode ("", "!tlabeldef", tlbl->key + 100);
1829 outBitC (IC_RESULT (ic));
1832 /* release the aops */
1833 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1834 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1838 /*-----------------------------------------------------------------*/
1839 /* genCpl - generate code for complement */
1840 /*-----------------------------------------------------------------*/
1848 D (emitcode (";", "genCpl "););
1851 /* assign asmOps to operand & result */
1852 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1853 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1855 /* special case if in bit space */
1856 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1857 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1858 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1859 emitcode ("cpl", "c");
1860 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1863 tlbl=newiTempLabel(NULL);
1864 emitcode ("cjne", "%s,#0x01,%05d$",
1865 aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE,NULL), tlbl->key+100);
1866 emitcode ("", "%05d$:", tlbl->key+100);
1867 outBitC (IC_RESULT(ic));
1871 size = AOP_SIZE (IC_RESULT (ic));
1872 _startLazyDPSEvaluation ();
1875 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
1876 emitcode ("cpl", "a");
1877 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1879 _endLazyDPSEvaluation ();
1883 /* release the aops */
1884 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1885 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1888 /*-----------------------------------------------------------------*/
1889 /* genUminusFloat - unary minus for floating points */
1890 /*-----------------------------------------------------------------*/
1892 genUminusFloat (operand * op, operand * result)
1894 int size, offset = 0;
1896 D(emitcode (";", "genUminusFloat"););
1898 /* for this we just copy and then flip the bit */
1900 _startLazyDPSEvaluation ();
1901 size = AOP_SIZE (op) - 1;
1905 aopPut (AOP (result),
1906 aopGet (AOP (op), offset, FALSE, FALSE, NULL),
1911 MOVA(aopGet (AOP (op), offset, FALSE, FALSE, NULL));
1913 emitcode ("cpl", "acc.7");
1914 aopPut (AOP (result), "a", offset);
1915 _endLazyDPSEvaluation ();
1918 /*-----------------------------------------------------------------*/
1919 /* genUminus - unary minus code generation */
1920 /*-----------------------------------------------------------------*/
1922 genUminus (iCode * ic)
1927 D (emitcode (";", "genUminus "););
1930 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1931 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1933 /* if both in bit space then special
1935 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1936 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1939 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1940 emitcode ("cpl", "c");
1941 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1945 optype = operandType (IC_LEFT (ic));
1947 /* if float then do float stuff */
1948 if (IS_FLOAT (optype))
1950 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1954 /* otherwise subtract from zero */
1955 size = AOP_SIZE (IC_LEFT (ic));
1957 _startLazyDPSEvaluation ();
1960 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL);
1961 if (!strcmp (l, "a"))
1965 emitcode ("cpl", "a");
1966 emitcode ("addc", "a,#0");
1972 emitcode ("clr", "a");
1973 emitcode ("subb", "a,%s", l);
1975 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1977 _endLazyDPSEvaluation ();
1979 /* if any remaining bytes in the result */
1980 /* we just need to propagate the sign */
1981 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic)))) != 0)
1983 emitcode ("rlc", "a");
1984 emitcode ("subb", "a,acc");
1986 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1990 /* release the aops */
1991 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1992 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1995 /*-----------------------------------------------------------------*/
1996 /* savermask - saves registers in the mask */
1997 /*-----------------------------------------------------------------*/
1998 static void savermask(bitVect *rs_mask)
2001 if (options.useXstack) {
2002 if (bitVectBitValue (rs_mask, R0_IDX))
2003 emitcode ("mov", "b,r0");
2004 emitcode ("mov", "r0,%s", spname);
2005 for (i = 0; i < ds390_nRegs; i++) {
2006 if (bitVectBitValue (rs_mask, i)) {
2008 emitcode ("mov", "a,b");
2010 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
2011 emitcode ("movx", "@r0,a");
2012 emitcode ("inc", "r0");
2015 emitcode ("mov", "%s,r0", spname);
2016 if (bitVectBitValue (rs_mask, R0_IDX))
2017 emitcode ("mov", "r0,b");
2019 for (i = 0; i < ds390_nRegs; i++) {
2020 if (bitVectBitValue (rs_mask, i))
2021 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2026 /*-----------------------------------------------------------------*/
2027 /* saveRegisters - will look for a call and save the registers */
2028 /*-----------------------------------------------------------------*/
2030 saveRegisters (iCode * lic)
2036 for (ic = lic; ic; ic = ic->next)
2037 if (ic->op == CALL || ic->op == PCALL)
2042 fprintf (stderr, "found parameter push with no function call\n");
2046 /* if the registers have been saved already then
2049 || (IS_SYMOP(IC_LEFT(ic)) && IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))) && !TARGET_IS_DS400) )
2052 /* special case if DPTR alive across a function call then must save it
2053 even though callee saves */
2054 if (IS_SYMOP(IC_LEFT(ic)) &&
2055 IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2057 rsave = newBitVect(ic->rMask->size);
2058 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2059 if (bitVectBitValue(ic->rMask,i))
2060 rsave = bitVectSetBit(rsave,i);
2062 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2064 /* safe the registers in use at this time but skip the
2065 ones for the result */
2066 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2067 ds390_rUmaskForOp (IC_RESULT(ic)));
2073 /*-----------------------------------------------------------------*/
2074 /* usavermask - restore registers with mask */
2075 /*-----------------------------------------------------------------*/
2076 static void unsavermask(bitVect *rs_mask)
2079 if (options.useXstack) {
2080 emitcode ("mov", "r0,%s", spname);
2081 for (i = ds390_nRegs; i >= 0; i--) {
2082 if (bitVectBitValue (rs_mask, i)) {
2083 emitcode ("dec", "r0");
2084 emitcode ("movx", "a,@r0");
2086 emitcode ("mov", "b,a");
2088 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
2091 emitcode ("mov", "%s,r0", spname);
2092 if (bitVectBitValue (rs_mask, R0_IDX))
2093 emitcode ("mov", "r0,b");
2095 for (i = ds390_nRegs; i >= 0; i--) {
2096 if (bitVectBitValue (rs_mask, i))
2097 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2102 /*-----------------------------------------------------------------*/
2103 /* unsaveRegisters - pop the pushed registers */
2104 /*-----------------------------------------------------------------*/
2106 unsaveRegisters (iCode * ic)
2110 if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2112 rsave = newBitVect(ic->rMask->size);
2113 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2114 if (bitVectBitValue(ic->rMask,i))
2115 rsave = bitVectSetBit(rsave,i);
2117 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2119 /* restore the registers in use at this time but skip the
2120 ones for the result */
2121 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2122 ds390_rUmaskForOp (IC_RESULT(ic)));
2128 /*-----------------------------------------------------------------*/
2130 /*-----------------------------------------------------------------*/
2132 pushSide (operand * oper, int size)
2135 _startLazyDPSEvaluation ();
2138 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, NULL);
2139 if (AOP_TYPE (oper) != AOP_REG &&
2140 AOP_TYPE (oper) != AOP_DIR &&
2143 emitcode ("mov", "a,%s", l);
2144 emitcode ("push", "acc");
2147 emitcode ("push", "%s", l);
2149 _endLazyDPSEvaluation ();
2152 /*-----------------------------------------------------------------*/
2153 /* assignResultValue - */
2154 /*-----------------------------------------------------------------*/
2156 assignResultValue (operand * oper)
2159 int size = AOP_SIZE (oper);
2160 bool pushedAcc = FALSE;
2162 if (size == fReturnSizeDS390)
2164 /* I don't think this case can ever happen... */
2165 /* ACC is the last part of this. If writing the result
2166 * uses AC, we must preserve it.
2168 if (AOP_NEEDSACC(oper))
2170 emitcode(";", "assignResultValue special case for ACC.");
2171 emitcode("push", "acc");
2178 _startLazyDPSEvaluation ();
2181 aopPut (AOP (oper), fReturn[offset], offset);
2184 _endLazyDPSEvaluation ();
2188 emitcode("pop", "acc");
2189 aopPut(AOP(oper), "a", offset);
2194 /*-----------------------------------------------------------------*/
2195 /* genXpush - pushes onto the external stack */
2196 /*-----------------------------------------------------------------*/
2198 genXpush (iCode * ic)
2200 asmop *aop = newAsmop (0);
2202 int size, offset = 0;
2204 D (emitcode (";", "genXpush ");
2207 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2208 r = getFreePtr (ic, &aop, FALSE);
2211 emitcode ("mov", "%s,_spx", r->name);
2213 size = AOP_SIZE (IC_LEFT (ic));
2214 _startLazyDPSEvaluation ();
2218 MOVA (aopGet (AOP (IC_LEFT (ic)),
2219 offset++, FALSE, FALSE, NULL));
2220 emitcode ("movx", "@%s,a", r->name);
2221 emitcode ("inc", "%s", r->name);
2224 _endLazyDPSEvaluation ();
2227 emitcode ("mov", "_spx,%s", r->name);
2229 freeAsmop (NULL, aop, ic, TRUE);
2230 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2233 /*-----------------------------------------------------------------*/
2234 /* genIpush - generate code for pushing this gets a little complex */
2235 /*-----------------------------------------------------------------*/
2237 genIpush (iCode * ic)
2239 int size, offset = 0;
2242 D (emitcode (";", "genIpush ");
2245 /* if this is not a parm push : ie. it is spill push
2246 and spill push is always done on the local stack */
2250 /* and the item is spilt then do nothing */
2251 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2254 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2255 size = AOP_SIZE (IC_LEFT (ic));
2256 /* push it on the stack */
2257 _startLazyDPSEvaluation ();
2260 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2266 emitcode ("push", "%s", l);
2268 _endLazyDPSEvaluation ();
2272 /* this is a paramter push: in this case we call
2273 the routine to find the call and save those
2274 registers that need to be saved */
2277 /* if use external stack then call the external
2278 stack pushing routine */
2279 if (options.useXstack)
2285 /* then do the push */
2286 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2288 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2289 size = AOP_SIZE (IC_LEFT (ic));
2291 _startLazyDPSEvaluation ();
2294 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2295 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2296 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2299 emitcode ("mov", "a,%s", l);
2300 emitcode ("push", "acc");
2304 emitcode ("push", "%s", l);
2307 _endLazyDPSEvaluation ();
2309 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2312 /*-----------------------------------------------------------------*/
2313 /* genIpop - recover the registers: can happen only for spilling */
2314 /*-----------------------------------------------------------------*/
2316 genIpop (iCode * ic)
2320 D (emitcode (";", "genIpop ");
2324 /* if the temp was not pushed then */
2325 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2328 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2329 size = AOP_SIZE (IC_LEFT (ic));
2330 offset = (size - 1);
2331 _startLazyDPSEvaluation ();
2334 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2335 FALSE, TRUE, NULL));
2337 _endLazyDPSEvaluation ();
2339 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2342 /*-----------------------------------------------------------------*/
2343 /* unsaveRBank - restores the resgister bank from stack */
2344 /*-----------------------------------------------------------------*/
2346 unsaveRBank (int bank, iCode * ic, bool popPsw)
2352 if (options.useXstack)
2356 /* Assume r0 is available for use. */
2357 r = ds390_regWithIdx (R0_IDX);;
2362 r = getFreePtr (ic, &aop, FALSE);
2364 emitcode ("mov", "%s,_spx", r->name);
2369 if (options.useXstack)
2371 emitcode ("movx", "a,@%s", r->name);
2372 emitcode ("mov", "psw,a");
2373 emitcode ("dec", "%s", r->name);
2377 emitcode ("pop", "psw");
2381 for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2383 if (options.useXstack)
2385 emitcode ("movx", "a,@%s", r->name);
2386 emitcode ("mov", "(%s+%d),a",
2387 regs390[i].base, 8 * bank + regs390[i].offset);
2388 emitcode ("dec", "%s", r->name);
2392 emitcode ("pop", "(%s+%d)",
2393 regs390[i].base, 8 * bank + regs390[i].offset);
2396 if (options.useXstack)
2398 emitcode ("mov", "_spx,%s", r->name);
2403 freeAsmop (NULL, aop, ic, TRUE);
2407 /*-----------------------------------------------------------------*/
2408 /* saveRBank - saves an entire register bank on the stack */
2409 /*-----------------------------------------------------------------*/
2411 saveRBank (int bank, iCode * ic, bool pushPsw)
2417 if (options.useXstack)
2421 /* Assume r0 is available for use. */
2422 r = ds390_regWithIdx (R0_IDX);;
2427 r = getFreePtr (ic, &aop, FALSE);
2429 emitcode ("mov", "%s,_spx", r->name);
2432 for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2434 if (options.useXstack)
2436 emitcode ("inc", "%s", r->name);
2437 emitcode ("mov", "a,(%s+%d)",
2438 regs390[i].base, 8 * bank + regs390[i].offset);
2439 emitcode ("movx", "@%s,a", r->name);
2442 emitcode ("push", "(%s+%d)",
2443 regs390[i].base, 8 * bank + regs390[i].offset);
2448 if (options.useXstack)
2450 emitcode ("mov", "a,psw");
2451 emitcode ("movx", "@%s,a", r->name);
2452 emitcode ("inc", "%s", r->name);
2453 emitcode ("mov", "_spx,%s", r->name);
2457 emitcode ("push", "psw");
2460 emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2465 freeAsmop (NULL, aop, ic, TRUE);
2474 /*-----------------------------------------------------------------*/
2475 /* genSend - gen code for SEND */
2476 /*-----------------------------------------------------------------*/
2477 static void genSend(set *sendSet)
2481 static int rb1_count = 0;
2483 for (sic = setFirstItem (sendSet); sic;
2484 sic = setNextItem (sendSet)) {
2485 int size, offset = 0;
2487 size=getSize(operandType(IC_LEFT(sic)));
2488 D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2489 if (sendCount == 0) { /* first parameter */
2490 // we know that dpl(hxb) is the result, so
2492 _startLazyDPSEvaluation ();
2494 aopOp (IC_LEFT (sic), sic, FALSE,
2495 (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2497 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2500 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2501 FALSE, FALSE, NULL);
2502 if (strcmp (l, fReturn[offset])) {
2503 emitcode ("mov", "%s,%s",
2509 _endLazyDPSEvaluation ();
2510 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2512 } else { /* if more parameter in registers */
2513 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2515 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
2516 FALSE, FALSE, NULL));
2518 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2525 adjustEsp(const char *reg)
2527 emitcode ("anl","%s,#3", reg);
2528 if (TARGET_IS_DS400)
2530 emitcode ("orl","%s,#!constbyte",
2532 (options.stack_loc >> 8) & 0xff);
2536 /*-----------------------------------------------------------------*/
2537 /* genCall - generates a call statement */
2538 /*-----------------------------------------------------------------*/
2540 genCall (iCode * ic)
2543 bool restoreBank = FALSE;
2544 bool swapBanks = FALSE;
2546 D (emitcode (";", "genCall "););
2548 /* if we are calling a not _naked function that is not using
2549 the same register bank then we need to save the
2550 destination registers on the stack */
2551 dtype = operandType (IC_LEFT (ic));
2552 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2553 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2554 IFFUNC_ISISR (currFunc->type))
2558 /* This is unexpected; the bank should have been saved in
2561 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2567 /* if caller saves & we have not saved then */
2571 /* if send set is not empty the assign */
2572 /* We've saved all the registers we care about;
2573 * therefore, we may clobber any register not used
2574 * in the calling convention (i.e. anything not in
2579 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2580 genSend(reverseSet(_G.sendSet));
2582 genSend(_G.sendSet);
2589 emitcode ("mov", "psw,#!constbyte",
2590 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2594 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2595 OP_SYMBOL (IC_LEFT (ic))->rname :
2596 OP_SYMBOL (IC_LEFT (ic))->name));
2600 emitcode ("mov", "psw,#!constbyte",
2601 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2604 /* if we need assign a result value */
2605 if ((IS_ITEMP (IC_RESULT (ic)) &&
2606 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2607 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2608 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2609 IS_TRUE_SYMOP (IC_RESULT (ic)))
2611 if (isOperandInFarSpace (IC_RESULT (ic))
2612 && getSize (operandType (IC_RESULT (ic))) <= 2)
2614 int size = getSize (operandType (IC_RESULT (ic)));
2616 /* Special case for 1 or 2 byte return in far space. */
2620 emitcode ("mov", "b,%s", fReturn[1]);
2623 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2624 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2628 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2630 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2635 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2638 assignResultValue (IC_RESULT (ic));
2640 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2644 /* adjust the stack for parameters if
2646 if (ic->parmBytes) {
2648 if (options.stack10bit) {
2649 if (ic->parmBytes <= 10) {
2650 emitcode(";","stack adjustment for parms");
2651 for (i=0; i < ic->parmBytes ; i++) {
2652 emitcode("pop","acc");
2656 emitcode ("clr","c");
2657 emitcode ("mov","a,sp");
2658 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2659 emitcode ("mov","sp,a");
2660 emitcode ("mov","a,esp");
2662 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2663 emitcode ("mov","esp,a");
2667 if (ic->parmBytes > 3) {
2668 emitcode ("mov", "a,%s", spname);
2669 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2670 emitcode ("mov", "%s,a", spname);
2672 for (i = 0; i < ic->parmBytes; i++)
2673 emitcode ("dec", "%s", spname);
2677 /* if we hade saved some registers then unsave them */
2679 unsaveRegisters (ic);
2681 /* if register bank was saved then pop them */
2683 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2686 /*-----------------------------------------------------------------*/
2687 /* genPcall - generates a call by pointer statement */
2688 /*-----------------------------------------------------------------*/
2690 genPcall (iCode * ic)
2693 symbol *rlbl = newiTempLabel (NULL);
2694 bool restoreBank=FALSE;
2696 D (emitcode (";", "genPcall ");
2700 /* if caller saves & we have not saved then */
2704 /* if we are calling a function that is not using
2705 the same register bank then we need to save the
2706 destination registers on the stack */
2707 dtype = operandType (IC_LEFT (ic));
2708 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2709 IFFUNC_ISISR (currFunc->type) &&
2710 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2711 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2715 /* push the return address on to the stack */
2716 emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2717 emitcode ("push", "acc");
2718 emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2719 emitcode ("push", "acc");
2721 if (options.model == MODEL_FLAT24)
2723 emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2724 emitcode ("push", "acc");
2727 /* now push the calling address */
2728 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2730 pushSide (IC_LEFT (ic), FPTRSIZE);
2732 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2734 /* if send set is not empty the assign */
2737 genSend(reverseSet(_G.sendSet));
2741 emitcode ("ret", "");
2742 emitcode ("", "!tlabeldef", (rlbl->key + 100));
2745 /* if we need assign a result value */
2746 if ((IS_ITEMP (IC_RESULT (ic)) &&
2747 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2748 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2749 IS_TRUE_SYMOP (IC_RESULT (ic)))
2753 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2756 assignResultValue (IC_RESULT (ic));
2758 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2761 /* adjust the stack for parameters if
2766 if (options.stack10bit) {
2767 if (ic->parmBytes <= 10) {
2768 emitcode(";","stack adjustment for parms");
2769 for (i=0; i < ic->parmBytes ; i++) {
2770 emitcode("pop","acc");
2774 emitcode ("clr","c");
2775 emitcode ("mov","a,sp");
2776 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2777 emitcode ("mov","sp,a");
2778 emitcode ("mov","a,esp");
2780 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2781 emitcode ("mov","esp,a");
2785 if (ic->parmBytes > 3) {
2786 emitcode ("mov", "a,%s", spname);
2787 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2788 emitcode ("mov", "%s,a", spname);
2791 for (i = 0; i < ic->parmBytes; i++)
2792 emitcode ("dec", "%s", spname);
2796 /* if register bank was saved then unsave them */
2798 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2800 /* if we hade saved some registers then
2803 unsaveRegisters (ic);
2807 /*-----------------------------------------------------------------*/
2808 /* resultRemat - result is rematerializable */
2809 /*-----------------------------------------------------------------*/
2811 resultRemat (iCode * ic)
2813 if (SKIP_IC (ic) || ic->op == IFX)
2816 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2818 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2819 if (sym->remat && !POINTER_SET (ic))
2826 #if defined(__BORLANDC__) || defined(_MSC_VER)
2827 #define STRCASECMP stricmp
2829 #define STRCASECMP strcasecmp
2832 /*-----------------------------------------------------------------*/
2833 /* inExcludeList - return 1 if the string is in exclude Reg list */
2834 /*-----------------------------------------------------------------*/
2836 regsCmp(void *p1, void *p2)
2838 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2842 inExcludeList (char *s)
2844 const char *p = setFirstItem(options.excludeRegsSet);
2846 if (p == NULL || STRCASECMP(p, "none") == 0)
2850 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2853 /*-----------------------------------------------------------------*/
2854 /* genFunction - generated code for function entry */
2855 /*-----------------------------------------------------------------*/
2857 genFunction (iCode * ic)
2861 bool switchedPSW = FALSE;
2863 D (emitcode (";", "genFunction "););
2866 /* create the function header */
2867 emitcode (";", "-----------------------------------------");
2868 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2869 emitcode (";", "-----------------------------------------");
2871 emitcode ("", "%s:", sym->rname);
2872 ftype = operandType (IC_LEFT (ic));
2874 if (IFFUNC_ISNAKED(ftype))
2876 emitcode(";", "naked function: no prologue.");
2880 if (options.stack_probe)
2881 emitcode ("lcall","__stack_probe");
2882 /* if critical function then turn interrupts off */
2883 if (IFFUNC_ISCRITICAL (ftype))
2884 emitcode ("clr", "ea");
2886 /* here we need to generate the equates for the
2887 register bank if required */
2888 if (FUNC_REGBANK (ftype) != rbank)
2892 rbank = FUNC_REGBANK (ftype);
2893 for (i = 0; i < ds390_nRegs; i++)
2895 if (regs390[i].print) {
2896 if (strcmp (regs390[i].base, "0") == 0)
2897 emitcode ("", "%s !equ !constbyte",
2899 8 * rbank + regs390[i].offset);
2901 emitcode ("", "%s !equ %s + !constbyte",
2904 8 * rbank + regs390[i].offset);
2909 /* if this is an interrupt service routine then
2910 save acc, b, dpl, dph */
2911 if (IFFUNC_ISISR (sym->type))
2913 if (!inExcludeList ("acc"))
2914 emitcode ("push", "acc");
2915 if (!inExcludeList ("b"))
2916 emitcode ("push", "b");
2917 if (!inExcludeList ("dpl"))
2918 emitcode ("push", "dpl");
2919 if (!inExcludeList ("dph"))
2920 emitcode ("push", "dph");
2921 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2923 emitcode ("push", "dpx");
2924 /* Make sure we're using standard DPTR */
2925 emitcode ("push", "dps");
2926 emitcode ("mov", "dps,#0");
2927 if (options.stack10bit)
2929 /* This ISR could conceivably use DPTR2. Better save it. */
2930 emitcode ("push", "dpl1");
2931 emitcode ("push", "dph1");
2932 emitcode ("push", "dpx1");
2933 emitcode ("push", DP2_RESULT_REG);
2936 /* if this isr has no bank i.e. is going to
2937 run with bank 0 , then we need to save more
2939 if (!FUNC_REGBANK (sym->type))
2943 /* if this function does not call any other
2944 function then we can be economical and
2945 save only those registers that are used */
2946 if (!IFFUNC_HASFCALL(sym->type))
2949 /* if any registers used */
2952 /* save the registers used */
2953 for (i = 0; i < sym->regsUsed->size; i++)
2955 if (bitVectBitValue (sym->regsUsed, i) ||
2956 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2957 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2964 /* this function has a function call cannot
2965 determines register usage so we will have to push the
2967 saveRBank (0, ic, FALSE);
2968 if (options.parms_in_bank1) {
2969 for (i=0; i < 8 ; i++ ) {
2970 emitcode ("push","%s",rb1regs[i]);
2977 /* This ISR uses a non-zero bank.
2979 * We assume that the bank is available for our
2982 * However, if this ISR calls a function which uses some
2983 * other bank, we must save that bank entirely.
2985 unsigned long banksToSave = 0;
2987 if (IFFUNC_HASFCALL(sym->type))
2990 #define MAX_REGISTER_BANKS 4
2995 for (i = ic; i; i = i->next)
2997 if (i->op == ENDFUNCTION)
2999 /* we got to the end OK. */
3007 dtype = operandType (IC_LEFT(i));
3009 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3011 /* Mark this bank for saving. */
3012 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3014 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3018 banksToSave |= (1 << FUNC_REGBANK(dtype));
3021 /* And note that we don't need to do it in
3029 /* This is a mess; we have no idea what
3030 * register bank the called function might
3033 * The only thing I can think of to do is
3034 * throw a warning and hope.
3036 werror(W_FUNCPTR_IN_USING_ISR);
3040 if (banksToSave && options.useXstack)
3042 /* Since we aren't passing it an ic,
3043 * saveRBank will assume r0 is available to abuse.
3045 * So switch to our (trashable) bank now, so
3046 * the caller's R0 isn't trashed.
3048 emitcode ("push", "psw");
3049 emitcode ("mov", "psw,#!constbyte",
3050 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3054 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3056 if (banksToSave & (1 << ix))
3058 saveRBank(ix, NULL, FALSE);
3062 // TODO: this needs a closer look
3063 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3068 /* if callee-save to be used for this function
3069 then save the registers being used in this function */
3070 if (IFFUNC_CALLEESAVES(sym->type))
3074 /* if any registers used */
3077 /* save the registers used */
3078 for (i = 0; i < sym->regsUsed->size; i++)
3080 if (bitVectBitValue (sym->regsUsed, i) ||
3081 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3083 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3091 /* set the register bank to the desired value */
3092 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3095 emitcode ("push", "psw");
3096 emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3099 if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3100 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3101 if (options.stack10bit) {
3102 emitcode ("push","_bpx");
3103 emitcode ("push","_bpx+1");
3104 emitcode ("mov","_bpx,%s",spname);
3105 emitcode ("mov","_bpx+1,esp");
3106 adjustEsp("_bpx+1");
3108 if (options.useXstack) {
3109 emitcode ("mov", "r0,%s", spname);
3110 emitcode ("mov", "a,_bp");
3111 emitcode ("movx", "@r0,a");
3112 emitcode ("inc", "%s", spname);
3114 /* set up the stack */
3115 emitcode ("push", "_bp"); /* save the callers stack */
3117 emitcode ("mov", "_bp,%s", spname);
3121 /* adjust the stack for the function */
3124 if (options.stack10bit) {
3125 if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
3126 assert (sym->recvSize <= 4);
3127 if (sym->stack <= 8) {
3128 while (i--) emitcode ("push","acc");
3131 emitcode ("mov","a,sp");
3132 emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3133 emitcode ("mov","sp,a");
3134 emitcode ("mov","a,esp");
3136 emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3137 emitcode ("mov","esp,a");
3142 werror (W_STACK_OVERFLOW, sym->name);
3144 if (i > 3 && sym->recvSize < 4) {
3146 emitcode ("mov", "a,sp");
3147 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3148 emitcode ("mov", "sp,a");
3152 emitcode ("inc", "sp");
3159 emitcode ("mov", "a,_spx");
3160 emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3161 emitcode ("mov", "_spx,a");
3166 /*-----------------------------------------------------------------*/
3167 /* genEndFunction - generates epilogue for functions */
3168 /*-----------------------------------------------------------------*/
3170 genEndFunction (iCode * ic)
3172 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3174 D (emitcode (";", "genEndFunction "););
3176 if (IFFUNC_ISNAKED(sym->type))
3178 emitcode(";", "naked function: no epilogue.");
3182 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3183 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3185 if (options.stack10bit) {
3187 emitcode ("mov", "sp,_bpx", spname);
3188 emitcode ("mov", "esp,_bpx+1", spname);
3191 emitcode ("mov", "%s,_bp", spname);
3195 /* if use external stack but some variables were
3196 added to the local stack then decrement the
3198 if (options.useXstack && sym->stack) {
3199 emitcode ("mov", "a,sp");
3200 emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3201 emitcode ("mov", "sp,a");
3205 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3206 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3208 if (options.useXstack) {
3209 emitcode ("mov", "r0,%s", spname);
3210 emitcode ("movx", "a,@r0");
3211 emitcode ("mov", "_bp,a");
3212 emitcode ("dec", "%s", spname);
3214 if (options.stack10bit) {
3215 emitcode ("pop", "_bpx+1");
3216 emitcode ("pop", "_bpx");
3218 emitcode ("pop", "_bp");
3223 /* restore the register bank */
3224 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3226 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3227 || !options.useXstack)
3229 /* Special case of ISR using non-zero bank with useXstack
3232 emitcode ("pop", "psw");
3236 if (IFFUNC_ISISR (sym->type))
3239 /* now we need to restore the registers */
3240 /* if this isr has no bank i.e. is going to
3241 run with bank 0 , then we need to save more
3243 if (!FUNC_REGBANK (sym->type))
3246 /* if this function does not call any other
3247 function then we can be economical and
3248 save only those registers that are used */
3249 if (!IFFUNC_HASFCALL(sym->type))
3252 /* if any registers used */
3255 /* save the registers used */
3256 for (i = sym->regsUsed->size; i >= 0; i--)
3258 if (bitVectBitValue (sym->regsUsed, i) ||
3259 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3260 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3267 /* this function has a function call cannot
3268 determines register usage so we will have to pop the
3270 if (options.parms_in_bank1) {
3271 for (i = 7 ; i >= 0 ; i-- ) {
3272 emitcode ("pop","%s",rb1regs[i]);
3275 unsaveRBank (0, ic, FALSE);
3280 /* This ISR uses a non-zero bank.
3282 * Restore any register banks saved by genFunction
3285 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3288 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3290 if (savedBanks & (1 << ix))
3292 unsaveRBank(ix, NULL, FALSE);
3296 if (options.useXstack)
3298 /* Restore bank AFTER calling unsaveRBank,
3299 * since it can trash r0.
3301 emitcode ("pop", "psw");
3305 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3307 if (options.stack10bit)
3309 emitcode ("pop", DP2_RESULT_REG);
3310 emitcode ("pop", "dpx1");
3311 emitcode ("pop", "dph1");
3312 emitcode ("pop", "dpl1");
3314 emitcode ("pop", "dps");
3315 emitcode ("pop", "dpx");
3317 if (!inExcludeList ("dph"))
3318 emitcode ("pop", "dph");
3319 if (!inExcludeList ("dpl"))
3320 emitcode ("pop", "dpl");
3321 if (!inExcludeList ("b"))
3322 emitcode ("pop", "b");
3323 if (!inExcludeList ("acc"))
3324 emitcode ("pop", "acc");
3326 if (IFFUNC_ISCRITICAL (sym->type))
3327 emitcode ("setb", "ea");
3329 /* if debug then send end of function */
3330 if (options.debug && currFunc) {
3332 emitcode ("", "C$%s$%d$%d$%d ==.",
3333 FileBaseName (ic->filename), currFunc->lastLine,
3334 ic->level, ic->block);
3335 if (IS_STATIC (currFunc->etype))
3336 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3338 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3342 emitcode ("reti", "");
3346 if (IFFUNC_ISCRITICAL (sym->type))
3347 emitcode ("setb", "ea");
3349 if (IFFUNC_CALLEESAVES(sym->type))
3353 /* if any registers used */
3356 /* save the registers used */
3357 for (i = sym->regsUsed->size; i >= 0; i--)
3359 if (bitVectBitValue (sym->regsUsed, i) ||
3360 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3361 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3367 /* if debug then send end of function */
3368 if (options.debug && currFunc)
3371 emitcode ("", "C$%s$%d$%d$%d ==.",
3372 FileBaseName (ic->filename), currFunc->lastLine,
3373 ic->level, ic->block);
3374 if (IS_STATIC (currFunc->etype))
3375 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3377 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3381 emitcode ("ret", "");
3386 /*-----------------------------------------------------------------*/
3387 /* genJavaNativeRet - generate code for return JavaNative */
3388 /*-----------------------------------------------------------------*/
3389 static void genJavaNativeRet(iCode *ic)
3393 aopOp (IC_LEFT (ic), ic, FALSE,
3394 AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
3395 size = AOP_SIZE (IC_LEFT (ic));
3399 /* it is assigned to GPR0-R3 then push them */
3400 if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3401 aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3402 for (i = 0 ; i < size ; i++ ) {
3403 emitcode ("push","%s",
3404 aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3406 for (i = (size-1) ; i >= 0 ; i--) {
3407 emitcode ("pop","a%s",javaRet[i]);
3410 for (i = 0 ; i < size ; i++)
3411 emitcode ("mov","%s,%s",javaRet[i],
3412 aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3414 for (i = size ; i < 4 ; i++ )
3415 emitcode ("mov","%s,#0",javaRet[i]);
3419 /*-----------------------------------------------------------------*/
3420 /* genRet - generate code for return statement */
3421 /*-----------------------------------------------------------------*/
3425 int size, offset = 0, pushed = 0;
3427 D (emitcode (";", "genRet "););
3429 /* if we have no return value then
3430 just generate the "ret" */
3434 /* if this is a JavaNative function then return
3435 value in different register */
3436 if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3437 genJavaNativeRet(ic);
3440 /* we have something to return then
3441 move the return value into place */
3442 aopOp (IC_LEFT (ic), ic, FALSE,
3443 (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
3444 size = AOP_SIZE (IC_LEFT (ic));
3446 _startLazyDPSEvaluation ();
3450 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3452 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3454 emitcode ("push", "%s", l);
3459 /* Since A is the last element of fReturn,
3460 * is is OK to clobber it in the aopGet.
3462 l = aopGet (AOP (IC_LEFT (ic)), offset,
3463 FALSE, FALSE, NULL);
3464 if (strcmp (fReturn[offset], l))
3465 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3468 _endLazyDPSEvaluation ();
3475 if (strcmp (fReturn[pushed], "a"))
3476 emitcode ("pop", fReturn[pushed]);
3478 emitcode ("pop", "acc");
3481 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3484 /* generate a jump to the return label
3485 if the next is not the return statement */
3486 if (!(ic->next && ic->next->op == LABEL &&
3487 IC_LABEL (ic->next) == returnLabel))
3489 emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3493 /*-----------------------------------------------------------------*/
3494 /* genLabel - generates a label */
3495 /*-----------------------------------------------------------------*/
3497 genLabel (iCode * ic)
3499 /* special case never generate */
3500 if (IC_LABEL (ic) == entryLabel)
3503 D (emitcode (";", "genLabel ");
3506 emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3509 /*-----------------------------------------------------------------*/
3510 /* genGoto - generates a ljmp */
3511 /*-----------------------------------------------------------------*/
3513 genGoto (iCode * ic)
3515 D (emitcode (";", "genGoto ");
3517 emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3520 /*-----------------------------------------------------------------*/
3521 /* findLabelBackwards: walks back through the iCode chain looking */
3522 /* for the given label. Returns number of iCode instructions */
3523 /* between that label and given ic. */
3524 /* Returns zero if label not found. */
3525 /*-----------------------------------------------------------------*/
3527 findLabelBackwards (iCode * ic, int key)
3536 /* If we have any pushes or pops, we cannot predict the distance.
3537 I don't like this at all, this should be dealt with in the
3539 if (ic->op == IPUSH || ic->op == IPOP) {
3543 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3545 /* printf("findLabelBackwards = %d\n", count); */
3553 /*-----------------------------------------------------------------*/
3554 /* genPlusIncr :- does addition with increment if possible */
3555 /*-----------------------------------------------------------------*/
3557 genPlusIncr (iCode * ic)
3559 unsigned int icount;
3560 unsigned int size = getDataSize (IC_RESULT (ic));
3562 /* will try to generate an increment */
3563 /* if the right side is not a literal
3565 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3568 /* if the literal value of the right hand side
3569 is greater than 4 then it is not worth it */
3570 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3573 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3574 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3576 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
3580 /* if increment 16 bits in register */
3582 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3583 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3584 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3593 /* If the next instruction is a goto and the goto target
3594 * is <= 5 instructions previous to this, we can generate
3595 * jumps straight to that target.
3597 if (ic->next && ic->next->op == GOTO
3598 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3601 D(emitcode (";", "tail increment optimized (range %d)", labelRange););
3602 tlbl = IC_LABEL (ic->next);
3607 tlbl = newiTempLabel (NULL);
3611 l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
3612 emitcode ("inc", "%s", l);
3614 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3615 IS_AOP_PREG (IC_RESULT (ic)))
3617 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3621 emitcode ("clr", "a");
3622 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3625 l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
3626 emitcode ("inc", "%s", l);
3629 if (!strcmp(l, "acc"))
3631 emitcode("jnz", "!tlabel", tlbl->key + 100);
3633 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3634 IS_AOP_PREG (IC_RESULT (ic)))
3636 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3640 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3643 l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
3644 emitcode ("inc", "%s", l);
3648 if (!strcmp(l, "acc"))
3650 emitcode("jnz", "!tlabel", tlbl->key + 100);
3652 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3653 IS_AOP_PREG (IC_RESULT (ic)))
3655 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3659 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3662 l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
3663 emitcode ("inc", "%s", l); }
3667 emitcode ("", "!tlabeldef", tlbl->key + 100);
3672 if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3673 !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 &&
3674 options.model == MODEL_FLAT24 ) {
3678 emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, NULL));
3680 emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, NULL));
3682 emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3685 while (icount--) emitcode ("inc","dptr");
3689 if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3690 AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3692 emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3693 while (icount--) emitcode ("inc","dptr");
3694 emitcode ("mov","dps,#0");
3698 /* if the sizes are greater than 1 then we cannot */
3699 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3700 AOP_SIZE (IC_LEFT (ic)) > 1)
3703 /* we can if the aops of the left & result match or
3704 if they are in registers and the registers are the
3707 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3708 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3709 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3714 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3715 emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3716 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3721 _startLazyDPSEvaluation ();
3724 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3726 _endLazyDPSEvaluation ();
3735 /*-----------------------------------------------------------------*/
3736 /* outBitAcc - output a bit in acc */
3737 /*-----------------------------------------------------------------*/
3739 outBitAcc (operand * result)
3741 symbol *tlbl = newiTempLabel (NULL);
3742 /* if the result is a bit */
3743 if (AOP_TYPE (result) == AOP_CRY)
3745 aopPut (AOP (result), "a", 0);
3749 emitcode ("jz", "!tlabel", tlbl->key + 100);
3750 emitcode ("mov", "a,%s", one);
3751 emitcode ("", "!tlabeldef", tlbl->key + 100);
3756 /*-----------------------------------------------------------------*/
3757 /* genPlusBits - generates code for addition of two bits */
3758 /*-----------------------------------------------------------------*/
3760 genPlusBits (iCode * ic)
3762 D (emitcode (";", "genPlusBits "););
3764 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3766 symbol *lbl = newiTempLabel (NULL);
3767 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3768 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3769 emitcode ("cpl", "c");
3770 emitcode ("", "!tlabeldef", (lbl->key + 100));
3771 outBitC (IC_RESULT (ic));
3775 emitcode ("clr", "a");
3776 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3777 emitcode ("rlc", "a");
3778 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3779 emitcode ("addc", "a,#0");
3780 outAcc (IC_RESULT (ic));
3785 adjustArithmeticResult (iCode * ic)
3787 if (opIsGptr (IC_RESULT (ic)) &&
3788 opIsGptr (IC_LEFT (ic)) &&
3789 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3791 aopPut (AOP (IC_RESULT (ic)),
3792 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3796 if (opIsGptr (IC_RESULT (ic)) &&
3797 opIsGptr (IC_RIGHT (ic)) &&
3798 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3800 aopPut (AOP (IC_RESULT (ic)),
3801 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3805 if (opIsGptr (IC_RESULT (ic)) &&
3806 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3807 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3808 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3809 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3812 SNPRINTF (buff, sizeof(buff),
3813 "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3814 aopPut (AOP (IC_RESULT (ic)), buff, GPTRSIZE - 1);
3818 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
3819 // generates the result if possible. If result is generated, returns TRUE; otherwise
3820 // returns false and caller must deal with fact that result isn't aopOp'd.
3821 bool aopOp3(iCode * ic)
3823 bool dp1InUse, dp2InUse;
3826 // First, generate the right opcode. DPTR may be used if neither left nor result are
3829 // D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
3830 // AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
3831 // AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
3832 // AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
3834 // D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
3835 // AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
3836 // AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
3837 // AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
3840 // Right uses DPTR unless left or result is an AOP_STR; however,
3841 // if right is an AOP_STR, it must use DPTR regardless.
3842 if ((AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)))
3843 && !AOP_IS_STR(IC_RIGHT(ic)))
3852 aopOp (IC_RIGHT(ic),ic,FALSE, useDp2);
3854 // if the right used DPTR, left MUST use DPTR2.
3855 // if the right used DPTR2, left MUST use DPTR.
3856 // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
3857 // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
3858 // enabling us to assign DPTR to result.
3860 if (AOP_USESDPTR(IC_RIGHT(ic)))
3864 else if (AOP_USESDPTR2(IC_RIGHT(ic)))
3870 if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
3880 aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
3882 // We've op'd the left & right. So, if left or right are the same operand as result,
3883 // we know aopOp will succeed, and we can just do it & bail.
3884 if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)) ||
3885 isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
3887 // D(emitcode(";", "aopOp3: (left | right) & result equal"););
3888 aopOp(IC_RESULT(ic),ic,TRUE, FALSE);
3892 // Note which dptrs are currently in use.
3893 dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
3894 dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
3896 // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot
3898 if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
3903 // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
3904 if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
3909 // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck
3910 if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
3915 aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
3917 // Some sanity checking...
3918 if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
3921 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
3922 __FILE__, __LINE__, ic->filename, ic->lineno);
3923 emitcode(";", ">>> unexpected DPTR here.");
3926 if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
3929 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
3930 __FILE__, __LINE__, ic->filename, ic->lineno);
3931 emitcode(";", ">>> unexpected DPTR2 here.");
3937 // Macro to aopOp all three operands of an ic. If this cannot be done,
3938 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3939 // will be set TRUE. The caller must then handle the case specially, noting
3940 // that the IC_RESULT operand is not aopOp'd.
3942 #define AOP_OP_3_NOFATAL(ic, rc) \
3943 do { rc = !aopOp3(ic); } while (0)
3945 // aopOp the left & right operands of an ic.
3946 #define AOP_OP_2(ic) \
3947 aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
3948 aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
3950 // convienience macro.
3951 #define AOP_SET_LOCALS(ic) \
3952 left = IC_LEFT(ic); \
3953 right = IC_RIGHT(ic); \
3954 result = IC_RESULT(ic);
3957 // Given an integer value of pushedSize bytes on the stack,
3958 // adjust it to be resultSize bytes, either by discarding
3959 // the most significant bytes or by zero-padding.
3961 // On exit from this macro, pushedSize will have been adjusted to
3962 // equal resultSize, and ACC may be trashed.
3963 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3964 /* If the pushed data is bigger than the result, \
3965 * simply discard unused bytes. Icky, but works. \
3967 while (pushedSize > resultSize) \
3969 D (emitcode (";", "discarding unused result byte."););\
3970 emitcode ("pop", "acc"); \
3973 if (pushedSize < resultSize) \
3975 emitcode ("clr", "a"); \
3976 /* Conversly, we haven't pushed enough here. \
3977 * just zero-pad, and all is well. \
3979 while (pushedSize < resultSize) \
3981 emitcode("push", "acc"); \
3985 assert(pushedSize == resultSize);
3987 /*-----------------------------------------------------------------*/
3988 /* genPlus - generates code for addition */
3989 /*-----------------------------------------------------------------*/
3991 genPlus (iCode * ic)
3993 int size, offset = 0;
3997 D (emitcode (";", "genPlus "););
3999 /* special cases :- */
4000 if ( AOP_IS_STR(IC_LEFT(ic)) &&
4001 isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
4002 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
4003 size = (int)floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
4005 while (size--) emitcode ("inc","dptr");
4007 emitcode ("mov","a,dpl");
4008 emitcode ("add","a,#!constbyte",size & 0xff);
4009 emitcode ("mov","dpl,a");
4010 emitcode ("mov","a,dph");
4011 emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
4012 emitcode ("mov","dph,a");
4013 emitcode ("mov","a,dpx");
4014 emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
4015 emitcode ("mov","dpx,a");
4017 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
4020 if ( IS_SYMOP(IC_LEFT(ic)) &&
4021 OP_SYMBOL(IC_LEFT(ic))->remat &&
4022 isOperandInFarSpace(IC_RIGHT(ic))) {
4023 operand *op = IC_RIGHT(ic);
4024 IC_RIGHT(ic) = IC_LEFT(ic);
4028 AOP_OP_3_NOFATAL (ic, pushResult);
4032 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
4037 /* if literal, literal on the right or
4038 if left requires ACC or right is already
4040 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4041 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
4042 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4044 operand *t = IC_RIGHT (ic);
4045 IC_RIGHT (ic) = IC_LEFT (ic);
4047 emitcode (";", "Swapped plus args.");
4050 /* if both left & right are in bit
4052 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4053 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4059 /* if left in bit space & right literal */
4060 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4061 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4063 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4064 /* if result in bit space */
4065 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4067 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4068 emitcode ("cpl", "c");
4069 outBitC (IC_RESULT (ic));
4073 size = getDataSize (IC_RESULT (ic));
4074 _startLazyDPSEvaluation ();
4077 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4078 emitcode ("addc", "a,#0");
4079 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4081 _endLazyDPSEvaluation ();
4086 /* if I can do an increment instead
4087 of add then GOOD for ME */
4088 if (genPlusIncr (ic) == TRUE)
4090 emitcode (";", "did genPlusIncr");
4095 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4097 _startLazyDPSEvaluation ();
4100 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4102 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4104 emitcode ("add", "a,%s",
4105 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4107 emitcode ("addc", "a,%s",
4108 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4112 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4114 /* right is going to use ACC or we would have taken the
4117 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4119 D(emitcode(";", "+ AOP_ACC special case."););
4120 emitcode("xch", "a, %s", DP2_RESULT_REG);
4122 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4125 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4128 emitcode("add", "a, %s", DP2_RESULT_REG);
4132 emitcode ("add", "a,%s",
4133 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE,
4139 emitcode ("addc", "a,%s",
4140 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE,
4146 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4150 emitcode ("push", "acc");
4154 _endLazyDPSEvaluation ();
4158 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4160 size = getDataSize (IC_LEFT (ic));
4161 rSize = getDataSize (IC_RESULT (ic));
4163 ADJUST_PUSHED_RESULT(size, rSize);
4165 _startLazyDPSEvaluation ();
4168 emitcode ("pop", "acc");
4169 aopPut (AOP (IC_RESULT (ic)), "a", size);
4171 _endLazyDPSEvaluation ();
4174 adjustArithmeticResult (ic);
4177 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4178 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4179 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4182 /*-----------------------------------------------------------------*/
4183 /* genMinusDec :- does subtraction with deccrement if possible */
4184 /*-----------------------------------------------------------------*/
4186 genMinusDec (iCode * ic)
4188 unsigned int icount;
4189 unsigned int size = getDataSize (IC_RESULT (ic));
4191 /* will try to generate an increment */
4192 /* if the right side is not a literal
4194 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4197 /* if the literal value of the right hand side
4198 is greater than 4 then it is not worth it */
4199 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4202 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4203 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4205 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
4209 /* if decrement 16 bits in register */
4210 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4211 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4212 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4221 /* If the next instruction is a goto and the goto target
4222 * is <= 5 instructions previous to this, we can generate
4223 * jumps straight to that target.
4225 if (ic->next && ic->next->op == GOTO
4226 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4229 emitcode (";", "tail decrement optimized (range %d)", labelRange);
4230 tlbl = IC_LABEL (ic->next);
4235 tlbl = newiTempLabel (NULL);
4239 l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
4240 emitcode ("dec", "%s", l);
4242 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4243 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4244 IS_AOP_PREG (IC_RESULT (ic)))
4246 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4250 emitcode ("mov", "a,#!constbyte",0xff);
4251 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4253 l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
4254 emitcode ("dec", "%s", l);
4257 if (!strcmp(l, "acc"))
4259 emitcode("jnz", "!tlabel", tlbl->key + 100);
4261 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4262 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4263 IS_AOP_PREG (IC_RESULT (ic)))
4265 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4269 emitcode ("mov", "a,#!constbyte",0xff);
4270 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4272 l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
4273 emitcode ("dec", "%s", l);
4277 if (!strcmp(l, "acc"))
4279 emitcode("jnz", "!tlabel", tlbl->key + 100);
4281 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4282 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4283 IS_AOP_PREG (IC_RESULT (ic)))
4285 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4289 emitcode ("mov", "a,#!constbyte",0xff);
4290 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4292 l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
4293 emitcode ("dec", "%s", l);
4297 emitcode ("", "!tlabeldef", tlbl->key + 100);
4302 /* if the sizes are greater than 1 then we cannot */
4303 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4304 AOP_SIZE (IC_LEFT (ic)) > 1)
4307 /* we can if the aops of the left & result match or
4308 if they are in registers and the registers are the
4311 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4312 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4313 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4316 _startLazyDPSEvaluation ();
4319 emitcode ("dec", "%s",
4320 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
4322 _endLazyDPSEvaluation ();
4330 /*-----------------------------------------------------------------*/
4331 /* addSign - complete with sign */
4332 /*-----------------------------------------------------------------*/
4334 addSign (operand * result, int offset, int sign)
4336 int size = (getDataSize (result) - offset);
4339 _startLazyDPSEvaluation();
4342 emitcode ("rlc", "a");
4343 emitcode ("subb", "a,acc");
4346 aopPut (AOP (result), "a", offset++);
4353 aopPut (AOP (result), zero, offset++);
4356 _endLazyDPSEvaluation();
4360 /*-----------------------------------------------------------------*/
4361 /* genMinusBits - generates code for subtraction of two bits */
4362 /*-----------------------------------------------------------------*/
4364 genMinusBits (iCode * ic)
4366 symbol *lbl = newiTempLabel (NULL);
4368 D (emitcode (";", "genMinusBits "););
4370 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4372 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4373 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4374 emitcode ("cpl", "c");
4375 emitcode ("", "!tlabeldef", (lbl->key + 100));
4376 outBitC (IC_RESULT (ic));
4380 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4381 emitcode ("subb", "a,acc");
4382 emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4383 emitcode ("inc", "a");
4384 emitcode ("", "!tlabeldef", (lbl->key + 100));
4385 aopPut (AOP (IC_RESULT (ic)), "a", 0);
4386 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4390 /*-----------------------------------------------------------------*/
4391 /* genMinus - generates code for subtraction */
4392 /*-----------------------------------------------------------------*/
4394 genMinus (iCode * ic)
4396 int size, offset = 0;
4401 D (emitcode (";", "genMinus "););
4403 AOP_OP_3_NOFATAL(ic, pushResult);
4407 /* special cases :- */
4408 /* if both left & right are in bit space */
4409 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4410 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4416 /* if I can do an decrement instead
4417 of subtract then GOOD for ME */
4418 if (genMinusDec (ic) == TRUE)
4423 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4425 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4431 lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4436 /* if literal, add a,#-lit, else normal subb */
4437 _startLazyDPSEvaluation ();
4439 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4440 if (AOP_USESDPTR(IC_RIGHT(ic))) {
4441 emitcode ("mov","b,%s",
4442 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4443 MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4444 emitcode ("subb","a,b");
4446 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4447 emitcode ("subb", "a,%s",
4448 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE,
4452 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4453 /* first add without previous c */
4455 if (!size && lit==-1) {
4456 emitcode ("dec", "a");
4458 emitcode ("add", "a,#!constbyte",
4459 (unsigned int) (lit & 0x0FFL));
4462 emitcode ("addc", "a,#!constbyte",
4463 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4468 emitcode ("push", "acc");
4470 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4474 _endLazyDPSEvaluation ();
4478 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4480 size = getDataSize (IC_LEFT (ic));
4481 rSize = getDataSize (IC_RESULT (ic));
4483 ADJUST_PUSHED_RESULT(size, rSize);
4485 _startLazyDPSEvaluation ();
4488 emitcode ("pop", "acc");
4489 aopPut (AOP (IC_RESULT (ic)), "a", size);
4491 _endLazyDPSEvaluation ();
4494 adjustArithmeticResult (ic);
4497 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4498 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4499 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4503 /*-----------------------------------------------------------------*/
4504 /* genMultbits :- multiplication of bits */
4505 /*-----------------------------------------------------------------*/
4507 genMultbits (operand * left,
4512 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4513 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4514 aopOp(result, ic, TRUE, FALSE);
4519 /*-----------------------------------------------------------------*/
4520 /* genMultOneByte : 8*8=8/16 bit multiplication */
4521 /*-----------------------------------------------------------------*/
4523 genMultOneByte (operand * left,
4528 sym_link *opetype = operandType (result);
4532 /* (if two literals: the value is computed before) */
4533 /* if one literal, literal on the right */
4534 if (AOP_TYPE (left) == AOP_LIT)
4539 emitcode (";", "swapped left and right");
4542 if (SPEC_USIGN(opetype)
4543 // ignore the sign of left and right, what else can we do?
4544 || (SPEC_USIGN(operandType(left)) &&
4545 SPEC_USIGN(operandType(right)))) {
4546 // just an unsigned 8*8=8/16 multiply
4547 //emitcode (";","unsigned");
4548 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4549 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4550 emitcode ("mul", "ab");
4552 _G.accInUse++; _G.bInUse++;
4553 aopOp(result, ic, TRUE, FALSE);
4555 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4557 // this should never happen
4558 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4559 AOP_SIZE(result), __FILE__, lineno);
4563 aopPut (AOP (result), "a", 0);
4564 _G.accInUse--; _G.bInUse--;
4565 if (AOP_SIZE(result)==2)
4567 aopPut (AOP (result), "b", 1);
4572 // we have to do a signed multiply
4574 emitcode (";", "signed");
4575 emitcode ("clr", "F0"); // reset sign flag
4576 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4578 lbl=newiTempLabel(NULL);
4579 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4580 // left side is negative, 8-bit two's complement, this fails for -128
4581 emitcode ("setb", "F0"); // set sign flag
4582 emitcode ("cpl", "a");
4583 emitcode ("inc", "a");
4585 emitcode ("", "!tlabeldef", lbl->key+100);
4588 if (AOP_TYPE(right)==AOP_LIT) {
4589 signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
4590 /* AND literal negative */
4591 if ((int) val < 0) {
4592 emitcode ("cpl", "F0"); // complement sign flag
4593 emitcode ("mov", "b,#!constbyte", -val);
4595 emitcode ("mov", "b,#!constbyte", val);
4598 lbl=newiTempLabel(NULL);
4599 emitcode ("mov", "b,a");
4600 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4601 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4602 // right side is negative, 8-bit two's complement
4603 emitcode ("cpl", "F0"); // complement sign flag
4604 emitcode ("cpl", "a");
4605 emitcode ("inc", "a");
4606 emitcode ("", "!tlabeldef", lbl->key+100);
4608 emitcode ("mul", "ab");
4610 _G.accInUse++;_G.bInUse++;
4611 aopOp(result, ic, TRUE, FALSE);
4613 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4615 // this should never happen
4616 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4617 AOP_SIZE(result), __FILE__, lineno);
4621 lbl=newiTempLabel(NULL);
4622 emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4623 // only ONE op was negative, we have to do a 8/16-bit two's complement
4624 emitcode ("cpl", "a"); // lsb
4625 if (AOP_SIZE(result)==1) {
4626 emitcode ("inc", "a");
4628 emitcode ("add", "a,#1");
4629 emitcode ("xch", "a,b");
4630 emitcode ("cpl", "a"); // msb
4631 emitcode ("addc", "a,#0");
4632 emitcode ("xch", "a,b");
4635 emitcode ("", "!tlabeldef", lbl->key+100);
4636 aopPut (AOP (result), "a", 0);
4637 _G.accInUse--;_G.bInUse--;
4638 if (AOP_SIZE(result)==2) {
4639 aopPut (AOP (result), "b", 1);
4643 /*-----------------------------------------------------------------*/
4644 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
4645 /*-----------------------------------------------------------------*/
4646 static void genMultTwoByte (operand *left, operand *right,
4647 operand *result, iCode *ic)
4649 sym_link *retype = getSpec(operandType(right));
4650 sym_link *letype = getSpec(operandType(left));
4651 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4654 if (AOP_TYPE (left) == AOP_LIT) {
4659 /* save EA bit in F1 */
4660 lbl = newiTempLabel(NULL);
4661 emitcode ("setb","F1");
4662 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4663 emitcode ("clr","F1");
4664 emitcode("","!tlabeldef",lbl->key+100);
4666 /* load up MB with right */
4668 emitcode("clr","F0");
4669 if (AOP_TYPE(right) == AOP_LIT) {
4670 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
4672 emitcode("setb","F0");
4675 emitcode ("mov","mb,#!constbyte",val & 0xff);
4676 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4678 lbl = newiTempLabel(NULL);
4679 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4680 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4681 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4682 emitcode ("xch", "a,b");
4683 emitcode ("cpl","a");
4684 emitcode ("add", "a,#1");
4685 emitcode ("xch", "a,b");
4686 emitcode ("cpl", "a"); // msb
4687 emitcode ("addc", "a,#0");
4688 emitcode ("setb","F0");
4689 emitcode ("","!tlabeldef",lbl->key+100);
4690 emitcode ("mov","mb,b");
4691 emitcode ("mov","mb,a");
4694 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4695 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4697 /* load up MA with left */
4699 lbl = newiTempLabel(NULL);
4700 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4701 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4702 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4703 emitcode ("xch", "a,b");
4704 emitcode ("cpl","a");
4705 emitcode ("add", "a,#1");
4706 emitcode ("xch", "a,b");
4707 emitcode ("cpl", "a"); // msb
4708 emitcode ("addc","a,#0");
4709 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4710 emitcode ("setb","F0");
4711 emitcode ("","!tlabeldef",lbl->key+100);
4712 emitcode ("mov","ma,b");
4713 emitcode ("mov","ma,a");
4715 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4716 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4718 /* wait for multiplication to finish */
4719 lbl = newiTempLabel(NULL);
4720 emitcode("","!tlabeldef", lbl->key+100);
4721 emitcode("mov","a,mcnt1");
4722 emitcode("anl","a,#!constbyte",0x80);
4723 emitcode("jnz","!tlabel",lbl->key+100);
4725 freeAsmop (left, NULL, ic, TRUE);
4726 freeAsmop (right, NULL, ic,TRUE);
4727 aopOp(result, ic, TRUE, FALSE);
4729 /* if unsigned then simple */
4731 emitcode ("mov","a,ma");
4732 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4733 emitcode ("mov","a,ma");
4734 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4735 aopPut(AOP(result),"ma",1);
4736 aopPut(AOP(result),"ma",0);
4738 emitcode("push","ma");
4739 emitcode("push","ma");
4740 emitcode("push","ma");
4742 /* negate result if needed */
4743 lbl = newiTempLabel(NULL);
4744 emitcode("jnb","F0,!tlabel",lbl->key+100);
4745 emitcode("cpl","a");
4746 emitcode("add","a,#1");
4747 emitcode("","!tlabeldef", lbl->key+100);
4748 if (AOP_TYPE(result) == AOP_ACC)
4750 D(emitcode(";", "ACC special case."););
4751 /* We know result is the only live aop, and
4752 * it's obviously not a DPTR2, so AP is available.
4754 emitcode("mov", "%s,acc", DP2_RESULT_REG);
4758 aopPut(AOP(result),"a",0);
4761 emitcode("pop","acc");
4762 lbl = newiTempLabel(NULL);
4763 emitcode("jnb","F0,!tlabel",lbl->key+100);
4764 emitcode("cpl","a");
4765 emitcode("addc","a,#0");
4766 emitcode("","!tlabeldef", lbl->key+100);
4767 aopPut(AOP(result),"a",1);
4768 emitcode("pop","acc");
4769 if (AOP_SIZE(result) >= 3) {
4770 lbl = newiTempLabel(NULL);
4771 emitcode("jnb","F0,!tlabel",lbl->key+100);
4772 emitcode("cpl","a");
4773 emitcode("addc","a,#0");
4774 emitcode("","!tlabeldef", lbl->key+100);
4775 aopPut(AOP(result),"a",2);
4777 emitcode("pop","acc");
4778 if (AOP_SIZE(result) >= 4) {
4779 lbl = newiTempLabel(NULL);
4780 emitcode("jnb","F0,!tlabel",lbl->key+100);
4781 emitcode("cpl","a");
4782 emitcode("addc","a,#0");
4783 emitcode("","!tlabeldef", lbl->key+100);
4784 aopPut(AOP(result),"a",3);
4786 if (AOP_TYPE(result) == AOP_ACC)
4788 /* We stashed the result away above. */
4789 emitcode("mov", "acc,%s", DP2_RESULT_REG);
4793 freeAsmop (result, NULL, ic, TRUE);
4795 /* restore EA bit in F1 */
4796 lbl = newiTempLabel(NULL);
4797 emitcode ("jnb","F1,!tlabel",lbl->key+100);
4798 emitcode ("setb","EA");
4799 emitcode("","!tlabeldef",lbl->key+100);
4803 /*-----------------------------------------------------------------*/
4804 /* genMult - generates code for multiplication */
4805 /*-----------------------------------------------------------------*/
4807 genMult (iCode * ic)
4809 operand *left = IC_LEFT (ic);
4810 operand *right = IC_RIGHT (ic);
4811 operand *result = IC_RESULT (ic);
4813 D (emitcode (";", "genMult "););
4815 /* assign the amsops */
4818 /* special cases first */
4820 if (AOP_TYPE (left) == AOP_CRY &&
4821 AOP_TYPE (right) == AOP_CRY)
4823 genMultbits (left, right, result, ic);
4827 /* if both are of size == 1 */
4828 if (AOP_SIZE (left) == 1 &&
4829 AOP_SIZE (right) == 1)
4831 genMultOneByte (left, right, result, ic);
4835 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4836 /* use the ds390 ARITHMETIC accel UNIT */
4837 genMultTwoByte (left, right, result, ic);
4840 /* should have been converted to function call */
4844 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4845 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4846 freeAsmop (result, NULL, ic, TRUE);
4849 /*-----------------------------------------------------------------*/
4850 /* genDivbits :- division of bits */
4851 /*-----------------------------------------------------------------*/
4853 genDivbits (operand * left,
4861 /* the result must be bit */
4862 LOAD_AB_FOR_DIV (left, right, l);
4863 emitcode ("div", "ab");
4864 emitcode ("rrc", "a");
4865 aopOp(result, ic, TRUE, FALSE);
4867 aopPut (AOP (result), "c", 0);
4870 /*-----------------------------------------------------------------*/
4871 /* genDivOneByte : 8 bit division */
4872 /*-----------------------------------------------------------------*/
4874 genDivOneByte (operand * left,
4879 sym_link *opetype = operandType (result);
4885 /* signed or unsigned */
4886 if (SPEC_USIGN (opetype))
4888 /* unsigned is easy */
4889 LOAD_AB_FOR_DIV (left, right, l);
4890 emitcode ("div", "ab");
4893 aopOp(result, ic, TRUE, FALSE);
4894 aopPut (AOP (result), "a", 0);
4897 size = AOP_SIZE (result) - 1;
4901 aopPut (AOP (result), zero, offset++);
4906 /* signed is a little bit more difficult */
4908 /* save the signs of the operands */
4909 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4910 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4911 emitcode ("push", "acc"); /* save it on the stack */
4913 /* now sign adjust for both left & right */
4914 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4915 lbl = newiTempLabel (NULL);
4916 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4917 emitcode ("cpl", "a");
4918 emitcode ("inc", "a");
4919 emitcode ("", "!tlabeldef", (lbl->key + 100));
4920 emitcode ("mov", "b,a");
4922 /* sign adjust left side */
4923 MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4925 lbl = newiTempLabel (NULL);
4926 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4927 emitcode ("cpl", "a");
4928 emitcode ("inc", "a");
4929 emitcode ("", "!tlabeldef", (lbl->key + 100));
4931 /* now the division */
4932 emitcode ("nop", "; workaround for DS80C390 div bug.");
4933 emitcode ("div", "ab");
4934 /* we are interested in the lower order
4936 emitcode ("mov", "b,a");
4937 lbl = newiTempLabel (NULL);
4938 emitcode ("pop", "acc");
4939 /* if there was an over flow we don't
4940 adjust the sign of the result */
4941 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4942 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4944 emitcode ("clr", "a");
4945 emitcode ("subb", "a,b");
4946 emitcode ("mov", "b,a");
4947 emitcode ("", "!tlabeldef", (lbl->key + 100));
4949 /* now we are done */
4950 _G.accInUse++; _G.bInUse++;
4951 aopOp(result, ic, TRUE, FALSE);
4953 aopPut (AOP (result), "b", 0);
4955 size = AOP_SIZE (result) - 1;
4959 emitcode ("mov", "c,b.7");
4960 emitcode ("subb", "a,acc");
4964 aopPut (AOP (result), "a", offset++);
4966 _G.accInUse--; _G.bInUse--;
4970 /*-----------------------------------------------------------------*/
4971 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
4972 /*-----------------------------------------------------------------*/
4973 static void genDivTwoByte (operand *left, operand *right,
4974 operand *result, iCode *ic)
4976 sym_link *retype = getSpec(operandType(right));
4977 sym_link *letype = getSpec(operandType(left));
4978 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4981 /* save EA bit in F1 */
4982 lbl = newiTempLabel(NULL);
4983 emitcode ("setb","F1");
4984 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4985 emitcode ("clr","F1");
4986 emitcode("","!tlabeldef",lbl->key+100);
4988 /* load up MA with left */
4990 emitcode("clr","F0");
4991 lbl = newiTempLabel(NULL);
4992 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4993 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4994 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4995 emitcode ("xch", "a,b");
4996 emitcode ("cpl","a");
4997 emitcode ("add", "a,#1");
4998 emitcode ("xch", "a,b");
4999 emitcode ("cpl", "a"); // msb
5000 emitcode ("addc","a,#0");
5001 emitcode ("setb","F0");
5002 emitcode ("","!tlabeldef",lbl->key+100);
5003 emitcode ("mov","ma,b");
5004 emitcode ("mov","ma,a");
5006 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5007 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5010 /* load up MB with right */
5012 if (AOP_TYPE(right) == AOP_LIT) {
5013 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5015 lbl = newiTempLabel(NULL);
5016 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5017 emitcode("setb","F0");
5018 emitcode ("","!tlabeldef",lbl->key+100);
5021 emitcode ("mov","mb,#!constbyte",val & 0xff);
5022 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5024 lbl = newiTempLabel(NULL);
5025 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5026 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5027 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5028 emitcode ("xch", "a,b");
5029 emitcode ("cpl","a");
5030 emitcode ("add", "a,#1");
5031 emitcode ("xch", "a,b");
5032 emitcode ("cpl", "a"); // msb
5033 emitcode ("addc", "a,#0");
5034 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5035 emitcode ("setb","F0");
5036 emitcode ("","!tlabeldef",lbl->key+100);
5037 emitcode ("mov","mb,b");
5038 emitcode ("mov","mb,a");
5041 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5042 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5045 /* wait for multiplication to finish */
5046 lbl = newiTempLabel(NULL);
5047 emitcode("","!tlabeldef", lbl->key+100);
5048 emitcode("mov","a,mcnt1");
5049 emitcode("anl","a,#!constbyte",0x80);
5050 emitcode("jnz","!tlabel",lbl->key+100);
5052 freeAsmop (left, NULL, ic, TRUE);
5053 freeAsmop (right, NULL, ic,TRUE);
5054 aopOp(result, ic, TRUE, FALSE);
5056 /* if unsigned then simple */
5058 aopPut(AOP(result),"ma",1);
5059 aopPut(AOP(result),"ma",0);
5061 emitcode("push","ma");
5063 /* negate result if needed */
5064 lbl = newiTempLabel(NULL);
5065 emitcode("jnb","F0,!tlabel",lbl->key+100);
5066 emitcode("cpl","a");
5067 emitcode("add","a,#1");
5068 emitcode("","!tlabeldef", lbl->key+100);
5069 aopPut(AOP(result),"a",0);
5070 emitcode("pop","acc");
5071 lbl = newiTempLabel(NULL);
5072 emitcode("jnb","F0,!tlabel",lbl->key+100);
5073 emitcode("cpl","a");
5074 emitcode("addc","a,#0");
5075 emitcode("","!tlabeldef", lbl->key+100);
5076 aopPut(AOP(result),"a",1);
5078 freeAsmop (result, NULL, ic, TRUE);
5079 /* restore EA bit in F1 */
5080 lbl = newiTempLabel(NULL);
5081 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5082 emitcode ("setb","EA");
5083 emitcode("","!tlabeldef",lbl->key+100);
5087 /*-----------------------------------------------------------------*/
5088 /* genDiv - generates code for division */
5089 /*-----------------------------------------------------------------*/
5093 operand *left = IC_LEFT (ic);
5094 operand *right = IC_RIGHT (ic);
5095 operand *result = IC_RESULT (ic);
5097 D (emitcode (";", "genDiv "););
5099 /* assign the amsops */
5102 /* special cases first */
5104 if (AOP_TYPE (left) == AOP_CRY &&
5105 AOP_TYPE (right) == AOP_CRY)
5107 genDivbits (left, right, result, ic);
5111 /* if both are of size == 1 */
5112 if (AOP_SIZE (left) == 1 &&
5113 AOP_SIZE (right) == 1)
5115 genDivOneByte (left, right, result, ic);
5119 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5120 /* use the ds390 ARITHMETIC accel UNIT */
5121 genDivTwoByte (left, right, result, ic);
5124 /* should have been converted to function call */
5127 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5128 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5129 freeAsmop (result, NULL, ic, TRUE);
5132 /*-----------------------------------------------------------------*/
5133 /* genModbits :- modulus of bits */
5134 /*-----------------------------------------------------------------*/
5136 genModbits (operand * left,
5144 /* the result must be bit */
5145 LOAD_AB_FOR_DIV (left, right, l);
5146 emitcode ("div", "ab");
5147 emitcode ("mov", "a,b");
5148 emitcode ("rrc", "a");
5149 aopOp(result, ic, TRUE, FALSE);
5150 aopPut (AOP (result), "c", 0);
5153 /*-----------------------------------------------------------------*/
5154 /* genModOneByte : 8 bit modulus */
5155 /*-----------------------------------------------------------------*/
5157 genModOneByte (operand * left,
5162 sym_link *opetype = operandType (result);
5166 /* signed or unsigned */
5167 if (SPEC_USIGN (opetype))
5169 /* unsigned is easy */
5170 LOAD_AB_FOR_DIV (left, right, l);
5171 emitcode ("div", "ab");
5172 aopOp(result, ic, TRUE, FALSE);
5173 aopPut (AOP (result), "b", 0);
5177 /* signed is a little bit more difficult */
5179 /* save the signs of the operands */
5180 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5182 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
5183 emitcode ("push", "acc"); /* save it on the stack */
5185 /* now sign adjust for both left & right */
5186 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5188 lbl = newiTempLabel (NULL);
5189 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5190 emitcode ("cpl", "a");
5191 emitcode ("inc", "a");
5192 emitcode ("", "!tlabeldef", (lbl->key + 100));
5193 emitcode ("mov", "b,a");
5195 /* sign adjust left side */
5196 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5198 lbl = newiTempLabel (NULL);
5199 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5200 emitcode ("cpl", "a");
5201 emitcode ("inc", "a");
5202 emitcode ("", "!tlabeldef", (lbl->key + 100));
5204 /* now the multiplication */
5205 emitcode ("nop", "; workaround for DS80C390 div bug.");
5206 emitcode ("div", "ab");
5207 /* we are interested in the lower order
5209 lbl = newiTempLabel (NULL);
5210 emitcode ("pop", "acc");
5211 /* if there was an over flow we don't
5212 adjust the sign of the result */
5213 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
5214 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5216 emitcode ("clr", "a");
5217 emitcode ("subb", "a,b");
5218 emitcode ("mov", "b,a");
5219 emitcode ("", "!tlabeldef", (lbl->key + 100));
5222 /* now we are done */
5223 aopOp(result, ic, TRUE, FALSE);
5224 aopPut (AOP (result), "b", 0);
5229 /*-----------------------------------------------------------------*/
5230 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
5231 /*-----------------------------------------------------------------*/
5232 static void genModTwoByte (operand *left, operand *right,
5233 operand *result, iCode *ic)
5235 sym_link *retype = getSpec(operandType(right));
5236 sym_link *letype = getSpec(operandType(left));
5237 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5240 /* load up MA with left */
5241 /* save EA bit in F1 */
5242 lbl = newiTempLabel(NULL);
5243 emitcode ("setb","F1");
5244 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5245 emitcode ("clr","F1");
5246 emitcode("","!tlabeldef",lbl->key+100);
5249 lbl = newiTempLabel(NULL);
5250 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5251 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5252 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5253 emitcode ("xch", "a,b");
5254 emitcode ("cpl","a");
5255 emitcode ("add", "a,#1");
5256 emitcode ("xch", "a,b");
5257 emitcode ("cpl", "a"); // msb
5258 emitcode ("addc","a,#0");
5259 emitcode ("","!tlabeldef",lbl->key+100);
5260 emitcode ("mov","ma,b");
5261 emitcode ("mov","ma,a");
5263 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5264 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5267 /* load up MB with right */
5269 if (AOP_TYPE(right) == AOP_LIT) {
5270 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5274 emitcode ("mov","mb,#!constbyte",val & 0xff);
5275 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5277 lbl = newiTempLabel(NULL);
5278 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5279 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5280 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5281 emitcode ("xch", "a,b");
5282 emitcode ("cpl","a");
5283 emitcode ("add", "a,#1");
5284 emitcode ("xch", "a,b");
5285 emitcode ("cpl", "a"); // msb
5286 emitcode ("addc", "a,#0");
5287 emitcode ("","!tlabeldef",lbl->key+100);
5288 emitcode ("mov","mb,b");
5289 emitcode ("mov","mb,a");
5292 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5293 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5296 /* wait for multiplication to finish */
5297 lbl = newiTempLabel(NULL);
5298 emitcode("","!tlabeldef", lbl->key+100);
5299 emitcode("mov","a,mcnt1");
5300 emitcode("anl","a,#!constbyte",0x80);
5301 emitcode("jnz","!tlabel",lbl->key+100);
5303 freeAsmop (left, NULL, ic, TRUE);
5304 freeAsmop (right, NULL, ic,TRUE);
5305 aopOp(result, ic, TRUE, FALSE);
5307 aopPut(AOP(result),"mb",1);
5308 aopPut(AOP(result),"mb",0);
5309 freeAsmop (result, NULL, ic, TRUE);
5311 /* restore EA bit in F1 */
5312 lbl = newiTempLabel(NULL);
5313 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5314 emitcode ("setb","EA");
5315 emitcode("","!tlabeldef",lbl->key+100);
5319 /*-----------------------------------------------------------------*/
5320 /* genMod - generates code for division */
5321 /*-----------------------------------------------------------------*/
5325 operand *left = IC_LEFT (ic);
5326 operand *right = IC_RIGHT (ic);
5327 operand *result = IC_RESULT (ic);
5329 D (emitcode (";", "genMod "); );
5331 /* assign the amsops */
5334 /* special cases first */
5336 if (AOP_TYPE (left) == AOP_CRY &&
5337 AOP_TYPE (right) == AOP_CRY)
5339 genModbits (left, right, result, ic);
5343 /* if both are of size == 1 */
5344 if (AOP_SIZE (left) == 1 &&
5345 AOP_SIZE (right) == 1)
5347 genModOneByte (left, right, result, ic);
5351 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5352 /* use the ds390 ARITHMETIC accel UNIT */
5353 genModTwoByte (left, right, result, ic);
5357 /* should have been converted to function call */
5361 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5362 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5363 freeAsmop (result, NULL, ic, TRUE);
5366 /*-----------------------------------------------------------------*/
5367 /* genIfxJump :- will create a jump depending on the ifx */
5368 /*-----------------------------------------------------------------*/
5370 genIfxJump (iCode * ic, char *jval)
5373 symbol *tlbl = newiTempLabel (NULL);
5376 D (emitcode (";", "genIfxJump"););
5378 /* if true label then we jump if condition
5382 jlbl = IC_TRUE (ic);
5383 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5384 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5388 /* false label is present */
5389 jlbl = IC_FALSE (ic);
5390 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5391 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5393 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5394 emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5396 emitcode (inst, "!tlabel", tlbl->key + 100);
5397 emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5398 emitcode ("", "!tlabeldef", tlbl->key + 100);
5400 /* mark the icode as generated */
5404 /*-----------------------------------------------------------------*/
5405 /* genCmp :- greater or less than comparison */
5406 /*-----------------------------------------------------------------*/
5408 genCmp (operand * left, operand * right,
5409 iCode * ic, iCode * ifx, int sign)
5411 int size, offset = 0;
5412 unsigned long lit = 0L;
5415 D (emitcode (";", "genCmp"););
5417 result = IC_RESULT (ic);
5419 /* if left & right are bit variables */
5420 if (AOP_TYPE (left) == AOP_CRY &&
5421 AOP_TYPE (right) == AOP_CRY)
5423 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5424 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5428 /* subtract right from left if at the
5429 end the carry flag is set then we know that
5430 left is greater than right */
5431 size = max (AOP_SIZE (left), AOP_SIZE (right));
5433 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5434 if ((size == 1) && !sign
5435 && (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5437 symbol *lbl = newiTempLabel (NULL);
5438 emitcode ("cjne", "%s,%s,!tlabel",
5439 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
5440 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5442 emitcode ("", "!tlabeldef", lbl->key + 100);
5446 if (AOP_TYPE (right) == AOP_LIT)
5448 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5449 /* optimize if(x < 0) or if(x >= 0) */
5458 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
5460 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5461 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5463 aopOp (result, ic, FALSE, FALSE);
5465 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5467 freeAsmop (result, NULL, ic, TRUE);
5468 genIfxJump (ifx, "acc.7");
5473 emitcode ("rlc", "a");
5475 goto release_freedLR;
5483 // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5484 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5485 // emitcode (";", "genCmp #2");
5486 if (sign && (size == 0))
5488 // emitcode (";", "genCmp #3");
5489 emitcode ("xrl", "a,#!constbyte",0x80);
5490 if (AOP_TYPE (right) == AOP_LIT)
5492 unsigned long lit = (unsigned long)
5493 floatFromVal (AOP (right)->aopu.aop_lit);
5494 // emitcode (";", "genCmp #3.1");
5495 emitcode ("subb", "a,#!constbyte",
5496 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5500 // emitcode (";", "genCmp #3.2");
5502 MOVB(aopGet (AOP (right), offset++, FALSE, FALSE, "b"));
5503 saveAccWarn = DEFAULT_ACC_WARNING;
5504 emitcode ("xrl", "b,#!constbyte",0x80);
5505 emitcode ("subb", "a,b");
5512 // emitcode (";", "genCmp #4");
5514 s = aopGet (AOP (right), offset++, FALSE, FALSE, "b");
5515 saveAccWarn = DEFAULT_ACC_WARNING;
5517 emitcode ("subb", "a,%s", s);
5524 /* Don't need the left & right operands any more; do need the result. */
5525 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5526 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5528 aopOp (result, ic, FALSE, FALSE);
5532 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5538 /* if the result is used in the next
5539 ifx conditional branch then generate
5540 code a little differently */
5543 genIfxJump (ifx, "c");
5549 /* leave the result in acc */
5551 freeAsmop (result, NULL, ic, TRUE);
5554 /*-----------------------------------------------------------------*/
5555 /* genCmpGt :- greater than comparison */
5556 /*-----------------------------------------------------------------*/
5558 genCmpGt (iCode * ic, iCode * ifx)
5560 operand *left, *right;
5561 sym_link *letype, *retype;
5564 D (emitcode (";", "genCmpGt ");
5567 left = IC_LEFT (ic);
5568 right = IC_RIGHT (ic);
5570 letype = getSpec (operandType (left));
5571 retype = getSpec (operandType (right));
5572 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5574 /* assign the left & right amsops */
5577 genCmp (right, left, ic, ifx, sign);
5580 /*-----------------------------------------------------------------*/
5581 /* genCmpLt - less than comparisons */
5582 /*-----------------------------------------------------------------*/
5584 genCmpLt (iCode * ic, iCode * ifx)
5586 operand *left, *right;
5587 sym_link *letype, *retype;
5590 D (emitcode (";", "genCmpLt "););
5592 left = IC_LEFT (ic);
5593 right = IC_RIGHT (ic);
5595 letype = getSpec (operandType (left));
5596 retype = getSpec (operandType (right));
5597 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5599 /* assign the left & right amsops */
5602 genCmp (left, right, ic, ifx, sign);
5605 /*-----------------------------------------------------------------*/
5606 /* gencjneshort - compare and jump if not equal */
5607 /*-----------------------------------------------------------------*/
5609 gencjneshort (operand * left, operand * right, symbol * lbl)
5611 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5613 unsigned long lit = 0L;
5615 D (emitcode (";", "gencjneshort");
5618 /* if the left side is a literal or
5619 if the right is in a pointer register and left
5621 if ((AOP_TYPE (left) == AOP_LIT) ||
5622 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5629 if (AOP_TYPE (right) == AOP_LIT)
5630 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5632 if (opIsGptr (left) || opIsGptr (right))
5634 /* We are comparing a generic pointer to something.
5635 * Exclude the generic type byte from the comparison.
5638 D (emitcode (";", "cjneshort: generic ptr special case."););
5642 /* if the right side is a literal then anything goes */
5643 if (AOP_TYPE (right) == AOP_LIT &&
5644 AOP_TYPE (left) != AOP_DIR)
5648 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5649 emitcode ("cjne", "a,%s,!tlabel",
5650 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5656 /* if the right side is in a register or in direct space or
5657 if the left is a pointer register & right is not */
5658 else if (AOP_TYPE (right) == AOP_REG ||
5659 AOP_TYPE (right) == AOP_DIR ||
5660 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5661 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5665 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5666 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5667 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5668 emitcode ("jnz", "!tlabel", lbl->key + 100);
5670 emitcode ("cjne", "a,%s,!tlabel",
5671 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
5678 /* right is a pointer reg need both a & b */
5681 MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5682 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
5683 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5689 /*-----------------------------------------------------------------*/
5690 /* gencjne - compare and jump if not equal */
5691 /*-----------------------------------------------------------------*/
5693 gencjne (operand * left, operand * right, symbol * lbl)
5695 symbol *tlbl = newiTempLabel (NULL);
5697 D (emitcode (";", "gencjne");
5700 gencjneshort (left, right, lbl);
5702 emitcode ("mov", "a,%s", one);
5703 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5704 emitcode ("", "!tlabeldef", lbl->key + 100);
5705 emitcode ("clr", "a");
5706 emitcode ("", "!tlabeldef", tlbl->key + 100);
5709 /*-----------------------------------------------------------------*/
5710 /* genCmpEq - generates code for equal to */
5711 /*-----------------------------------------------------------------*/
5713 genCmpEq (iCode * ic, iCode * ifx)
5715 operand *left, *right, *result;
5717 D (emitcode (";", "genCmpEq ");
5721 AOP_SET_LOCALS (ic);
5723 /* if literal, literal on the right or
5724 if the right is in a pointer register and left
5726 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5727 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5729 operand *t = IC_RIGHT (ic);
5730 IC_RIGHT (ic) = IC_LEFT (ic);
5734 if (ifx && /* !AOP_SIZE(result) */
5735 OP_SYMBOL (result) &&
5736 OP_SYMBOL (result)->regType == REG_CND)
5739 /* if they are both bit variables */
5740 if (AOP_TYPE (left) == AOP_CRY &&
5741 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5743 if (AOP_TYPE (right) == AOP_LIT)
5745 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5748 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5749 emitcode ("cpl", "c");
5753 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5757 emitcode ("clr", "c");
5759 /* AOP_TYPE(right) == AOP_CRY */
5763 symbol *lbl = newiTempLabel (NULL);
5764 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5765 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5766 emitcode ("cpl", "c");
5767 emitcode ("", "!tlabeldef", (lbl->key + 100));
5769 /* if true label then we jump if condition
5771 tlbl = newiTempLabel (NULL);
5774 emitcode ("jnc", "!tlabel", tlbl->key + 100);
5775 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5779 emitcode ("jc", "!tlabel", tlbl->key + 100);
5780 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5782 emitcode ("", "!tlabeldef", tlbl->key + 100);
5786 tlbl = newiTempLabel (NULL);
5787 gencjneshort (left, right, tlbl);
5790 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5791 emitcode ("", "!tlabeldef", tlbl->key + 100);
5795 symbol *lbl = newiTempLabel (NULL);
5796 emitcode ("sjmp", "!tlabel", lbl->key + 100);
5797 emitcode ("", "!tlabeldef", tlbl->key + 100);
5798 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5799 emitcode ("", "!tlabeldef", lbl->key + 100);
5802 /* mark the icode as generated */
5805 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5806 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5810 /* if they are both bit variables */
5811 if (AOP_TYPE (left) == AOP_CRY &&
5812 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5814 if (AOP_TYPE (right) == AOP_LIT)
5816 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5819 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5820 emitcode ("cpl", "c");
5824 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5828 emitcode ("clr", "c");
5830 /* AOP_TYPE(right) == AOP_CRY */
5834 symbol *lbl = newiTempLabel (NULL);
5835 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5836 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5837 emitcode ("cpl", "c");
5838 emitcode ("", "!tlabeldef", (lbl->key + 100));
5841 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5842 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5844 aopOp (result, ic, TRUE, FALSE);
5847 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5854 genIfxJump (ifx, "c");
5857 /* if the result is used in an arithmetic operation
5858 then put the result in place */
5863 gencjne (left, right, newiTempLabel (NULL));
5865 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5866 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5868 aopOp (result, ic, TRUE, FALSE);
5870 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5872 aopPut (AOP (result), "a", 0);
5877 genIfxJump (ifx, "a");
5880 /* if the result is used in an arithmetic operation
5881 then put the result in place */
5882 if (AOP_TYPE (result) != AOP_CRY)
5884 /* leave the result in acc */
5888 freeAsmop (result, NULL, ic, TRUE);
5891 /*-----------------------------------------------------------------*/
5892 /* ifxForOp - returns the icode containing the ifx for operand */
5893 /*-----------------------------------------------------------------*/
5895 ifxForOp (operand * op, iCode * ic)
5897 /* if true symbol then needs to be assigned */
5898 if (IS_TRUE_SYMOP (op))
5901 /* if this has register type condition and
5902 the next instruction is ifx with the same operand
5903 and live to of the operand is upto the ifx only then */
5905 ic->next->op == IFX &&
5906 IC_COND (ic->next)->key == op->key &&
5907 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5912 /*-----------------------------------------------------------------*/
5913 /* hasInc - operand is incremented before any other use */
5914 /*-----------------------------------------------------------------*/
5916 hasInc (operand *op, iCode *ic, int osize)
5918 sym_link *type = operandType(op);
5919 sym_link *retype = getSpec (type);
5920 iCode *lic = ic->next;
5923 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5924 if (!IS_SYMOP(op)) return NULL;
5926 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5927 if (IS_AGGREGATE(type->next)) return NULL;
5928 if (osize != (isize = getSize(type->next))) return NULL;
5931 /* if operand of the form op = op + <sizeof *op> */
5932 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5933 isOperandEqual(IC_RESULT(lic),op) &&
5934 isOperandLiteral(IC_RIGHT(lic)) &&
5935 operandLitValue(IC_RIGHT(lic)) == isize) {
5938 /* if the operand used or deffed */
5939 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5942 /* if GOTO or IFX */
5943 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5949 /*-----------------------------------------------------------------*/
5950 /* genAndOp - for && operation */
5951 /*-----------------------------------------------------------------*/
5953 genAndOp (iCode * ic)
5955 operand *left, *right, *result;
5958 D (emitcode (";", "genAndOp "););
5960 /* note here that && operations that are in an
5961 if statement are taken away by backPatchLabels
5962 only those used in arthmetic operations remain */
5964 AOP_SET_LOCALS (ic);
5966 /* if both are bit variables */
5967 if (AOP_TYPE (left) == AOP_CRY &&
5968 AOP_TYPE (right) == AOP_CRY)
5970 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5971 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5972 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5973 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5975 aopOp (result,ic,FALSE, FALSE);
5980 tlbl = newiTempLabel (NULL);
5982 emitcode ("jz", "!tlabel", tlbl->key + 100);
5984 emitcode ("", "!tlabeldef", tlbl->key + 100);
5985 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5986 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5988 aopOp (result,ic,FALSE, FALSE);
5991 freeAsmop (result, NULL, ic, TRUE);
5995 /*-----------------------------------------------------------------*/
5996 /* genOrOp - for || operation */
5997 /*-----------------------------------------------------------------*/
5999 genOrOp (iCode * ic)
6001 operand *left, *right, *result;
6004 D (emitcode (";", "genOrOp "););
6006 /* note here that || operations that are in an
6007 if statement are taken away by backPatchLabels
6008 only those used in arthmetic operations remain */
6010 AOP_SET_LOCALS (ic);
6012 /* if both are bit variables */
6013 if (AOP_TYPE (left) == AOP_CRY &&
6014 AOP_TYPE (right) == AOP_CRY)
6016 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6017 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6018 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6019 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6021 aopOp (result,ic,FALSE, FALSE);
6027 tlbl = newiTempLabel (NULL);
6029 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6031 emitcode ("", "!tlabeldef", tlbl->key + 100);
6032 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6033 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6035 aopOp (result,ic,FALSE, FALSE);
6040 freeAsmop (result, NULL, ic, TRUE);
6043 /*-----------------------------------------------------------------*/
6044 /* isLiteralBit - test if lit == 2^n */
6045 /*-----------------------------------------------------------------*/
6047 isLiteralBit (unsigned long lit)
6049 unsigned long pw[32] =
6050 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6051 0x100L, 0x200L, 0x400L, 0x800L,
6052 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6053 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6054 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6055 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6056 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6059 for (idx = 0; idx < 32; idx++)
6065 /*-----------------------------------------------------------------*/
6066 /* continueIfTrue - */
6067 /*-----------------------------------------------------------------*/
6069 continueIfTrue (iCode * ic)
6072 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6076 /*-----------------------------------------------------------------*/
6078 /*-----------------------------------------------------------------*/
6080 jumpIfTrue (iCode * ic)
6083 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6087 /*-----------------------------------------------------------------*/
6088 /* jmpTrueOrFalse - */
6089 /*-----------------------------------------------------------------*/
6091 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6093 // ugly but optimized by peephole
6096 symbol *nlbl = newiTempLabel (NULL);
6097 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6098 emitcode ("", "!tlabeldef", tlbl->key + 100);
6099 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6100 emitcode ("", "!tlabeldef", nlbl->key + 100);
6104 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6105 emitcode ("", "!tlabeldef", tlbl->key + 100);
6110 // Generate code to perform a bit-wise logic operation
6111 // on two operands in far space (assumed to already have been
6112 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6113 // in far space. This requires pushing the result on the stack
6114 // then popping it into the result.
6116 genFarFarLogicOp(iCode *ic, char *logicOp)
6118 int size, resultSize, compSize;
6122 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6123 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
6124 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6126 _startLazyDPSEvaluation();
6127 for (size = compSize; (size--); offset++)
6129 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6130 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6131 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6133 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6134 emitcode ("push", "acc");
6136 _endLazyDPSEvaluation();
6138 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6139 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6140 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6142 resultSize = AOP_SIZE(IC_RESULT(ic));
6144 ADJUST_PUSHED_RESULT(compSize, resultSize);
6146 _startLazyDPSEvaluation();
6149 emitcode ("pop", "acc");
6150 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6152 _endLazyDPSEvaluation();
6153 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6157 /*-----------------------------------------------------------------*/
6158 /* genAnd - code for and */
6159 /*-----------------------------------------------------------------*/
6161 genAnd (iCode * ic, iCode * ifx)
6163 operand *left, *right, *result;
6164 int size, offset = 0;
6165 unsigned long lit = 0L;
6170 D (emitcode (";", "genAnd "););
6172 AOP_OP_3_NOFATAL (ic, pushResult);
6173 AOP_SET_LOCALS (ic);
6177 genFarFarLogicOp(ic, "anl");
6182 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6184 AOP_TYPE (left), AOP_TYPE (right));
6185 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6187 AOP_SIZE (left), AOP_SIZE (right));
6190 /* if left is a literal & right is not then exchange them */
6191 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6192 #ifdef LOGIC_OPS_BROKEN
6193 || AOP_NEEDSACC (left)
6197 operand *tmp = right;
6202 /* if result = right then exchange them */
6203 if (sameRegs (AOP (result), AOP (right)))
6205 operand *tmp = right;
6210 /* if right is bit then exchange them */
6211 if (AOP_TYPE (right) == AOP_CRY &&
6212 AOP_TYPE (left) != AOP_CRY)
6214 operand *tmp = right;
6218 if (AOP_TYPE (right) == AOP_LIT)
6219 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6221 size = AOP_SIZE (result);
6224 // result = bit & yy;
6225 if (AOP_TYPE (left) == AOP_CRY)
6227 // c = bit & literal;
6228 if (AOP_TYPE (right) == AOP_LIT)
6232 if (size && sameRegs (AOP (result), AOP (left)))
6235 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6240 if (size && (AOP_TYPE (result) == AOP_CRY))
6242 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6245 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6250 emitcode ("clr", "c");
6255 if (AOP_TYPE (right) == AOP_CRY)
6258 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6259 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6264 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6266 emitcode ("rrc", "a");
6267 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6275 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6276 genIfxJump (ifx, "c");
6280 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6281 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6282 if ((AOP_TYPE (right) == AOP_LIT) &&
6283 (AOP_TYPE (result) == AOP_CRY) &&
6284 (AOP_TYPE (left) != AOP_CRY))
6286 int posbit = isLiteralBit (lit);
6291 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6294 emitcode ("mov", "c,acc.%d", posbit & 0x07);
6300 SNPRINTF (buff, sizeof(buff),
6301 "acc.%d", posbit & 0x07);
6302 genIfxJump (ifx, buff);
6306 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6313 symbol *tlbl = newiTempLabel (NULL);
6314 int sizel = AOP_SIZE (left);
6316 emitcode ("setb", "c");
6319 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6321 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6323 if ((posbit = isLiteralBit (bytelit)) != 0)
6324 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6327 if (bytelit != 0x0FFL)
6328 emitcode ("anl", "a,%s",
6329 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6330 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6335 // bit = left & literal
6338 emitcode ("clr", "c");
6339 emitcode ("", "!tlabeldef", tlbl->key + 100);
6341 // if(left & literal)
6345 jmpTrueOrFalse (ifx, tlbl);
6353 /* if left is same as result */
6354 if (sameRegs (AOP (result), AOP (left)))
6356 for (; size--; offset++)
6358 if (AOP_TYPE (right) == AOP_LIT)
6360 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6362 else if (bytelit == 0)
6363 aopPut (AOP (result), zero, offset);
6364 else if (IS_AOP_PREG (result))
6366 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6367 emitcode ("anl", "a,%s",
6368 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6369 aopPut (AOP (result), "a", offset);
6372 emitcode ("anl", "%s,%s",
6373 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6374 aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6378 if (AOP_TYPE (left) == AOP_ACC)
6379 emitcode ("anl", "a,%s",
6380 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6383 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6384 if (IS_AOP_PREG (result))
6386 emitcode ("anl", "a,%s",
6387 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6388 aopPut (AOP (result), "a", offset);
6391 emitcode ("anl", "%s,a",
6392 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6399 // left & result in different registers
6400 if (AOP_TYPE (result) == AOP_CRY)
6403 // if(size), result in bit
6404 // if(!size && ifx), conditional oper: if(left & right)
6405 symbol *tlbl = newiTempLabel (NULL);
6406 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6408 emitcode ("setb", "c");
6411 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6412 emitcode ("anl", "a,%s",
6413 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6415 if (AOP_TYPE(left)==AOP_ACC) {
6416 emitcode("mov", "b,a");
6417 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6418 emitcode("anl", "a,b");
6420 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6421 emitcode ("anl", "a,%s",
6422 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6425 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6431 emitcode ("", "!tlabeldef", tlbl->key + 100);
6435 jmpTrueOrFalse (ifx, tlbl);
6439 for (; (size--); offset++)
6442 // result = left & right
6443 if (AOP_TYPE (right) == AOP_LIT)
6445 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6447 aopPut (AOP (result),
6448 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6452 else if (bytelit == 0)
6454 aopPut (AOP (result), zero, offset);
6457 D (emitcode (";", "better literal AND."););
6458 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6459 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6460 FALSE, FALSE, DP2_RESULT_REG));
6465 // faster than result <- left, anl result,right
6466 // and better if result is SFR
6467 if (AOP_TYPE (left) == AOP_ACC)
6469 emitcode ("anl", "a,%s",
6470 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6474 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6475 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6477 emitcode("mov", "b,a");
6481 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6482 emitcode ("anl", "a,%s", rOp);
6485 aopPut (AOP (result), "a", offset);
6491 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6492 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6493 freeAsmop (result, NULL, ic, TRUE);
6497 /*-----------------------------------------------------------------*/
6498 /* genOr - code for or */
6499 /*-----------------------------------------------------------------*/
6501 genOr (iCode * ic, iCode * ifx)
6503 operand *left, *right, *result;
6504 int size, offset = 0;
6505 unsigned long lit = 0L;
6508 D (emitcode (";", "genOr "););
6510 AOP_OP_3_NOFATAL (ic, pushResult);
6511 AOP_SET_LOCALS (ic);
6515 genFarFarLogicOp(ic, "orl");
6521 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6523 AOP_TYPE (left), AOP_TYPE (right));
6524 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6526 AOP_SIZE (left), AOP_SIZE (right));
6529 /* if left is a literal & right is not then exchange them */
6530 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6531 #ifdef LOGIC_OPS_BROKEN
6532 || AOP_NEEDSACC (left) // I think this is a net loss now.
6536 operand *tmp = right;
6541 /* if result = right then exchange them */
6542 if (sameRegs (AOP (result), AOP (right)))
6544 operand *tmp = right;
6549 /* if right is bit then exchange them */
6550 if (AOP_TYPE (right) == AOP_CRY &&
6551 AOP_TYPE (left) != AOP_CRY)
6553 operand *tmp = right;
6557 if (AOP_TYPE (right) == AOP_LIT)
6558 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6560 size = AOP_SIZE (result);
6564 if (AOP_TYPE (left) == AOP_CRY)
6566 if (AOP_TYPE (right) == AOP_LIT)
6568 // c = bit & literal;
6571 // lit != 0 => result = 1
6572 if (AOP_TYPE (result) == AOP_CRY)
6575 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6577 continueIfTrue (ifx);
6580 emitcode ("setb", "c");
6584 // lit == 0 => result = left
6585 if (size && sameRegs (AOP (result), AOP (left)))
6587 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6592 if (AOP_TYPE (right) == AOP_CRY)
6595 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6596 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6601 symbol *tlbl = newiTempLabel (NULL);
6602 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6603 emitcode ("setb", "c");
6604 emitcode ("jb", "%s,!tlabel",
6605 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6607 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6608 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6610 jmpTrueOrFalse (ifx, tlbl);
6616 emitcode ("", "!tlabeldef", tlbl->key + 100);
6625 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6626 genIfxJump (ifx, "c");
6630 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6631 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6632 if ((AOP_TYPE (right) == AOP_LIT) &&
6633 (AOP_TYPE (result) == AOP_CRY) &&
6634 (AOP_TYPE (left) != AOP_CRY))
6640 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6642 continueIfTrue (ifx);
6647 // lit = 0, result = boolean(left)
6649 emitcode ("setb", "c");
6653 symbol *tlbl = newiTempLabel (NULL);
6654 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6656 emitcode ("", "!tlabeldef", tlbl->key + 100);
6660 genIfxJump (ifx, "a");
6668 /* if left is same as result */
6669 if (sameRegs (AOP (result), AOP (left)))
6671 for (; size--; offset++)
6673 if (AOP_TYPE (right) == AOP_LIT)
6675 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6681 if (IS_AOP_PREG (left))
6683 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6684 emitcode ("orl", "a,%s",
6685 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6686 aopPut (AOP (result), "a", offset);
6690 emitcode ("orl", "%s,%s",
6691 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6692 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6698 if (AOP_TYPE (left) == AOP_ACC)
6700 emitcode ("orl", "a,%s",
6701 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6705 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6706 if (IS_AOP_PREG (left))
6708 emitcode ("orl", "a,%s",
6709 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6710 aopPut (AOP (result), "a", offset);
6714 emitcode ("orl", "%s,a",
6715 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6723 // left & result in different registers
6724 if (AOP_TYPE (result) == AOP_CRY)
6727 // if(size), result in bit
6728 // if(!size && ifx), conditional oper: if(left | right)
6729 symbol *tlbl = newiTempLabel (NULL);
6730 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6732 emitcode ("setb", "c");
6735 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6736 emitcode ("orl", "a,%s",
6737 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6739 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6740 emitcode ("orl", "a,%s",
6741 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6743 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6749 emitcode ("", "!tlabeldef", tlbl->key + 100);
6753 jmpTrueOrFalse (ifx, tlbl);
6757 _startLazyDPSEvaluation();
6758 for (; (size--); offset++)
6761 // result = left & right
6762 if (AOP_TYPE (right) == AOP_LIT)
6764 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6766 aopPut (AOP (result),
6767 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6771 D (emitcode (";", "better literal OR."););
6772 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6773 emitcode ("orl", "a, %s",
6774 aopGet (AOP (right), offset,
6775 FALSE, FALSE, DP2_RESULT_REG));
6780 // faster than result <- left, anl result,right
6781 // and better if result is SFR
6782 if (AOP_TYPE (left) == AOP_ACC)
6784 emitcode ("orl", "a,%s",
6785 aopGet (AOP (right), offset,
6786 FALSE, FALSE, DP2_RESULT_REG));
6790 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6792 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6794 emitcode("mov", "b,a");
6798 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6799 emitcode ("orl", "a,%s", rOp);
6802 aopPut (AOP (result), "a", offset);
6804 _endLazyDPSEvaluation();
6809 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6810 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6811 freeAsmop (result, NULL, ic, TRUE);
6814 /*-----------------------------------------------------------------*/
6815 /* genXor - code for xclusive or */
6816 /*-----------------------------------------------------------------*/
6818 genXor (iCode * ic, iCode * ifx)
6820 operand *left, *right, *result;
6821 int size, offset = 0;
6822 unsigned long lit = 0L;
6825 D (emitcode (";", "genXor "););
6827 AOP_OP_3_NOFATAL (ic, pushResult);
6828 AOP_SET_LOCALS (ic);
6832 genFarFarLogicOp(ic, "xrl");
6837 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6839 AOP_TYPE (left), AOP_TYPE (right));
6840 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6842 AOP_SIZE (left), AOP_SIZE (right));
6845 /* if left is a literal & right is not ||
6846 if left needs acc & right does not */
6847 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6848 #ifdef LOGIC_OPS_BROKEN
6849 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6853 operand *tmp = right;
6858 /* if result = right then exchange them */
6859 if (sameRegs (AOP (result), AOP (right)))
6861 operand *tmp = right;
6866 /* if right is bit then exchange them */
6867 if (AOP_TYPE (right) == AOP_CRY &&
6868 AOP_TYPE (left) != AOP_CRY)
6870 operand *tmp = right;
6874 if (AOP_TYPE (right) == AOP_LIT)
6875 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6877 size = AOP_SIZE (result);
6881 if (AOP_TYPE (left) == AOP_CRY)
6883 if (AOP_TYPE (right) == AOP_LIT)
6885 // c = bit & literal;
6888 // lit>>1 != 0 => result = 1
6889 if (AOP_TYPE (result) == AOP_CRY)
6892 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6894 continueIfTrue (ifx);
6897 emitcode ("setb", "c");
6904 // lit == 0, result = left
6905 if (size && sameRegs (AOP (result), AOP (left)))
6907 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6911 // lit == 1, result = not(left)
6912 if (size && sameRegs (AOP (result), AOP (left)))
6914 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6919 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6920 emitcode ("cpl", "c");
6929 symbol *tlbl = newiTempLabel (NULL);
6930 if (AOP_TYPE (right) == AOP_CRY)
6933 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6937 int sizer = AOP_SIZE (right);
6939 // if val>>1 != 0, result = 1
6940 emitcode ("setb", "c");
6943 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
6945 // test the msb of the lsb
6946 emitcode ("anl", "a,#!constbyte",0xfe);
6947 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6951 emitcode ("rrc", "a");
6953 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6954 emitcode ("cpl", "c");
6955 emitcode ("", "!tlabeldef", (tlbl->key + 100));
6962 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6963 genIfxJump (ifx, "c");
6967 if (sameRegs (AOP (result), AOP (left)))
6969 /* if left is same as result */
6970 for (; size--; offset++)
6972 if (AOP_TYPE (right) == AOP_LIT)
6974 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6976 else if (IS_AOP_PREG (left))
6978 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6979 emitcode ("xrl", "a,%s",
6980 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6981 aopPut (AOP (result), "a", offset);
6984 emitcode ("xrl", "%s,%s",
6985 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6986 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6990 if (AOP_TYPE (left) == AOP_ACC)
6991 emitcode ("xrl", "a,%s",
6992 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6995 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6996 if (IS_AOP_PREG (left))
6998 emitcode ("xrl", "a,%s",
6999 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7000 aopPut (AOP (result), "a", offset);
7003 emitcode ("xrl", "%s,a",
7004 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7011 // left & result in different registers
7012 if (AOP_TYPE (result) == AOP_CRY)
7015 // if(size), result in bit
7016 // if(!size && ifx), conditional oper: if(left ^ right)
7017 symbol *tlbl = newiTempLabel (NULL);
7018 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7021 emitcode ("setb", "c");
7024 if ((AOP_TYPE (right) == AOP_LIT) &&
7025 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7027 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7031 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7032 emitcode ("xrl", "a,%s",
7033 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7035 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7036 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7038 emitcode("mov", "b,a");
7042 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7043 emitcode ("xrl", "a,%s", rOp);
7046 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7052 emitcode ("", "!tlabeldef", tlbl->key + 100);
7056 jmpTrueOrFalse (ifx, tlbl);
7060 for (; (size--); offset++)
7063 // result = left & right
7064 if (AOP_TYPE (right) == AOP_LIT)
7066 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7068 aopPut (AOP (result),
7069 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7073 D (emitcode (";", "better literal XOR."););
7074 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7075 emitcode ("xrl", "a, %s",
7076 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7080 // faster than result <- left, anl result,right
7081 // and better if result is SFR
7082 if (AOP_TYPE (left) == AOP_ACC)
7084 emitcode ("xrl", "a,%s",
7085 aopGet (AOP (right), offset,
7086 FALSE, FALSE, DP2_RESULT_REG));
7090 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7091 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7093 emitcode("mov", "b,a");
7097 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7098 emitcode ("xrl", "a,%s", rOp);
7101 aopPut (AOP (result), "a", offset);
7108 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7109 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7110 freeAsmop (result, NULL, ic, TRUE);
7113 /*-----------------------------------------------------------------*/
7114 /* genInline - write the inline code out */
7115 /*-----------------------------------------------------------------*/
7117 genInline (iCode * ic)
7119 char *buffer, *bp, *bp1;
7121 D (emitcode (";", "genInline "); );
7123 _G.inLine += (!options.asmpeep);
7125 buffer = Safe_strdup(IC_INLINE(ic));
7129 /* emit each line as a code */
7154 /* emitcode("",buffer); */
7155 _G.inLine -= (!options.asmpeep);
7158 /*-----------------------------------------------------------------*/
7159 /* genRRC - rotate right with carry */
7160 /*-----------------------------------------------------------------*/
7164 operand *left, *result;
7167 D (emitcode (";", "genRRC "););
7169 /* rotate right with carry */
7170 left = IC_LEFT (ic);
7171 result = IC_RESULT (ic);
7172 aopOp (left, ic, FALSE, FALSE);
7173 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7175 /* move it to the result */
7176 size = AOP_SIZE (result);
7180 _startLazyDPSEvaluation ();
7183 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7184 emitcode ("rrc", "a");
7185 if (AOP_SIZE (result) > 1)
7186 aopPut (AOP (result), "a", offset--);
7188 _endLazyDPSEvaluation ();
7190 /* now we need to put the carry into the
7191 highest order byte of the result */
7192 if (AOP_SIZE (result) > 1)
7194 MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7196 emitcode ("mov", "acc.7,c");
7197 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7198 freeAsmop (left, NULL, ic, TRUE);
7199 freeAsmop (result, NULL, ic, TRUE);
7202 /*-----------------------------------------------------------------*/
7203 /* genRLC - generate code for rotate left with carry */
7204 /*-----------------------------------------------------------------*/
7208 operand *left, *result;
7212 D (emitcode (";", "genRLC "););
7214 /* rotate right with carry */
7215 left = IC_LEFT (ic);
7216 result = IC_RESULT (ic);
7217 aopOp (left, ic, FALSE, FALSE);
7218 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7220 /* move it to the result */
7221 size = AOP_SIZE (result);
7225 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7227 emitcode ("add", "a,acc");
7228 if (AOP_SIZE (result) > 1)
7230 aopPut (AOP (result), "a", offset++);
7233 _startLazyDPSEvaluation ();
7236 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7238 emitcode ("rlc", "a");
7239 if (AOP_SIZE (result) > 1)
7240 aopPut (AOP (result), "a", offset++);
7242 _endLazyDPSEvaluation ();
7244 /* now we need to put the carry into the
7245 highest order byte of the result */
7246 if (AOP_SIZE (result) > 1)
7248 l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7251 emitcode ("mov", "acc.0,c");
7252 aopPut (AOP (result), "a", 0);
7253 freeAsmop (left, NULL, ic, TRUE);
7254 freeAsmop (result, NULL, ic, TRUE);
7257 /*-----------------------------------------------------------------*/
7258 /* genGetHbit - generates code get highest order bit */
7259 /*-----------------------------------------------------------------*/
7261 genGetHbit (iCode * ic)
7263 operand *left, *result;
7264 left = IC_LEFT (ic);
7265 result = IC_RESULT (ic);
7266 aopOp (left, ic, FALSE, FALSE);
7267 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7269 D (emitcode (";", "genGetHbit "););
7271 /* get the highest order byte into a */
7272 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7273 if (AOP_TYPE (result) == AOP_CRY)
7275 emitcode ("rlc", "a");
7280 emitcode ("rl", "a");
7281 emitcode ("anl", "a,#1");
7286 freeAsmop (left, NULL, ic, TRUE);
7287 freeAsmop (result, NULL, ic, TRUE);
7290 /*-----------------------------------------------------------------*/
7291 /* AccRol - rotate left accumulator by known count */
7292 /*-----------------------------------------------------------------*/
7294 AccRol (int shCount)
7296 shCount &= 0x0007; // shCount : 0..7
7303 emitcode ("rl", "a");
7306 emitcode ("rl", "a");
7307 emitcode ("rl", "a");
7310 emitcode ("swap", "a");
7311 emitcode ("rr", "a");
7314 emitcode ("swap", "a");
7317 emitcode ("swap", "a");
7318 emitcode ("rl", "a");
7321 emitcode ("rr", "a");
7322 emitcode ("rr", "a");
7325 emitcode ("rr", "a");
7330 /*-----------------------------------------------------------------*/
7331 /* AccLsh - left shift accumulator by known count */
7332 /*-----------------------------------------------------------------*/
7334 AccLsh (int shCount)
7339 emitcode ("add", "a,acc");
7340 else if (shCount == 2)
7342 emitcode ("add", "a,acc");
7343 emitcode ("add", "a,acc");
7347 /* rotate left accumulator */
7349 /* and kill the lower order bits */
7350 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7355 /*-----------------------------------------------------------------*/
7356 /* AccRsh - right shift accumulator by known count */
7357 /*-----------------------------------------------------------------*/
7359 AccRsh (int shCount)
7366 emitcode ("rrc", "a");
7370 /* rotate right accumulator */
7371 AccRol (8 - shCount);
7372 /* and kill the higher order bits */
7373 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7378 #ifdef BETTER_LITERAL_SHIFT
7379 /*-----------------------------------------------------------------*/
7380 /* AccSRsh - signed right shift accumulator by known count */
7381 /*-----------------------------------------------------------------*/
7383 AccSRsh (int shCount)
7390 emitcode ("mov", "c,acc.7");
7391 emitcode ("rrc", "a");
7393 else if (shCount == 2)
7395 emitcode ("mov", "c,acc.7");
7396 emitcode ("rrc", "a");
7397 emitcode ("mov", "c,acc.7");
7398 emitcode ("rrc", "a");
7402 tlbl = newiTempLabel (NULL);
7403 /* rotate right accumulator */
7404 AccRol (8 - shCount);
7405 /* and kill the higher order bits */
7406 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7407 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7408 emitcode ("orl", "a,#!constbyte",
7409 (unsigned char) ~SRMask[shCount]);
7410 emitcode ("", "!tlabeldef", tlbl->key + 100);
7416 #ifdef BETTER_LITERAL_SHIFT
7417 /*-----------------------------------------------------------------*/
7418 /* shiftR1Left2Result - shift right one byte from left to result */
7419 /*-----------------------------------------------------------------*/
7421 shiftR1Left2Result (operand * left, int offl,
7422 operand * result, int offr,
7423 int shCount, int sign)
7425 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7426 /* shift right accumulator */
7431 aopPut (AOP (result), "a", offr);
7435 #ifdef BETTER_LITERAL_SHIFT
7436 /*-----------------------------------------------------------------*/
7437 /* shiftL1Left2Result - shift left one byte from left to result */
7438 /*-----------------------------------------------------------------*/
7440 shiftL1Left2Result (operand * left, int offl,
7441 operand * result, int offr, int shCount)
7443 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7444 /* shift left accumulator */
7446 aopPut (AOP (result), "a", offr);
7450 #ifdef BETTER_LITERAL_SHIFT
7451 /*-----------------------------------------------------------------*/
7452 /* movLeft2Result - move byte from left to result */
7453 /*-----------------------------------------------------------------*/
7455 movLeft2Result (operand * left, int offl,
7456 operand * result, int offr, int sign)
7459 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7461 l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
7463 if (*l == '@' && (IS_AOP_PREG (result)))
7465 emitcode ("mov", "a,%s", l);
7466 aopPut (AOP (result), "a", offr);
7472 aopPut (AOP (result), l, offr);
7476 /* MSB sign in acc.7 ! */
7477 if (getDataSize (left) == offl + 1)
7479 emitcode ("mov", "a,%s", l);
7480 aopPut (AOP (result), "a", offr);
7488 #ifdef BETTER_LITERAL_SHIFT
7489 /*-----------------------------------------------------------------*/
7490 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7491 /*-----------------------------------------------------------------*/
7495 emitcode ("rrc", "a");
7496 emitcode ("xch", "a,%s", x);
7497 emitcode ("rrc", "a");
7498 emitcode ("xch", "a,%s", x);
7502 #ifdef BETTER_LITERAL_SHIFT
7504 /*-----------------------------------------------------------------*/
7505 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7506 /*-----------------------------------------------------------------*/
7510 emitcode ("xch", "a,%s", x);
7511 emitcode ("rlc", "a");
7512 emitcode ("xch", "a,%s", x);
7513 emitcode ("rlc", "a");
7517 #ifdef BETTER_LITERAL_SHIFT
7518 /*-----------------------------------------------------------------*/
7519 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7520 /*-----------------------------------------------------------------*/
7524 emitcode ("xch", "a,%s", x);
7525 emitcode ("add", "a,acc");
7526 emitcode ("xch", "a,%s", x);
7527 emitcode ("rlc", "a");
7531 #ifdef BETTER_LITERAL_SHIFT
7532 /*-----------------------------------------------------------------*/
7533 /* AccAXLsh - left shift a:x by known count (0..7) */
7534 /*-----------------------------------------------------------------*/
7536 AccAXLsh (char *x, int shCount)
7551 case 5: // AAAAABBB:CCCCCDDD
7553 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7555 emitcode ("anl", "a,#!constbyte",
7556 SLMask[shCount]); // BBB00000:CCCCCDDD
7558 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7560 AccRol (shCount); // DDDCCCCC:BBB00000
7562 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7564 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7566 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7568 emitcode ("anl", "a,#!constbyte",
7569 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7571 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7573 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7576 case 6: // AAAAAABB:CCCCCCDD
7577 emitcode ("anl", "a,#!constbyte",
7578 SRMask[shCount]); // 000000BB:CCCCCCDD
7579 emitcode ("mov", "c,acc.0"); // c = B
7580 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7582 AccAXRrl1 (x); // BCCCCCCD:D000000B
7583 AccAXRrl1 (x); // BBCCCCCC:DD000000
7585 emitcode("rrc","a");
7586 emitcode("xch","a,%s", x);
7587 emitcode("rrc","a");
7588 emitcode("mov","c,acc.0"); //<< get correct bit
7589 emitcode("xch","a,%s", x);
7591 emitcode("rrc","a");
7592 emitcode("xch","a,%s", x);
7593 emitcode("rrc","a");
7594 emitcode("xch","a,%s", x);
7597 case 7: // a:x <<= 7
7599 emitcode ("anl", "a,#!constbyte",
7600 SRMask[shCount]); // 0000000B:CCCCCCCD
7602 emitcode ("mov", "c,acc.0"); // c = B
7604 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7606 AccAXRrl1 (x); // BCCCCCCC:D0000000
7615 #ifdef BETTER_LITERAL_SHIFT
7617 /*-----------------------------------------------------------------*/
7618 /* AccAXRsh - right shift a:x known count (0..7) */
7619 /*-----------------------------------------------------------------*/
7621 AccAXRsh (char *x, int shCount)
7629 AccAXRrl1 (x); // 0->a:x
7634 AccAXRrl1 (x); // 0->a:x
7637 AccAXRrl1 (x); // 0->a:x
7642 case 5: // AAAAABBB:CCCCCDDD = a:x
7644 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7646 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7648 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7650 emitcode ("anl", "a,#!constbyte",
7651 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7653 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7655 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7657 emitcode ("anl", "a,#!constbyte",
7658 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7660 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7662 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7664 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7667 case 6: // AABBBBBB:CCDDDDDD
7669 emitcode ("mov", "c,acc.7");
7670 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7672 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7674 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7676 emitcode ("anl", "a,#!constbyte",
7677 SRMask[shCount]); // 000000AA:BBBBBBCC
7680 case 7: // ABBBBBBB:CDDDDDDD
7682 emitcode ("mov", "c,acc.7"); // c = A
7684 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7686 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7688 emitcode ("anl", "a,#!constbyte",
7689 SRMask[shCount]); // 0000000A:BBBBBBBC
7698 #ifdef BETTER_LITERAL_SHIFT
7699 /*-----------------------------------------------------------------*/
7700 /* AccAXRshS - right shift signed a:x known count (0..7) */
7701 /*-----------------------------------------------------------------*/
7703 AccAXRshS (char *x, int shCount)
7711 emitcode ("mov", "c,acc.7");
7712 AccAXRrl1 (x); // s->a:x
7716 emitcode ("mov", "c,acc.7");
7717 AccAXRrl1 (x); // s->a:x
7719 emitcode ("mov", "c,acc.7");
7720 AccAXRrl1 (x); // s->a:x
7725 case 5: // AAAAABBB:CCCCCDDD = a:x
7727 tlbl = newiTempLabel (NULL);
7728 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7730 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7732 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7734 emitcode ("anl", "a,#!constbyte",
7735 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7737 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7739 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7741 emitcode ("anl", "a,#!constbyte",
7742 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7744 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7746 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7748 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7750 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7751 emitcode ("orl", "a,#!constbyte",
7752 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7754 emitcode ("", "!tlabeldef", tlbl->key + 100);
7755 break; // SSSSAAAA:BBBCCCCC
7757 case 6: // AABBBBBB:CCDDDDDD
7759 tlbl = newiTempLabel (NULL);
7760 emitcode ("mov", "c,acc.7");
7761 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7763 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7765 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7767 emitcode ("anl", "a,#!constbyte",
7768 SRMask[shCount]); // 000000AA:BBBBBBCC
7770 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7771 emitcode ("orl", "a,#!constbyte",
7772 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7774 emitcode ("", "!tlabeldef", tlbl->key + 100);
7776 case 7: // ABBBBBBB:CDDDDDDD
7778 tlbl = newiTempLabel (NULL);
7779 emitcode ("mov", "c,acc.7"); // c = A
7781 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7783 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7785 emitcode ("anl", "a,#!constbyte",
7786 SRMask[shCount]); // 0000000A:BBBBBBBC
7788 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7789 emitcode ("orl", "a,#!constbyte",
7790 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7792 emitcode ("", "!tlabeldef", tlbl->key + 100);
7800 #ifdef BETTER_LITERAL_SHIFT
7802 _loadLeftIntoAx(char **lsb,
7808 // Get the initial value from left into a pair of registers.
7809 // MSB must be in A, LSB can be any register.
7811 // If the result is held in registers, it is an optimization
7812 // if the LSB can be held in the register which will hold the,
7813 // result LSB since this saves us from having to copy it into
7814 // the result following AccAXLsh.
7816 // If the result is addressed indirectly, this is not a gain.
7817 if (AOP_NEEDSACC(result))
7821 _startLazyDPSEvaluation();
7822 if (AOP_TYPE(left) == AOP_DPTR2)
7825 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
7826 // get LSB in DP2_RESULT_REG.
7827 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
7828 assert(!strcmp(leftByte, DP2_RESULT_REG));
7832 // get LSB into DP2_RESULT_REG
7833 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
7834 if (strcmp(leftByte, DP2_RESULT_REG))
7837 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7840 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
7841 assert(strcmp(leftByte, DP2_RESULT_REG));
7844 _endLazyDPSEvaluation();
7845 *lsb = DP2_RESULT_REG;
7849 if (sameRegs (AOP (result), AOP (left)) &&
7850 ((offl + MSB16) == offr))
7852 /* don't crash result[offr] */
7853 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
7854 emitcode ("xch", "a,%s",
7855 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
7859 movLeft2Result (left, offl, result, offr, 0);
7860 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
7862 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
7863 assert(strcmp(*lsb,"a"));
7868 _storeAxResults(char *lsb,
7872 _startLazyDPSEvaluation();
7873 if (AOP_NEEDSACC(result))
7875 /* We have to explicitly update the result LSB.
7877 emitcode("xch","a,%s", lsb);
7878 aopPut(AOP(result), "a", offr);
7879 emitcode("mov","a,%s", lsb);
7881 if (getDataSize (result) > 1)
7883 aopPut (AOP (result), "a", offr + MSB16);
7885 _endLazyDPSEvaluation();
7888 /*-----------------------------------------------------------------*/
7889 /* shiftL2Left2Result - shift left two bytes from left to result */
7890 /*-----------------------------------------------------------------*/
7892 shiftL2Left2Result (operand * left, int offl,
7893 operand * result, int offr, int shCount)
7897 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7899 AccAXLsh (lsb, shCount);
7901 _storeAxResults(lsb, result, offr);
7905 #ifdef BETTER_LITERAL_SHIFT
7906 /*-----------------------------------------------------------------*/
7907 /* shiftR2Left2Result - shift right two bytes from left to result */
7908 /*-----------------------------------------------------------------*/
7910 shiftR2Left2Result (operand * left, int offl,
7911 operand * result, int offr,
7912 int shCount, int sign)
7916 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7918 /* a:x >> shCount (x = lsb(result)) */
7921 AccAXRshS(lsb, shCount);
7925 AccAXRsh(lsb, shCount);
7928 _storeAxResults(lsb, result, offr);
7932 /*-----------------------------------------------------------------*/
7933 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7934 /*-----------------------------------------------------------------*/
7936 shiftLLeftOrResult (operand * left, int offl,
7937 operand * result, int offr, int shCount)
7939 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7940 /* shift left accumulator */
7942 /* or with result */
7943 emitcode ("orl", "a,%s",
7944 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7945 /* back to result */
7946 aopPut (AOP (result), "a", offr);
7951 /*-----------------------------------------------------------------*/
7952 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7953 /*-----------------------------------------------------------------*/
7955 shiftRLeftOrResult (operand * left, int offl,
7956 operand * result, int offr, int shCount)
7958 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7959 /* shift right accumulator */
7961 /* or with result */
7962 emitcode ("orl", "a,%s",
7963 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7964 /* back to result */
7965 aopPut (AOP (result), "a", offr);
7969 #ifdef BETTER_LITERAL_SHIFT
7970 /*-----------------------------------------------------------------*/
7971 /* genlshOne - left shift a one byte quantity by known count */
7972 /*-----------------------------------------------------------------*/
7974 genlshOne (operand * result, operand * left, int shCount)
7976 D (emitcode (";", "genlshOne "););
7977 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7981 #ifdef BETTER_LITERAL_SHIFT
7982 /*-----------------------------------------------------------------*/
7983 /* genlshTwo - left shift two bytes by known amount != 0 */
7984 /*-----------------------------------------------------------------*/
7986 genlshTwo (operand * result, operand * left, int shCount)
7990 D (emitcode (";", "genlshTwo "););
7992 size = getDataSize (result);
7994 /* if shCount >= 8 */
7999 _startLazyDPSEvaluation();
8005 _endLazyDPSEvaluation();
8006 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8007 aopPut (AOP (result), zero, LSB);
8011 movLeft2Result (left, LSB, result, MSB16, 0);
8012 aopPut (AOP (result), zero, LSB);
8013 _endLazyDPSEvaluation();
8018 aopPut (AOP (result), zero, LSB);
8019 _endLazyDPSEvaluation();
8023 /* 1 <= shCount <= 7 */
8028 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8032 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8040 /*-----------------------------------------------------------------*/
8041 /* shiftLLong - shift left one long from left to result */
8042 /* offl = LSB or MSB16 */
8043 /*-----------------------------------------------------------------*/
8045 shiftLLong (operand * left, operand * result, int offr)
8048 int size = AOP_SIZE (result);
8050 if (size >= LSB + offr)
8052 l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8054 emitcode ("add", "a,acc");
8055 if (sameRegs (AOP (left), AOP (result)) &&
8056 size >= MSB16 + offr && offr != LSB)
8057 emitcode ("xch", "a,%s",
8058 aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8060 aopPut (AOP (result), "a", LSB + offr);
8063 if (size >= MSB16 + offr)
8065 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8067 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8069 emitcode ("rlc", "a");
8070 if (sameRegs (AOP (left), AOP (result)) &&
8071 size >= MSB24 + offr && offr != LSB)
8072 emitcode ("xch", "a,%s",
8073 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8075 aopPut (AOP (result), "a", MSB16 + offr);
8078 if (size >= MSB24 + offr)
8080 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8082 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8084 emitcode ("rlc", "a");
8085 if (sameRegs (AOP (left), AOP (result)) &&
8086 size >= MSB32 + offr && offr != LSB)
8087 emitcode ("xch", "a,%s",
8088 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8090 aopPut (AOP (result), "a", MSB24 + offr);
8093 if (size > MSB32 + offr)
8095 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8097 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8099 emitcode ("rlc", "a");
8100 aopPut (AOP (result), "a", MSB32 + offr);
8103 aopPut (AOP (result), zero, LSB);
8109 /*-----------------------------------------------------------------*/
8110 /* genlshFour - shift four byte by a known amount != 0 */
8111 /*-----------------------------------------------------------------*/
8113 genlshFour (operand * result, operand * left, int shCount)
8117 D (emitcode (";", "genlshFour ");
8120 size = AOP_SIZE (result);
8122 /* if shifting more that 3 bytes */
8127 /* lowest order of left goes to the highest
8128 order of the destination */
8129 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8131 movLeft2Result (left, LSB, result, MSB32, 0);
8132 aopPut (AOP (result), zero, LSB);
8133 aopPut (AOP (result), zero, MSB16);
8134 aopPut (AOP (result), zero, MSB24);
8138 /* more than two bytes */
8139 else if (shCount >= 16)
8141 /* lower order two bytes goes to higher order two bytes */
8143 /* if some more remaining */
8145 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8148 movLeft2Result (left, MSB16, result, MSB32, 0);
8149 movLeft2Result (left, LSB, result, MSB24, 0);
8151 aopPut (AOP (result), zero, MSB16);
8152 aopPut (AOP (result), zero, LSB);
8156 /* if more than 1 byte */
8157 else if (shCount >= 8)
8159 /* lower order three bytes goes to higher order three bytes */
8164 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8166 movLeft2Result (left, LSB, result, MSB16, 0);
8172 movLeft2Result (left, MSB24, result, MSB32, 0);
8173 movLeft2Result (left, MSB16, result, MSB24, 0);
8174 movLeft2Result (left, LSB, result, MSB16, 0);
8175 aopPut (AOP (result), zero, LSB);
8177 else if (shCount == 1)
8178 shiftLLong (left, result, MSB16);
8181 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8182 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8183 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8184 aopPut (AOP (result), zero, LSB);
8189 /* 1 <= shCount <= 7 */
8190 else if (shCount <= 2)
8192 shiftLLong (left, result, LSB);
8194 shiftLLong (result, result, LSB);
8196 /* 3 <= shCount <= 7, optimize */
8199 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8200 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8201 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8206 #ifdef BETTER_LITERAL_SHIFT
8207 /*-----------------------------------------------------------------*/
8208 /* genLeftShiftLiteral - left shifting by known count */
8209 /*-----------------------------------------------------------------*/
8211 genLeftShiftLiteral (operand * left,
8216 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8219 size = getSize (operandType (result));
8221 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8223 /* We only handle certain easy cases so far. */
8225 && (shCount < (size * 8))
8229 D(emitcode (";", "genLeftShiftLiteral wimping out"););
8233 freeAsmop (right, NULL, ic, TRUE);
8235 aopOp(left, ic, FALSE, FALSE);
8236 aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8239 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8241 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8242 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8244 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8247 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8249 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8250 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8252 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8258 emitcode ("; shift left ", "result %d, left %d", size,
8262 /* I suppose that the left size >= result size */
8265 _startLazyDPSEvaluation();
8268 movLeft2Result (left, size, result, size, 0);
8270 _endLazyDPSEvaluation();
8272 else if (shCount >= (size * 8))
8274 _startLazyDPSEvaluation();
8277 aopPut (AOP (result), zero, size);
8279 _endLazyDPSEvaluation();
8286 genlshOne (result, left, shCount);
8290 genlshTwo (result, left, shCount);
8294 genlshFour (result, left, shCount);
8298 fprintf(stderr, "*** ack! mystery literal shift!\n");
8302 freeAsmop (left, NULL, ic, TRUE);
8303 freeAsmop (result, NULL, ic, TRUE);
8308 /*-----------------------------------------------------------------*/
8309 /* genLeftShift - generates code for left shifting */
8310 /*-----------------------------------------------------------------*/
8312 genLeftShift (iCode * ic)
8314 operand *left, *right, *result;
8317 symbol *tlbl, *tlbl1;
8319 D (emitcode (";", "genLeftShift "););
8321 right = IC_RIGHT (ic);
8322 left = IC_LEFT (ic);
8323 result = IC_RESULT (ic);
8325 aopOp (right, ic, FALSE, FALSE);
8328 #ifdef BETTER_LITERAL_SHIFT
8329 /* if the shift count is known then do it
8330 as efficiently as possible */
8331 if (AOP_TYPE (right) == AOP_LIT)
8333 if (genLeftShiftLiteral (left, right, result, ic))
8340 /* shift count is unknown then we have to form
8341 a loop get the loop count in B : Note: we take
8342 only the lower order byte since shifting
8343 more that 32 bits make no sense anyway, ( the
8344 largest size of an object can be only 32 bits ) */
8346 if (AOP_TYPE (right) == AOP_LIT)
8348 /* Really should be handled by genLeftShiftLiteral,
8349 * but since I'm too lazy to fix that today, at least we can make
8350 * some small improvement.
8352 emitcode("mov", "b,#!constbyte",
8353 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8357 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8358 emitcode ("inc", "b");
8360 freeAsmop (right, NULL, ic, TRUE);
8361 aopOp (left, ic, FALSE, FALSE);
8362 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8364 /* now move the left to the result if they are not the
8366 if (!sameRegs (AOP (left), AOP (result)) &&
8367 AOP_SIZE (result) > 1)
8370 size = AOP_SIZE (result);
8372 _startLazyDPSEvaluation ();
8375 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8376 if (*l == '@' && (IS_AOP_PREG (result)))
8379 emitcode ("mov", "a,%s", l);
8380 aopPut (AOP (result), "a", offset);
8383 aopPut (AOP (result), l, offset);
8386 _endLazyDPSEvaluation ();
8389 tlbl = newiTempLabel (NULL);
8390 size = AOP_SIZE (result);
8392 tlbl1 = newiTempLabel (NULL);
8394 /* if it is only one byte then */
8397 symbol *tlbl1 = newiTempLabel (NULL);
8399 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8400 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8401 emitcode ("", "!tlabeldef", tlbl->key + 100);
8402 emitcode ("add", "a,acc");
8403 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8404 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8405 aopPut (AOP (result), "a", 0);
8409 reAdjustPreg (AOP (result));
8411 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8412 emitcode ("", "!tlabeldef", tlbl->key + 100);
8413 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8414 emitcode ("add", "a,acc");
8415 aopPut (AOP (result), "a", offset++);
8416 _startLazyDPSEvaluation ();
8419 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8420 emitcode ("rlc", "a");
8421 aopPut (AOP (result), "a", offset++);
8423 _endLazyDPSEvaluation ();
8424 reAdjustPreg (AOP (result));
8426 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8427 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8429 freeAsmop (left, NULL, ic, TRUE);
8430 freeAsmop (result, NULL, ic, TRUE);
8433 #ifdef BETTER_LITERAL_SHIFT
8434 /*-----------------------------------------------------------------*/
8435 /* genrshOne - right shift a one byte quantity by known count */
8436 /*-----------------------------------------------------------------*/
8438 genrshOne (operand * result, operand * left,
8439 int shCount, int sign)
8441 D (emitcode (";", "genrshOne"););
8442 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8446 #ifdef BETTER_LITERAL_SHIFT
8447 /*-----------------------------------------------------------------*/
8448 /* genrshTwo - right shift two bytes by known amount != 0 */
8449 /*-----------------------------------------------------------------*/
8451 genrshTwo (operand * result, operand * left,
8452 int shCount, int sign)
8454 D (emitcode (";", "genrshTwo"););
8456 /* if shCount >= 8 */
8460 _startLazyDPSEvaluation();
8463 shiftR1Left2Result (left, MSB16, result, LSB,
8468 movLeft2Result (left, MSB16, result, LSB, sign);
8470 addSign (result, MSB16, sign);
8471 _endLazyDPSEvaluation();
8474 /* 1 <= shCount <= 7 */
8477 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8482 /*-----------------------------------------------------------------*/
8483 /* shiftRLong - shift right one long from left to result */
8484 /* offl = LSB or MSB16 */
8485 /*-----------------------------------------------------------------*/
8487 shiftRLong (operand * left, int offl,
8488 operand * result, int sign)
8490 int isSameRegs=sameRegs(AOP(left),AOP(result));
8492 if (isSameRegs && offl>1) {
8493 // we are in big trouble, but this shouldn't happen
8494 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8497 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8502 emitcode ("rlc", "a");
8503 emitcode ("subb", "a,acc");
8504 emitcode ("xch", "a,%s",
8505 aopGet(AOP(left), MSB32, FALSE, FALSE, DP2_RESULT_REG));
8507 aopPut (AOP(result), zero, MSB32);
8512 emitcode ("clr", "c");
8514 emitcode ("mov", "c,acc.7");
8517 emitcode ("rrc", "a");
8519 if (isSameRegs && offl==MSB16) {
8521 "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE, DP2_RESULT_REG));
8523 aopPut (AOP (result), "a", MSB32);
8524 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8527 emitcode ("rrc", "a");
8528 if (isSameRegs && offl==1) {
8529 emitcode ("xch", "a,%s",
8530 aopGet (AOP (left), MSB16, FALSE, FALSE, DP2_RESULT_REG));
8532 aopPut (AOP (result), "a", MSB24);
8533 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, NULL));
8535 emitcode ("rrc", "a");
8536 aopPut (AOP (result), "a", MSB16 - offl);
8540 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, NULL));
8541 emitcode ("rrc", "a");
8542 aopPut (AOP (result), "a", LSB);
8546 /*-----------------------------------------------------------------*/
8547 /* genrshFour - shift four byte by a known amount != 0 */
8548 /*-----------------------------------------------------------------*/
8550 genrshFour (operand * result, operand * left,
8551 int shCount, int sign)
8553 D (emitcode (";", "genrshFour"););
8555 /* if shifting more that 3 bytes */
8559 _startLazyDPSEvaluation();
8561 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8563 movLeft2Result (left, MSB32, result, LSB, sign);
8564 addSign (result, MSB16, sign);
8565 _endLazyDPSEvaluation();
8567 else if (shCount >= 16)
8570 _startLazyDPSEvaluation();
8572 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8575 movLeft2Result (left, MSB24, result, LSB, 0);
8576 movLeft2Result (left, MSB32, result, MSB16, sign);
8578 addSign (result, MSB24, sign);
8579 _endLazyDPSEvaluation();
8581 else if (shCount >= 8)
8584 _startLazyDPSEvaluation();
8587 shiftRLong (left, MSB16, result, sign);
8589 else if (shCount == 0)
8591 movLeft2Result (left, MSB16, result, LSB, 0);
8592 movLeft2Result (left, MSB24, result, MSB16, 0);
8593 movLeft2Result (left, MSB32, result, MSB24, sign);
8594 addSign (result, MSB32, sign);
8598 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8599 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8600 /* the last shift is signed */
8601 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8602 addSign (result, MSB32, sign);
8604 _endLazyDPSEvaluation();
8608 /* 1 <= shCount <= 7 */
8611 shiftRLong (left, LSB, result, sign);
8613 shiftRLong (result, LSB, result, sign);
8617 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8618 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8619 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8624 #ifdef BETTER_LITERAL_SHIFT
8625 /*-----------------------------------------------------------------*/
8626 /* genRightShiftLiteral - right shifting by known count */
8627 /*-----------------------------------------------------------------*/
8629 genRightShiftLiteral (operand * left,
8635 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8638 size = getSize (operandType (result));
8640 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8642 /* We only handle certain easy cases so far. */
8644 && (shCount < (size * 8))
8649 D(emitcode (";", "genRightShiftLiteral wimping out"););
8653 freeAsmop (right, NULL, ic, TRUE);
8655 aopOp (left, ic, FALSE, FALSE);
8656 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8659 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8663 /* test the LEFT size !!! */
8665 /* I suppose that the left size >= result size */
8668 size = getDataSize (result);
8669 _startLazyDPSEvaluation();
8672 movLeft2Result (left, size, result, size, 0);
8674 _endLazyDPSEvaluation();
8676 else if (shCount >= (size * 8))
8680 /* get sign in acc.7 */
8681 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
8683 addSign (result, LSB, sign);
8690 genrshOne (result, left, shCount, sign);
8694 genrshTwo (result, left, shCount, sign);
8698 genrshFour (result, left, shCount, sign);
8705 freeAsmop (left, NULL, ic, TRUE);
8706 freeAsmop (result, NULL, ic, TRUE);
8712 /*-----------------------------------------------------------------*/
8713 /* genSignedRightShift - right shift of signed number */
8714 /*-----------------------------------------------------------------*/
8716 genSignedRightShift (iCode * ic)
8718 operand *right, *left, *result;
8721 symbol *tlbl, *tlbl1;
8723 D (emitcode (";", "genSignedRightShift "););
8725 /* we do it the hard way put the shift count in b
8726 and loop thru preserving the sign */
8728 right = IC_RIGHT (ic);
8729 left = IC_LEFT (ic);
8730 result = IC_RESULT (ic);
8732 aopOp (right, ic, FALSE, FALSE);
8734 #ifdef BETTER_LITERAL_SHIFT
8735 if (AOP_TYPE (right) == AOP_LIT)
8737 if (genRightShiftLiteral (left, right, result, ic, 1))
8743 /* shift count is unknown then we have to form
8744 a loop get the loop count in B : Note: we take
8745 only the lower order byte since shifting
8746 more that 32 bits make no sense anyway, ( the
8747 largest size of an object can be only 32 bits ) */
8749 if (AOP_TYPE (right) == AOP_LIT)
8751 /* Really should be handled by genRightShiftLiteral,
8752 * but since I'm too lazy to fix that today, at least we can make
8753 * some small improvement.
8755 emitcode("mov", "b,#!constbyte",
8756 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8760 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8761 emitcode ("inc", "b");
8763 freeAsmop (right, NULL, ic, TRUE);
8764 aopOp (left, ic, FALSE, FALSE);
8765 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8767 /* now move the left to the result if they are not the
8769 if (!sameRegs (AOP (left), AOP (result)) &&
8770 AOP_SIZE (result) > 1)
8773 size = AOP_SIZE (result);
8775 _startLazyDPSEvaluation ();
8778 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8779 if (*l == '@' && IS_AOP_PREG (result))
8782 emitcode ("mov", "a,%s", l);
8783 aopPut (AOP (result), "a", offset);
8786 aopPut (AOP (result), l, offset);
8789 _endLazyDPSEvaluation ();
8792 /* mov the highest order bit to OVR */
8793 tlbl = newiTempLabel (NULL);
8794 tlbl1 = newiTempLabel (NULL);
8796 size = AOP_SIZE (result);
8798 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
8799 emitcode ("rlc", "a");
8800 emitcode ("mov", "ov,c");
8801 /* if it is only one byte then */
8804 MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8805 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8806 emitcode ("", "!tlabeldef", tlbl->key + 100);
8807 emitcode ("mov", "c,ov");
8808 emitcode ("rrc", "a");
8809 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8810 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8811 aopPut (AOP (result), "a", 0);
8815 reAdjustPreg (AOP (result));
8816 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8817 emitcode ("", "!tlabeldef", tlbl->key + 100);
8818 emitcode ("mov", "c,ov");
8819 _startLazyDPSEvaluation ();
8822 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8823 emitcode ("rrc", "a");
8824 aopPut (AOP (result), "a", offset--);
8826 _endLazyDPSEvaluation ();
8827 reAdjustPreg (AOP (result));
8828 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8829 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8832 freeAsmop (left, NULL, ic, TRUE);
8833 freeAsmop (result, NULL, ic, TRUE);
8836 /*-----------------------------------------------------------------*/
8837 /* genRightShift - generate code for right shifting */
8838 /*-----------------------------------------------------------------*/
8840 genRightShift (iCode * ic)
8842 operand *right, *left, *result;
8846 symbol *tlbl, *tlbl1;
8848 D (emitcode (";", "genRightShift "););
8850 /* if signed then we do it the hard way preserve the
8851 sign bit moving it inwards */
8852 retype = getSpec (operandType (IC_RESULT (ic)));
8854 if (!SPEC_USIGN (retype))
8856 genSignedRightShift (ic);
8860 /* signed & unsigned types are treated the same : i.e. the
8861 signed is NOT propagated inwards : quoting from the
8862 ANSI - standard : "for E1 >> E2, is equivalent to division
8863 by 2**E2 if unsigned or if it has a non-negative value,
8864 otherwise the result is implementation defined ", MY definition
8865 is that the sign does not get propagated */
8867 right = IC_RIGHT (ic);
8868 left = IC_LEFT (ic);
8869 result = IC_RESULT (ic);
8871 aopOp (right, ic, FALSE, FALSE);
8873 #ifdef BETTER_LITERAL_SHIFT
8874 /* if the shift count is known then do it
8875 as efficiently as possible */
8876 if (AOP_TYPE (right) == AOP_LIT)
8878 if (genRightShiftLiteral (left, right, result, ic, 0))
8885 /* shift count is unknown then we have to form
8886 a loop get the loop count in B : Note: we take
8887 only the lower order byte since shifting
8888 more that 32 bits make no sense anyway, ( the
8889 largest size of an object can be only 32 bits ) */
8891 if (AOP_TYPE (right) == AOP_LIT)
8893 /* Really should be handled by genRightShiftLiteral,
8894 * but since I'm too lazy to fix that today, at least we can make
8895 * some small improvement.
8897 emitcode("mov", "b,#!constbyte",
8898 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8902 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8903 emitcode ("inc", "b");
8905 freeAsmop (right, NULL, ic, TRUE);
8906 aopOp (left, ic, FALSE, FALSE);
8907 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8909 /* now move the left to the result if they are not the
8911 if (!sameRegs (AOP (left), AOP (result)) &&
8912 AOP_SIZE (result) > 1)
8915 size = AOP_SIZE (result);
8917 _startLazyDPSEvaluation ();
8920 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8921 if (*l == '@' && IS_AOP_PREG (result))
8924 emitcode ("mov", "a,%s", l);
8925 aopPut (AOP (result), "a", offset);
8928 aopPut (AOP (result), l, offset);
8931 _endLazyDPSEvaluation ();
8934 tlbl = newiTempLabel (NULL);
8935 tlbl1 = newiTempLabel (NULL);
8936 size = AOP_SIZE (result);
8939 /* if it is only one byte then */
8942 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8943 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8944 emitcode ("", "!tlabeldef", tlbl->key + 100);
8946 emitcode ("rrc", "a");
8947 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8948 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8949 aopPut (AOP (result), "a", 0);
8953 reAdjustPreg (AOP (result));
8954 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8955 emitcode ("", "!tlabeldef", tlbl->key + 100);
8957 _startLazyDPSEvaluation ();
8960 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8961 emitcode ("rrc", "a");
8962 aopPut (AOP (result), "a", offset--);
8964 _endLazyDPSEvaluation ();
8965 reAdjustPreg (AOP (result));
8967 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8968 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8971 freeAsmop (left, NULL, ic, TRUE);
8972 freeAsmop (result, NULL, ic, TRUE);
8975 /*-----------------------------------------------------------------*/
8976 /* genUnpackBits - generates code for unpacking bits */
8977 /*-----------------------------------------------------------------*/
8979 genUnpackBits (operand * result, char *rname, int ptype)
8986 D (emitcode (";", "genUnpackBits "););
8988 etype = getSpec (operandType (result));
8990 /* read the first byte */
8996 emitcode ("mov", "a,@%s", rname);
9000 emitcode ("movx", "a,@%s", rname);
9004 emitcode ("movx", "a,@dptr");
9008 emitcode ("clr", "a");
9009 emitcode ("movc", "a,@a+dptr");
9013 emitcode ("lcall", "__gptrget");
9017 /* if we have bitdisplacement then it fits */
9018 /* into this byte completely or if length is */
9019 /* less than a byte */
9020 if (((shCnt = SPEC_BSTR (etype)) != 0) || (SPEC_BLEN (etype) <= 8))
9023 /* shift right acc */
9026 emitcode ("anl", "a,#!constbyte",
9027 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
9028 aopPut (AOP (result), "a", offset);
9032 /* bit field did not fit in a byte */
9033 rlen = SPEC_BLEN (etype) - 8;
9034 aopPut (AOP (result), "a", offset++);
9043 emitcode ("inc", "%s", rname);
9044 emitcode ("mov", "a,@%s", rname);
9048 emitcode ("inc", "%s", rname);
9049 emitcode ("movx", "a,@%s", rname);
9053 emitcode ("inc", "dptr");
9054 emitcode ("movx", "a,@dptr");
9058 emitcode ("clr", "a");
9059 emitcode ("inc", "dptr");
9060 emitcode ("movc", "a,@a+dptr");
9064 emitcode ("inc", "dptr");
9065 emitcode ("lcall", "__gptrget");
9070 /* if we are done */
9074 aopPut (AOP (result), "a", offset++);
9080 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (rlen));
9081 aopPut (AOP (result), "a", offset);
9088 /*-----------------------------------------------------------------*/
9089 /* genDataPointerGet - generates code when ptr offset is known */
9090 /*-----------------------------------------------------------------*/
9092 genDataPointerGet (operand * left,
9098 int size, offset = 0;
9099 aopOp (result, ic, TRUE, FALSE);
9101 /* get the string representation of the name */
9102 l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9103 size = AOP_SIZE (result);
9104 _startLazyDPSEvaluation ();
9109 SNPRINTF (buff, sizeof(buff),
9110 "(%s + %d)", l + 1, offset);
9114 SNPRINTF (buff, sizeof(buff),
9117 aopPut (AOP (result), buff, offset++);
9119 _endLazyDPSEvaluation ();
9121 freeAsmop (left, NULL, ic, TRUE);
9122 freeAsmop (result, NULL, ic, TRUE);
9125 /*-----------------------------------------------------------------*/
9126 /* genNearPointerGet - emitcode for near pointer fetch */
9127 /*-----------------------------------------------------------------*/
9129 genNearPointerGet (operand * left,
9137 sym_link *rtype, *retype, *letype;
9138 sym_link *ltype = operandType (left);
9141 rtype = operandType (result);
9142 retype = getSpec (rtype);
9143 letype = getSpec (ltype);
9145 aopOp (left, ic, FALSE, FALSE);
9147 /* if left is rematerialisable and
9148 result is not bit variable type and
9149 the left is pointer to data space i.e
9150 lower 128 bytes of space */
9151 if (AOP_TYPE (left) == AOP_IMMD &&
9152 !IS_BITVAR (retype) &&
9153 !IS_BITVAR (letype) &&
9154 DCL_TYPE (ltype) == POINTER)
9156 genDataPointerGet (left, result, ic);
9160 /* if the value is already in a pointer register
9161 then don't need anything more */
9162 if (!AOP_INPREG (AOP (left)))
9164 /* otherwise get a free pointer register */
9166 preg = getFreePtr (ic, &aop, FALSE);
9167 emitcode ("mov", "%s,%s",
9169 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9173 rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9175 freeAsmop (left, NULL, ic, TRUE);
9176 aopOp (result, ic, FALSE, FALSE);
9178 /* if bitfield then unpack the bits */
9179 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9180 genUnpackBits (result, rname, POINTER);
9183 /* we have can just get the values */
9184 int size = AOP_SIZE (result);
9189 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9192 emitcode ("mov", "a,@%s", rname);
9193 aopPut (AOP (result), "a", offset);
9197 SNPRINTF (buff, sizeof(buff), "@%s", rname);
9198 aopPut (AOP (result), buff, offset);
9203 emitcode ("inc", "%s", rname);
9208 /* now some housekeeping stuff */
9211 /* we had to allocate for this iCode */
9212 if (pi) { /* post increment present */
9213 aopPut(AOP ( left ),rname,0);
9215 freeAsmop (NULL, aop, ic, TRUE);
9219 /* we did not allocate which means left
9220 already in a pointer register, then
9221 if size > 0 && this could be used again
9222 we have to point it back to where it
9224 if (AOP_SIZE (result) > 1 &&
9225 !OP_SYMBOL (left)->remat &&
9226 (OP_SYMBOL (left)->liveTo > ic->seq ||
9230 int size = AOP_SIZE (result) - 1;
9232 emitcode ("dec", "%s", rname);
9237 freeAsmop (result, NULL, ic, TRUE);
9238 if (pi) pi->generated = 1;
9241 /*-----------------------------------------------------------------*/
9242 /* genPagedPointerGet - emitcode for paged pointer fetch */
9243 /*-----------------------------------------------------------------*/
9245 genPagedPointerGet (operand * left,
9253 sym_link *rtype, *retype, *letype;
9255 rtype = operandType (result);
9256 retype = getSpec (rtype);
9257 letype = getSpec (operandType (left));
9258 aopOp (left, ic, FALSE, FALSE);
9260 /* if the value is already in a pointer register
9261 then don't need anything more */
9262 if (!AOP_INPREG (AOP (left)))
9264 /* otherwise get a free pointer register */
9266 preg = getFreePtr (ic, &aop, FALSE);
9267 emitcode ("mov", "%s,%s",
9269 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9273 rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9275 freeAsmop (left, NULL, ic, TRUE);
9276 aopOp (result, ic, FALSE, FALSE);
9278 /* if bitfield then unpack the bits */
9279 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9280 genUnpackBits (result, rname, PPOINTER);
9283 /* we have can just get the values */
9284 int size = AOP_SIZE (result);
9290 emitcode ("movx", "a,@%s", rname);
9291 aopPut (AOP (result), "a", offset);
9296 emitcode ("inc", "%s", rname);
9300 /* now some housekeeping stuff */
9303 /* we had to allocate for this iCode */
9304 if (pi) aopPut ( AOP (left), rname, 0);
9305 freeAsmop (NULL, aop, ic, TRUE);
9309 /* we did not allocate which means left
9310 already in a pointer register, then
9311 if size > 0 && this could be used again
9312 we have to point it back to where it
9314 if (AOP_SIZE (result) > 1 &&
9315 !OP_SYMBOL (left)->remat &&
9316 (OP_SYMBOL (left)->liveTo > ic->seq ||
9320 int size = AOP_SIZE (result) - 1;
9322 emitcode ("dec", "%s", rname);
9327 freeAsmop (result, NULL, ic, TRUE);
9328 if (pi) pi->generated = 1;
9331 /*-----------------------------------------------------------------*/
9332 /* genFarPointerGet - gget value from far space */
9333 /*-----------------------------------------------------------------*/
9335 genFarPointerGet (operand * left,
9336 operand * result, iCode * ic, iCode *pi)
9338 int size, offset, dopi=1;
9339 sym_link *retype = getSpec (operandType (result));
9340 sym_link *letype = getSpec (operandType (left));
9341 D (emitcode (";", "genFarPointerGet"););
9343 aopOp (left, ic, FALSE, FALSE);
9345 /* if the operand is already in dptr
9346 then we do nothing else we move the value to dptr */
9347 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9349 /* if this is remateriazable */
9350 if (AOP_TYPE (left) == AOP_IMMD)
9352 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9356 /* we need to get it byte by byte */
9357 _startLazyDPSEvaluation ();
9358 if (AOP_TYPE (left) != AOP_DPTR)
9360 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9361 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9362 if (options.model == MODEL_FLAT24)
9363 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9367 /* We need to generate a load to DPTR indirect through DPTR. */
9368 D (emitcode (";", "genFarPointerGet -- indirection special case."););
9369 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9370 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9371 if (options.model == MODEL_FLAT24)
9372 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9373 emitcode ("pop", "dph");
9374 emitcode ("pop", "dpl");
9377 _endLazyDPSEvaluation ();
9380 /* so dptr know contains the address */
9381 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9383 /* if bit then unpack */
9384 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9385 if (AOP_INDPTRn(left)) {
9386 genSetDPTR(AOP(left)->aopu.dptr);
9388 genUnpackBits (result, "dptr", FPOINTER);
9389 if (AOP_INDPTRn(left)) {
9394 size = AOP_SIZE (result);
9397 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9399 genSetDPTR(AOP(left)->aopu.dptr);
9400 emitcode ("movx", "a,@dptr");
9401 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9402 emitcode ("inc", "dptr");
9404 aopPut (AOP (result), "a", offset++);
9407 _startLazyDPSEvaluation ();
9409 if (AOP_INDPTRn(left)) {
9410 genSetDPTR(AOP(left)->aopu.dptr);
9416 emitcode ("movx", "a,@dptr");
9417 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9418 emitcode ("inc", "dptr");
9420 aopPut (AOP (result), "a", offset++);
9422 _endLazyDPSEvaluation ();
9425 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9426 if (!AOP_INDPTRn(left)) {
9427 _startLazyDPSEvaluation ();
9428 aopPut ( AOP (left), "dpl", 0);
9429 aopPut ( AOP (left), "dph", 1);
9430 if (options.model == MODEL_FLAT24)
9431 aopPut ( AOP (left), "dpx", 2);
9432 _endLazyDPSEvaluation ();
9435 } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) &&
9436 AOP_SIZE(result) > 1 &&
9438 (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
9440 size = AOP_SIZE (result) - 1;
9441 if (AOP_INDPTRn(left)) {
9442 genSetDPTR(AOP(left)->aopu.dptr);
9444 while (size--) emitcode ("lcall","__decdptr");
9445 if (AOP_INDPTRn(left)) {
9450 freeAsmop (left, NULL, ic, TRUE);
9451 freeAsmop (result, NULL, ic, TRUE);
9454 /*-----------------------------------------------------------------*/
9455 /* genCodePointerGet - get value from code space */
9456 /*-----------------------------------------------------------------*/
9458 genCodePointerGet (operand * left,
9459 operand * result, iCode * ic, iCode *pi)
9461 int size, offset, dopi=1;
9462 sym_link *retype = getSpec (operandType (result));
9464 aopOp (left, ic, FALSE, FALSE);
9466 /* if the operand is already in dptr
9467 then we do nothing else we move the value to dptr */
9468 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
9470 /* if this is remateriazable */
9471 if (AOP_TYPE (left) == AOP_IMMD)
9473 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9476 { /* we need to get it byte by byte */
9477 _startLazyDPSEvaluation ();
9478 if (AOP_TYPE (left) != AOP_DPTR)
9480 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9481 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9482 if (options.model == MODEL_FLAT24)
9483 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9487 /* We need to generate a load to DPTR indirect through DPTR. */
9488 D (emitcode (";", "gencodePointerGet -- indirection special case."););
9489 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9490 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9491 if (options.model == MODEL_FLAT24)
9492 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9493 emitcode ("pop", "dph");
9494 emitcode ("pop", "dpl");
9497 _endLazyDPSEvaluation ();
9500 /* so dptr know contains the address */
9501 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9503 /* if bit then unpack */
9504 if (IS_BITVAR (retype)) {
9505 if (AOP_INDPTRn(left)) {
9506 genSetDPTR(AOP(left)->aopu.dptr);
9508 genUnpackBits (result, "dptr", CPOINTER);
9509 if (AOP_INDPTRn(left)) {
9514 size = AOP_SIZE (result);
9516 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9518 genSetDPTR(AOP(left)->aopu.dptr);
9519 emitcode ("clr", "a");
9520 emitcode ("movc", "a,@a+dptr");
9521 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9522 emitcode ("inc", "dptr");
9524 aopPut (AOP (result), "a", offset++);
9527 _startLazyDPSEvaluation ();
9530 if (AOP_INDPTRn(left)) {
9531 genSetDPTR(AOP(left)->aopu.dptr);
9537 emitcode ("clr", "a");
9538 emitcode ("movc", "a,@a+dptr");
9539 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9540 emitcode ("inc", "dptr");
9541 aopPut (AOP (result), "a", offset++);
9543 _endLazyDPSEvaluation ();
9546 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9547 if (!AOP_INDPTRn(left)) {
9548 _startLazyDPSEvaluation ();
9550 aopPut ( AOP (left), "dpl", 0);
9551 aopPut ( AOP (left), "dph", 1);
9552 if (options.model == MODEL_FLAT24)
9553 aopPut ( AOP (left), "dpx", 2);
9555 _endLazyDPSEvaluation ();
9558 } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
9559 AOP_SIZE(result) > 1 &&
9560 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9562 size = AOP_SIZE (result) - 1;
9563 if (AOP_INDPTRn(left)) {
9564 genSetDPTR(AOP(left)->aopu.dptr);
9566 while (size--) emitcode ("lcall","__decdptr");
9567 if (AOP_INDPTRn(left)) {
9572 freeAsmop (left, NULL, ic, TRUE);
9573 freeAsmop (result, NULL, ic, TRUE);
9576 /*-----------------------------------------------------------------*/
9577 /* genGenPointerGet - gget value from generic pointer space */
9578 /*-----------------------------------------------------------------*/
9580 genGenPointerGet (operand * left,
9581 operand * result, iCode * ic, iCode * pi)
9584 sym_link *retype = getSpec (operandType (result));
9585 sym_link *letype = getSpec (operandType (left));
9587 D (emitcode (";", "genGenPointerGet "); );
9589 aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
9591 /* if the operand is already in dptr
9592 then we do nothing else we move the value to dptr */
9593 if (AOP_TYPE (left) != AOP_STR)
9595 /* if this is remateriazable */
9596 if (AOP_TYPE (left) == AOP_IMMD)
9598 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9599 if (AOP(left)->aopu.aop_immd.from_cast_remat)
9601 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
9605 emitcode ("mov", "b,#%d", pointerCode (retype));
9609 { /* we need to get it byte by byte */
9610 _startLazyDPSEvaluation ();
9611 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
9612 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
9613 if (options.model == MODEL_FLAT24) {
9614 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9615 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
9617 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9619 _endLazyDPSEvaluation ();
9623 /* so dptr-b now contains the address */
9625 aopOp (result, ic, FALSE, TRUE);
9628 /* if bit then unpack */
9629 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9631 genUnpackBits (result, "dptr", GPOINTER);
9635 size = AOP_SIZE (result);
9642 // Get two bytes at a time, results in _AP & A.
9643 // dptr will be incremented ONCE by __gptrgetWord.
9645 // Note: any change here must be coordinated
9646 // with the implementation of __gptrgetWord
9647 // in device/lib/_gptrget.c
9648 emitcode ("lcall", "__gptrgetWord");
9649 aopPut (AOP (result), DP2_RESULT_REG, offset++);
9650 aopPut (AOP (result), "a", offset++);
9655 // Only one byte to get.
9656 emitcode ("lcall", "__gptrget");
9657 aopPut (AOP (result), "a", offset++);
9660 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9662 emitcode ("inc", "dptr");
9667 if (pi && AOP_TYPE (left) != AOP_IMMD) {
9668 _startLazyDPSEvaluation ();
9670 aopPut ( AOP (left), "dpl", 0);
9671 aopPut ( AOP (left), "dph", 1);
9672 if (options.model == MODEL_FLAT24) {
9673 aopPut ( AOP (left), "dpx", 2);
9674 aopPut ( AOP (left), "b", 3);
9675 } else aopPut ( AOP (left), "b", 2);
9677 _endLazyDPSEvaluation ();
9680 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9681 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9683 size = AOP_SIZE (result) - 1;
9684 while (size--) emitcode ("lcall","__decdptr");
9687 freeAsmop (left, NULL, ic, TRUE);
9688 freeAsmop (result, NULL, ic, TRUE);
9691 /*-----------------------------------------------------------------*/
9692 /* genPointerGet - generate code for pointer get */
9693 /*-----------------------------------------------------------------*/
9695 genPointerGet (iCode * ic, iCode *pi)
9697 operand *left, *result;
9698 sym_link *type, *etype;
9701 D (emitcode (";", "genPointerGet ");
9704 left = IC_LEFT (ic);
9705 result = IC_RESULT (ic);
9707 /* depending on the type of pointer we need to
9708 move it to the correct pointer register */
9709 type = operandType (left);
9710 etype = getSpec (type);
9711 /* if left is of type of pointer then it is simple */
9712 if (IS_PTR (type) && !IS_FUNC (type->next))
9713 p_type = DCL_TYPE (type);
9716 /* we have to go by the storage class */
9717 p_type = PTR_TYPE (SPEC_OCLS (etype));
9719 /* special case when cast remat */
9720 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9721 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9722 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9723 type = operandType (left);
9724 p_type = DCL_TYPE (type);
9726 /* now that we have the pointer type we assign
9727 the pointer values */
9733 genNearPointerGet (left, result, ic, pi);
9737 genPagedPointerGet (left, result, ic, pi);
9741 genFarPointerGet (left, result, ic, pi);
9745 genCodePointerGet (left, result, ic, pi);
9749 genGenPointerGet (left, result, ic, pi);
9755 /*-----------------------------------------------------------------*/
9756 /* genPackBits - generates code for packed bit storage */
9757 /*-----------------------------------------------------------------*/
9759 genPackBits (sym_link * etype,
9761 char *rname, int p_type)
9768 blen = SPEC_BLEN (etype);
9769 bstr = SPEC_BSTR (etype);
9771 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9773 /* if the bit lenth is less than or */
9774 /* it exactly fits a byte then */
9775 if (SPEC_BLEN (etype) <= 8)
9777 /* shift left acc */
9778 AccLsh (SPEC_BSTR (etype));
9780 if (SPEC_BLEN (etype) < 8)
9781 { /* if smaller than a byte */
9787 emitcode ("mov", "b,a");
9788 emitcode ("mov", "a,@%s", rname);
9792 emitcode ("mov", "b,a");
9793 emitcode ("movx", "a,@dptr");
9797 emitcode ("push", "b");
9798 emitcode ("push", "acc");
9799 emitcode ("lcall", "__gptrget");
9800 emitcode ("pop", "b");
9804 emitcode ("anl", "a,#!constbyte", (unsigned char)
9805 ((unsigned char) (0xFF << (blen + bstr)) |
9806 (unsigned char) (0xFF >> (8 - bstr))));
9807 emitcode ("orl", "a,b");
9808 if (p_type == GPOINTER)
9809 emitcode ("pop", "b");
9816 emitcode ("mov", "@%s,a", rname);
9820 emitcode ("movx", "@dptr,a");
9824 emitcode ("lcall", "__gptrput");
9829 if (SPEC_BLEN (etype) <= 8)
9832 emitcode ("inc", "%s", rname);
9833 rLen = SPEC_BLEN (etype);
9835 /* now generate for lengths greater than one byte */
9839 l = aopGet (AOP (right), offset++, FALSE, TRUE, NULL);
9851 emitcode ("mov", "@%s,a", rname);
9854 emitcode ("mov", "@%s,%s", rname, l);
9859 emitcode ("movx", "@dptr,a");
9864 emitcode ("lcall", "__gptrput");
9867 emitcode ("inc", "%s", rname);
9872 /* last last was not complete */
9875 /* save the byte & read byte */
9879 emitcode ("mov", "b,a");
9880 emitcode ("mov", "a,@%s", rname);
9884 emitcode ("mov", "b,a");
9885 emitcode ("movx", "a,@dptr");
9889 emitcode ("push", "b");
9890 emitcode ("push", "acc");
9891 emitcode ("lcall", "__gptrget");
9892 emitcode ("pop", "b");
9896 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1 << rLen));
9897 emitcode ("orl", "a,b");
9900 if (p_type == GPOINTER)
9901 emitcode ("pop", "b");
9907 emitcode ("mov", "@%s,a", rname);
9911 emitcode ("movx", "@dptr,a");
9915 emitcode ("lcall", "__gptrput");
9919 /*-----------------------------------------------------------------*/
9920 /* genDataPointerSet - remat pointer to data space */
9921 /*-----------------------------------------------------------------*/
9923 genDataPointerSet (operand * right,
9927 int size, offset = 0;
9930 aopOp (right, ic, FALSE, FALSE);
9932 l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
9933 size = AOP_SIZE (right);
9938 SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
9942 SNPRINTF (buff, sizeof(buff), "%s", l + 1);
9945 emitcode ("mov", "%s,%s", buff,
9946 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9949 freeAsmop (right, NULL, ic, TRUE);
9950 freeAsmop (result, NULL, ic, TRUE);
9953 /*-----------------------------------------------------------------*/
9954 /* genNearPointerSet - emitcode for near pointer put */
9955 /*-----------------------------------------------------------------*/
9957 genNearPointerSet (operand * right,
9964 sym_link *retype, *letype;
9965 sym_link *ptype = operandType (result);
9967 retype = getSpec (operandType (right));
9968 letype = getSpec (ptype);
9970 aopOp (result, ic, FALSE, FALSE);
9972 /* if the result is rematerializable &
9973 in data space & not a bit variable */
9974 if (AOP_TYPE (result) == AOP_IMMD &&
9975 DCL_TYPE (ptype) == POINTER &&
9976 !IS_BITVAR (retype) &&
9977 !IS_BITVAR (letype))
9979 genDataPointerSet (right, result, ic);
9983 /* if the value is already in a pointer register
9984 then don't need anything more */
9985 if (!AOP_INPREG (AOP (result)))
9987 /* otherwise get a free pointer register */
9991 preg = getFreePtr (ic, &aop, FALSE);
9992 emitcode ("mov", "%s,%s",
9994 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
9998 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10000 aopOp (right, ic, FALSE, FALSE);
10002 /* if bitfield then unpack the bits */
10003 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10004 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
10007 /* we have can just get the values */
10008 int size = AOP_SIZE (right);
10013 l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
10017 emitcode ("mov", "@%s,a", rname);
10020 emitcode ("mov", "@%s,%s", rname, l);
10022 emitcode ("inc", "%s", rname);
10027 /* now some housekeeping stuff */
10030 /* we had to allocate for this iCode */
10031 if (pi) aopPut (AOP (result),rname,0);
10032 freeAsmop (NULL, aop, ic, TRUE);
10036 /* we did not allocate which means left
10037 already in a pointer register, then
10038 if size > 0 && this could be used again
10039 we have to point it back to where it
10041 if (AOP_SIZE (right) > 1 &&
10042 !OP_SYMBOL (result)->remat &&
10043 (OP_SYMBOL (result)->liveTo > ic->seq ||
10047 int size = AOP_SIZE (right) - 1;
10049 emitcode ("dec", "%s", rname);
10054 if (pi) pi->generated = 1;
10055 freeAsmop (result, NULL, ic, TRUE);
10056 freeAsmop (right, NULL, ic, TRUE);
10061 /*-----------------------------------------------------------------*/
10062 /* genPagedPointerSet - emitcode for Paged pointer put */
10063 /*-----------------------------------------------------------------*/
10065 genPagedPointerSet (operand * right,
10072 sym_link *retype, *letype;
10074 retype = getSpec (operandType (right));
10075 letype = getSpec (operandType (result));
10077 aopOp (result, ic, FALSE, FALSE);
10079 /* if the value is already in a pointer register
10080 then don't need anything more */
10081 if (!AOP_INPREG (AOP (result)))
10083 /* otherwise get a free pointer register */
10086 aop = newAsmop (0);
10087 preg = getFreePtr (ic, &aop, FALSE);
10088 emitcode ("mov", "%s,%s",
10090 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10091 rname = preg->name;
10094 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10096 aopOp (right, ic, FALSE, FALSE);
10098 /* if bitfield then unpack the bits */
10099 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10100 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
10103 /* we have can just get the values */
10104 int size = AOP_SIZE (right);
10109 MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10111 emitcode ("movx", "@%s,a", rname);
10114 emitcode ("inc", "%s", rname);
10120 /* now some housekeeping stuff */
10123 if (pi) aopPut (AOP (result),rname,0);
10124 /* we had to allocate for this iCode */
10125 freeAsmop (NULL, aop, ic, TRUE);
10129 /* we did not allocate which means left
10130 already in a pointer register, then
10131 if size > 0 && this could be used again
10132 we have to point it back to where it
10134 if (AOP_SIZE (right) > 1 &&
10135 !OP_SYMBOL (result)->remat &&
10136 (OP_SYMBOL (result)->liveTo > ic->seq ||
10140 int size = AOP_SIZE (right) - 1;
10142 emitcode ("dec", "%s", rname);
10147 if (pi) pi->generated = 1;
10148 freeAsmop (result, NULL, ic, TRUE);
10149 freeAsmop (right, NULL, ic, TRUE);
10154 /*-----------------------------------------------------------------*/
10155 /* genFarPointerSet - set value from far space */
10156 /*-----------------------------------------------------------------*/
10158 genFarPointerSet (operand * right,
10159 operand * result, iCode * ic, iCode *pi)
10161 int size, offset, dopi=1;
10162 sym_link *retype = getSpec (operandType (right));
10163 sym_link *letype = getSpec (operandType (result));
10165 aopOp (result, ic, FALSE, FALSE);
10167 /* if the operand is already in dptr
10168 then we do nothing else we move the value to dptr */
10169 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10171 /* if this is remateriazable */
10172 if (AOP_TYPE (result) == AOP_IMMD)
10173 emitcode ("mov", "dptr,%s",
10174 aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10177 /* we need to get it byte by byte */
10178 _startLazyDPSEvaluation ();
10179 if (AOP_TYPE (result) != AOP_DPTR)
10181 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10182 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10183 if (options.model == MODEL_FLAT24)
10184 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10188 /* We need to generate a load to DPTR indirect through DPTR. */
10189 D (emitcode (";", "genFarPointerSet -- indirection special case."););
10191 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10192 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10193 if (options.model == MODEL_FLAT24)
10194 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10195 emitcode ("pop", "dph");
10196 emitcode ("pop", "dpl");
10199 _endLazyDPSEvaluation ();
10202 /* so dptr know contains the address */
10203 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10205 /* if bit then unpack */
10206 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
10207 if (AOP_INDPTRn(result)) {
10208 genSetDPTR(AOP(result)->aopu.dptr);
10210 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
10211 if (AOP_INDPTRn(result)) {
10215 size = AOP_SIZE (right);
10217 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10219 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10221 genSetDPTR(AOP(result)->aopu.dptr);
10222 emitcode ("movx", "@dptr,a");
10223 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10224 emitcode ("inc", "dptr");
10228 _startLazyDPSEvaluation ();
10230 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10232 if (AOP_INDPTRn(result)) {
10233 genSetDPTR(AOP(result)->aopu.dptr);
10239 emitcode ("movx", "@dptr,a");
10240 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10241 emitcode ("inc", "dptr");
10243 _endLazyDPSEvaluation ();
10247 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10248 if (!AOP_INDPTRn(result)) {
10249 _startLazyDPSEvaluation ();
10251 aopPut (AOP(result),"dpl",0);
10252 aopPut (AOP(result),"dph",1);
10253 if (options.model == MODEL_FLAT24)
10254 aopPut (AOP(result),"dpx",2);
10256 _endLazyDPSEvaluation ();
10259 } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
10260 AOP_SIZE(right) > 1 &&
10261 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10263 size = AOP_SIZE (right) - 1;
10264 if (AOP_INDPTRn(result)) {
10265 genSetDPTR(AOP(result)->aopu.dptr);
10267 while (size--) emitcode ("lcall","__decdptr");
10268 if (AOP_INDPTRn(result)) {
10272 freeAsmop (result, NULL, ic, TRUE);
10273 freeAsmop (right, NULL, ic, TRUE);
10276 /*-----------------------------------------------------------------*/
10277 /* genGenPointerSet - set value from generic pointer space */
10278 /*-----------------------------------------------------------------*/
10280 genGenPointerSet (operand * right,
10281 operand * result, iCode * ic, iCode *pi)
10284 sym_link *retype = getSpec (operandType (right));
10285 sym_link *letype = getSpec (operandType (result));
10287 aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10289 /* if the operand is already in dptr
10290 then we do nothing else we move the value to dptr */
10291 if (AOP_TYPE (result) != AOP_STR)
10293 _startLazyDPSEvaluation ();
10294 /* if this is remateriazable */
10295 if (AOP_TYPE (result) == AOP_IMMD)
10297 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10298 if (AOP(result)->aopu.aop_immd.from_cast_remat)
10300 MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10305 "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10309 { /* we need to get it byte by byte */
10310 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10311 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10312 if (options.model == MODEL_FLAT24) {
10313 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10314 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10316 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10319 _endLazyDPSEvaluation ();
10321 /* so dptr + b now contains the address */
10323 aopOp (right, ic, FALSE, TRUE);
10327 /* if bit then unpack */
10328 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10330 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
10334 size = AOP_SIZE (right);
10337 _startLazyDPSEvaluation ();
10342 // Set two bytes at a time, passed in _AP & A.
10343 // dptr will be incremented ONCE by __gptrputWord.
10345 // Note: any change here must be coordinated
10346 // with the implementation of __gptrputWord
10347 // in device/lib/_gptrput.c
10348 emitcode("mov", "_ap, %s",
10349 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10350 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10354 emitcode ("lcall", "__gptrputWord");
10359 // Only one byte to put.
10360 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10364 emitcode ("lcall", "__gptrput");
10367 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10369 emitcode ("inc", "dptr");
10372 _endLazyDPSEvaluation ();
10375 if (pi && AOP_TYPE (result) != AOP_IMMD) {
10376 _startLazyDPSEvaluation ();
10378 aopPut (AOP(result),"dpl",0);
10379 aopPut (AOP(result),"dph",1);
10380 if (options.model == MODEL_FLAT24) {
10381 aopPut (AOP(result),"dpx",2);
10382 aopPut (AOP(result),"b",3);
10384 aopPut (AOP(result),"b",2);
10386 _endLazyDPSEvaluation ();
10389 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10390 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10392 size = AOP_SIZE (right) - 1;
10393 while (size--) emitcode ("lcall","__decdptr");
10395 freeAsmop (result, NULL, ic, TRUE);
10396 freeAsmop (right, NULL, ic, TRUE);
10399 /*-----------------------------------------------------------------*/
10400 /* genPointerSet - stores the value into a pointer location */
10401 /*-----------------------------------------------------------------*/
10403 genPointerSet (iCode * ic, iCode *pi)
10405 operand *right, *result;
10406 sym_link *type, *etype;
10409 D (emitcode (";", "genPointerSet "););
10411 right = IC_RIGHT (ic);
10412 result = IC_RESULT (ic);
10414 /* depending on the type of pointer we need to
10415 move it to the correct pointer register */
10416 type = operandType (result);
10417 etype = getSpec (type);
10418 /* if left is of type of pointer then it is simple */
10419 if (IS_PTR (type) && !IS_FUNC (type->next))
10421 p_type = DCL_TYPE (type);
10425 /* we have to go by the storage class */
10426 p_type = PTR_TYPE (SPEC_OCLS (etype));
10428 /* special case when cast remat */
10429 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10430 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10431 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10432 type = operandType (result);
10433 p_type = DCL_TYPE (type);
10436 /* now that we have the pointer type we assign
10437 the pointer values */
10443 genNearPointerSet (right, result, ic, pi);
10447 genPagedPointerSet (right, result, ic, pi);
10451 genFarPointerSet (right, result, ic, pi);
10455 genGenPointerSet (right, result, ic, pi);
10459 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10460 "genPointerSet: illegal pointer type");
10465 /*-----------------------------------------------------------------*/
10466 /* genIfx - generate code for Ifx statement */
10467 /*-----------------------------------------------------------------*/
10469 genIfx (iCode * ic, iCode * popIc)
10471 operand *cond = IC_COND (ic);
10474 D (emitcode (";", "genIfx "););
10476 aopOp (cond, ic, FALSE, FALSE);
10478 /* get the value into acc */
10479 if (AOP_TYPE (cond) != AOP_CRY)
10488 /* the result is now in the accumulator */
10489 freeAsmop (cond, NULL, ic, TRUE);
10491 /* if there was something to be popped then do it */
10495 /* if the condition is a bit variable */
10496 if (isbit && IS_ITEMP (cond) &&
10499 genIfxJump (ic, SPIL_LOC (cond)->rname);
10501 else if (isbit && !IS_ITEMP (cond))
10503 genIfxJump (ic, OP_SYMBOL (cond)->rname);
10507 genIfxJump (ic, "a");
10513 /*-----------------------------------------------------------------*/
10514 /* genAddrOf - generates code for address of */
10515 /*-----------------------------------------------------------------*/
10517 genAddrOf (iCode * ic)
10519 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10522 D (emitcode (";", "genAddrOf ");
10525 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10527 /* if the operand is on the stack then we
10528 need to get the stack offset of this
10530 if (sym->onStack) {
10532 /* if 10 bit stack */
10533 if (options.stack10bit) {
10537 tsprintf(buff, sizeof(buff),
10538 "#!constbyte",(options.stack_loc >> 16) & 0xff);
10539 /* if it has an offset then we need to compute it */
10540 /* emitcode ("subb", "a,#!constbyte", */
10541 /* -((sym->stack < 0) ? */
10542 /* ((short) (sym->stack - _G.nRegsSaved)) : */
10543 /* ((short) sym->stack)) & 0xff); */
10544 /* emitcode ("mov","b,a"); */
10545 /* emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
10546 /* ((short) (sym->stack - _G.nRegsSaved)) : */
10547 /* ((short) sym->stack)) >> 8) & 0xff); */
10549 emitcode ("mov", "a,_bpx");
10550 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
10551 ((char) (sym->stack - _G.nRegsSaved)) :
10552 ((char) sym->stack )) & 0xff);
10553 emitcode ("mov", "b,a");
10554 emitcode ("mov", "a,_bpx+1");
10556 offset = (((sym->stack < 0) ?
10557 ((short) (sym->stack - _G.nRegsSaved)) :
10558 ((short) sym->stack )) >> 8) & 0xff;
10560 emitcode ("addc","a,#!constbyte", offset);
10562 aopPut (AOP (IC_RESULT (ic)), "b", 0);
10563 aopPut (AOP (IC_RESULT (ic)), "a", 1);
10564 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10566 /* we can just move _bp */
10567 aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10568 aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10569 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10572 /* if it has an offset then we need to compute it */
10574 emitcode ("mov", "a,_bp");
10575 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10576 aopPut (AOP (IC_RESULT (ic)), "a", 0);
10578 /* we can just move _bp */
10579 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10581 /* fill the result with zero */
10582 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10585 if (options.stack10bit && size < (FPTRSIZE - 1)) {
10587 "*** warning: pointer to stack var truncated.\n");
10592 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10598 /* object not on stack then we need the name */
10599 size = AOP_SIZE (IC_RESULT (ic));
10604 char s[SDCC_NAME_MAX];
10608 tsprintf(s, sizeof(s), "#!his",sym->rname);
10611 tsprintf(s, sizeof(s), "#!hihis",sym->rname);
10614 tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
10616 default: /* should not need this (just in case) */
10617 SNPRINTF (s, sizeof(s), "#(%s >> %d)",
10624 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10627 aopPut (AOP (IC_RESULT (ic)), s, offset++);
10631 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10635 #if 0 // obsolete, and buggy for != xdata
10636 /*-----------------------------------------------------------------*/
10637 /* genArrayInit - generates code for address of */
10638 /*-----------------------------------------------------------------*/
10640 genArrayInit (iCode * ic)
10642 literalList *iLoop;
10644 int elementSize = 0, eIndex;
10645 unsigned val, lastVal;
10647 operand *left=IC_LEFT(ic);
10649 D (emitcode (";", "genArrayInit "););
10651 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10653 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10655 // Load immediate value into DPTR.
10656 emitcode("mov", "dptr, %s",
10657 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
10659 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10662 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10663 "Unexpected operand to genArrayInit.\n");
10666 // a regression because of SDCCcse.c:1.52
10667 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10668 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10669 if (options.model == MODEL_FLAT24)
10670 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10674 type = operandType(IC_LEFT(ic));
10676 if (type && type->next)
10678 elementSize = getSize(type->next);
10682 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10683 "can't determine element size in genArrayInit.\n");
10687 iLoop = IC_ARRAYILIST(ic);
10692 bool firstpass = TRUE;
10694 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
10695 iLoop->count, (int)iLoop->literalValue, elementSize);
10701 symbol *tlbl = NULL;
10703 count = ix > 256 ? 256 : ix;
10707 tlbl = newiTempLabel (NULL);
10708 if (firstpass || (count & 0xff))
10710 emitcode("mov", "b, #!constbyte", count & 0xff);
10713 emitcode ("", "!tlabeldef", tlbl->key + 100);
10718 for (eIndex = 0; eIndex < elementSize; eIndex++)
10720 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10721 if (val != lastVal)
10723 emitcode("mov", "a, #!constbyte", val);
10727 emitcode("movx", "@dptr, a");
10728 emitcode("inc", "dptr");
10733 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10739 iLoop = iLoop->next;
10742 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10746 /*-----------------------------------------------------------------*/
10747 /* genFarFarAssign - assignment when both are in far space */
10748 /*-----------------------------------------------------------------*/
10750 genFarFarAssign (operand * result, operand * right, iCode * ic)
10752 int size = AOP_SIZE (right);
10754 symbol *rSym = NULL;
10758 /* quick & easy case. */
10759 D(emitcode(";","genFarFarAssign (1 byte case)"););
10760 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
10761 freeAsmop (right, NULL, ic, FALSE);
10762 /* now assign DPTR to result */
10764 aopOp(result, ic, FALSE, FALSE);
10766 aopPut(AOP(result), "a", 0);
10767 freeAsmop(result, NULL, ic, FALSE);
10771 /* See if we've got an underlying symbol to abuse. */
10772 if (IS_SYMOP(result) && OP_SYMBOL(result))
10774 if (IS_TRUE_SYMOP(result))
10776 rSym = OP_SYMBOL(result);
10778 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10780 rSym = OP_SYMBOL(result)->usl.spillLoc;
10784 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10786 /* We can use the '390 auto-toggle feature to good effect here. */
10788 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10789 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
10790 emitcode ("mov", "dptr,#%s", rSym->rname);
10791 /* DP2 = result, DP1 = right, DP1 is current. */
10794 emitcode("movx", "a,@dptr");
10795 emitcode("movx", "@dptr,a");
10798 emitcode("inc", "dptr");
10799 emitcode("inc", "dptr");
10802 emitcode("mov", "dps,#0");
10803 freeAsmop (right, NULL, ic, FALSE);
10805 some alternative code for processors without auto-toggle
10806 no time to test now, so later well put in...kpb
10807 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10808 emitcode("mov", "dps,#1"); /* Select DPTR2. */
10809 emitcode ("mov", "dptr,#%s", rSym->rname);
10810 /* DP2 = result, DP1 = right, DP1 is current. */
10814 emitcode("movx", "a,@dptr");
10816 emitcode("inc", "dptr");
10817 emitcode("inc", "dps");
10818 emitcode("movx", "@dptr,a");
10820 emitcode("inc", "dptr");
10821 emitcode("inc", "dps");
10823 emitcode("mov", "dps,#0");
10824 freeAsmop (right, NULL, ic, FALSE);
10829 D (emitcode (";", "genFarFarAssign"););
10830 aopOp (result, ic, TRUE, TRUE);
10832 _startLazyDPSEvaluation ();
10836 aopPut (AOP (result),
10837 aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
10840 _endLazyDPSEvaluation ();
10841 freeAsmop (result, NULL, ic, FALSE);
10842 freeAsmop (right, NULL, ic, FALSE);
10846 /*-----------------------------------------------------------------*/
10847 /* genAssign - generate code for assignment */
10848 /*-----------------------------------------------------------------*/
10850 genAssign (iCode * ic)
10852 operand *result, *right;
10854 unsigned long lit = 0L;
10856 D (emitcode (";", "genAssign ");
10859 result = IC_RESULT (ic);
10860 right = IC_RIGHT (ic);
10862 /* if they are the same */
10863 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10866 aopOp (right, ic, FALSE, FALSE);
10868 emitcode (";", "genAssign: resultIsFar = %s",
10869 isOperandInFarSpace (result) ?
10872 /* special case both in far space */
10873 if ((AOP_TYPE (right) == AOP_DPTR ||
10874 AOP_TYPE (right) == AOP_DPTR2) &&
10875 /* IS_TRUE_SYMOP(result) && */
10876 isOperandInFarSpace (result))
10878 genFarFarAssign (result, right, ic);
10882 aopOp (result, ic, TRUE, FALSE);
10884 /* if they are the same registers */
10885 if (sameRegs (AOP (right), AOP (result)))
10888 /* if the result is a bit */
10889 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10891 /* if the right size is a literal then
10892 we know what the value is */
10893 if (AOP_TYPE (right) == AOP_LIT)
10895 if (((int) operandLitValue (right)))
10896 aopPut (AOP (result), one, 0);
10898 aopPut (AOP (result), zero, 0);
10902 /* the right is also a bit variable */
10903 if (AOP_TYPE (right) == AOP_CRY)
10905 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10906 aopPut (AOP (result), "c", 0);
10910 /* we need to or */
10912 aopPut (AOP (result), "a", 0);
10916 /* bit variables done */
10918 size = AOP_SIZE (result);
10920 if (AOP_TYPE (right) == AOP_LIT)
10921 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10924 (AOP_TYPE (result) != AOP_REG) &&
10925 (AOP_TYPE (right) == AOP_LIT) &&
10926 !IS_FLOAT (operandType (right)))
10928 _startLazyDPSEvaluation ();
10929 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10931 aopPut (AOP (result),
10932 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10937 /* And now fill the rest with zeros. */
10940 emitcode ("clr", "a");
10944 aopPut (AOP (result), "a", offset++);
10946 _endLazyDPSEvaluation ();
10950 _startLazyDPSEvaluation ();
10953 aopPut (AOP (result),
10954 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10958 _endLazyDPSEvaluation ();
10962 freeAsmop (right, NULL, ic, FALSE);
10963 freeAsmop (result, NULL, ic, TRUE);
10966 /*-----------------------------------------------------------------*/
10967 /* genJumpTab - generates code for jump table */
10968 /*-----------------------------------------------------------------*/
10970 genJumpTab (iCode * ic)
10975 D (emitcode (";", "genJumpTab ");
10978 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10979 /* get the condition into accumulator */
10980 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
10982 /* multiply by four! */
10983 emitcode ("add", "a,acc");
10984 emitcode ("add", "a,acc");
10985 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10987 jtab = newiTempLabel (NULL);
10988 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
10989 emitcode ("jmp", "@a+dptr");
10990 emitcode ("", "!tlabeldef", jtab->key + 100);
10991 /* now generate the jump labels */
10992 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10993 jtab = setNextItem (IC_JTLABELS (ic)))
10994 emitcode ("ljmp", "!tlabel", jtab->key + 100);
10998 /*-----------------------------------------------------------------*/
10999 /* genCast - gen code for casting */
11000 /*-----------------------------------------------------------------*/
11002 genCast (iCode * ic)
11004 operand *result = IC_RESULT (ic);
11005 sym_link *ctype = operandType (IC_LEFT (ic));
11006 sym_link *rtype = operandType (IC_RIGHT (ic));
11007 operand *right = IC_RIGHT (ic);
11010 D (emitcode (";", "genCast "););
11012 /* if they are equivalent then do nothing */
11013 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11016 aopOp (right, ic, FALSE, FALSE);
11017 aopOp (result, ic, FALSE, AOP_USESDPTR(right));
11019 /* if the result is a bit */
11020 // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
11021 if (IS_BITVAR(OP_SYMBOL(result)->type))
11023 /* if the right size is a literal then
11024 we know what the value is */
11025 if (AOP_TYPE (right) == AOP_LIT)
11027 if (((int) operandLitValue (right)))
11028 aopPut (AOP (result), one, 0);
11030 aopPut (AOP (result), zero, 0);
11035 /* the right is also a bit variable */
11036 if (AOP_TYPE (right) == AOP_CRY)
11038 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11039 aopPut (AOP (result), "c", 0);
11043 /* we need to or */
11045 aopPut (AOP (result), "a", 0);
11049 /* if they are the same size : or less */
11050 if (AOP_SIZE (result) <= AOP_SIZE (right))
11053 /* if they are in the same place */
11054 if (sameRegs (AOP (right), AOP (result)))
11057 /* if they in different places then copy */
11058 size = AOP_SIZE (result);
11060 _startLazyDPSEvaluation ();
11063 aopPut (AOP (result),
11064 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11068 _endLazyDPSEvaluation ();
11073 /* if the result is of type pointer */
11074 if (IS_PTR (ctype))
11078 sym_link *type = operandType (right);
11080 /* pointer to generic pointer */
11081 if (IS_GENPTR (ctype))
11085 p_type = DCL_TYPE (type);
11089 #if OLD_CAST_BEHAVIOR
11090 /* KV: we are converting a non-pointer type to
11091 * a generic pointer. This (ifdef'd out) code
11092 * says that the resulting generic pointer
11093 * should have the same class as the storage
11094 * location of the non-pointer variable.
11096 * For example, converting an int (which happens
11097 * to be stored in DATA space) to a pointer results
11098 * in a DATA generic pointer; if the original int
11099 * in XDATA space, so will be the resulting pointer.
11101 * I don't like that behavior, and thus this change:
11102 * all such conversions will be forced to XDATA and
11103 * throw a warning. If you want some non-XDATA
11104 * type, or you want to suppress the warning, you
11105 * must go through an intermediate cast, like so:
11107 * char _generic *gp = (char _xdata *)(intVar);
11109 sym_link *etype = getSpec (type);
11111 /* we have to go by the storage class */
11112 if (SPEC_OCLS (etype) != generic)
11114 p_type = PTR_TYPE (SPEC_OCLS (etype));
11119 /* Converting unknown class (i.e. register variable)
11120 * to generic pointer. This is not good, but
11121 * we'll make a guess (and throw a warning).
11124 werror (W_INT_TO_GEN_PTR_CAST);
11128 /* the first two bytes are known */
11129 size = GPTRSIZE - 1;
11131 _startLazyDPSEvaluation ();
11134 aopPut (AOP (result),
11135 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11139 _endLazyDPSEvaluation ();
11141 /* the last byte depending on type */
11143 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11148 // pointerTypeToGPByte will have bitched.
11152 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11153 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11158 /* just copy the pointers */
11159 size = AOP_SIZE (result);
11161 _startLazyDPSEvaluation ();
11164 aopPut (AOP (result),
11165 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11169 _endLazyDPSEvaluation ();
11173 /* so we now know that the size of destination is greater
11174 than the size of the source */
11175 /* we move to result for the size of source */
11176 size = AOP_SIZE (right);
11178 _startLazyDPSEvaluation ();
11181 aopPut (AOP (result),
11182 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11186 _endLazyDPSEvaluation ();
11188 /* now depending on the sign of the source && destination */
11189 size = AOP_SIZE (result) - AOP_SIZE (right);
11190 /* if unsigned or not an integral type */
11191 /* also, if the source is a bit, we don't need to sign extend, because
11192 * it can't possibly have set the sign bit.
11194 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
11198 aopPut (AOP (result), zero, offset++);
11203 /* we need to extend the sign :{ */
11204 MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11205 FALSE, FALSE, NULL));
11206 emitcode ("rlc", "a");
11207 emitcode ("subb", "a,acc");
11209 aopPut (AOP (result), "a", offset++);
11212 /* we are done hurray !!!! */
11215 freeAsmop (right, NULL, ic, TRUE);
11216 freeAsmop (result, NULL, ic, TRUE);
11220 /*-----------------------------------------------------------------*/
11221 /* genDjnz - generate decrement & jump if not zero instrucion */
11222 /*-----------------------------------------------------------------*/
11224 genDjnz (iCode * ic, iCode * ifx)
11226 symbol *lbl, *lbl1;
11230 /* if the if condition has a false label
11231 then we cannot save */
11232 if (IC_FALSE (ifx))
11235 /* if the minus is not of the form
11237 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11238 !IS_OP_LITERAL (IC_RIGHT (ic)))
11241 if (operandLitValue (IC_RIGHT (ic)) != 1)
11244 /* if the size of this greater than one then no
11246 if (getSize (operandType (IC_RESULT (ic))) > 1)
11249 /* otherwise we can save BIG */
11250 D(emitcode(";", "genDjnz"););
11252 lbl = newiTempLabel (NULL);
11253 lbl1 = newiTempLabel (NULL);
11255 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11257 if (AOP_NEEDSACC(IC_RESULT(ic)))
11259 /* If the result is accessed indirectly via
11260 * the accumulator, we must explicitly write
11261 * it back after the decrement.
11263 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11265 if (strcmp(rByte, "a"))
11267 /* Something is hopelessly wrong */
11268 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11269 __FILE__, __LINE__);
11270 /* We can just give up; the generated code will be inefficient,
11271 * but what the hey.
11273 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11276 emitcode ("dec", "%s", rByte);
11277 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11278 emitcode ("jnz", "!tlabel", lbl->key + 100);
11280 else if (IS_AOP_PREG (IC_RESULT (ic)))
11282 emitcode ("dec", "%s",
11283 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11284 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11285 emitcode ("jnz", "!tlabel", lbl->key + 100);
11289 emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11292 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11293 emitcode ("", "!tlabeldef", lbl->key + 100);
11294 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11295 emitcode ("", "!tlabeldef", lbl1->key + 100);
11297 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11298 ifx->generated = 1;
11302 /*-----------------------------------------------------------------*/
11303 /* genReceive - generate code for a receive iCode */
11304 /*-----------------------------------------------------------------*/
11306 genReceive (iCode * ic)
11308 int size = getSize (operandType (IC_RESULT (ic)));
11312 D (emitcode (";", "genReceive "););
11314 if (ic->argreg == 1)
11316 /* first parameter */
11317 if (AOP_IS_STR(IC_RESULT(ic)))
11319 /* Nothing to do: it's already in the proper place. */
11326 useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11327 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11328 IS_TRUE_SYMOP (IC_RESULT (ic)));
11331 aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11334 /* Sanity checking... */
11335 if (AOP_USESDPTR(IC_RESULT(ic)))
11337 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11338 "genReceive got unexpected DPTR.");
11340 assignResultValue (IC_RESULT (ic));
11345 /* second receive onwards */
11346 /* this gets a little tricky since unused recevies will be
11347 eliminated, we have saved the reg in the type field . and
11348 we use that to figure out which register to use */
11349 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11350 rb1off = ic->argreg;
11353 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11356 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11359 /*-----------------------------------------------------------------*/
11360 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
11361 /*-----------------------------------------------------------------*/
11362 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11364 operand *from , *to , *count;
11369 /* we know it has to be 3 parameters */
11370 assert (nparms == 3);
11372 rsave = newBitVect(16);
11373 /* save DPTR if it needs to be saved */
11374 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11375 if (bitVectBitValue(ic->rMask,i))
11376 rsave = bitVectSetBit(rsave,i);
11378 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11379 ds390_rUmaskForOp (IC_RESULT(ic))));
11386 aopOp (from, ic->next, FALSE, FALSE);
11388 /* get from into DPTR1 */
11389 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11390 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11391 if (options.model == MODEL_FLAT24) {
11392 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11395 freeAsmop (from, NULL, ic, FALSE);
11396 aopOp (to, ic, FALSE, FALSE);
11397 /* get "to" into DPTR */
11398 /* if the operand is already in dptr
11399 then we do nothing else we move the value to dptr */
11400 if (AOP_TYPE (to) != AOP_STR) {
11401 /* if already in DPTR then we need to push */
11402 if (AOP_TYPE(to) == AOP_DPTR) {
11403 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11404 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11405 if (options.model == MODEL_FLAT24)
11406 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11407 emitcode ("pop", "dph");
11408 emitcode ("pop", "dpl");
11410 _startLazyDPSEvaluation ();
11411 /* if this is remateriazable */
11412 if (AOP_TYPE (to) == AOP_IMMD) {
11413 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11414 } else { /* we need to get it byte by byte */
11415 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11416 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11417 if (options.model == MODEL_FLAT24) {
11418 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11421 _endLazyDPSEvaluation ();
11424 freeAsmop (to, NULL, ic, FALSE);
11425 _G.dptrInUse = _G.dptr1InUse = 1;
11426 aopOp (count, ic->next->next, FALSE,FALSE);
11427 lbl =newiTempLabel(NULL);
11429 /* now for the actual copy */
11430 if (AOP_TYPE(count) == AOP_LIT &&
11431 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11432 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11434 emitcode ("lcall","__bi_memcpyc2x_s");
11436 emitcode ("lcall","__bi_memcpyx2x_s");
11438 freeAsmop (count, NULL, ic, FALSE);
11440 symbol *lbl1 = newiTempLabel(NULL);
11442 emitcode (";"," Auto increment but no djnz");
11443 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11444 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11445 freeAsmop (count, NULL, ic, FALSE);
11446 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11447 emitcode ("","!tlabeldef",lbl->key+100);
11449 emitcode ("clr","a");
11450 emitcode ("movc", "a,@a+dptr");
11452 emitcode ("movx", "a,@dptr");
11453 emitcode ("movx", "@dptr,a");
11454 emitcode ("inc", "dptr");
11455 emitcode ("inc", "dptr");
11456 emitcode ("mov","a,b");
11457 emitcode ("orl","a,_ap");
11458 emitcode ("jz","!tlabel",lbl1->key+100);
11459 emitcode ("mov","a,_ap");
11460 emitcode ("add","a,#!constbyte",0xFF);
11461 emitcode ("mov","_ap,a");
11462 emitcode ("mov","a,b");
11463 emitcode ("addc","a,#!constbyte",0xFF);
11464 emitcode ("mov","b,a");
11465 emitcode ("sjmp","!tlabel",lbl->key+100);
11466 emitcode ("","!tlabeldef",lbl1->key+100);
11468 emitcode ("mov", "dps,#0");
11469 _G.dptrInUse = _G.dptr1InUse = 0;
11470 unsavermask(rsave);
11474 /*-----------------------------------------------------------------*/
11475 /* genMemcmpX2X - gen code for memcmp xdata to xdata */
11476 /*-----------------------------------------------------------------*/
11477 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11479 operand *from , *to , *count;
11484 /* we know it has to be 3 parameters */
11485 assert (nparms == 3);
11487 rsave = newBitVect(16);
11488 /* save DPTR if it needs to be saved */
11489 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11490 if (bitVectBitValue(ic->rMask,i))
11491 rsave = bitVectSetBit(rsave,i);
11493 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11494 ds390_rUmaskForOp (IC_RESULT(ic))));
11501 aopOp (from, ic->next, FALSE, FALSE);
11503 /* get from into DPTR1 */
11504 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11505 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11506 if (options.model == MODEL_FLAT24) {
11507 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11510 freeAsmop (from, NULL, ic, FALSE);
11511 aopOp (to, ic, FALSE, FALSE);
11512 /* get "to" into DPTR */
11513 /* if the operand is already in dptr
11514 then we do nothing else we move the value to dptr */
11515 if (AOP_TYPE (to) != AOP_STR) {
11516 /* if already in DPTR then we need to push */
11517 if (AOP_TYPE(to) == AOP_DPTR) {
11518 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11519 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11520 if (options.model == MODEL_FLAT24)
11521 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11522 emitcode ("pop", "dph");
11523 emitcode ("pop", "dpl");
11525 _startLazyDPSEvaluation ();
11526 /* if this is remateriazable */
11527 if (AOP_TYPE (to) == AOP_IMMD) {
11528 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11529 } else { /* we need to get it byte by byte */
11530 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11531 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11532 if (options.model == MODEL_FLAT24) {
11533 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11536 _endLazyDPSEvaluation ();
11539 freeAsmop (to, NULL, ic, FALSE);
11540 _G.dptrInUse = _G.dptr1InUse = 1;
11541 aopOp (count, ic->next->next, FALSE,FALSE);
11542 lbl =newiTempLabel(NULL);
11543 lbl2 =newiTempLabel(NULL);
11545 /* now for the actual compare */
11546 if (AOP_TYPE(count) == AOP_LIT &&
11547 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11548 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11550 emitcode("lcall","__bi_memcmpc2x_s");
11552 emitcode("lcall","__bi_memcmpx2x_s");
11553 freeAsmop (count, NULL, ic, FALSE);
11554 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11555 aopPut(AOP(IC_RESULT(ic)),"a",0);
11556 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11558 symbol *lbl1 = newiTempLabel(NULL);
11560 emitcode("push","ar0");
11561 emitcode (";"," Auto increment but no djnz");
11562 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11563 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11564 freeAsmop (count, NULL, ic, FALSE);
11565 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11566 emitcode ("","!tlabeldef",lbl->key+100);
11568 emitcode ("clr","a");
11569 emitcode ("movc", "a,@a+dptr");
11571 emitcode ("movx", "a,@dptr");
11572 emitcode ("mov","r0,a");
11573 emitcode ("movx", "a,@dptr");
11574 emitcode ("clr","c");
11575 emitcode ("subb","a,r0");
11576 emitcode ("jnz","!tlabel",lbl2->key+100);
11577 emitcode ("inc", "dptr");
11578 emitcode ("inc", "dptr");
11579 emitcode ("mov","a,b");
11580 emitcode ("orl","a,_ap");
11581 emitcode ("jz","!tlabel",lbl1->key+100);
11582 emitcode ("mov","a,_ap");
11583 emitcode ("add","a,#!constbyte",0xFF);
11584 emitcode ("mov","_ap,a");
11585 emitcode ("mov","a,b");
11586 emitcode ("addc","a,#!constbyte",0xFF);
11587 emitcode ("mov","b,a");
11588 emitcode ("sjmp","!tlabel",lbl->key+100);
11589 emitcode ("","!tlabeldef",lbl1->key+100);
11590 emitcode ("clr","a");
11591 emitcode ("","!tlabeldef",lbl2->key+100);
11592 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11593 aopPut(AOP(IC_RESULT(ic)),"a",0);
11594 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11595 emitcode("pop","ar0");
11596 emitcode ("mov", "dps,#0");
11598 _G.dptrInUse = _G.dptr1InUse = 0;
11599 unsavermask(rsave);
11603 /*-----------------------------------------------------------------*/
11604 /* genInp - gen code for __builtin_inp read data from a mem mapped */
11605 /* port, first parameter output area second parameter pointer to */
11606 /* port third parameter count */
11607 /*-----------------------------------------------------------------*/
11608 static void genInp( iCode *ic, int nparms, operand **parms)
11610 operand *from , *to , *count;
11615 /* we know it has to be 3 parameters */
11616 assert (nparms == 3);
11618 rsave = newBitVect(16);
11619 /* save DPTR if it needs to be saved */
11620 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11621 if (bitVectBitValue(ic->rMask,i))
11622 rsave = bitVectSetBit(rsave,i);
11624 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11625 ds390_rUmaskForOp (IC_RESULT(ic))));
11632 aopOp (from, ic->next, FALSE, FALSE);
11634 /* get from into DPTR1 */
11635 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11636 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11637 if (options.model == MODEL_FLAT24) {
11638 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11641 freeAsmop (from, NULL, ic, FALSE);
11642 aopOp (to, ic, FALSE, FALSE);
11643 /* get "to" into DPTR */
11644 /* if the operand is already in dptr
11645 then we do nothing else we move the value to dptr */
11646 if (AOP_TYPE (to) != AOP_STR) {
11647 /* if already in DPTR then we need to push */
11648 if (AOP_TYPE(to) == AOP_DPTR) {
11649 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11650 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11651 if (options.model == MODEL_FLAT24)
11652 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11653 emitcode ("pop", "dph");
11654 emitcode ("pop", "dpl");
11656 _startLazyDPSEvaluation ();
11657 /* if this is remateriazable */
11658 if (AOP_TYPE (to) == AOP_IMMD) {
11659 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11660 } else { /* we need to get it byte by byte */
11661 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11662 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11663 if (options.model == MODEL_FLAT24) {
11664 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11667 _endLazyDPSEvaluation ();
11670 freeAsmop (to, NULL, ic, FALSE);
11672 _G.dptrInUse = _G.dptr1InUse = 1;
11673 aopOp (count, ic->next->next, FALSE,FALSE);
11674 lbl =newiTempLabel(NULL);
11676 /* now for the actual copy */
11677 if (AOP_TYPE(count) == AOP_LIT &&
11678 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11679 emitcode (";","OH JOY auto increment with djnz (very fast)");
11680 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11681 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11682 freeAsmop (count, NULL, ic, FALSE);
11683 emitcode ("","!tlabeldef",lbl->key+100);
11684 emitcode ("movx", "a,@dptr"); /* read data from port */
11685 emitcode ("dec","dps"); /* switch to DPTR */
11686 emitcode ("movx", "@dptr,a"); /* save into location */
11687 emitcode ("inc", "dptr"); /* point to next area */
11688 emitcode ("inc","dps"); /* switch to DPTR2 */
11689 emitcode ("djnz","b,!tlabel",lbl->key+100);
11691 symbol *lbl1 = newiTempLabel(NULL);
11693 emitcode (";"," Auto increment but no djnz");
11694 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11695 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11696 freeAsmop (count, NULL, ic, FALSE);
11697 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11698 emitcode ("","!tlabeldef",lbl->key+100);
11699 emitcode ("movx", "a,@dptr");
11700 emitcode ("dec","dps"); /* switch to DPTR */
11701 emitcode ("movx", "@dptr,a");
11702 emitcode ("inc", "dptr");
11703 emitcode ("inc","dps"); /* switch to DPTR2 */
11704 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
11705 /* emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
11706 emitcode ("mov","a,b");
11707 emitcode ("orl","a,_ap");
11708 emitcode ("jz","!tlabel",lbl1->key+100);
11709 emitcode ("mov","a,_ap");
11710 emitcode ("add","a,#!constbyte",0xFF);
11711 emitcode ("mov","_ap,a");
11712 emitcode ("mov","a,b");
11713 emitcode ("addc","a,#!constbyte",0xFF);
11714 emitcode ("mov","b,a");
11715 emitcode ("sjmp","!tlabel",lbl->key+100);
11716 emitcode ("","!tlabeldef",lbl1->key+100);
11718 emitcode ("mov", "dps,#0");
11719 _G.dptrInUse = _G.dptr1InUse = 0;
11720 unsavermask(rsave);
11724 /*-----------------------------------------------------------------*/
11725 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
11726 /* port, first parameter output area second parameter pointer to */
11727 /* port third parameter count */
11728 /*-----------------------------------------------------------------*/
11729 static void genOutp( iCode *ic, int nparms, operand **parms)
11731 operand *from , *to , *count;
11736 /* we know it has to be 3 parameters */
11737 assert (nparms == 3);
11739 rsave = newBitVect(16);
11740 /* save DPTR if it needs to be saved */
11741 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11742 if (bitVectBitValue(ic->rMask,i))
11743 rsave = bitVectSetBit(rsave,i);
11745 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11746 ds390_rUmaskForOp (IC_RESULT(ic))));
11753 aopOp (from, ic->next, FALSE, FALSE);
11755 /* get from into DPTR1 */
11756 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11757 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11758 if (options.model == MODEL_FLAT24) {
11759 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11762 freeAsmop (from, NULL, ic, FALSE);
11763 aopOp (to, ic, FALSE, FALSE);
11764 /* get "to" into DPTR */
11765 /* if the operand is already in dptr
11766 then we do nothing else we move the value to dptr */
11767 if (AOP_TYPE (to) != AOP_STR) {
11768 /* if already in DPTR then we need to push */
11769 if (AOP_TYPE(to) == AOP_DPTR) {
11770 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11771 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11772 if (options.model == MODEL_FLAT24)
11773 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11774 emitcode ("pop", "dph");
11775 emitcode ("pop", "dpl");
11777 _startLazyDPSEvaluation ();
11778 /* if this is remateriazable */
11779 if (AOP_TYPE (to) == AOP_IMMD) {
11780 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11781 } else { /* we need to get it byte by byte */
11782 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11783 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11784 if (options.model == MODEL_FLAT24) {
11785 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11788 _endLazyDPSEvaluation ();
11791 freeAsmop (to, NULL, ic, FALSE);
11793 _G.dptrInUse = _G.dptr1InUse = 1;
11794 aopOp (count, ic->next->next, FALSE,FALSE);
11795 lbl =newiTempLabel(NULL);
11797 /* now for the actual copy */
11798 if (AOP_TYPE(count) == AOP_LIT &&
11799 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11800 emitcode (";","OH JOY auto increment with djnz (very fast)");
11801 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
11802 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11803 emitcode ("","!tlabeldef",lbl->key+100);
11804 emitcode ("movx", "a,@dptr"); /* read data from port */
11805 emitcode ("inc","dps"); /* switch to DPTR2 */
11806 emitcode ("movx", "@dptr,a"); /* save into location */
11807 emitcode ("inc", "dptr"); /* point to next area */
11808 emitcode ("dec","dps"); /* switch to DPTR */
11809 emitcode ("djnz","b,!tlabel",lbl->key+100);
11810 freeAsmop (count, NULL, ic, FALSE);
11812 symbol *lbl1 = newiTempLabel(NULL);
11814 emitcode (";"," Auto increment but no djnz");
11815 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11816 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11817 freeAsmop (count, NULL, ic, FALSE);
11818 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
11819 emitcode ("","!tlabeldef",lbl->key+100);
11820 emitcode ("movx", "a,@dptr");
11821 emitcode ("inc", "dptr");
11822 emitcode ("inc","dps"); /* switch to DPTR2 */
11823 emitcode ("movx", "@dptr,a");
11824 emitcode ("dec","dps"); /* switch to DPTR */
11825 emitcode ("mov","a,b");
11826 emitcode ("orl","a,_ap");
11827 emitcode ("jz","!tlabel",lbl1->key+100);
11828 emitcode ("mov","a,_ap");
11829 emitcode ("add","a,#!constbyte",0xFF);
11830 emitcode ("mov","_ap,a");
11831 emitcode ("mov","a,b");
11832 emitcode ("addc","a,#!constbyte",0xFF);
11833 emitcode ("mov","b,a");
11834 emitcode ("sjmp","!tlabel",lbl->key+100);
11835 emitcode ("","!tlabeldef",lbl1->key+100);
11837 emitcode ("mov", "dps,#0");
11838 _G.dptrInUse = _G.dptr1InUse = 0;
11839 unsavermask(rsave);
11843 /*-----------------------------------------------------------------*/
11844 /* genSwapW - swap lower & high order bytes */
11845 /*-----------------------------------------------------------------*/
11846 static void genSwapW(iCode *ic, int nparms, operand **parms)
11850 assert (nparms==1);
11853 dest=IC_RESULT(ic);
11855 assert(getSize(operandType(src))==2);
11857 aopOp (src, ic, FALSE, FALSE);
11858 emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
11860 MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
11862 freeAsmop (src, NULL, ic, FALSE);
11864 aopOp (dest,ic, FALSE, FALSE);
11865 aopPut(AOP(dest),"b",0);
11866 aopPut(AOP(dest),"a",1);
11867 freeAsmop (dest, NULL, ic, FALSE);
11870 /*-----------------------------------------------------------------*/
11871 /* genMemsetX - gencode for memSetX data */
11872 /*-----------------------------------------------------------------*/
11873 static void genMemsetX(iCode *ic, int nparms, operand **parms)
11875 operand *to , *val , *count;
11881 /* we know it has to be 3 parameters */
11882 assert (nparms == 3);
11888 /* save DPTR if it needs to be saved */
11889 rsave = newBitVect(16);
11890 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11891 if (bitVectBitValue(ic->rMask,i))
11892 rsave = bitVectSetBit(rsave,i);
11894 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11895 ds390_rUmaskForOp (IC_RESULT(ic))));
11898 aopOp (to, ic, FALSE, FALSE);
11899 /* get "to" into DPTR */
11900 /* if the operand is already in dptr
11901 then we do nothing else we move the value to dptr */
11902 if (AOP_TYPE (to) != AOP_STR) {
11903 /* if already in DPTR then we need to push */
11904 if (AOP_TYPE(to) == AOP_DPTR) {
11905 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11906 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11907 if (options.model == MODEL_FLAT24)
11908 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11909 emitcode ("pop", "dph");
11910 emitcode ("pop", "dpl");
11912 _startLazyDPSEvaluation ();
11913 /* if this is remateriazable */
11914 if (AOP_TYPE (to) == AOP_IMMD) {
11915 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11916 } else { /* we need to get it byte by byte */
11917 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11918 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11919 if (options.model == MODEL_FLAT24) {
11920 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11923 _endLazyDPSEvaluation ();
11926 freeAsmop (to, NULL, ic, FALSE);
11928 aopOp (val, ic->next->next, FALSE,FALSE);
11929 aopOp (count, ic->next->next, FALSE,FALSE);
11930 lbl =newiTempLabel(NULL);
11931 /* now for the actual copy */
11932 if (AOP_TYPE(count) == AOP_LIT &&
11933 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11934 l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
11935 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11937 emitcode ("","!tlabeldef",lbl->key+100);
11938 emitcode ("movx", "@dptr,a");
11939 emitcode ("inc", "dptr");
11940 emitcode ("djnz","b,!tlabel",lbl->key+100);
11942 symbol *lbl1 = newiTempLabel(NULL);
11944 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11945 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11946 emitcode ("","!tlabeldef",lbl->key+100);
11947 MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
11948 emitcode ("movx", "@dptr,a");
11949 emitcode ("inc", "dptr");
11950 emitcode ("mov","a,b");
11951 emitcode ("orl","a,_ap");
11952 emitcode ("jz","!tlabel",lbl1->key+100);
11953 emitcode ("mov","a,_ap");
11954 emitcode ("add","a,#!constbyte",0xFF);
11955 emitcode ("mov","_ap,a");
11956 emitcode ("mov","a,b");
11957 emitcode ("addc","a,#!constbyte",0xFF);
11958 emitcode ("mov","b,a");
11959 emitcode ("sjmp","!tlabel",lbl->key+100);
11960 emitcode ("","!tlabeldef",lbl1->key+100);
11962 freeAsmop (count, NULL, ic, FALSE);
11963 unsavermask(rsave);
11966 /*-----------------------------------------------------------------*/
11967 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
11968 /*-----------------------------------------------------------------*/
11969 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
11972 operand *pnum, *result;
11975 assert (nparms==1);
11976 /* save registers that need to be saved */
11977 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11978 ds390_rUmaskForOp (IC_RESULT(ic))));
11981 aopOp (pnum, ic, FALSE, FALSE);
11982 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
11983 freeAsmop (pnum, NULL, ic, FALSE);
11984 emitcode ("lcall","NatLib_LoadPrimitive");
11985 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11986 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
11987 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
11988 for (i = (size-1) ; i >= 0 ; i-- ) {
11989 emitcode ("push","a%s",javaRet[i]);
11991 for (i=0; i < size ; i++ ) {
11992 emitcode ("pop","a%s",
11993 aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
11996 for (i = 0 ; i < size ; i++ ) {
11997 aopPut(AOP(result),javaRet[i],i);
12000 freeAsmop (result, NULL, ic, FALSE);
12001 unsavermask(rsave);
12004 /*-----------------------------------------------------------------*/
12005 /* genNatLibLoadPointer - calls TINI api function to load pointer */
12006 /*-----------------------------------------------------------------*/
12007 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
12010 operand *pnum, *result;
12014 assert (nparms==1);
12015 /* save registers that need to be saved */
12016 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12017 ds390_rUmaskForOp (IC_RESULT(ic))));
12020 aopOp (pnum, ic, FALSE, FALSE);
12021 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12022 freeAsmop (pnum, NULL, ic, FALSE);
12023 emitcode ("lcall","NatLib_LoadPointer");
12024 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12025 if (AOP_TYPE(result)!=AOP_STR) {
12026 for (i = 0 ; i < size ; i++ ) {
12027 aopPut(AOP(result),fReturn[i],i);
12030 freeAsmop (result, NULL, ic, FALSE);
12031 unsavermask(rsave);
12034 /*-----------------------------------------------------------------*/
12035 /* genNatLibInstallStateBlock - */
12036 /*-----------------------------------------------------------------*/
12037 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
12038 operand **parms, const char *name)
12041 operand *psb, *handle;
12042 assert (nparms==2);
12044 /* save registers that need to be saved */
12045 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12046 ds390_rUmaskForOp (IC_RESULT(ic))));
12050 /* put pointer to state block into DPTR1 */
12051 aopOp (psb, ic, FALSE, FALSE);
12052 if (AOP_TYPE (psb) == AOP_IMMD) {
12053 emitcode ("mov","dps,#1");
12054 emitcode ("mov", "dptr,%s",
12055 aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12056 emitcode ("mov","dps,#0");
12058 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12059 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12060 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12062 freeAsmop (psb, NULL, ic, FALSE);
12064 /* put libraryID into DPTR */
12065 emitcode ("mov","dptr,#LibraryID");
12067 /* put handle into r3:r2 */
12068 aopOp (handle, ic, FALSE, FALSE);
12069 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12070 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12071 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12072 emitcode ("pop","ar3");
12073 emitcode ("pop","ar2");
12075 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12076 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12078 freeAsmop (psb, NULL, ic, FALSE);
12080 /* make the call */
12081 emitcode ("lcall","NatLib_Install%sStateBlock",name);
12083 /* put return value into place*/
12085 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12087 aopPut(AOP(IC_RESULT(ic)),"a",0);
12088 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12089 unsavermask(rsave);
12092 /*-----------------------------------------------------------------*/
12093 /* genNatLibRemoveStateBlock - */
12094 /*-----------------------------------------------------------------*/
12095 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12101 /* save registers that need to be saved */
12102 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12103 ds390_rUmaskForOp (IC_RESULT(ic))));
12105 /* put libraryID into DPTR */
12106 emitcode ("mov","dptr,#LibraryID");
12107 /* make the call */
12108 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12109 unsavermask(rsave);
12112 /*-----------------------------------------------------------------*/
12113 /* genNatLibGetStateBlock - */
12114 /*-----------------------------------------------------------------*/
12115 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12116 operand **parms,const char *name)
12119 symbol *lbl = newiTempLabel(NULL);
12122 /* save registers that need to be saved */
12123 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12124 ds390_rUmaskForOp (IC_RESULT(ic))));
12126 /* put libraryID into DPTR */
12127 emitcode ("mov","dptr,#LibraryID");
12128 /* make the call */
12129 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12130 emitcode ("jnz","!tlabel",lbl->key+100);
12132 /* put return value into place */
12133 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12134 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12135 emitcode ("push","ar3");
12136 emitcode ("push","ar2");
12137 emitcode ("pop","%s",
12138 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12139 emitcode ("pop","%s",
12140 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12142 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12143 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12145 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12146 emitcode ("","!tlabeldef",lbl->key+100);
12147 unsavermask(rsave);
12150 /*-----------------------------------------------------------------*/
12151 /* genMMMalloc - */
12152 /*-----------------------------------------------------------------*/
12153 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12154 int size, const char *name)
12159 symbol *lbl = newiTempLabel(NULL);
12161 assert (nparms == 1);
12162 /* save registers that need to be saved */
12163 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12164 ds390_rUmaskForOp (IC_RESULT(ic))));
12167 aopOp (bsize,ic,FALSE,FALSE);
12169 /* put the size in R4-R2 */
12170 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12171 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12172 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12174 emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12175 emitcode("pop","ar4");
12177 emitcode("pop","ar3");
12178 emitcode("pop","ar2");
12180 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12181 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12183 emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12186 freeAsmop (bsize, NULL, ic, FALSE);
12188 /* make the call */
12189 emitcode ("lcall","MM_%s",name);
12190 emitcode ("jz","!tlabel",lbl->key+100);
12191 emitcode ("mov","r2,#!constbyte",0xff);
12192 emitcode ("mov","r3,#!constbyte",0xff);
12193 emitcode ("","!tlabeldef",lbl->key+100);
12194 /* we don't care about the pointer : we just save the handle */
12195 rsym = OP_SYMBOL(IC_RESULT(ic));
12196 if (rsym->liveFrom != rsym->liveTo) {
12197 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12198 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12199 emitcode ("push","ar3");
12200 emitcode ("push","ar2");
12201 emitcode ("pop","%s",
12202 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12203 emitcode ("pop","%s",
12204 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12206 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12207 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12209 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12211 unsavermask(rsave);
12214 /*-----------------------------------------------------------------*/
12216 /*-----------------------------------------------------------------*/
12217 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12222 assert (nparms == 1);
12223 /* save registers that need to be saved */
12224 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12225 ds390_rUmaskForOp (IC_RESULT(ic))));
12228 aopOp (handle,ic,FALSE,FALSE);
12230 /* put the size in R4-R2 */
12231 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12232 emitcode("push","%s",
12233 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12234 emitcode("push","%s",
12235 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12236 emitcode("pop","ar3");
12237 emitcode("pop","ar2");
12239 emitcode ("mov","r2,%s",
12240 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12241 emitcode ("mov","r3,%s",
12242 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12244 freeAsmop (handle, NULL, ic, FALSE);
12246 /* make the call */
12247 emitcode ("lcall","MM_Deref");
12250 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12251 if (rsym->liveFrom != rsym->liveTo) {
12252 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12253 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12254 _startLazyDPSEvaluation ();
12256 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12257 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12258 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12260 _endLazyDPSEvaluation ();
12265 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12266 unsavermask(rsave);
12269 /*-----------------------------------------------------------------*/
12270 /* genMMUnrestrictedPersist - */
12271 /*-----------------------------------------------------------------*/
12272 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12277 assert (nparms == 1);
12278 /* save registers that need to be saved */
12279 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12280 ds390_rUmaskForOp (IC_RESULT(ic))));
12283 aopOp (handle,ic,FALSE,FALSE);
12285 /* put the size in R3-R2 */
12286 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12287 emitcode("push","%s",
12288 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12289 emitcode("push","%s",
12290 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12291 emitcode("pop","ar3");
12292 emitcode("pop","ar2");
12294 emitcode ("mov","r2,%s",
12295 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12296 emitcode ("mov","r3,%s",
12297 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12299 freeAsmop (handle, NULL, ic, FALSE);
12301 /* make the call */
12302 emitcode ("lcall","MM_UnrestrictedPersist");
12305 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12306 if (rsym->liveFrom != rsym->liveTo) {
12307 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12308 aopPut(AOP(IC_RESULT(ic)),"a",0);
12309 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12312 unsavermask(rsave);
12315 /*-----------------------------------------------------------------*/
12316 /* genSystemExecJavaProcess - */
12317 /*-----------------------------------------------------------------*/
12318 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12321 operand *handle, *pp;
12323 assert (nparms==2);
12324 /* save registers that need to be saved */
12325 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12326 ds390_rUmaskForOp (IC_RESULT(ic))));
12331 /* put the handle in R3-R2 */
12332 aopOp (handle,ic,FALSE,FALSE);
12333 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12334 emitcode("push","%s",
12335 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12336 emitcode("push","%s",
12337 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12338 emitcode("pop","ar3");
12339 emitcode("pop","ar2");
12341 emitcode ("mov","r2,%s",
12342 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12343 emitcode ("mov","r3,%s",
12344 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12346 freeAsmop (handle, NULL, ic, FALSE);
12348 /* put pointer in DPTR */
12349 aopOp (pp,ic,FALSE,FALSE);
12350 if (AOP_TYPE(pp) == AOP_IMMD) {
12351 emitcode ("mov", "dptr,%s",
12352 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12353 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12354 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12355 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12356 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12358 freeAsmop (handle, NULL, ic, FALSE);
12360 /* make the call */
12361 emitcode ("lcall","System_ExecJavaProcess");
12363 /* put result in place */
12365 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12366 if (rsym->liveFrom != rsym->liveTo) {
12367 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12368 aopPut(AOP(IC_RESULT(ic)),"a",0);
12369 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12373 unsavermask(rsave);
12376 /*-----------------------------------------------------------------*/
12377 /* genSystemRTCRegisters - */
12378 /*-----------------------------------------------------------------*/
12379 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12385 assert (nparms==1);
12386 /* save registers that need to be saved */
12387 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12388 ds390_rUmaskForOp (IC_RESULT(ic))));
12391 /* put pointer in DPTR */
12392 aopOp (pp,ic,FALSE,FALSE);
12393 if (AOP_TYPE (pp) == AOP_IMMD) {
12394 emitcode ("mov","dps,#1");
12395 emitcode ("mov", "dptr,%s",
12396 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12397 emitcode ("mov","dps,#0");
12399 emitcode ("mov","dpl1,%s",
12400 aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12401 emitcode ("mov","dph1,%s",
12402 aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12403 emitcode ("mov","dpx1,%s",
12404 aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12406 freeAsmop (pp, NULL, ic, FALSE);
12408 /* make the call */
12409 emitcode ("lcall","System_%sRTCRegisters",name);
12411 unsavermask(rsave);
12414 /*-----------------------------------------------------------------*/
12415 /* genSystemThreadSleep - */
12416 /*-----------------------------------------------------------------*/
12417 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12422 assert (nparms==1);
12423 /* save registers that need to be saved */
12424 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12425 ds390_rUmaskForOp (IC_RESULT(ic))));
12428 aopOp(to,ic,FALSE,FALSE);
12429 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12430 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12431 emitcode ("push","%s",
12432 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12433 emitcode ("push","%s",
12434 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12435 emitcode ("push","%s",
12436 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12437 emitcode ("push","%s",
12438 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12439 emitcode ("pop","ar3");
12440 emitcode ("pop","ar2");
12441 emitcode ("pop","ar1");
12442 emitcode ("pop","ar0");
12444 emitcode ("mov","r0,%s",
12445 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12446 emitcode ("mov","r1,%s",
12447 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12448 emitcode ("mov","r2,%s",
12449 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12450 emitcode ("mov","r3,%s",
12451 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12453 freeAsmop (to, NULL, ic, FALSE);
12455 /* suspend in acc */
12457 aopOp(s,ic,FALSE,FALSE);
12458 emitcode ("mov","a,%s",
12459 aopGet(AOP(s),0,FALSE,TRUE,NULL));
12460 freeAsmop (s, NULL, ic, FALSE);
12462 /* make the call */
12463 emitcode ("lcall","System_%s",name);
12465 unsavermask(rsave);
12468 /*-----------------------------------------------------------------*/
12469 /* genSystemThreadResume - */
12470 /*-----------------------------------------------------------------*/
12471 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12476 assert (nparms==2);
12477 /* save registers that need to be saved */
12478 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12479 ds390_rUmaskForOp (IC_RESULT(ic))));
12485 aopOp(pid,ic,FALSE,FALSE);
12486 emitcode ("mov","r0,%s",
12487 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12488 freeAsmop (pid, NULL, ic, FALSE);
12491 aopOp(tid,ic,FALSE,FALSE);
12492 emitcode ("mov","a,%s",
12493 aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
12494 freeAsmop (tid, NULL, ic, FALSE);
12496 emitcode ("lcall","System_ThreadResume");
12498 /* put result into place */
12500 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12501 if (rsym->liveFrom != rsym->liveTo) {
12502 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12503 aopPut(AOP(IC_RESULT(ic)),"a",0);
12504 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12507 unsavermask(rsave);
12510 /*-----------------------------------------------------------------*/
12511 /* genSystemProcessResume - */
12512 /*-----------------------------------------------------------------*/
12513 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
12518 assert (nparms==1);
12519 /* save registers that need to be saved */
12520 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12521 ds390_rUmaskForOp (IC_RESULT(ic))));
12526 aopOp(pid,ic,FALSE,FALSE);
12527 emitcode ("mov","a,%s",
12528 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12529 freeAsmop (pid, NULL, ic, FALSE);
12531 emitcode ("lcall","System_ProcessResume");
12533 unsavermask(rsave);
12536 /*-----------------------------------------------------------------*/
12538 /*-----------------------------------------------------------------*/
12539 static void genSystem (iCode *ic,int nparms,char *name)
12541 assert(nparms == 0);
12543 emitcode ("lcall","System_%s",name);
12546 /*-----------------------------------------------------------------*/
12547 /* genSystemPoll - */
12548 /*-----------------------------------------------------------------*/
12549 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
12554 assert (nparms==1);
12555 /* save registers that need to be saved */
12556 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12557 ds390_rUmaskForOp (IC_RESULT(ic))));
12560 aopOp (fp,ic,FALSE,FALSE);
12561 if (AOP_TYPE (fp) == AOP_IMMD) {
12562 emitcode ("mov", "dptr,%s",
12563 aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
12564 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
12565 emitcode ("mov","dpl,%s",
12566 aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
12567 emitcode ("mov","dph,%s",
12568 aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
12569 emitcode ("mov","dpx,%s",
12570 aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
12572 freeAsmop (fp, NULL, ic, FALSE);
12574 emitcode ("lcall","System_%sPoll",name);
12576 /* put result into place */
12578 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12579 if (rsym->liveFrom != rsym->liveTo) {
12580 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12581 aopPut(AOP(IC_RESULT(ic)),"a",0);
12582 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12585 unsavermask(rsave);
12588 /*-----------------------------------------------------------------*/
12589 /* genSystemGetCurrentID - */
12590 /*-----------------------------------------------------------------*/
12591 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
12593 assert (nparms==0);
12595 emitcode ("lcall","System_GetCurrent%sId",name);
12596 /* put result into place */
12598 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12599 if (rsym->liveFrom != rsym->liveTo) {
12600 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12601 aopPut(AOP(IC_RESULT(ic)),"a",0);
12602 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12607 /*-----------------------------------------------------------------*/
12608 /* genDummyRead - generate code for dummy read of volatiles */
12609 /*-----------------------------------------------------------------*/
12611 genDummyRead (iCode * ic)
12616 D(emitcode("; genDummyRead",""));
12618 right = IC_RIGHT (ic);
12620 aopOp (right, ic, FALSE, FALSE);
12622 /* if the result is a bit */
12623 if (AOP_TYPE (right) == AOP_CRY)
12625 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
12629 /* bit variables done */
12631 size = AOP_SIZE (right);
12635 emitcode ("mov", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
12640 freeAsmop (right, NULL, ic, TRUE);
12643 /*-----------------------------------------------------------------*/
12644 /* genBuiltIn - calls the appropriate function to generating code */
12645 /* for a built in function */
12646 /*-----------------------------------------------------------------*/
12647 static void genBuiltIn (iCode *ic)
12649 operand *bi_parms[MAX_BUILTIN_ARGS];
12654 /* get all the arguments for a built in function */
12655 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
12657 /* which function is it */
12658 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
12659 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
12660 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
12661 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
12662 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
12663 } else if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
12664 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
12665 } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
12666 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
12667 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
12668 genMemsetX(bi_iCode,nbi_parms,bi_parms);
12669 } else if (strcmp(bif->name,"__builtin_inp")==0) {
12670 genInp(bi_iCode,nbi_parms,bi_parms);
12671 } else if (strcmp(bif->name,"__builtin_outp")==0) {
12672 genOutp(bi_iCode,nbi_parms,bi_parms);
12673 } else if (strcmp(bif->name,"__builtin_swapw")==0) {
12674 genSwapW(bi_iCode,nbi_parms,bi_parms);
12675 /* JavaNative builtIns */
12676 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
12677 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
12678 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
12679 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
12680 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
12681 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
12682 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
12683 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
12684 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
12685 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12686 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
12687 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12688 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
12689 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
12690 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
12691 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
12692 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
12693 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12694 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
12695 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12696 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
12697 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
12698 } else if (strcmp(bif->name,"MM_Malloc")==0) {
12699 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
12700 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
12701 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
12702 } else if (strcmp(bif->name,"MM_Free")==0) {
12703 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
12704 } else if (strcmp(bif->name,"MM_Deref")==0) {
12705 genMMDeref(bi_iCode,nbi_parms,bi_parms);
12706 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
12707 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
12708 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
12709 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
12710 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
12711 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
12712 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
12713 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
12714 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
12715 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
12716 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
12717 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
12718 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
12719 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
12720 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
12721 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
12722 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12723 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12724 } else if (strcmp(bif->name,"System_SaveThread")==0) {
12725 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12726 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12727 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12728 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
12729 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
12730 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
12731 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
12732 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
12733 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
12734 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
12735 genSystem(bi_iCode,nbi_parms,"ProcessYield");
12736 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
12737 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
12738 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
12739 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
12740 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
12741 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
12742 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
12743 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
12744 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
12745 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
12747 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
12753 /*-----------------------------------------------------------------*/
12754 /* gen390Code - generate code for Dallas 390 based controllers */
12755 /*-----------------------------------------------------------------*/
12757 gen390Code (iCode * lic)
12762 lineHead = lineCurr = NULL;
12763 dptrn[1][0] = "dpl1";
12764 dptrn[1][1] = "dph1";
12765 dptrn[1][2] = "dpx1";
12767 if (options.model == MODEL_FLAT24) {
12768 fReturnSizeDS390 = 5;
12769 fReturn = fReturn24;
12771 fReturnSizeDS390 = 4;
12772 fReturn = fReturn16;
12773 options.stack10bit=0;
12776 /* print the allocation information */
12777 if (allocInfo && currFunc)
12778 printAllocInfo (currFunc, codeOutFile);
12780 /* if debug information required */
12781 if (options.debug && currFunc)
12783 debugFile->writeFunction(currFunc);
12785 if (IS_STATIC (currFunc->etype))
12786 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
12788 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
12791 /* stack pointer name */
12792 if (options.useXstack)
12798 for (ic = lic; ic; ic = ic->next)
12801 if (ic->lineno && cln != ic->lineno)
12806 emitcode ("", "C$%s$%d$%d$%d ==.",
12807 FileBaseName (ic->filename), ic->lineno,
12808 ic->level, ic->block);
12811 if (!options.noCcodeInAsm) {
12812 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
12813 printCLine(ic->filename, ic->lineno));
12817 if (options.iCodeInAsm) {
12818 emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
12820 /* if the result is marked as
12821 spilt and rematerializable or code for
12822 this has already been generated then
12824 if (resultRemat (ic) || ic->generated)
12827 /* depending on the operation */
12847 /* IPOP happens only when trying to restore a
12848 spilt live range, if there is an ifx statement
12849 following this pop then the if statement might
12850 be using some of the registers being popped which
12851 would destory the contents of the register so
12852 we need to check for this condition and handle it */
12854 ic->next->op == IFX &&
12855 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
12856 genIfx (ic->next, ic);
12874 genEndFunction (ic);
12894 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
12911 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
12915 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
12922 /* note these two are xlated by algebraic equivalence
12923 during parsing SDCC.y */
12924 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12925 "got '>=' or '<=' shouldn't have come here");
12929 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
12941 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
12945 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
12949 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
12973 genRightShift (ic);
12976 case GET_VALUE_AT_ADDRESS:
12977 genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
12981 if (POINTER_SET (ic))
12982 genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
13008 if (ic->builtinSEND) genBuiltIn(ic);
13009 else addSet (&_G.sendSet, ic);
13012 case DUMMY_READ_VOLATILE:
13016 #if 0 // obsolete, and buggy for != xdata
13028 /* now we are ready to call the
13029 peep hole optimizer */
13030 if (!options.nopeep)
13031 peepHole (&lineHead);
13033 /* now do the actual printing */
13034 printLine (lineHead, codeOutFile);