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) && !(sym->isitmp))
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);
8976 /*-----------------------------------------------------------------*/
8977 /* emitPtrByteGet - emits code to get a byte into A through a */
8978 /* pointer register (R0, R1, or DPTR). The */
8979 /* original value of A can be preserved in B. */
8980 /*-----------------------------------------------------------------*/
8982 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
8989 emitcode ("mov", "b,a");
8990 emitcode ("mov", "a,@%s", rname);
8995 emitcode ("mov", "b,a");
8996 emitcode ("movx", "a,@%s", rname);
9001 emitcode ("mov", "b,a");
9002 emitcode ("movx", "a,@dptr");
9007 emitcode ("mov", "b,a");
9008 emitcode ("clr", "a");
9009 emitcode ("movc", "a,@a+dptr");
9015 emitcode ("push", "b");
9016 emitcode ("push", "acc");
9018 emitcode ("lcall", "__gptrget");
9020 emitcode ("pop", "b");
9025 /*-----------------------------------------------------------------*/
9026 /* emitPtrByteSet - emits code to set a byte from src through a */
9027 /* pointer register (R0, R1, or DPTR). */
9028 /*-----------------------------------------------------------------*/
9030 emitPtrByteSet (char *rname, int p_type, char *src)
9039 emitcode ("mov", "@%s,a", rname);
9042 emitcode ("mov", "@%s,%s", rname, src);
9047 emitcode ("movx", "@%s,a", rname);
9052 emitcode ("movx", "@dptr,a");
9057 emitcode ("lcall", "__gptrput");
9062 /*-----------------------------------------------------------------*/
9063 /* genUnpackBits - generates code for unpacking bits */
9064 /*-----------------------------------------------------------------*/
9066 genUnpackBits (operand * result, char *rname, int ptype)
9068 int offset = 0; /* result byte offset */
9069 int rsize; /* result size */
9070 int rlen = 0; /* remaining bitfield length */
9071 sym_link *etype; /* bitfield type information */
9072 int blen; /* bitfield length */
9073 int bstr; /* bitfield starting bit within byte */
9075 D(emitcode ("; genUnpackBits",""));
9077 etype = getSpec (operandType (result));
9078 rsize = getSize (operandType (result));
9079 blen = SPEC_BLEN (etype);
9080 bstr = SPEC_BSTR (etype);
9082 /* If the bitfield length is less than a byte */
9085 emitPtrByteGet (rname, ptype, FALSE);
9087 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
9088 aopPut (AOP (result), "a", offset++);
9092 /* Bit field did not fit in a byte. Copy all
9093 but the partial byte at the end. */
9094 for (rlen=blen;rlen>=8;rlen-=8)
9096 emitPtrByteGet (rname, ptype, FALSE);
9097 aopPut (AOP (result), "a", offset++);
9099 emitcode ("inc", "%s", rname);
9102 /* Handle the partial byte at the end */
9105 emitPtrByteGet (rname, ptype, FALSE);
9106 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
9107 aopPut (AOP (result), "a", offset++);
9115 aopPut (AOP (result), zero, offset++);
9120 /*-----------------------------------------------------------------*/
9121 /* genDataPointerGet - generates code when ptr offset is known */
9122 /*-----------------------------------------------------------------*/
9124 genDataPointerGet (operand * left,
9130 int size, offset = 0;
9131 aopOp (result, ic, TRUE, FALSE);
9133 /* get the string representation of the name */
9134 l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9135 size = AOP_SIZE (result);
9136 _startLazyDPSEvaluation ();
9141 SNPRINTF (buff, sizeof(buff),
9142 "(%s + %d)", l + 1, offset);
9146 SNPRINTF (buff, sizeof(buff),
9149 aopPut (AOP (result), buff, offset++);
9151 _endLazyDPSEvaluation ();
9153 freeAsmop (left, NULL, ic, TRUE);
9154 freeAsmop (result, NULL, ic, TRUE);
9157 /*-----------------------------------------------------------------*/
9158 /* genNearPointerGet - emitcode for near pointer fetch */
9159 /*-----------------------------------------------------------------*/
9161 genNearPointerGet (operand * left,
9169 sym_link *rtype, *retype, *letype;
9170 sym_link *ltype = operandType (left);
9173 rtype = operandType (result);
9174 retype = getSpec (rtype);
9175 letype = getSpec (ltype);
9177 aopOp (left, ic, FALSE, FALSE);
9179 /* if left is rematerialisable and
9180 result is not bit variable type and
9181 the left is pointer to data space i.e
9182 lower 128 bytes of space */
9183 if (AOP_TYPE (left) == AOP_IMMD &&
9184 !IS_BITVAR (retype) &&
9185 !IS_BITVAR (letype) &&
9186 DCL_TYPE (ltype) == POINTER)
9188 genDataPointerGet (left, result, ic);
9192 /* if the value is already in a pointer register
9193 then don't need anything more */
9194 if (!AOP_INPREG (AOP (left)))
9196 /* otherwise get a free pointer register */
9198 preg = getFreePtr (ic, &aop, FALSE);
9199 emitcode ("mov", "%s,%s",
9201 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9205 rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9207 freeAsmop (left, NULL, ic, TRUE);
9208 aopOp (result, ic, FALSE, FALSE);
9210 /* if bitfield then unpack the bits */
9211 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9212 genUnpackBits (result, rname, POINTER);
9215 /* we have can just get the values */
9216 int size = AOP_SIZE (result);
9221 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9224 emitcode ("mov", "a,@%s", rname);
9225 aopPut (AOP (result), "a", offset);
9229 SNPRINTF (buff, sizeof(buff), "@%s", rname);
9230 aopPut (AOP (result), buff, offset);
9235 emitcode ("inc", "%s", rname);
9240 /* now some housekeeping stuff */
9243 /* we had to allocate for this iCode */
9244 if (pi) { /* post increment present */
9245 aopPut(AOP ( left ),rname,0);
9247 freeAsmop (NULL, aop, ic, TRUE);
9251 /* we did not allocate which means left
9252 already in a pointer register, then
9253 if size > 0 && this could be used again
9254 we have to point it back to where it
9256 if (AOP_SIZE (result) > 1 &&
9257 !OP_SYMBOL (left)->remat &&
9258 (OP_SYMBOL (left)->liveTo > ic->seq ||
9262 int size = AOP_SIZE (result) - 1;
9264 emitcode ("dec", "%s", rname);
9269 freeAsmop (result, NULL, ic, TRUE);
9270 if (pi) pi->generated = 1;
9273 /*-----------------------------------------------------------------*/
9274 /* genPagedPointerGet - emitcode for paged pointer fetch */
9275 /*-----------------------------------------------------------------*/
9277 genPagedPointerGet (operand * left,
9285 sym_link *rtype, *retype, *letype;
9287 rtype = operandType (result);
9288 retype = getSpec (rtype);
9289 letype = getSpec (operandType (left));
9290 aopOp (left, ic, FALSE, FALSE);
9292 /* if the value is already in a pointer register
9293 then don't need anything more */
9294 if (!AOP_INPREG (AOP (left)))
9296 /* otherwise get a free pointer register */
9298 preg = getFreePtr (ic, &aop, FALSE);
9299 emitcode ("mov", "%s,%s",
9301 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9305 rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9307 freeAsmop (left, NULL, ic, TRUE);
9308 aopOp (result, ic, FALSE, FALSE);
9310 /* if bitfield then unpack the bits */
9311 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9312 genUnpackBits (result, rname, PPOINTER);
9315 /* we have can just get the values */
9316 int size = AOP_SIZE (result);
9322 emitcode ("movx", "a,@%s", rname);
9323 aopPut (AOP (result), "a", offset);
9328 emitcode ("inc", "%s", rname);
9332 /* now some housekeeping stuff */
9335 /* we had to allocate for this iCode */
9336 if (pi) aopPut ( AOP (left), rname, 0);
9337 freeAsmop (NULL, aop, ic, TRUE);
9341 /* we did not allocate which means left
9342 already in a pointer register, then
9343 if size > 0 && this could be used again
9344 we have to point it back to where it
9346 if (AOP_SIZE (result) > 1 &&
9347 !OP_SYMBOL (left)->remat &&
9348 (OP_SYMBOL (left)->liveTo > ic->seq ||
9352 int size = AOP_SIZE (result) - 1;
9354 emitcode ("dec", "%s", rname);
9359 freeAsmop (result, NULL, ic, TRUE);
9360 if (pi) pi->generated = 1;
9363 /*-----------------------------------------------------------------*/
9364 /* genFarPointerGet - gget value from far space */
9365 /*-----------------------------------------------------------------*/
9367 genFarPointerGet (operand * left,
9368 operand * result, iCode * ic, iCode *pi)
9370 int size, offset, dopi=1;
9371 sym_link *retype = getSpec (operandType (result));
9372 sym_link *letype = getSpec (operandType (left));
9373 D (emitcode (";", "genFarPointerGet"););
9375 aopOp (left, ic, FALSE, FALSE);
9377 /* if the operand is already in dptr
9378 then we do nothing else we move the value to dptr */
9379 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9381 /* if this is remateriazable */
9382 if (AOP_TYPE (left) == AOP_IMMD)
9384 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9388 /* we need to get it byte by byte */
9389 _startLazyDPSEvaluation ();
9390 if (AOP_TYPE (left) != AOP_DPTR)
9392 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9393 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9394 if (options.model == MODEL_FLAT24)
9395 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9399 /* We need to generate a load to DPTR indirect through DPTR. */
9400 D (emitcode (";", "genFarPointerGet -- indirection special case."););
9401 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9402 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9403 if (options.model == MODEL_FLAT24)
9404 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9405 emitcode ("pop", "dph");
9406 emitcode ("pop", "dpl");
9409 _endLazyDPSEvaluation ();
9412 /* so dptr know contains the address */
9413 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9415 /* if bit then unpack */
9416 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9417 if (AOP_INDPTRn(left)) {
9418 genSetDPTR(AOP(left)->aopu.dptr);
9420 genUnpackBits (result, "dptr", FPOINTER);
9421 if (AOP_INDPTRn(left)) {
9426 size = AOP_SIZE (result);
9429 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9431 genSetDPTR(AOP(left)->aopu.dptr);
9432 emitcode ("movx", "a,@dptr");
9433 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9434 emitcode ("inc", "dptr");
9436 aopPut (AOP (result), "a", offset++);
9439 _startLazyDPSEvaluation ();
9441 if (AOP_INDPTRn(left)) {
9442 genSetDPTR(AOP(left)->aopu.dptr);
9448 emitcode ("movx", "a,@dptr");
9449 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9450 emitcode ("inc", "dptr");
9452 aopPut (AOP (result), "a", offset++);
9454 _endLazyDPSEvaluation ();
9457 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9458 if (!AOP_INDPTRn(left)) {
9459 _startLazyDPSEvaluation ();
9460 aopPut ( AOP (left), "dpl", 0);
9461 aopPut ( AOP (left), "dph", 1);
9462 if (options.model == MODEL_FLAT24)
9463 aopPut ( AOP (left), "dpx", 2);
9464 _endLazyDPSEvaluation ();
9467 } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) &&
9468 AOP_SIZE(result) > 1 &&
9470 (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
9472 size = AOP_SIZE (result) - 1;
9473 if (AOP_INDPTRn(left)) {
9474 genSetDPTR(AOP(left)->aopu.dptr);
9476 while (size--) emitcode ("lcall","__decdptr");
9477 if (AOP_INDPTRn(left)) {
9482 freeAsmop (left, NULL, ic, TRUE);
9483 freeAsmop (result, NULL, ic, TRUE);
9486 /*-----------------------------------------------------------------*/
9487 /* genCodePointerGet - get value from code space */
9488 /*-----------------------------------------------------------------*/
9490 genCodePointerGet (operand * left,
9491 operand * result, iCode * ic, iCode *pi)
9493 int size, offset, dopi=1;
9494 sym_link *retype = getSpec (operandType (result));
9496 aopOp (left, ic, FALSE, FALSE);
9498 /* if the operand is already in dptr
9499 then we do nothing else we move the value to dptr */
9500 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
9502 /* if this is remateriazable */
9503 if (AOP_TYPE (left) == AOP_IMMD)
9505 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9508 { /* we need to get it byte by byte */
9509 _startLazyDPSEvaluation ();
9510 if (AOP_TYPE (left) != AOP_DPTR)
9512 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9513 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9514 if (options.model == MODEL_FLAT24)
9515 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9519 /* We need to generate a load to DPTR indirect through DPTR. */
9520 D (emitcode (";", "gencodePointerGet -- indirection special case."););
9521 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9522 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9523 if (options.model == MODEL_FLAT24)
9524 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9525 emitcode ("pop", "dph");
9526 emitcode ("pop", "dpl");
9529 _endLazyDPSEvaluation ();
9532 /* so dptr know contains the address */
9533 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9535 /* if bit then unpack */
9536 if (IS_BITVAR (retype)) {
9537 if (AOP_INDPTRn(left)) {
9538 genSetDPTR(AOP(left)->aopu.dptr);
9540 genUnpackBits (result, "dptr", CPOINTER);
9541 if (AOP_INDPTRn(left)) {
9546 size = AOP_SIZE (result);
9548 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9550 genSetDPTR(AOP(left)->aopu.dptr);
9551 emitcode ("clr", "a");
9552 emitcode ("movc", "a,@a+dptr");
9553 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9554 emitcode ("inc", "dptr");
9556 aopPut (AOP (result), "a", offset++);
9559 _startLazyDPSEvaluation ();
9562 if (AOP_INDPTRn(left)) {
9563 genSetDPTR(AOP(left)->aopu.dptr);
9569 emitcode ("clr", "a");
9570 emitcode ("movc", "a,@a+dptr");
9571 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9572 emitcode ("inc", "dptr");
9573 aopPut (AOP (result), "a", offset++);
9575 _endLazyDPSEvaluation ();
9578 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9579 if (!AOP_INDPTRn(left)) {
9580 _startLazyDPSEvaluation ();
9582 aopPut ( AOP (left), "dpl", 0);
9583 aopPut ( AOP (left), "dph", 1);
9584 if (options.model == MODEL_FLAT24)
9585 aopPut ( AOP (left), "dpx", 2);
9587 _endLazyDPSEvaluation ();
9590 } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
9591 AOP_SIZE(result) > 1 &&
9592 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9594 size = AOP_SIZE (result) - 1;
9595 if (AOP_INDPTRn(left)) {
9596 genSetDPTR(AOP(left)->aopu.dptr);
9598 while (size--) emitcode ("lcall","__decdptr");
9599 if (AOP_INDPTRn(left)) {
9604 freeAsmop (left, NULL, ic, TRUE);
9605 freeAsmop (result, NULL, ic, TRUE);
9608 /*-----------------------------------------------------------------*/
9609 /* genGenPointerGet - gget value from generic pointer space */
9610 /*-----------------------------------------------------------------*/
9612 genGenPointerGet (operand * left,
9613 operand * result, iCode * ic, iCode * pi)
9616 sym_link *retype = getSpec (operandType (result));
9617 sym_link *letype = getSpec (operandType (left));
9619 D (emitcode (";", "genGenPointerGet "); );
9621 aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
9623 /* if the operand is already in dptr
9624 then we do nothing else we move the value to dptr */
9625 if (AOP_TYPE (left) != AOP_STR)
9627 /* if this is remateriazable */
9628 if (AOP_TYPE (left) == AOP_IMMD)
9630 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9631 if (AOP(left)->aopu.aop_immd.from_cast_remat)
9633 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
9637 emitcode ("mov", "b,#%d", pointerCode (retype));
9641 { /* we need to get it byte by byte */
9642 _startLazyDPSEvaluation ();
9643 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
9644 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
9645 if (options.model == MODEL_FLAT24) {
9646 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9647 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
9649 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9651 _endLazyDPSEvaluation ();
9655 /* so dptr-b now contains the address */
9657 aopOp (result, ic, FALSE, TRUE);
9660 /* if bit then unpack */
9661 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9663 genUnpackBits (result, "dptr", GPOINTER);
9667 size = AOP_SIZE (result);
9674 // Get two bytes at a time, results in _AP & A.
9675 // dptr will be incremented ONCE by __gptrgetWord.
9677 // Note: any change here must be coordinated
9678 // with the implementation of __gptrgetWord
9679 // in device/lib/_gptrget.c
9680 emitcode ("lcall", "__gptrgetWord");
9681 aopPut (AOP (result), DP2_RESULT_REG, offset++);
9682 aopPut (AOP (result), "a", offset++);
9687 // Only one byte to get.
9688 emitcode ("lcall", "__gptrget");
9689 aopPut (AOP (result), "a", offset++);
9692 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9694 emitcode ("inc", "dptr");
9699 if (pi && AOP_TYPE (left) != AOP_IMMD) {
9700 _startLazyDPSEvaluation ();
9702 aopPut ( AOP (left), "dpl", 0);
9703 aopPut ( AOP (left), "dph", 1);
9704 if (options.model == MODEL_FLAT24) {
9705 aopPut ( AOP (left), "dpx", 2);
9706 aopPut ( AOP (left), "b", 3);
9707 } else aopPut ( AOP (left), "b", 2);
9709 _endLazyDPSEvaluation ();
9712 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9713 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9715 size = AOP_SIZE (result) - 1;
9716 while (size--) emitcode ("lcall","__decdptr");
9719 freeAsmop (left, NULL, ic, TRUE);
9720 freeAsmop (result, NULL, ic, TRUE);
9723 /*-----------------------------------------------------------------*/
9724 /* genPointerGet - generate code for pointer get */
9725 /*-----------------------------------------------------------------*/
9727 genPointerGet (iCode * ic, iCode *pi)
9729 operand *left, *result;
9730 sym_link *type, *etype;
9733 D (emitcode (";", "genPointerGet ");
9736 left = IC_LEFT (ic);
9737 result = IC_RESULT (ic);
9739 /* depending on the type of pointer we need to
9740 move it to the correct pointer register */
9741 type = operandType (left);
9742 etype = getSpec (type);
9743 /* if left is of type of pointer then it is simple */
9744 if (IS_PTR (type) && !IS_FUNC (type->next))
9745 p_type = DCL_TYPE (type);
9748 /* we have to go by the storage class */
9749 p_type = PTR_TYPE (SPEC_OCLS (etype));
9751 /* special case when cast remat */
9752 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9753 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9754 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9755 type = operandType (left);
9756 p_type = DCL_TYPE (type);
9758 /* now that we have the pointer type we assign
9759 the pointer values */
9765 genNearPointerGet (left, result, ic, pi);
9769 genPagedPointerGet (left, result, ic, pi);
9773 genFarPointerGet (left, result, ic, pi);
9777 genCodePointerGet (left, result, ic, pi);
9781 genGenPointerGet (left, result, ic, pi);
9787 /*-----------------------------------------------------------------*/
9788 /* genPackBits - generates code for packed bit storage */
9789 /*-----------------------------------------------------------------*/
9791 genPackBits (sym_link * etype,
9793 char *rname, int p_type)
9795 int offset = 0; /* source byte offset */
9796 int rlen = 0; /* remaining bitfield length */
9797 int blen; /* bitfield length */
9798 int bstr; /* bitfield starting bit within byte */
9799 int litval; /* source literal value (if AOP_LIT) */
9800 unsigned char mask; /* bitmask within current byte */
9802 D(emitcode ("; genPackBits",""));
9804 blen = SPEC_BLEN (etype);
9805 bstr = SPEC_BSTR (etype);
9807 /* If the bitfield length is less than a byte */
9810 mask = ((unsigned char) (0xFF << (blen + bstr)) |
9811 (unsigned char) (0xFF >> (8 - bstr)));
9813 if (AOP_TYPE (right) == AOP_LIT)
9815 /* Case with a bitfield length <8 and literal source
9817 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9819 litval &= (~mask) & 0xff;
9820 emitPtrByteGet (rname, p_type, FALSE);
9821 if ((mask|litval)!=0xff)
9822 emitcode ("anl","a,#!constbyte", mask);
9824 emitcode ("orl","a,#!constbyte", litval);
9828 if ((blen==1) && (p_type!=GPOINTER))
9830 /* Case with a bitfield length == 1 and no generic pointer
9832 if (AOP_TYPE (right) == AOP_CRY)
9833 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9836 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
9837 emitcode ("rrc","a");
9839 emitPtrByteGet (rname, p_type, FALSE);
9840 emitcode ("mov","acc.%d,c",bstr);
9844 /* Case with a bitfield length < 8 and arbitrary source
9846 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
9847 /* shift and mask source value */
9849 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
9851 /* transfer A to B and get next byte */
9852 emitPtrByteGet (rname, p_type, TRUE);
9854 emitcode ("anl", "a,#!constbyte", mask);
9855 emitcode ("orl", "a,b");
9856 if (p_type == GPOINTER)
9857 emitcode ("pop", "b");
9861 emitPtrByteSet (rname, p_type, "a");
9865 /* Bit length is greater than 7 bits. In this case, copy */
9866 /* all except the partial byte at the end */
9867 for (rlen=blen;rlen>=8;rlen-=8)
9869 emitPtrByteSet (rname, p_type,
9870 aopGet (AOP (right), offset++, FALSE, TRUE, NULL) );
9872 emitcode ("inc", "%s", rname);
9875 /* If there was a partial byte at the end */
9878 mask = (((unsigned char) -1 << rlen) & 0xff);
9880 if (AOP_TYPE (right) == AOP_LIT)
9882 /* Case with partial byte and literal source
9884 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9885 litval >>= (blen-rlen);
9886 litval &= (~mask) & 0xff;
9887 emitPtrByteGet (rname, p_type, FALSE);
9888 if ((mask|litval)!=0xff)
9889 emitcode ("anl","a,#!constbyte", mask);
9891 emitcode ("orl","a,#!constbyte", litval);
9895 /* Case with partial byte and arbitrary source
9897 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9898 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
9900 /* transfer A to B and get next byte */
9901 emitPtrByteGet (rname, p_type, TRUE);
9903 emitcode ("anl", "a,#!constbyte", mask);
9904 emitcode ("orl", "a,b");
9905 if (p_type == GPOINTER)
9906 emitcode ("pop", "b");
9908 emitPtrByteSet (rname, p_type, "a");
9914 /*-----------------------------------------------------------------*/
9915 /* genDataPointerSet - remat pointer to data space */
9916 /*-----------------------------------------------------------------*/
9918 genDataPointerSet (operand * right,
9922 int size, offset = 0;
9925 aopOp (right, ic, FALSE, FALSE);
9927 l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
9928 size = AOP_SIZE (right);
9933 SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
9937 SNPRINTF (buff, sizeof(buff), "%s", l + 1);
9940 emitcode ("mov", "%s,%s", buff,
9941 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9944 freeAsmop (right, NULL, ic, TRUE);
9945 freeAsmop (result, NULL, ic, TRUE);
9948 /*-----------------------------------------------------------------*/
9949 /* genNearPointerSet - emitcode for near pointer put */
9950 /*-----------------------------------------------------------------*/
9952 genNearPointerSet (operand * right,
9959 sym_link *retype, *letype;
9960 sym_link *ptype = operandType (result);
9962 retype = getSpec (operandType (right));
9963 letype = getSpec (ptype);
9965 aopOp (result, ic, FALSE, FALSE);
9967 /* if the result is rematerializable &
9968 in data space & not a bit variable */
9969 if (AOP_TYPE (result) == AOP_IMMD &&
9970 DCL_TYPE (ptype) == POINTER &&
9971 !IS_BITVAR (retype) &&
9972 !IS_BITVAR (letype))
9974 genDataPointerSet (right, result, ic);
9978 /* if the value is already in a pointer register
9979 then don't need anything more */
9980 if (!AOP_INPREG (AOP (result)))
9982 /* otherwise get a free pointer register */
9986 preg = getFreePtr (ic, &aop, FALSE);
9987 emitcode ("mov", "%s,%s",
9989 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
9993 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
9995 aopOp (right, ic, FALSE, FALSE);
9997 /* if bitfield then unpack the bits */
9998 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9999 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
10002 /* we have can just get the values */
10003 int size = AOP_SIZE (right);
10008 l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
10012 emitcode ("mov", "@%s,a", rname);
10015 emitcode ("mov", "@%s,%s", rname, l);
10017 emitcode ("inc", "%s", rname);
10022 /* now some housekeeping stuff */
10025 /* we had to allocate for this iCode */
10026 if (pi) aopPut (AOP (result),rname,0);
10027 freeAsmop (NULL, aop, ic, TRUE);
10031 /* we did not allocate which means left
10032 already in a pointer register, then
10033 if size > 0 && this could be used again
10034 we have to point it back to where it
10036 if (AOP_SIZE (right) > 1 &&
10037 !OP_SYMBOL (result)->remat &&
10038 (OP_SYMBOL (result)->liveTo > ic->seq ||
10042 int size = AOP_SIZE (right) - 1;
10044 emitcode ("dec", "%s", rname);
10049 if (pi) pi->generated = 1;
10050 freeAsmop (result, NULL, ic, TRUE);
10051 freeAsmop (right, NULL, ic, TRUE);
10056 /*-----------------------------------------------------------------*/
10057 /* genPagedPointerSet - emitcode for Paged pointer put */
10058 /*-----------------------------------------------------------------*/
10060 genPagedPointerSet (operand * right,
10067 sym_link *retype, *letype;
10069 retype = getSpec (operandType (right));
10070 letype = getSpec (operandType (result));
10072 aopOp (result, ic, FALSE, FALSE);
10074 /* if the value is already in a pointer register
10075 then don't need anything more */
10076 if (!AOP_INPREG (AOP (result)))
10078 /* otherwise get a free pointer register */
10081 aop = newAsmop (0);
10082 preg = getFreePtr (ic, &aop, FALSE);
10083 emitcode ("mov", "%s,%s",
10085 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10086 rname = preg->name;
10089 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10091 aopOp (right, ic, FALSE, FALSE);
10093 /* if bitfield then unpack the bits */
10094 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10095 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
10098 /* we have can just get the values */
10099 int size = AOP_SIZE (right);
10104 MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10106 emitcode ("movx", "@%s,a", rname);
10109 emitcode ("inc", "%s", rname);
10115 /* now some housekeeping stuff */
10118 if (pi) aopPut (AOP (result),rname,0);
10119 /* we had to allocate for this iCode */
10120 freeAsmop (NULL, aop, ic, TRUE);
10124 /* we did not allocate which means left
10125 already in a pointer register, then
10126 if size > 0 && this could be used again
10127 we have to point it back to where it
10129 if (AOP_SIZE (right) > 1 &&
10130 !OP_SYMBOL (result)->remat &&
10131 (OP_SYMBOL (result)->liveTo > ic->seq ||
10135 int size = AOP_SIZE (right) - 1;
10137 emitcode ("dec", "%s", rname);
10142 if (pi) pi->generated = 1;
10143 freeAsmop (result, NULL, ic, TRUE);
10144 freeAsmop (right, NULL, ic, TRUE);
10149 /*-----------------------------------------------------------------*/
10150 /* genFarPointerSet - set value from far space */
10151 /*-----------------------------------------------------------------*/
10153 genFarPointerSet (operand * right,
10154 operand * result, iCode * ic, iCode *pi)
10156 int size, offset, dopi=1;
10157 sym_link *retype = getSpec (operandType (right));
10158 sym_link *letype = getSpec (operandType (result));
10160 aopOp (result, ic, FALSE, FALSE);
10162 /* if the operand is already in dptr
10163 then we do nothing else we move the value to dptr */
10164 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10166 /* if this is remateriazable */
10167 if (AOP_TYPE (result) == AOP_IMMD)
10168 emitcode ("mov", "dptr,%s",
10169 aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10172 /* we need to get it byte by byte */
10173 _startLazyDPSEvaluation ();
10174 if (AOP_TYPE (result) != AOP_DPTR)
10176 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10177 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10178 if (options.model == MODEL_FLAT24)
10179 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10183 /* We need to generate a load to DPTR indirect through DPTR. */
10184 D (emitcode (";", "genFarPointerSet -- indirection special case."););
10186 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10187 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10188 if (options.model == MODEL_FLAT24)
10189 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10190 emitcode ("pop", "dph");
10191 emitcode ("pop", "dpl");
10194 _endLazyDPSEvaluation ();
10197 /* so dptr know contains the address */
10198 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10200 /* if bit then unpack */
10201 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
10202 if (AOP_INDPTRn(result)) {
10203 genSetDPTR(AOP(result)->aopu.dptr);
10205 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
10206 if (AOP_INDPTRn(result)) {
10210 size = AOP_SIZE (right);
10212 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10214 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10216 genSetDPTR(AOP(result)->aopu.dptr);
10217 emitcode ("movx", "@dptr,a");
10218 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10219 emitcode ("inc", "dptr");
10223 _startLazyDPSEvaluation ();
10225 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10227 if (AOP_INDPTRn(result)) {
10228 genSetDPTR(AOP(result)->aopu.dptr);
10234 emitcode ("movx", "@dptr,a");
10235 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10236 emitcode ("inc", "dptr");
10238 _endLazyDPSEvaluation ();
10242 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10243 if (!AOP_INDPTRn(result)) {
10244 _startLazyDPSEvaluation ();
10246 aopPut (AOP(result),"dpl",0);
10247 aopPut (AOP(result),"dph",1);
10248 if (options.model == MODEL_FLAT24)
10249 aopPut (AOP(result),"dpx",2);
10251 _endLazyDPSEvaluation ();
10254 } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
10255 AOP_SIZE(right) > 1 &&
10256 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10258 size = AOP_SIZE (right) - 1;
10259 if (AOP_INDPTRn(result)) {
10260 genSetDPTR(AOP(result)->aopu.dptr);
10262 while (size--) emitcode ("lcall","__decdptr");
10263 if (AOP_INDPTRn(result)) {
10267 freeAsmop (result, NULL, ic, TRUE);
10268 freeAsmop (right, NULL, ic, TRUE);
10271 /*-----------------------------------------------------------------*/
10272 /* genGenPointerSet - set value from generic pointer space */
10273 /*-----------------------------------------------------------------*/
10275 genGenPointerSet (operand * right,
10276 operand * result, iCode * ic, iCode *pi)
10279 sym_link *retype = getSpec (operandType (right));
10280 sym_link *letype = getSpec (operandType (result));
10282 aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10284 /* if the operand is already in dptr
10285 then we do nothing else we move the value to dptr */
10286 if (AOP_TYPE (result) != AOP_STR)
10288 _startLazyDPSEvaluation ();
10289 /* if this is remateriazable */
10290 if (AOP_TYPE (result) == AOP_IMMD)
10292 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10293 if (AOP(result)->aopu.aop_immd.from_cast_remat)
10295 MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10300 "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10304 { /* we need to get it byte by byte */
10305 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10306 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10307 if (options.model == MODEL_FLAT24) {
10308 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10309 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10311 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10314 _endLazyDPSEvaluation ();
10316 /* so dptr + b now contains the address */
10318 aopOp (right, ic, FALSE, TRUE);
10322 /* if bit then unpack */
10323 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10325 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
10329 size = AOP_SIZE (right);
10332 _startLazyDPSEvaluation ();
10337 // Set two bytes at a time, passed in _AP & A.
10338 // dptr will be incremented ONCE by __gptrputWord.
10340 // Note: any change here must be coordinated
10341 // with the implementation of __gptrputWord
10342 // in device/lib/_gptrput.c
10343 emitcode("mov", "_ap, %s",
10344 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10345 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10349 emitcode ("lcall", "__gptrputWord");
10354 // Only one byte to put.
10355 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10359 emitcode ("lcall", "__gptrput");
10362 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10364 emitcode ("inc", "dptr");
10367 _endLazyDPSEvaluation ();
10370 if (pi && AOP_TYPE (result) != AOP_IMMD) {
10371 _startLazyDPSEvaluation ();
10373 aopPut (AOP(result),"dpl",0);
10374 aopPut (AOP(result),"dph",1);
10375 if (options.model == MODEL_FLAT24) {
10376 aopPut (AOP(result),"dpx",2);
10377 aopPut (AOP(result),"b",3);
10379 aopPut (AOP(result),"b",2);
10381 _endLazyDPSEvaluation ();
10384 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10385 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10387 size = AOP_SIZE (right) - 1;
10388 while (size--) emitcode ("lcall","__decdptr");
10390 freeAsmop (result, NULL, ic, TRUE);
10391 freeAsmop (right, NULL, ic, TRUE);
10394 /*-----------------------------------------------------------------*/
10395 /* genPointerSet - stores the value into a pointer location */
10396 /*-----------------------------------------------------------------*/
10398 genPointerSet (iCode * ic, iCode *pi)
10400 operand *right, *result;
10401 sym_link *type, *etype;
10404 D (emitcode (";", "genPointerSet "););
10406 right = IC_RIGHT (ic);
10407 result = IC_RESULT (ic);
10409 /* depending on the type of pointer we need to
10410 move it to the correct pointer register */
10411 type = operandType (result);
10412 etype = getSpec (type);
10413 /* if left is of type of pointer then it is simple */
10414 if (IS_PTR (type) && !IS_FUNC (type->next))
10416 p_type = DCL_TYPE (type);
10420 /* we have to go by the storage class */
10421 p_type = PTR_TYPE (SPEC_OCLS (etype));
10423 /* special case when cast remat */
10424 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10425 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10426 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10427 type = operandType (result);
10428 p_type = DCL_TYPE (type);
10431 /* now that we have the pointer type we assign
10432 the pointer values */
10438 genNearPointerSet (right, result, ic, pi);
10442 genPagedPointerSet (right, result, ic, pi);
10446 genFarPointerSet (right, result, ic, pi);
10450 genGenPointerSet (right, result, ic, pi);
10454 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10455 "genPointerSet: illegal pointer type");
10460 /*-----------------------------------------------------------------*/
10461 /* genIfx - generate code for Ifx statement */
10462 /*-----------------------------------------------------------------*/
10464 genIfx (iCode * ic, iCode * popIc)
10466 operand *cond = IC_COND (ic);
10469 D (emitcode (";", "genIfx "););
10471 aopOp (cond, ic, FALSE, FALSE);
10473 /* get the value into acc */
10474 if (AOP_TYPE (cond) != AOP_CRY)
10483 /* the result is now in the accumulator */
10484 freeAsmop (cond, NULL, ic, TRUE);
10486 /* if there was something to be popped then do it */
10490 /* if the condition is a bit variable */
10491 if (isbit && IS_ITEMP (cond) &&
10494 genIfxJump (ic, SPIL_LOC (cond)->rname);
10496 else if (isbit && !IS_ITEMP (cond))
10498 genIfxJump (ic, OP_SYMBOL (cond)->rname);
10502 genIfxJump (ic, "a");
10508 /*-----------------------------------------------------------------*/
10509 /* genAddrOf - generates code for address of */
10510 /*-----------------------------------------------------------------*/
10512 genAddrOf (iCode * ic)
10514 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10517 D (emitcode (";", "genAddrOf ");
10520 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10522 /* if the operand is on the stack then we
10523 need to get the stack offset of this
10525 if (sym->onStack) {
10527 /* if 10 bit stack */
10528 if (options.stack10bit) {
10532 tsprintf(buff, sizeof(buff),
10533 "#!constbyte",(options.stack_loc >> 16) & 0xff);
10534 /* if it has an offset then we need to compute it */
10535 /* emitcode ("subb", "a,#!constbyte", */
10536 /* -((sym->stack < 0) ? */
10537 /* ((short) (sym->stack - _G.nRegsSaved)) : */
10538 /* ((short) sym->stack)) & 0xff); */
10539 /* emitcode ("mov","b,a"); */
10540 /* emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
10541 /* ((short) (sym->stack - _G.nRegsSaved)) : */
10542 /* ((short) sym->stack)) >> 8) & 0xff); */
10544 emitcode ("mov", "a,_bpx");
10545 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
10546 ((char) (sym->stack - _G.nRegsSaved)) :
10547 ((char) sym->stack )) & 0xff);
10548 emitcode ("mov", "b,a");
10549 emitcode ("mov", "a,_bpx+1");
10551 offset = (((sym->stack < 0) ?
10552 ((short) (sym->stack - _G.nRegsSaved)) :
10553 ((short) sym->stack )) >> 8) & 0xff;
10555 emitcode ("addc","a,#!constbyte", offset);
10557 aopPut (AOP (IC_RESULT (ic)), "b", 0);
10558 aopPut (AOP (IC_RESULT (ic)), "a", 1);
10559 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10561 /* we can just move _bp */
10562 aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10563 aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10564 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10567 /* if it has an offset then we need to compute it */
10569 emitcode ("mov", "a,_bp");
10570 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10571 aopPut (AOP (IC_RESULT (ic)), "a", 0);
10573 /* we can just move _bp */
10574 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10576 /* fill the result with zero */
10577 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10580 if (options.stack10bit && size < (FPTRSIZE - 1)) {
10582 "*** warning: pointer to stack var truncated.\n");
10587 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10593 /* object not on stack then we need the name */
10594 size = AOP_SIZE (IC_RESULT (ic));
10599 char s[SDCC_NAME_MAX];
10603 tsprintf(s, sizeof(s), "#!his",sym->rname);
10606 tsprintf(s, sizeof(s), "#!hihis",sym->rname);
10609 tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
10611 default: /* should not need this (just in case) */
10612 SNPRINTF (s, sizeof(s), "#(%s >> %d)",
10619 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10622 aopPut (AOP (IC_RESULT (ic)), s, offset++);
10626 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10630 #if 0 // obsolete, and buggy for != xdata
10631 /*-----------------------------------------------------------------*/
10632 /* genArrayInit - generates code for address of */
10633 /*-----------------------------------------------------------------*/
10635 genArrayInit (iCode * ic)
10637 literalList *iLoop;
10639 int elementSize = 0, eIndex;
10640 unsigned val, lastVal;
10642 operand *left=IC_LEFT(ic);
10644 D (emitcode (";", "genArrayInit "););
10646 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10648 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10650 // Load immediate value into DPTR.
10651 emitcode("mov", "dptr, %s",
10652 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
10654 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10657 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10658 "Unexpected operand to genArrayInit.\n");
10661 // a regression because of SDCCcse.c:1.52
10662 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10663 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10664 if (options.model == MODEL_FLAT24)
10665 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10669 type = operandType(IC_LEFT(ic));
10671 if (type && type->next)
10673 elementSize = getSize(type->next);
10677 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10678 "can't determine element size in genArrayInit.\n");
10682 iLoop = IC_ARRAYILIST(ic);
10687 bool firstpass = TRUE;
10689 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
10690 iLoop->count, (int)iLoop->literalValue, elementSize);
10696 symbol *tlbl = NULL;
10698 count = ix > 256 ? 256 : ix;
10702 tlbl = newiTempLabel (NULL);
10703 if (firstpass || (count & 0xff))
10705 emitcode("mov", "b, #!constbyte", count & 0xff);
10708 emitcode ("", "!tlabeldef", tlbl->key + 100);
10713 for (eIndex = 0; eIndex < elementSize; eIndex++)
10715 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10716 if (val != lastVal)
10718 emitcode("mov", "a, #!constbyte", val);
10722 emitcode("movx", "@dptr, a");
10723 emitcode("inc", "dptr");
10728 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10734 iLoop = iLoop->next;
10737 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10741 /*-----------------------------------------------------------------*/
10742 /* genFarFarAssign - assignment when both are in far space */
10743 /*-----------------------------------------------------------------*/
10745 genFarFarAssign (operand * result, operand * right, iCode * ic)
10747 int size = AOP_SIZE (right);
10749 symbol *rSym = NULL;
10753 /* quick & easy case. */
10754 D(emitcode(";","genFarFarAssign (1 byte case)"););
10755 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
10756 freeAsmop (right, NULL, ic, FALSE);
10757 /* now assign DPTR to result */
10759 aopOp(result, ic, FALSE, FALSE);
10761 aopPut(AOP(result), "a", 0);
10762 freeAsmop(result, NULL, ic, FALSE);
10766 /* See if we've got an underlying symbol to abuse. */
10767 if (IS_SYMOP(result) && OP_SYMBOL(result))
10769 if (IS_TRUE_SYMOP(result))
10771 rSym = OP_SYMBOL(result);
10773 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10775 rSym = OP_SYMBOL(result)->usl.spillLoc;
10779 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10781 /* We can use the '390 auto-toggle feature to good effect here. */
10783 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10784 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
10785 emitcode ("mov", "dptr,#%s", rSym->rname);
10786 /* DP2 = result, DP1 = right, DP1 is current. */
10789 emitcode("movx", "a,@dptr");
10790 emitcode("movx", "@dptr,a");
10793 emitcode("inc", "dptr");
10794 emitcode("inc", "dptr");
10797 emitcode("mov", "dps,#0");
10798 freeAsmop (right, NULL, ic, FALSE);
10800 some alternative code for processors without auto-toggle
10801 no time to test now, so later well put in...kpb
10802 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10803 emitcode("mov", "dps,#1"); /* Select DPTR2. */
10804 emitcode ("mov", "dptr,#%s", rSym->rname);
10805 /* DP2 = result, DP1 = right, DP1 is current. */
10809 emitcode("movx", "a,@dptr");
10811 emitcode("inc", "dptr");
10812 emitcode("inc", "dps");
10813 emitcode("movx", "@dptr,a");
10815 emitcode("inc", "dptr");
10816 emitcode("inc", "dps");
10818 emitcode("mov", "dps,#0");
10819 freeAsmop (right, NULL, ic, FALSE);
10824 D (emitcode (";", "genFarFarAssign"););
10825 aopOp (result, ic, TRUE, TRUE);
10827 _startLazyDPSEvaluation ();
10831 aopPut (AOP (result),
10832 aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
10835 _endLazyDPSEvaluation ();
10836 freeAsmop (result, NULL, ic, FALSE);
10837 freeAsmop (right, NULL, ic, FALSE);
10841 /*-----------------------------------------------------------------*/
10842 /* genAssign - generate code for assignment */
10843 /*-----------------------------------------------------------------*/
10845 genAssign (iCode * ic)
10847 operand *result, *right;
10849 unsigned long lit = 0L;
10851 D (emitcode (";", "genAssign ");
10854 result = IC_RESULT (ic);
10855 right = IC_RIGHT (ic);
10857 /* if they are the same */
10858 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10861 aopOp (right, ic, FALSE, FALSE);
10863 emitcode (";", "genAssign: resultIsFar = %s",
10864 isOperandInFarSpace (result) ?
10867 /* special case both in far space */
10868 if ((AOP_TYPE (right) == AOP_DPTR ||
10869 AOP_TYPE (right) == AOP_DPTR2) &&
10870 /* IS_TRUE_SYMOP(result) && */
10871 isOperandInFarSpace (result))
10873 genFarFarAssign (result, right, ic);
10877 aopOp (result, ic, TRUE, FALSE);
10879 /* if they are the same registers */
10880 if (sameRegs (AOP (right), AOP (result)))
10883 /* if the result is a bit */
10884 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10886 /* if the right size is a literal then
10887 we know what the value is */
10888 if (AOP_TYPE (right) == AOP_LIT)
10890 if (((int) operandLitValue (right)))
10891 aopPut (AOP (result), one, 0);
10893 aopPut (AOP (result), zero, 0);
10897 /* the right is also a bit variable */
10898 if (AOP_TYPE (right) == AOP_CRY)
10900 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10901 aopPut (AOP (result), "c", 0);
10905 /* we need to or */
10907 aopPut (AOP (result), "a", 0);
10911 /* bit variables done */
10913 size = AOP_SIZE (result);
10915 if (AOP_TYPE (right) == AOP_LIT)
10916 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10919 (AOP_TYPE (result) != AOP_REG) &&
10920 (AOP_TYPE (right) == AOP_LIT) &&
10921 !IS_FLOAT (operandType (right)))
10923 _startLazyDPSEvaluation ();
10924 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10926 aopPut (AOP (result),
10927 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10932 /* And now fill the rest with zeros. */
10935 emitcode ("clr", "a");
10939 aopPut (AOP (result), "a", offset++);
10941 _endLazyDPSEvaluation ();
10945 _startLazyDPSEvaluation ();
10948 aopPut (AOP (result),
10949 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10953 _endLazyDPSEvaluation ();
10957 freeAsmop (right, NULL, ic, FALSE);
10958 freeAsmop (result, NULL, ic, TRUE);
10961 /*-----------------------------------------------------------------*/
10962 /* genJumpTab - generates code for jump table */
10963 /*-----------------------------------------------------------------*/
10965 genJumpTab (iCode * ic)
10970 D (emitcode (";", "genJumpTab ");
10973 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10974 /* get the condition into accumulator */
10975 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
10977 /* multiply by four! */
10978 emitcode ("add", "a,acc");
10979 emitcode ("add", "a,acc");
10980 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10982 jtab = newiTempLabel (NULL);
10983 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
10984 emitcode ("jmp", "@a+dptr");
10985 emitcode ("", "!tlabeldef", jtab->key + 100);
10986 /* now generate the jump labels */
10987 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10988 jtab = setNextItem (IC_JTLABELS (ic)))
10989 emitcode ("ljmp", "!tlabel", jtab->key + 100);
10993 /*-----------------------------------------------------------------*/
10994 /* genCast - gen code for casting */
10995 /*-----------------------------------------------------------------*/
10997 genCast (iCode * ic)
10999 operand *result = IC_RESULT (ic);
11000 sym_link *ctype = operandType (IC_LEFT (ic));
11001 sym_link *rtype = operandType (IC_RIGHT (ic));
11002 operand *right = IC_RIGHT (ic);
11005 D (emitcode (";", "genCast "););
11007 /* if they are equivalent then do nothing */
11008 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11011 aopOp (right, ic, FALSE, FALSE);
11012 aopOp (result, ic, FALSE, AOP_USESDPTR(right));
11014 /* if the result is a bit */
11015 if (IS_BITVAR (OP_SYMBOL (result)->type)
11016 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
11018 /* if the right size is a literal then
11019 we know what the value is */
11020 if (AOP_TYPE (right) == AOP_LIT)
11022 if (((int) operandLitValue (right)))
11023 aopPut (AOP (result), one, 0);
11025 aopPut (AOP (result), zero, 0);
11030 /* the right is also a bit variable */
11031 if (AOP_TYPE (right) == AOP_CRY)
11033 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11034 aopPut (AOP (result), "c", 0);
11038 /* we need to or */
11040 aopPut (AOP (result), "a", 0);
11044 /* if they are the same size : or less */
11045 if (AOP_SIZE (result) <= AOP_SIZE (right))
11048 /* if they are in the same place */
11049 if (sameRegs (AOP (right), AOP (result)))
11052 /* if they in different places then copy */
11053 size = AOP_SIZE (result);
11055 _startLazyDPSEvaluation ();
11058 aopPut (AOP (result),
11059 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11063 _endLazyDPSEvaluation ();
11068 /* if the result is of type pointer */
11069 if (IS_PTR (ctype))
11073 sym_link *type = operandType (right);
11075 /* pointer to generic pointer */
11076 if (IS_GENPTR (ctype))
11080 p_type = DCL_TYPE (type);
11084 #if OLD_CAST_BEHAVIOR
11085 /* KV: we are converting a non-pointer type to
11086 * a generic pointer. This (ifdef'd out) code
11087 * says that the resulting generic pointer
11088 * should have the same class as the storage
11089 * location of the non-pointer variable.
11091 * For example, converting an int (which happens
11092 * to be stored in DATA space) to a pointer results
11093 * in a DATA generic pointer; if the original int
11094 * in XDATA space, so will be the resulting pointer.
11096 * I don't like that behavior, and thus this change:
11097 * all such conversions will be forced to XDATA and
11098 * throw a warning. If you want some non-XDATA
11099 * type, or you want to suppress the warning, you
11100 * must go through an intermediate cast, like so:
11102 * char _generic *gp = (char _xdata *)(intVar);
11104 sym_link *etype = getSpec (type);
11106 /* we have to go by the storage class */
11107 if (SPEC_OCLS (etype) != generic)
11109 p_type = PTR_TYPE (SPEC_OCLS (etype));
11114 /* Converting unknown class (i.e. register variable)
11115 * to generic pointer. This is not good, but
11116 * we'll make a guess (and throw a warning).
11119 werror (W_INT_TO_GEN_PTR_CAST);
11123 /* the first two bytes are known */
11124 size = GPTRSIZE - 1;
11126 _startLazyDPSEvaluation ();
11129 aopPut (AOP (result),
11130 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11134 _endLazyDPSEvaluation ();
11136 /* the last byte depending on type */
11138 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11143 // pointerTypeToGPByte will have bitched.
11147 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11148 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11153 /* just copy the pointers */
11154 size = AOP_SIZE (result);
11156 _startLazyDPSEvaluation ();
11159 aopPut (AOP (result),
11160 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11164 _endLazyDPSEvaluation ();
11168 /* so we now know that the size of destination is greater
11169 than the size of the source */
11170 /* we move to result for the size of source */
11171 size = AOP_SIZE (right);
11173 _startLazyDPSEvaluation ();
11176 aopPut (AOP (result),
11177 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11181 _endLazyDPSEvaluation ();
11183 /* now depending on the sign of the source && destination */
11184 size = AOP_SIZE (result) - AOP_SIZE (right);
11185 /* if unsigned or not an integral type */
11186 /* also, if the source is a bit, we don't need to sign extend, because
11187 * it can't possibly have set the sign bit.
11189 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
11193 aopPut (AOP (result), zero, offset++);
11198 /* we need to extend the sign :{ */
11199 MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11200 FALSE, FALSE, NULL));
11201 emitcode ("rlc", "a");
11202 emitcode ("subb", "a,acc");
11204 aopPut (AOP (result), "a", offset++);
11207 /* we are done hurray !!!! */
11210 freeAsmop (right, NULL, ic, TRUE);
11211 freeAsmop (result, NULL, ic, TRUE);
11215 /*-----------------------------------------------------------------*/
11216 /* genDjnz - generate decrement & jump if not zero instrucion */
11217 /*-----------------------------------------------------------------*/
11219 genDjnz (iCode * ic, iCode * ifx)
11221 symbol *lbl, *lbl1;
11225 /* if the if condition has a false label
11226 then we cannot save */
11227 if (IC_FALSE (ifx))
11230 /* if the minus is not of the form
11232 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11233 !IS_OP_LITERAL (IC_RIGHT (ic)))
11236 if (operandLitValue (IC_RIGHT (ic)) != 1)
11239 /* if the size of this greater than one then no
11241 if (getSize (operandType (IC_RESULT (ic))) > 1)
11244 /* otherwise we can save BIG */
11245 D(emitcode(";", "genDjnz"););
11247 lbl = newiTempLabel (NULL);
11248 lbl1 = newiTempLabel (NULL);
11250 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11252 if (AOP_NEEDSACC(IC_RESULT(ic)))
11254 /* If the result is accessed indirectly via
11255 * the accumulator, we must explicitly write
11256 * it back after the decrement.
11258 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11260 if (strcmp(rByte, "a"))
11262 /* Something is hopelessly wrong */
11263 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11264 __FILE__, __LINE__);
11265 /* We can just give up; the generated code will be inefficient,
11266 * but what the hey.
11268 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11271 emitcode ("dec", "%s", rByte);
11272 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11273 emitcode ("jnz", "!tlabel", lbl->key + 100);
11275 else if (IS_AOP_PREG (IC_RESULT (ic)))
11277 emitcode ("dec", "%s",
11278 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11279 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11280 emitcode ("jnz", "!tlabel", lbl->key + 100);
11284 emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11287 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11288 emitcode ("", "!tlabeldef", lbl->key + 100);
11289 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11290 emitcode ("", "!tlabeldef", lbl1->key + 100);
11292 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11293 ifx->generated = 1;
11297 /*-----------------------------------------------------------------*/
11298 /* genReceive - generate code for a receive iCode */
11299 /*-----------------------------------------------------------------*/
11301 genReceive (iCode * ic)
11303 int size = getSize (operandType (IC_RESULT (ic)));
11307 D (emitcode (";", "genReceive "););
11309 if (ic->argreg == 1)
11311 /* first parameter */
11312 if (AOP_IS_STR(IC_RESULT(ic)))
11314 /* Nothing to do: it's already in the proper place. */
11321 useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11322 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11323 IS_TRUE_SYMOP (IC_RESULT (ic)));
11326 aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11329 /* Sanity checking... */
11330 if (AOP_USESDPTR(IC_RESULT(ic)))
11332 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11333 "genReceive got unexpected DPTR.");
11335 assignResultValue (IC_RESULT (ic));
11340 /* second receive onwards */
11341 /* this gets a little tricky since unused recevies will be
11342 eliminated, we have saved the reg in the type field . and
11343 we use that to figure out which register to use */
11344 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11345 rb1off = ic->argreg;
11348 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11351 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11354 /*-----------------------------------------------------------------*/
11355 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
11356 /*-----------------------------------------------------------------*/
11357 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11359 operand *from , *to , *count;
11364 /* we know it has to be 3 parameters */
11365 assert (nparms == 3);
11367 rsave = newBitVect(16);
11368 /* save DPTR if it needs to be saved */
11369 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11370 if (bitVectBitValue(ic->rMask,i))
11371 rsave = bitVectSetBit(rsave,i);
11373 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11374 ds390_rUmaskForOp (IC_RESULT(ic))));
11381 aopOp (from, ic->next, FALSE, FALSE);
11383 /* get from into DPTR1 */
11384 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11385 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11386 if (options.model == MODEL_FLAT24) {
11387 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11390 freeAsmop (from, NULL, ic, FALSE);
11391 aopOp (to, ic, FALSE, FALSE);
11392 /* get "to" into DPTR */
11393 /* if the operand is already in dptr
11394 then we do nothing else we move the value to dptr */
11395 if (AOP_TYPE (to) != AOP_STR) {
11396 /* if already in DPTR then we need to push */
11397 if (AOP_TYPE(to) == AOP_DPTR) {
11398 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11399 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11400 if (options.model == MODEL_FLAT24)
11401 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11402 emitcode ("pop", "dph");
11403 emitcode ("pop", "dpl");
11405 _startLazyDPSEvaluation ();
11406 /* if this is remateriazable */
11407 if (AOP_TYPE (to) == AOP_IMMD) {
11408 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11409 } else { /* we need to get it byte by byte */
11410 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11411 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11412 if (options.model == MODEL_FLAT24) {
11413 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11416 _endLazyDPSEvaluation ();
11419 freeAsmop (to, NULL, ic, FALSE);
11420 _G.dptrInUse = _G.dptr1InUse = 1;
11421 aopOp (count, ic->next->next, FALSE,FALSE);
11422 lbl =newiTempLabel(NULL);
11424 /* now for the actual copy */
11425 if (AOP_TYPE(count) == AOP_LIT &&
11426 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11427 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11429 emitcode ("lcall","__bi_memcpyc2x_s");
11431 emitcode ("lcall","__bi_memcpyx2x_s");
11433 freeAsmop (count, NULL, ic, FALSE);
11435 symbol *lbl1 = newiTempLabel(NULL);
11437 emitcode (";"," Auto increment but no djnz");
11438 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11439 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11440 freeAsmop (count, NULL, ic, FALSE);
11441 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11442 emitcode ("","!tlabeldef",lbl->key+100);
11444 emitcode ("clr","a");
11445 emitcode ("movc", "a,@a+dptr");
11447 emitcode ("movx", "a,@dptr");
11448 emitcode ("movx", "@dptr,a");
11449 emitcode ("inc", "dptr");
11450 emitcode ("inc", "dptr");
11451 emitcode ("mov","a,b");
11452 emitcode ("orl","a,_ap");
11453 emitcode ("jz","!tlabel",lbl1->key+100);
11454 emitcode ("mov","a,_ap");
11455 emitcode ("add","a,#!constbyte",0xFF);
11456 emitcode ("mov","_ap,a");
11457 emitcode ("mov","a,b");
11458 emitcode ("addc","a,#!constbyte",0xFF);
11459 emitcode ("mov","b,a");
11460 emitcode ("sjmp","!tlabel",lbl->key+100);
11461 emitcode ("","!tlabeldef",lbl1->key+100);
11463 emitcode ("mov", "dps,#0");
11464 _G.dptrInUse = _G.dptr1InUse = 0;
11465 unsavermask(rsave);
11469 /*-----------------------------------------------------------------*/
11470 /* genMemcmpX2X - gen code for memcmp xdata to xdata */
11471 /*-----------------------------------------------------------------*/
11472 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11474 operand *from , *to , *count;
11479 /* we know it has to be 3 parameters */
11480 assert (nparms == 3);
11482 rsave = newBitVect(16);
11483 /* save DPTR if it needs to be saved */
11484 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11485 if (bitVectBitValue(ic->rMask,i))
11486 rsave = bitVectSetBit(rsave,i);
11488 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11489 ds390_rUmaskForOp (IC_RESULT(ic))));
11496 aopOp (from, ic->next, FALSE, FALSE);
11498 /* get from into DPTR1 */
11499 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11500 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11501 if (options.model == MODEL_FLAT24) {
11502 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11505 freeAsmop (from, NULL, ic, FALSE);
11506 aopOp (to, ic, FALSE, FALSE);
11507 /* get "to" into DPTR */
11508 /* if the operand is already in dptr
11509 then we do nothing else we move the value to dptr */
11510 if (AOP_TYPE (to) != AOP_STR) {
11511 /* if already in DPTR then we need to push */
11512 if (AOP_TYPE(to) == AOP_DPTR) {
11513 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11514 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11515 if (options.model == MODEL_FLAT24)
11516 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11517 emitcode ("pop", "dph");
11518 emitcode ("pop", "dpl");
11520 _startLazyDPSEvaluation ();
11521 /* if this is remateriazable */
11522 if (AOP_TYPE (to) == AOP_IMMD) {
11523 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11524 } else { /* we need to get it byte by byte */
11525 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11526 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11527 if (options.model == MODEL_FLAT24) {
11528 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11531 _endLazyDPSEvaluation ();
11534 freeAsmop (to, NULL, ic, FALSE);
11535 _G.dptrInUse = _G.dptr1InUse = 1;
11536 aopOp (count, ic->next->next, FALSE,FALSE);
11537 lbl =newiTempLabel(NULL);
11538 lbl2 =newiTempLabel(NULL);
11540 /* now for the actual compare */
11541 if (AOP_TYPE(count) == AOP_LIT &&
11542 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11543 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11545 emitcode("lcall","__bi_memcmpc2x_s");
11547 emitcode("lcall","__bi_memcmpx2x_s");
11548 freeAsmop (count, NULL, ic, FALSE);
11549 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11550 aopPut(AOP(IC_RESULT(ic)),"a",0);
11551 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11553 symbol *lbl1 = newiTempLabel(NULL);
11555 emitcode("push","ar0");
11556 emitcode (";"," Auto increment but no djnz");
11557 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11558 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11559 freeAsmop (count, NULL, ic, FALSE);
11560 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11561 emitcode ("","!tlabeldef",lbl->key+100);
11563 emitcode ("clr","a");
11564 emitcode ("movc", "a,@a+dptr");
11566 emitcode ("movx", "a,@dptr");
11567 emitcode ("mov","r0,a");
11568 emitcode ("movx", "a,@dptr");
11569 emitcode ("clr","c");
11570 emitcode ("subb","a,r0");
11571 emitcode ("jnz","!tlabel",lbl2->key+100);
11572 emitcode ("inc", "dptr");
11573 emitcode ("inc", "dptr");
11574 emitcode ("mov","a,b");
11575 emitcode ("orl","a,_ap");
11576 emitcode ("jz","!tlabel",lbl1->key+100);
11577 emitcode ("mov","a,_ap");
11578 emitcode ("add","a,#!constbyte",0xFF);
11579 emitcode ("mov","_ap,a");
11580 emitcode ("mov","a,b");
11581 emitcode ("addc","a,#!constbyte",0xFF);
11582 emitcode ("mov","b,a");
11583 emitcode ("sjmp","!tlabel",lbl->key+100);
11584 emitcode ("","!tlabeldef",lbl1->key+100);
11585 emitcode ("clr","a");
11586 emitcode ("","!tlabeldef",lbl2->key+100);
11587 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11588 aopPut(AOP(IC_RESULT(ic)),"a",0);
11589 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11590 emitcode("pop","ar0");
11591 emitcode ("mov", "dps,#0");
11593 _G.dptrInUse = _G.dptr1InUse = 0;
11594 unsavermask(rsave);
11598 /*-----------------------------------------------------------------*/
11599 /* genInp - gen code for __builtin_inp read data from a mem mapped */
11600 /* port, first parameter output area second parameter pointer to */
11601 /* port third parameter count */
11602 /*-----------------------------------------------------------------*/
11603 static void genInp( iCode *ic, int nparms, operand **parms)
11605 operand *from , *to , *count;
11610 /* we know it has to be 3 parameters */
11611 assert (nparms == 3);
11613 rsave = newBitVect(16);
11614 /* save DPTR if it needs to be saved */
11615 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11616 if (bitVectBitValue(ic->rMask,i))
11617 rsave = bitVectSetBit(rsave,i);
11619 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11620 ds390_rUmaskForOp (IC_RESULT(ic))));
11627 aopOp (from, ic->next, FALSE, FALSE);
11629 /* get from into DPTR1 */
11630 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11631 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11632 if (options.model == MODEL_FLAT24) {
11633 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11636 freeAsmop (from, NULL, ic, FALSE);
11637 aopOp (to, ic, FALSE, FALSE);
11638 /* get "to" into DPTR */
11639 /* if the operand is already in dptr
11640 then we do nothing else we move the value to dptr */
11641 if (AOP_TYPE (to) != AOP_STR) {
11642 /* if already in DPTR then we need to push */
11643 if (AOP_TYPE(to) == AOP_DPTR) {
11644 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11645 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11646 if (options.model == MODEL_FLAT24)
11647 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11648 emitcode ("pop", "dph");
11649 emitcode ("pop", "dpl");
11651 _startLazyDPSEvaluation ();
11652 /* if this is remateriazable */
11653 if (AOP_TYPE (to) == AOP_IMMD) {
11654 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11655 } else { /* we need to get it byte by byte */
11656 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11657 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11658 if (options.model == MODEL_FLAT24) {
11659 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11662 _endLazyDPSEvaluation ();
11665 freeAsmop (to, NULL, ic, FALSE);
11667 _G.dptrInUse = _G.dptr1InUse = 1;
11668 aopOp (count, ic->next->next, FALSE,FALSE);
11669 lbl =newiTempLabel(NULL);
11671 /* now for the actual copy */
11672 if (AOP_TYPE(count) == AOP_LIT &&
11673 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11674 emitcode (";","OH JOY auto increment with djnz (very fast)");
11675 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11676 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11677 freeAsmop (count, NULL, ic, FALSE);
11678 emitcode ("","!tlabeldef",lbl->key+100);
11679 emitcode ("movx", "a,@dptr"); /* read data from port */
11680 emitcode ("dec","dps"); /* switch to DPTR */
11681 emitcode ("movx", "@dptr,a"); /* save into location */
11682 emitcode ("inc", "dptr"); /* point to next area */
11683 emitcode ("inc","dps"); /* switch to DPTR2 */
11684 emitcode ("djnz","b,!tlabel",lbl->key+100);
11686 symbol *lbl1 = newiTempLabel(NULL);
11688 emitcode (";"," Auto increment but no djnz");
11689 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11690 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11691 freeAsmop (count, NULL, ic, FALSE);
11692 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11693 emitcode ("","!tlabeldef",lbl->key+100);
11694 emitcode ("movx", "a,@dptr");
11695 emitcode ("dec","dps"); /* switch to DPTR */
11696 emitcode ("movx", "@dptr,a");
11697 emitcode ("inc", "dptr");
11698 emitcode ("inc","dps"); /* switch to DPTR2 */
11699 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
11700 /* emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
11701 emitcode ("mov","a,b");
11702 emitcode ("orl","a,_ap");
11703 emitcode ("jz","!tlabel",lbl1->key+100);
11704 emitcode ("mov","a,_ap");
11705 emitcode ("add","a,#!constbyte",0xFF);
11706 emitcode ("mov","_ap,a");
11707 emitcode ("mov","a,b");
11708 emitcode ("addc","a,#!constbyte",0xFF);
11709 emitcode ("mov","b,a");
11710 emitcode ("sjmp","!tlabel",lbl->key+100);
11711 emitcode ("","!tlabeldef",lbl1->key+100);
11713 emitcode ("mov", "dps,#0");
11714 _G.dptrInUse = _G.dptr1InUse = 0;
11715 unsavermask(rsave);
11719 /*-----------------------------------------------------------------*/
11720 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
11721 /* port, first parameter output area second parameter pointer to */
11722 /* port third parameter count */
11723 /*-----------------------------------------------------------------*/
11724 static void genOutp( iCode *ic, int nparms, operand **parms)
11726 operand *from , *to , *count;
11731 /* we know it has to be 3 parameters */
11732 assert (nparms == 3);
11734 rsave = newBitVect(16);
11735 /* save DPTR if it needs to be saved */
11736 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11737 if (bitVectBitValue(ic->rMask,i))
11738 rsave = bitVectSetBit(rsave,i);
11740 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11741 ds390_rUmaskForOp (IC_RESULT(ic))));
11748 aopOp (from, ic->next, FALSE, FALSE);
11750 /* get from into DPTR1 */
11751 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11752 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11753 if (options.model == MODEL_FLAT24) {
11754 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11757 freeAsmop (from, NULL, ic, FALSE);
11758 aopOp (to, ic, FALSE, FALSE);
11759 /* get "to" into DPTR */
11760 /* if the operand is already in dptr
11761 then we do nothing else we move the value to dptr */
11762 if (AOP_TYPE (to) != AOP_STR) {
11763 /* if already in DPTR then we need to push */
11764 if (AOP_TYPE(to) == AOP_DPTR) {
11765 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11766 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11767 if (options.model == MODEL_FLAT24)
11768 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11769 emitcode ("pop", "dph");
11770 emitcode ("pop", "dpl");
11772 _startLazyDPSEvaluation ();
11773 /* if this is remateriazable */
11774 if (AOP_TYPE (to) == AOP_IMMD) {
11775 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11776 } else { /* we need to get it byte by byte */
11777 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11778 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11779 if (options.model == MODEL_FLAT24) {
11780 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11783 _endLazyDPSEvaluation ();
11786 freeAsmop (to, NULL, ic, FALSE);
11788 _G.dptrInUse = _G.dptr1InUse = 1;
11789 aopOp (count, ic->next->next, FALSE,FALSE);
11790 lbl =newiTempLabel(NULL);
11792 /* now for the actual copy */
11793 if (AOP_TYPE(count) == AOP_LIT &&
11794 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11795 emitcode (";","OH JOY auto increment with djnz (very fast)");
11796 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
11797 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11798 emitcode ("","!tlabeldef",lbl->key+100);
11799 emitcode ("movx", "a,@dptr"); /* read data from port */
11800 emitcode ("inc","dps"); /* switch to DPTR2 */
11801 emitcode ("movx", "@dptr,a"); /* save into location */
11802 emitcode ("inc", "dptr"); /* point to next area */
11803 emitcode ("dec","dps"); /* switch to DPTR */
11804 emitcode ("djnz","b,!tlabel",lbl->key+100);
11805 freeAsmop (count, NULL, ic, FALSE);
11807 symbol *lbl1 = newiTempLabel(NULL);
11809 emitcode (";"," Auto increment but no djnz");
11810 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11811 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11812 freeAsmop (count, NULL, ic, FALSE);
11813 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
11814 emitcode ("","!tlabeldef",lbl->key+100);
11815 emitcode ("movx", "a,@dptr");
11816 emitcode ("inc", "dptr");
11817 emitcode ("inc","dps"); /* switch to DPTR2 */
11818 emitcode ("movx", "@dptr,a");
11819 emitcode ("dec","dps"); /* switch to DPTR */
11820 emitcode ("mov","a,b");
11821 emitcode ("orl","a,_ap");
11822 emitcode ("jz","!tlabel",lbl1->key+100);
11823 emitcode ("mov","a,_ap");
11824 emitcode ("add","a,#!constbyte",0xFF);
11825 emitcode ("mov","_ap,a");
11826 emitcode ("mov","a,b");
11827 emitcode ("addc","a,#!constbyte",0xFF);
11828 emitcode ("mov","b,a");
11829 emitcode ("sjmp","!tlabel",lbl->key+100);
11830 emitcode ("","!tlabeldef",lbl1->key+100);
11832 emitcode ("mov", "dps,#0");
11833 _G.dptrInUse = _G.dptr1InUse = 0;
11834 unsavermask(rsave);
11838 /*-----------------------------------------------------------------*/
11839 /* genSwapW - swap lower & high order bytes */
11840 /*-----------------------------------------------------------------*/
11841 static void genSwapW(iCode *ic, int nparms, operand **parms)
11845 assert (nparms==1);
11848 dest=IC_RESULT(ic);
11850 assert(getSize(operandType(src))==2);
11852 aopOp (src, ic, FALSE, FALSE);
11853 emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
11855 MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
11857 freeAsmop (src, NULL, ic, FALSE);
11859 aopOp (dest,ic, FALSE, FALSE);
11860 aopPut(AOP(dest),"b",0);
11861 aopPut(AOP(dest),"a",1);
11862 freeAsmop (dest, NULL, ic, FALSE);
11865 /*-----------------------------------------------------------------*/
11866 /* genMemsetX - gencode for memSetX data */
11867 /*-----------------------------------------------------------------*/
11868 static void genMemsetX(iCode *ic, int nparms, operand **parms)
11870 operand *to , *val , *count;
11876 /* we know it has to be 3 parameters */
11877 assert (nparms == 3);
11883 /* save DPTR if it needs to be saved */
11884 rsave = newBitVect(16);
11885 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11886 if (bitVectBitValue(ic->rMask,i))
11887 rsave = bitVectSetBit(rsave,i);
11889 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11890 ds390_rUmaskForOp (IC_RESULT(ic))));
11893 aopOp (to, ic, FALSE, FALSE);
11894 /* get "to" into DPTR */
11895 /* if the operand is already in dptr
11896 then we do nothing else we move the value to dptr */
11897 if (AOP_TYPE (to) != AOP_STR) {
11898 /* if already in DPTR then we need to push */
11899 if (AOP_TYPE(to) == AOP_DPTR) {
11900 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11901 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11902 if (options.model == MODEL_FLAT24)
11903 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11904 emitcode ("pop", "dph");
11905 emitcode ("pop", "dpl");
11907 _startLazyDPSEvaluation ();
11908 /* if this is remateriazable */
11909 if (AOP_TYPE (to) == AOP_IMMD) {
11910 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11911 } else { /* we need to get it byte by byte */
11912 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11913 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11914 if (options.model == MODEL_FLAT24) {
11915 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11918 _endLazyDPSEvaluation ();
11921 freeAsmop (to, NULL, ic, FALSE);
11923 aopOp (val, ic->next->next, FALSE,FALSE);
11924 aopOp (count, ic->next->next, FALSE,FALSE);
11925 lbl =newiTempLabel(NULL);
11926 /* now for the actual copy */
11927 if (AOP_TYPE(count) == AOP_LIT &&
11928 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11929 l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
11930 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11932 emitcode ("","!tlabeldef",lbl->key+100);
11933 emitcode ("movx", "@dptr,a");
11934 emitcode ("inc", "dptr");
11935 emitcode ("djnz","b,!tlabel",lbl->key+100);
11937 symbol *lbl1 = newiTempLabel(NULL);
11939 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11940 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11941 emitcode ("","!tlabeldef",lbl->key+100);
11942 MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
11943 emitcode ("movx", "@dptr,a");
11944 emitcode ("inc", "dptr");
11945 emitcode ("mov","a,b");
11946 emitcode ("orl","a,_ap");
11947 emitcode ("jz","!tlabel",lbl1->key+100);
11948 emitcode ("mov","a,_ap");
11949 emitcode ("add","a,#!constbyte",0xFF);
11950 emitcode ("mov","_ap,a");
11951 emitcode ("mov","a,b");
11952 emitcode ("addc","a,#!constbyte",0xFF);
11953 emitcode ("mov","b,a");
11954 emitcode ("sjmp","!tlabel",lbl->key+100);
11955 emitcode ("","!tlabeldef",lbl1->key+100);
11957 freeAsmop (count, NULL, ic, FALSE);
11958 unsavermask(rsave);
11961 /*-----------------------------------------------------------------*/
11962 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
11963 /*-----------------------------------------------------------------*/
11964 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
11967 operand *pnum, *result;
11970 assert (nparms==1);
11971 /* save registers that need to be saved */
11972 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11973 ds390_rUmaskForOp (IC_RESULT(ic))));
11976 aopOp (pnum, ic, FALSE, FALSE);
11977 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
11978 freeAsmop (pnum, NULL, ic, FALSE);
11979 emitcode ("lcall","NatLib_LoadPrimitive");
11980 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11981 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
11982 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
11983 for (i = (size-1) ; i >= 0 ; i-- ) {
11984 emitcode ("push","a%s",javaRet[i]);
11986 for (i=0; i < size ; i++ ) {
11987 emitcode ("pop","a%s",
11988 aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
11991 for (i = 0 ; i < size ; i++ ) {
11992 aopPut(AOP(result),javaRet[i],i);
11995 freeAsmop (result, NULL, ic, FALSE);
11996 unsavermask(rsave);
11999 /*-----------------------------------------------------------------*/
12000 /* genNatLibLoadPointer - calls TINI api function to load pointer */
12001 /*-----------------------------------------------------------------*/
12002 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
12005 operand *pnum, *result;
12009 assert (nparms==1);
12010 /* save registers that need to be saved */
12011 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12012 ds390_rUmaskForOp (IC_RESULT(ic))));
12015 aopOp (pnum, ic, FALSE, FALSE);
12016 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12017 freeAsmop (pnum, NULL, ic, FALSE);
12018 emitcode ("lcall","NatLib_LoadPointer");
12019 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12020 if (AOP_TYPE(result)!=AOP_STR) {
12021 for (i = 0 ; i < size ; i++ ) {
12022 aopPut(AOP(result),fReturn[i],i);
12025 freeAsmop (result, NULL, ic, FALSE);
12026 unsavermask(rsave);
12029 /*-----------------------------------------------------------------*/
12030 /* genNatLibInstallStateBlock - */
12031 /*-----------------------------------------------------------------*/
12032 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
12033 operand **parms, const char *name)
12036 operand *psb, *handle;
12037 assert (nparms==2);
12039 /* save registers that need to be saved */
12040 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12041 ds390_rUmaskForOp (IC_RESULT(ic))));
12045 /* put pointer to state block into DPTR1 */
12046 aopOp (psb, ic, FALSE, FALSE);
12047 if (AOP_TYPE (psb) == AOP_IMMD) {
12048 emitcode ("mov","dps,#1");
12049 emitcode ("mov", "dptr,%s",
12050 aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12051 emitcode ("mov","dps,#0");
12053 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12054 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12055 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12057 freeAsmop (psb, NULL, ic, FALSE);
12059 /* put libraryID into DPTR */
12060 emitcode ("mov","dptr,#LibraryID");
12062 /* put handle into r3:r2 */
12063 aopOp (handle, ic, FALSE, FALSE);
12064 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12065 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12066 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12067 emitcode ("pop","ar3");
12068 emitcode ("pop","ar2");
12070 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12071 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12073 freeAsmop (psb, NULL, ic, FALSE);
12075 /* make the call */
12076 emitcode ("lcall","NatLib_Install%sStateBlock",name);
12078 /* put return value into place*/
12080 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12082 aopPut(AOP(IC_RESULT(ic)),"a",0);
12083 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12084 unsavermask(rsave);
12087 /*-----------------------------------------------------------------*/
12088 /* genNatLibRemoveStateBlock - */
12089 /*-----------------------------------------------------------------*/
12090 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12096 /* save registers that need to be saved */
12097 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12098 ds390_rUmaskForOp (IC_RESULT(ic))));
12100 /* put libraryID into DPTR */
12101 emitcode ("mov","dptr,#LibraryID");
12102 /* make the call */
12103 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12104 unsavermask(rsave);
12107 /*-----------------------------------------------------------------*/
12108 /* genNatLibGetStateBlock - */
12109 /*-----------------------------------------------------------------*/
12110 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12111 operand **parms,const char *name)
12114 symbol *lbl = newiTempLabel(NULL);
12117 /* save registers that need to be saved */
12118 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12119 ds390_rUmaskForOp (IC_RESULT(ic))));
12121 /* put libraryID into DPTR */
12122 emitcode ("mov","dptr,#LibraryID");
12123 /* make the call */
12124 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12125 emitcode ("jnz","!tlabel",lbl->key+100);
12127 /* put return value into place */
12128 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12129 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12130 emitcode ("push","ar3");
12131 emitcode ("push","ar2");
12132 emitcode ("pop","%s",
12133 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12134 emitcode ("pop","%s",
12135 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12137 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12138 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12140 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12141 emitcode ("","!tlabeldef",lbl->key+100);
12142 unsavermask(rsave);
12145 /*-----------------------------------------------------------------*/
12146 /* genMMMalloc - */
12147 /*-----------------------------------------------------------------*/
12148 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12149 int size, const char *name)
12154 symbol *lbl = newiTempLabel(NULL);
12156 assert (nparms == 1);
12157 /* save registers that need to be saved */
12158 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12159 ds390_rUmaskForOp (IC_RESULT(ic))));
12162 aopOp (bsize,ic,FALSE,FALSE);
12164 /* put the size in R4-R2 */
12165 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12166 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12167 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12169 emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12170 emitcode("pop","ar4");
12172 emitcode("pop","ar3");
12173 emitcode("pop","ar2");
12175 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12176 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12178 emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12181 freeAsmop (bsize, NULL, ic, FALSE);
12183 /* make the call */
12184 emitcode ("lcall","MM_%s",name);
12185 emitcode ("jz","!tlabel",lbl->key+100);
12186 emitcode ("mov","r2,#!constbyte",0xff);
12187 emitcode ("mov","r3,#!constbyte",0xff);
12188 emitcode ("","!tlabeldef",lbl->key+100);
12189 /* we don't care about the pointer : we just save the handle */
12190 rsym = OP_SYMBOL(IC_RESULT(ic));
12191 if (rsym->liveFrom != rsym->liveTo) {
12192 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12193 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12194 emitcode ("push","ar3");
12195 emitcode ("push","ar2");
12196 emitcode ("pop","%s",
12197 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12198 emitcode ("pop","%s",
12199 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12201 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12202 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12204 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12206 unsavermask(rsave);
12209 /*-----------------------------------------------------------------*/
12211 /*-----------------------------------------------------------------*/
12212 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12217 assert (nparms == 1);
12218 /* save registers that need to be saved */
12219 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12220 ds390_rUmaskForOp (IC_RESULT(ic))));
12223 aopOp (handle,ic,FALSE,FALSE);
12225 /* put the size in R4-R2 */
12226 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12227 emitcode("push","%s",
12228 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12229 emitcode("push","%s",
12230 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12231 emitcode("pop","ar3");
12232 emitcode("pop","ar2");
12234 emitcode ("mov","r2,%s",
12235 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12236 emitcode ("mov","r3,%s",
12237 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12239 freeAsmop (handle, NULL, ic, FALSE);
12241 /* make the call */
12242 emitcode ("lcall","MM_Deref");
12245 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12246 if (rsym->liveFrom != rsym->liveTo) {
12247 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12248 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12249 _startLazyDPSEvaluation ();
12251 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12252 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12253 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12255 _endLazyDPSEvaluation ();
12260 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12261 unsavermask(rsave);
12264 /*-----------------------------------------------------------------*/
12265 /* genMMUnrestrictedPersist - */
12266 /*-----------------------------------------------------------------*/
12267 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12272 assert (nparms == 1);
12273 /* save registers that need to be saved */
12274 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12275 ds390_rUmaskForOp (IC_RESULT(ic))));
12278 aopOp (handle,ic,FALSE,FALSE);
12280 /* put the size in R3-R2 */
12281 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12282 emitcode("push","%s",
12283 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12284 emitcode("push","%s",
12285 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12286 emitcode("pop","ar3");
12287 emitcode("pop","ar2");
12289 emitcode ("mov","r2,%s",
12290 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12291 emitcode ("mov","r3,%s",
12292 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12294 freeAsmop (handle, NULL, ic, FALSE);
12296 /* make the call */
12297 emitcode ("lcall","MM_UnrestrictedPersist");
12300 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12301 if (rsym->liveFrom != rsym->liveTo) {
12302 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12303 aopPut(AOP(IC_RESULT(ic)),"a",0);
12304 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12307 unsavermask(rsave);
12310 /*-----------------------------------------------------------------*/
12311 /* genSystemExecJavaProcess - */
12312 /*-----------------------------------------------------------------*/
12313 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12316 operand *handle, *pp;
12318 assert (nparms==2);
12319 /* save registers that need to be saved */
12320 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12321 ds390_rUmaskForOp (IC_RESULT(ic))));
12326 /* put the handle in R3-R2 */
12327 aopOp (handle,ic,FALSE,FALSE);
12328 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12329 emitcode("push","%s",
12330 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12331 emitcode("push","%s",
12332 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12333 emitcode("pop","ar3");
12334 emitcode("pop","ar2");
12336 emitcode ("mov","r2,%s",
12337 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12338 emitcode ("mov","r3,%s",
12339 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12341 freeAsmop (handle, NULL, ic, FALSE);
12343 /* put pointer in DPTR */
12344 aopOp (pp,ic,FALSE,FALSE);
12345 if (AOP_TYPE(pp) == AOP_IMMD) {
12346 emitcode ("mov", "dptr,%s",
12347 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12348 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12349 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12350 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12351 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12353 freeAsmop (handle, NULL, ic, FALSE);
12355 /* make the call */
12356 emitcode ("lcall","System_ExecJavaProcess");
12358 /* put result in place */
12360 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12361 if (rsym->liveFrom != rsym->liveTo) {
12362 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12363 aopPut(AOP(IC_RESULT(ic)),"a",0);
12364 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12368 unsavermask(rsave);
12371 /*-----------------------------------------------------------------*/
12372 /* genSystemRTCRegisters - */
12373 /*-----------------------------------------------------------------*/
12374 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12380 assert (nparms==1);
12381 /* save registers that need to be saved */
12382 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12383 ds390_rUmaskForOp (IC_RESULT(ic))));
12386 /* put pointer in DPTR */
12387 aopOp (pp,ic,FALSE,FALSE);
12388 if (AOP_TYPE (pp) == AOP_IMMD) {
12389 emitcode ("mov","dps,#1");
12390 emitcode ("mov", "dptr,%s",
12391 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12392 emitcode ("mov","dps,#0");
12394 emitcode ("mov","dpl1,%s",
12395 aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12396 emitcode ("mov","dph1,%s",
12397 aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12398 emitcode ("mov","dpx1,%s",
12399 aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12401 freeAsmop (pp, NULL, ic, FALSE);
12403 /* make the call */
12404 emitcode ("lcall","System_%sRTCRegisters",name);
12406 unsavermask(rsave);
12409 /*-----------------------------------------------------------------*/
12410 /* genSystemThreadSleep - */
12411 /*-----------------------------------------------------------------*/
12412 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12417 assert (nparms==1);
12418 /* save registers that need to be saved */
12419 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12420 ds390_rUmaskForOp (IC_RESULT(ic))));
12423 aopOp(to,ic,FALSE,FALSE);
12424 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12425 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12426 emitcode ("push","%s",
12427 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12428 emitcode ("push","%s",
12429 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12430 emitcode ("push","%s",
12431 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12432 emitcode ("push","%s",
12433 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12434 emitcode ("pop","ar3");
12435 emitcode ("pop","ar2");
12436 emitcode ("pop","ar1");
12437 emitcode ("pop","ar0");
12439 emitcode ("mov","r0,%s",
12440 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12441 emitcode ("mov","r1,%s",
12442 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12443 emitcode ("mov","r2,%s",
12444 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12445 emitcode ("mov","r3,%s",
12446 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12448 freeAsmop (to, NULL, ic, FALSE);
12450 /* suspend in acc */
12452 aopOp(s,ic,FALSE,FALSE);
12453 emitcode ("mov","a,%s",
12454 aopGet(AOP(s),0,FALSE,TRUE,NULL));
12455 freeAsmop (s, NULL, ic, FALSE);
12457 /* make the call */
12458 emitcode ("lcall","System_%s",name);
12460 unsavermask(rsave);
12463 /*-----------------------------------------------------------------*/
12464 /* genSystemThreadResume - */
12465 /*-----------------------------------------------------------------*/
12466 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12471 assert (nparms==2);
12472 /* save registers that need to be saved */
12473 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12474 ds390_rUmaskForOp (IC_RESULT(ic))));
12480 aopOp(pid,ic,FALSE,FALSE);
12481 emitcode ("mov","r0,%s",
12482 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12483 freeAsmop (pid, NULL, ic, FALSE);
12486 aopOp(tid,ic,FALSE,FALSE);
12487 emitcode ("mov","a,%s",
12488 aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
12489 freeAsmop (tid, NULL, ic, FALSE);
12491 emitcode ("lcall","System_ThreadResume");
12493 /* put result into place */
12495 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12496 if (rsym->liveFrom != rsym->liveTo) {
12497 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12498 aopPut(AOP(IC_RESULT(ic)),"a",0);
12499 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12502 unsavermask(rsave);
12505 /*-----------------------------------------------------------------*/
12506 /* genSystemProcessResume - */
12507 /*-----------------------------------------------------------------*/
12508 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
12513 assert (nparms==1);
12514 /* save registers that need to be saved */
12515 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12516 ds390_rUmaskForOp (IC_RESULT(ic))));
12521 aopOp(pid,ic,FALSE,FALSE);
12522 emitcode ("mov","a,%s",
12523 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12524 freeAsmop (pid, NULL, ic, FALSE);
12526 emitcode ("lcall","System_ProcessResume");
12528 unsavermask(rsave);
12531 /*-----------------------------------------------------------------*/
12533 /*-----------------------------------------------------------------*/
12534 static void genSystem (iCode *ic,int nparms,char *name)
12536 assert(nparms == 0);
12538 emitcode ("lcall","System_%s",name);
12541 /*-----------------------------------------------------------------*/
12542 /* genSystemPoll - */
12543 /*-----------------------------------------------------------------*/
12544 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
12549 assert (nparms==1);
12550 /* save registers that need to be saved */
12551 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12552 ds390_rUmaskForOp (IC_RESULT(ic))));
12555 aopOp (fp,ic,FALSE,FALSE);
12556 if (AOP_TYPE (fp) == AOP_IMMD) {
12557 emitcode ("mov", "dptr,%s",
12558 aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
12559 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
12560 emitcode ("mov","dpl,%s",
12561 aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
12562 emitcode ("mov","dph,%s",
12563 aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
12564 emitcode ("mov","dpx,%s",
12565 aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
12567 freeAsmop (fp, NULL, ic, FALSE);
12569 emitcode ("lcall","System_%sPoll",name);
12571 /* put result into place */
12573 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12574 if (rsym->liveFrom != rsym->liveTo) {
12575 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12576 aopPut(AOP(IC_RESULT(ic)),"a",0);
12577 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12580 unsavermask(rsave);
12583 /*-----------------------------------------------------------------*/
12584 /* genSystemGetCurrentID - */
12585 /*-----------------------------------------------------------------*/
12586 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
12588 assert (nparms==0);
12590 emitcode ("lcall","System_GetCurrent%sId",name);
12591 /* put result into place */
12593 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12594 if (rsym->liveFrom != rsym->liveTo) {
12595 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12596 aopPut(AOP(IC_RESULT(ic)),"a",0);
12597 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12602 /*-----------------------------------------------------------------*/
12603 /* genDummyRead - generate code for dummy read of volatiles */
12604 /*-----------------------------------------------------------------*/
12606 genDummyRead (iCode * ic)
12611 D(emitcode("; genDummyRead",""));
12613 right = IC_RIGHT (ic);
12615 aopOp (right, ic, FALSE, FALSE);
12617 /* if the result is a bit */
12618 if (AOP_TYPE (right) == AOP_CRY)
12620 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
12624 /* bit variables done */
12626 size = AOP_SIZE (right);
12630 emitcode ("mov", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
12635 freeAsmop (right, NULL, ic, TRUE);
12638 /*-----------------------------------------------------------------*/
12639 /* genBuiltIn - calls the appropriate function to generating code */
12640 /* for a built in function */
12641 /*-----------------------------------------------------------------*/
12642 static void genBuiltIn (iCode *ic)
12644 operand *bi_parms[MAX_BUILTIN_ARGS];
12649 /* get all the arguments for a built in function */
12650 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
12652 /* which function is it */
12653 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
12654 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
12655 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
12656 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
12657 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
12658 } else if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
12659 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
12660 } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
12661 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
12662 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
12663 genMemsetX(bi_iCode,nbi_parms,bi_parms);
12664 } else if (strcmp(bif->name,"__builtin_inp")==0) {
12665 genInp(bi_iCode,nbi_parms,bi_parms);
12666 } else if (strcmp(bif->name,"__builtin_outp")==0) {
12667 genOutp(bi_iCode,nbi_parms,bi_parms);
12668 } else if (strcmp(bif->name,"__builtin_swapw")==0) {
12669 genSwapW(bi_iCode,nbi_parms,bi_parms);
12670 /* JavaNative builtIns */
12671 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
12672 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
12673 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
12674 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
12675 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
12676 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
12677 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
12678 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
12679 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
12680 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12681 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
12682 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12683 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
12684 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
12685 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
12686 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
12687 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
12688 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12689 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
12690 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12691 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
12692 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
12693 } else if (strcmp(bif->name,"MM_Malloc")==0) {
12694 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
12695 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
12696 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
12697 } else if (strcmp(bif->name,"MM_Free")==0) {
12698 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
12699 } else if (strcmp(bif->name,"MM_Deref")==0) {
12700 genMMDeref(bi_iCode,nbi_parms,bi_parms);
12701 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
12702 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
12703 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
12704 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
12705 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
12706 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
12707 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
12708 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
12709 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
12710 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
12711 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
12712 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
12713 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
12714 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
12715 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
12716 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
12717 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12718 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12719 } else if (strcmp(bif->name,"System_SaveThread")==0) {
12720 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12721 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12722 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12723 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
12724 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
12725 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
12726 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
12727 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
12728 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
12729 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
12730 genSystem(bi_iCode,nbi_parms,"ProcessYield");
12731 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
12732 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
12733 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
12734 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
12735 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
12736 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
12737 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
12738 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
12739 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
12740 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
12742 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
12748 /*-----------------------------------------------------------------*/
12749 /* gen390Code - generate code for Dallas 390 based controllers */
12750 /*-----------------------------------------------------------------*/
12752 gen390Code (iCode * lic)
12757 lineHead = lineCurr = NULL;
12758 dptrn[1][0] = "dpl1";
12759 dptrn[1][1] = "dph1";
12760 dptrn[1][2] = "dpx1";
12762 if (options.model == MODEL_FLAT24) {
12763 fReturnSizeDS390 = 5;
12764 fReturn = fReturn24;
12766 fReturnSizeDS390 = 4;
12767 fReturn = fReturn16;
12768 options.stack10bit=0;
12771 /* print the allocation information */
12772 if (allocInfo && currFunc)
12773 printAllocInfo (currFunc, codeOutFile);
12775 /* if debug information required */
12776 if (options.debug && currFunc)
12778 debugFile->writeFunction(currFunc);
12780 if (IS_STATIC (currFunc->etype))
12781 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
12783 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
12786 /* stack pointer name */
12787 if (options.useXstack)
12793 for (ic = lic; ic; ic = ic->next)
12796 if (ic->lineno && cln != ic->lineno)
12801 emitcode ("", "C$%s$%d$%d$%d ==.",
12802 FileBaseName (ic->filename), ic->lineno,
12803 ic->level, ic->block);
12806 if (!options.noCcodeInAsm) {
12807 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
12808 printCLine(ic->filename, ic->lineno));
12812 if (options.iCodeInAsm) {
12813 emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
12815 /* if the result is marked as
12816 spilt and rematerializable or code for
12817 this has already been generated then
12819 if (resultRemat (ic) || ic->generated)
12822 /* depending on the operation */
12842 /* IPOP happens only when trying to restore a
12843 spilt live range, if there is an ifx statement
12844 following this pop then the if statement might
12845 be using some of the registers being popped which
12846 would destory the contents of the register so
12847 we need to check for this condition and handle it */
12849 ic->next->op == IFX &&
12850 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
12851 genIfx (ic->next, ic);
12869 genEndFunction (ic);
12889 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
12906 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
12910 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
12917 /* note these two are xlated by algebraic equivalence
12918 during parsing SDCC.y */
12919 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12920 "got '>=' or '<=' shouldn't have come here");
12924 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
12936 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
12940 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
12944 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
12968 genRightShift (ic);
12971 case GET_VALUE_AT_ADDRESS:
12972 genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
12976 if (POINTER_SET (ic))
12977 genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
13003 if (ic->builtinSEND) genBuiltIn(ic);
13004 else addSet (&_G.sendSet, ic);
13007 case DUMMY_READ_VOLATILE:
13011 #if 0 // obsolete, and buggy for != xdata
13023 /* now we are ready to call the
13024 peep hole optimizer */
13025 if (!options.nopeep)
13026 peepHole (&lineHead);
13028 /* now do the actual printing */
13029 printLine (lineHead, codeOutFile);