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);
8975 /*-----------------------------------------------------------------*/
8976 /* genUnpackBits - generates code for unpacking bits */
8977 /*-----------------------------------------------------------------*/
8979 genUnpackBits (operand * result, char *rname, int ptype)
8987 D (emitcode (";", "genUnpackBits "););
8989 etype = getSpec (operandType (result));
8990 rsize = getSize (operandType (result));
8992 /* read the first byte */
8998 emitcode ("mov", "a,@%s", rname);
9002 emitcode ("movx", "a,@%s", rname);
9006 emitcode ("movx", "a,@dptr");
9010 emitcode ("clr", "a");
9011 emitcode ("movc", "a,@a+dptr");
9015 emitcode ("lcall", "__gptrget");
9019 /* if we have bitdisplacement then it fits */
9020 /* into this byte completely or if length is */
9021 /* less than a byte */
9022 if (((shCnt = SPEC_BSTR (etype)) != 0) || (SPEC_BLEN (etype) <= 8))
9025 /* shift right acc */
9028 emitcode ("anl", "a,#!constbyte",
9029 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
9030 aopPut (AOP (result), "a", offset++);
9034 /* bit field did not fit in a byte */
9035 rlen = SPEC_BLEN (etype);
9036 aopPut (AOP (result), "a", offset++);
9045 emitcode ("inc", "%s", rname);
9046 emitcode ("mov", "a,@%s", rname);
9050 emitcode ("inc", "%s", rname);
9051 emitcode ("movx", "a,@%s", rname);
9055 emitcode ("inc", "dptr");
9056 emitcode ("movx", "a,@dptr");
9060 emitcode ("clr", "a");
9061 emitcode ("inc", "dptr");
9062 emitcode ("movc", "a,@a+dptr");
9066 emitcode ("inc", "dptr");
9067 emitcode ("lcall", "__gptrget");
9072 /* if we are done */
9076 aopPut (AOP (result), "a", offset++);
9082 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
9083 aopPut (AOP (result), "a", offset++);
9091 aopPut (AOP (result), zero, offset++);
9096 /*-----------------------------------------------------------------*/
9097 /* genDataPointerGet - generates code when ptr offset is known */
9098 /*-----------------------------------------------------------------*/
9100 genDataPointerGet (operand * left,
9106 int size, offset = 0;
9107 aopOp (result, ic, TRUE, FALSE);
9109 /* get the string representation of the name */
9110 l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9111 size = AOP_SIZE (result);
9112 _startLazyDPSEvaluation ();
9117 SNPRINTF (buff, sizeof(buff),
9118 "(%s + %d)", l + 1, offset);
9122 SNPRINTF (buff, sizeof(buff),
9125 aopPut (AOP (result), buff, offset++);
9127 _endLazyDPSEvaluation ();
9129 freeAsmop (left, NULL, ic, TRUE);
9130 freeAsmop (result, NULL, ic, TRUE);
9133 /*-----------------------------------------------------------------*/
9134 /* genNearPointerGet - emitcode for near pointer fetch */
9135 /*-----------------------------------------------------------------*/
9137 genNearPointerGet (operand * left,
9145 sym_link *rtype, *retype, *letype;
9146 sym_link *ltype = operandType (left);
9149 rtype = operandType (result);
9150 retype = getSpec (rtype);
9151 letype = getSpec (ltype);
9153 aopOp (left, ic, FALSE, FALSE);
9155 /* if left is rematerialisable and
9156 result is not bit variable type and
9157 the left is pointer to data space i.e
9158 lower 128 bytes of space */
9159 if (AOP_TYPE (left) == AOP_IMMD &&
9160 !IS_BITVAR (retype) &&
9161 !IS_BITVAR (letype) &&
9162 DCL_TYPE (ltype) == POINTER)
9164 genDataPointerGet (left, result, ic);
9168 /* if the value is already in a pointer register
9169 then don't need anything more */
9170 if (!AOP_INPREG (AOP (left)))
9172 /* otherwise get a free pointer register */
9174 preg = getFreePtr (ic, &aop, FALSE);
9175 emitcode ("mov", "%s,%s",
9177 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9181 rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9183 freeAsmop (left, NULL, ic, TRUE);
9184 aopOp (result, ic, FALSE, FALSE);
9186 /* if bitfield then unpack the bits */
9187 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9188 genUnpackBits (result, rname, POINTER);
9191 /* we have can just get the values */
9192 int size = AOP_SIZE (result);
9197 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9200 emitcode ("mov", "a,@%s", rname);
9201 aopPut (AOP (result), "a", offset);
9205 SNPRINTF (buff, sizeof(buff), "@%s", rname);
9206 aopPut (AOP (result), buff, offset);
9211 emitcode ("inc", "%s", rname);
9216 /* now some housekeeping stuff */
9219 /* we had to allocate for this iCode */
9220 if (pi) { /* post increment present */
9221 aopPut(AOP ( left ),rname,0);
9223 freeAsmop (NULL, aop, ic, TRUE);
9227 /* we did not allocate which means left
9228 already in a pointer register, then
9229 if size > 0 && this could be used again
9230 we have to point it back to where it
9232 if (AOP_SIZE (result) > 1 &&
9233 !OP_SYMBOL (left)->remat &&
9234 (OP_SYMBOL (left)->liveTo > ic->seq ||
9238 int size = AOP_SIZE (result) - 1;
9240 emitcode ("dec", "%s", rname);
9245 freeAsmop (result, NULL, ic, TRUE);
9246 if (pi) pi->generated = 1;
9249 /*-----------------------------------------------------------------*/
9250 /* genPagedPointerGet - emitcode for paged pointer fetch */
9251 /*-----------------------------------------------------------------*/
9253 genPagedPointerGet (operand * left,
9261 sym_link *rtype, *retype, *letype;
9263 rtype = operandType (result);
9264 retype = getSpec (rtype);
9265 letype = getSpec (operandType (left));
9266 aopOp (left, ic, FALSE, FALSE);
9268 /* if the value is already in a pointer register
9269 then don't need anything more */
9270 if (!AOP_INPREG (AOP (left)))
9272 /* otherwise get a free pointer register */
9274 preg = getFreePtr (ic, &aop, FALSE);
9275 emitcode ("mov", "%s,%s",
9277 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9281 rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9283 freeAsmop (left, NULL, ic, TRUE);
9284 aopOp (result, ic, FALSE, FALSE);
9286 /* if bitfield then unpack the bits */
9287 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9288 genUnpackBits (result, rname, PPOINTER);
9291 /* we have can just get the values */
9292 int size = AOP_SIZE (result);
9298 emitcode ("movx", "a,@%s", rname);
9299 aopPut (AOP (result), "a", offset);
9304 emitcode ("inc", "%s", rname);
9308 /* now some housekeeping stuff */
9311 /* we had to allocate for this iCode */
9312 if (pi) aopPut ( AOP (left), rname, 0);
9313 freeAsmop (NULL, aop, ic, TRUE);
9317 /* we did not allocate which means left
9318 already in a pointer register, then
9319 if size > 0 && this could be used again
9320 we have to point it back to where it
9322 if (AOP_SIZE (result) > 1 &&
9323 !OP_SYMBOL (left)->remat &&
9324 (OP_SYMBOL (left)->liveTo > ic->seq ||
9328 int size = AOP_SIZE (result) - 1;
9330 emitcode ("dec", "%s", rname);
9335 freeAsmop (result, NULL, ic, TRUE);
9336 if (pi) pi->generated = 1;
9339 /*-----------------------------------------------------------------*/
9340 /* genFarPointerGet - gget value from far space */
9341 /*-----------------------------------------------------------------*/
9343 genFarPointerGet (operand * left,
9344 operand * result, iCode * ic, iCode *pi)
9346 int size, offset, dopi=1;
9347 sym_link *retype = getSpec (operandType (result));
9348 sym_link *letype = getSpec (operandType (left));
9349 D (emitcode (";", "genFarPointerGet"););
9351 aopOp (left, ic, FALSE, FALSE);
9353 /* if the operand is already in dptr
9354 then we do nothing else we move the value to dptr */
9355 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9357 /* if this is remateriazable */
9358 if (AOP_TYPE (left) == AOP_IMMD)
9360 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9364 /* we need to get it byte by byte */
9365 _startLazyDPSEvaluation ();
9366 if (AOP_TYPE (left) != AOP_DPTR)
9368 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9369 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9370 if (options.model == MODEL_FLAT24)
9371 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9375 /* We need to generate a load to DPTR indirect through DPTR. */
9376 D (emitcode (";", "genFarPointerGet -- indirection special case."););
9377 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9378 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9379 if (options.model == MODEL_FLAT24)
9380 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9381 emitcode ("pop", "dph");
9382 emitcode ("pop", "dpl");
9385 _endLazyDPSEvaluation ();
9388 /* so dptr know contains the address */
9389 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9391 /* if bit then unpack */
9392 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9393 if (AOP_INDPTRn(left)) {
9394 genSetDPTR(AOP(left)->aopu.dptr);
9396 genUnpackBits (result, "dptr", FPOINTER);
9397 if (AOP_INDPTRn(left)) {
9402 size = AOP_SIZE (result);
9405 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9407 genSetDPTR(AOP(left)->aopu.dptr);
9408 emitcode ("movx", "a,@dptr");
9409 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9410 emitcode ("inc", "dptr");
9412 aopPut (AOP (result), "a", offset++);
9415 _startLazyDPSEvaluation ();
9417 if (AOP_INDPTRn(left)) {
9418 genSetDPTR(AOP(left)->aopu.dptr);
9424 emitcode ("movx", "a,@dptr");
9425 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9426 emitcode ("inc", "dptr");
9428 aopPut (AOP (result), "a", offset++);
9430 _endLazyDPSEvaluation ();
9433 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9434 if (!AOP_INDPTRn(left)) {
9435 _startLazyDPSEvaluation ();
9436 aopPut ( AOP (left), "dpl", 0);
9437 aopPut ( AOP (left), "dph", 1);
9438 if (options.model == MODEL_FLAT24)
9439 aopPut ( AOP (left), "dpx", 2);
9440 _endLazyDPSEvaluation ();
9443 } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) &&
9444 AOP_SIZE(result) > 1 &&
9446 (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
9448 size = AOP_SIZE (result) - 1;
9449 if (AOP_INDPTRn(left)) {
9450 genSetDPTR(AOP(left)->aopu.dptr);
9452 while (size--) emitcode ("lcall","__decdptr");
9453 if (AOP_INDPTRn(left)) {
9458 freeAsmop (left, NULL, ic, TRUE);
9459 freeAsmop (result, NULL, ic, TRUE);
9462 /*-----------------------------------------------------------------*/
9463 /* genCodePointerGet - get value from code space */
9464 /*-----------------------------------------------------------------*/
9466 genCodePointerGet (operand * left,
9467 operand * result, iCode * ic, iCode *pi)
9469 int size, offset, dopi=1;
9470 sym_link *retype = getSpec (operandType (result));
9472 aopOp (left, ic, FALSE, FALSE);
9474 /* if the operand is already in dptr
9475 then we do nothing else we move the value to dptr */
9476 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
9478 /* if this is remateriazable */
9479 if (AOP_TYPE (left) == AOP_IMMD)
9481 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9484 { /* we need to get it byte by byte */
9485 _startLazyDPSEvaluation ();
9486 if (AOP_TYPE (left) != AOP_DPTR)
9488 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9489 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9490 if (options.model == MODEL_FLAT24)
9491 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9495 /* We need to generate a load to DPTR indirect through DPTR. */
9496 D (emitcode (";", "gencodePointerGet -- indirection special case."););
9497 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9498 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9499 if (options.model == MODEL_FLAT24)
9500 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9501 emitcode ("pop", "dph");
9502 emitcode ("pop", "dpl");
9505 _endLazyDPSEvaluation ();
9508 /* so dptr know contains the address */
9509 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9511 /* if bit then unpack */
9512 if (IS_BITVAR (retype)) {
9513 if (AOP_INDPTRn(left)) {
9514 genSetDPTR(AOP(left)->aopu.dptr);
9516 genUnpackBits (result, "dptr", CPOINTER);
9517 if (AOP_INDPTRn(left)) {
9522 size = AOP_SIZE (result);
9524 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9526 genSetDPTR(AOP(left)->aopu.dptr);
9527 emitcode ("clr", "a");
9528 emitcode ("movc", "a,@a+dptr");
9529 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9530 emitcode ("inc", "dptr");
9532 aopPut (AOP (result), "a", offset++);
9535 _startLazyDPSEvaluation ();
9538 if (AOP_INDPTRn(left)) {
9539 genSetDPTR(AOP(left)->aopu.dptr);
9545 emitcode ("clr", "a");
9546 emitcode ("movc", "a,@a+dptr");
9547 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9548 emitcode ("inc", "dptr");
9549 aopPut (AOP (result), "a", offset++);
9551 _endLazyDPSEvaluation ();
9554 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9555 if (!AOP_INDPTRn(left)) {
9556 _startLazyDPSEvaluation ();
9558 aopPut ( AOP (left), "dpl", 0);
9559 aopPut ( AOP (left), "dph", 1);
9560 if (options.model == MODEL_FLAT24)
9561 aopPut ( AOP (left), "dpx", 2);
9563 _endLazyDPSEvaluation ();
9566 } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
9567 AOP_SIZE(result) > 1 &&
9568 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9570 size = AOP_SIZE (result) - 1;
9571 if (AOP_INDPTRn(left)) {
9572 genSetDPTR(AOP(left)->aopu.dptr);
9574 while (size--) emitcode ("lcall","__decdptr");
9575 if (AOP_INDPTRn(left)) {
9580 freeAsmop (left, NULL, ic, TRUE);
9581 freeAsmop (result, NULL, ic, TRUE);
9584 /*-----------------------------------------------------------------*/
9585 /* genGenPointerGet - gget value from generic pointer space */
9586 /*-----------------------------------------------------------------*/
9588 genGenPointerGet (operand * left,
9589 operand * result, iCode * ic, iCode * pi)
9592 sym_link *retype = getSpec (operandType (result));
9593 sym_link *letype = getSpec (operandType (left));
9595 D (emitcode (";", "genGenPointerGet "); );
9597 aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
9599 /* if the operand is already in dptr
9600 then we do nothing else we move the value to dptr */
9601 if (AOP_TYPE (left) != AOP_STR)
9603 /* if this is remateriazable */
9604 if (AOP_TYPE (left) == AOP_IMMD)
9606 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9607 if (AOP(left)->aopu.aop_immd.from_cast_remat)
9609 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
9613 emitcode ("mov", "b,#%d", pointerCode (retype));
9617 { /* we need to get it byte by byte */
9618 _startLazyDPSEvaluation ();
9619 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
9620 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
9621 if (options.model == MODEL_FLAT24) {
9622 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9623 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
9625 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9627 _endLazyDPSEvaluation ();
9631 /* so dptr-b now contains the address */
9633 aopOp (result, ic, FALSE, TRUE);
9636 /* if bit then unpack */
9637 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9639 genUnpackBits (result, "dptr", GPOINTER);
9643 size = AOP_SIZE (result);
9650 // Get two bytes at a time, results in _AP & A.
9651 // dptr will be incremented ONCE by __gptrgetWord.
9653 // Note: any change here must be coordinated
9654 // with the implementation of __gptrgetWord
9655 // in device/lib/_gptrget.c
9656 emitcode ("lcall", "__gptrgetWord");
9657 aopPut (AOP (result), DP2_RESULT_REG, offset++);
9658 aopPut (AOP (result), "a", offset++);
9663 // Only one byte to get.
9664 emitcode ("lcall", "__gptrget");
9665 aopPut (AOP (result), "a", offset++);
9668 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9670 emitcode ("inc", "dptr");
9675 if (pi && AOP_TYPE (left) != AOP_IMMD) {
9676 _startLazyDPSEvaluation ();
9678 aopPut ( AOP (left), "dpl", 0);
9679 aopPut ( AOP (left), "dph", 1);
9680 if (options.model == MODEL_FLAT24) {
9681 aopPut ( AOP (left), "dpx", 2);
9682 aopPut ( AOP (left), "b", 3);
9683 } else aopPut ( AOP (left), "b", 2);
9685 _endLazyDPSEvaluation ();
9688 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9689 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9691 size = AOP_SIZE (result) - 1;
9692 while (size--) emitcode ("lcall","__decdptr");
9695 freeAsmop (left, NULL, ic, TRUE);
9696 freeAsmop (result, NULL, ic, TRUE);
9699 /*-----------------------------------------------------------------*/
9700 /* genPointerGet - generate code for pointer get */
9701 /*-----------------------------------------------------------------*/
9703 genPointerGet (iCode * ic, iCode *pi)
9705 operand *left, *result;
9706 sym_link *type, *etype;
9709 D (emitcode (";", "genPointerGet ");
9712 left = IC_LEFT (ic);
9713 result = IC_RESULT (ic);
9715 /* depending on the type of pointer we need to
9716 move it to the correct pointer register */
9717 type = operandType (left);
9718 etype = getSpec (type);
9719 /* if left is of type of pointer then it is simple */
9720 if (IS_PTR (type) && !IS_FUNC (type->next))
9721 p_type = DCL_TYPE (type);
9724 /* we have to go by the storage class */
9725 p_type = PTR_TYPE (SPEC_OCLS (etype));
9727 /* special case when cast remat */
9728 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9729 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9730 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9731 type = operandType (left);
9732 p_type = DCL_TYPE (type);
9734 /* now that we have the pointer type we assign
9735 the pointer values */
9741 genNearPointerGet (left, result, ic, pi);
9745 genPagedPointerGet (left, result, ic, pi);
9749 genFarPointerGet (left, result, ic, pi);
9753 genCodePointerGet (left, result, ic, pi);
9757 genGenPointerGet (left, result, ic, pi);
9763 /*-----------------------------------------------------------------*/
9764 /* genPackBits - generates code for packed bit storage */
9765 /*-----------------------------------------------------------------*/
9767 genPackBits (sym_link * etype,
9769 char *rname, int p_type)
9777 blen = SPEC_BLEN (etype);
9778 bstr = SPEC_BSTR (etype);
9780 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9782 /* if the bit lenth is less than or */
9783 /* it exactly fits a byte then */
9784 if (SPEC_BLEN (etype) <= 8)
9786 unsigned char mask = ((unsigned char) (0xFF << (blen + bstr)) |
9787 (unsigned char) (0xFF >> (8 - bstr)));
9788 shCount = SPEC_BSTR (etype);
9790 /* shift left acc */
9793 if (SPEC_BLEN (etype) < 8)
9794 { /* if smaller than a byte */
9796 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9801 emitcode ("mov", "b,a");
9802 emitcode ("mov", "a,@%s", rname);
9806 emitcode ("mov", "b,a");
9807 emitcode ("movx", "a,@dptr");
9811 emitcode ("push", "b");
9812 emitcode ("push", "acc");
9813 emitcode ("lcall", "__gptrget");
9814 emitcode ("pop", "b");
9818 emitcode ("anl", "a,#!constbyte", mask);
9819 emitcode ("orl", "a,b");
9820 if (p_type == GPOINTER)
9821 emitcode ("pop", "b");
9828 emitcode ("mov", "@%s,a", rname);
9832 emitcode ("movx", "@dptr,a");
9836 emitcode ("lcall", "__gptrput");
9841 if (SPEC_BLEN (etype) <= 8)
9844 emitcode ("inc", "%s", rname);
9845 rLen = SPEC_BLEN (etype);
9847 /* now generate for lengths greater than one byte */
9851 l = aopGet (AOP (right), offset++, FALSE, TRUE, NULL);
9863 emitcode ("mov", "@%s,a", rname);
9866 emitcode ("mov", "@%s,%s", rname, l);
9871 emitcode ("movx", "@dptr,a");
9876 emitcode ("lcall", "__gptrput");
9879 emitcode ("inc", "%s", rname);
9884 /* last last was not complete */
9887 emitcode ("anl", "a,#!constbyte",
9888 (~(((unsigned char) -1 << rLen) & 0xff)) & 0xff);
9890 /* save the byte & read byte */
9894 emitcode ("mov", "b,a");
9895 emitcode ("mov", "a,@%s", rname);
9899 emitcode ("mov", "b,a");
9900 emitcode ("movx", "a,@dptr");
9904 emitcode ("push", "b");
9905 emitcode ("push", "acc");
9906 emitcode ("lcall", "__gptrget");
9907 emitcode ("pop", "b");
9911 emitcode ("anl", "a,#!constbyte", (((unsigned char) -1 << rLen) & 0xff));
9912 emitcode ("orl", "a,b");
9915 if (p_type == GPOINTER)
9916 emitcode ("pop", "b");
9922 emitcode ("mov", "@%s,a", rname);
9926 emitcode ("movx", "@dptr,a");
9930 emitcode ("lcall", "__gptrput");
9934 /*-----------------------------------------------------------------*/
9935 /* genDataPointerSet - remat pointer to data space */
9936 /*-----------------------------------------------------------------*/
9938 genDataPointerSet (operand * right,
9942 int size, offset = 0;
9945 aopOp (right, ic, FALSE, FALSE);
9947 l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
9948 size = AOP_SIZE (right);
9953 SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
9957 SNPRINTF (buff, sizeof(buff), "%s", l + 1);
9960 emitcode ("mov", "%s,%s", buff,
9961 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9964 freeAsmop (right, NULL, ic, TRUE);
9965 freeAsmop (result, NULL, ic, TRUE);
9968 /*-----------------------------------------------------------------*/
9969 /* genNearPointerSet - emitcode for near pointer put */
9970 /*-----------------------------------------------------------------*/
9972 genNearPointerSet (operand * right,
9979 sym_link *retype, *letype;
9980 sym_link *ptype = operandType (result);
9982 retype = getSpec (operandType (right));
9983 letype = getSpec (ptype);
9985 aopOp (result, ic, FALSE, FALSE);
9987 /* if the result is rematerializable &
9988 in data space & not a bit variable */
9989 if (AOP_TYPE (result) == AOP_IMMD &&
9990 DCL_TYPE (ptype) == POINTER &&
9991 !IS_BITVAR (retype) &&
9992 !IS_BITVAR (letype))
9994 genDataPointerSet (right, result, ic);
9998 /* if the value is already in a pointer register
9999 then don't need anything more */
10000 if (!AOP_INPREG (AOP (result)))
10002 /* otherwise get a free pointer register */
10005 aop = newAsmop (0);
10006 preg = getFreePtr (ic, &aop, FALSE);
10007 emitcode ("mov", "%s,%s",
10009 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10010 rname = preg->name;
10013 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10015 aopOp (right, ic, FALSE, FALSE);
10017 /* if bitfield then unpack the bits */
10018 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10019 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
10022 /* we have can just get the values */
10023 int size = AOP_SIZE (right);
10028 l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
10032 emitcode ("mov", "@%s,a", rname);
10035 emitcode ("mov", "@%s,%s", rname, l);
10037 emitcode ("inc", "%s", rname);
10042 /* now some housekeeping stuff */
10045 /* we had to allocate for this iCode */
10046 if (pi) aopPut (AOP (result),rname,0);
10047 freeAsmop (NULL, aop, ic, TRUE);
10051 /* we did not allocate which means left
10052 already in a pointer register, then
10053 if size > 0 && this could be used again
10054 we have to point it back to where it
10056 if (AOP_SIZE (right) > 1 &&
10057 !OP_SYMBOL (result)->remat &&
10058 (OP_SYMBOL (result)->liveTo > ic->seq ||
10062 int size = AOP_SIZE (right) - 1;
10064 emitcode ("dec", "%s", rname);
10069 if (pi) pi->generated = 1;
10070 freeAsmop (result, NULL, ic, TRUE);
10071 freeAsmop (right, NULL, ic, TRUE);
10076 /*-----------------------------------------------------------------*/
10077 /* genPagedPointerSet - emitcode for Paged pointer put */
10078 /*-----------------------------------------------------------------*/
10080 genPagedPointerSet (operand * right,
10087 sym_link *retype, *letype;
10089 retype = getSpec (operandType (right));
10090 letype = getSpec (operandType (result));
10092 aopOp (result, ic, FALSE, FALSE);
10094 /* if the value is already in a pointer register
10095 then don't need anything more */
10096 if (!AOP_INPREG (AOP (result)))
10098 /* otherwise get a free pointer register */
10101 aop = newAsmop (0);
10102 preg = getFreePtr (ic, &aop, FALSE);
10103 emitcode ("mov", "%s,%s",
10105 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10106 rname = preg->name;
10109 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10111 aopOp (right, ic, FALSE, FALSE);
10113 /* if bitfield then unpack the bits */
10114 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10115 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
10118 /* we have can just get the values */
10119 int size = AOP_SIZE (right);
10124 MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10126 emitcode ("movx", "@%s,a", rname);
10129 emitcode ("inc", "%s", rname);
10135 /* now some housekeeping stuff */
10138 if (pi) aopPut (AOP (result),rname,0);
10139 /* we had to allocate for this iCode */
10140 freeAsmop (NULL, aop, ic, TRUE);
10144 /* we did not allocate which means left
10145 already in a pointer register, then
10146 if size > 0 && this could be used again
10147 we have to point it back to where it
10149 if (AOP_SIZE (right) > 1 &&
10150 !OP_SYMBOL (result)->remat &&
10151 (OP_SYMBOL (result)->liveTo > ic->seq ||
10155 int size = AOP_SIZE (right) - 1;
10157 emitcode ("dec", "%s", rname);
10162 if (pi) pi->generated = 1;
10163 freeAsmop (result, NULL, ic, TRUE);
10164 freeAsmop (right, NULL, ic, TRUE);
10169 /*-----------------------------------------------------------------*/
10170 /* genFarPointerSet - set value from far space */
10171 /*-----------------------------------------------------------------*/
10173 genFarPointerSet (operand * right,
10174 operand * result, iCode * ic, iCode *pi)
10176 int size, offset, dopi=1;
10177 sym_link *retype = getSpec (operandType (right));
10178 sym_link *letype = getSpec (operandType (result));
10180 aopOp (result, ic, FALSE, FALSE);
10182 /* if the operand is already in dptr
10183 then we do nothing else we move the value to dptr */
10184 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10186 /* if this is remateriazable */
10187 if (AOP_TYPE (result) == AOP_IMMD)
10188 emitcode ("mov", "dptr,%s",
10189 aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10192 /* we need to get it byte by byte */
10193 _startLazyDPSEvaluation ();
10194 if (AOP_TYPE (result) != AOP_DPTR)
10196 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10197 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10198 if (options.model == MODEL_FLAT24)
10199 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10203 /* We need to generate a load to DPTR indirect through DPTR. */
10204 D (emitcode (";", "genFarPointerSet -- indirection special case."););
10206 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10207 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10208 if (options.model == MODEL_FLAT24)
10209 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10210 emitcode ("pop", "dph");
10211 emitcode ("pop", "dpl");
10214 _endLazyDPSEvaluation ();
10217 /* so dptr know contains the address */
10218 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10220 /* if bit then unpack */
10221 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
10222 if (AOP_INDPTRn(result)) {
10223 genSetDPTR(AOP(result)->aopu.dptr);
10225 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
10226 if (AOP_INDPTRn(result)) {
10230 size = AOP_SIZE (right);
10232 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10234 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10236 genSetDPTR(AOP(result)->aopu.dptr);
10237 emitcode ("movx", "@dptr,a");
10238 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10239 emitcode ("inc", "dptr");
10243 _startLazyDPSEvaluation ();
10245 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10247 if (AOP_INDPTRn(result)) {
10248 genSetDPTR(AOP(result)->aopu.dptr);
10254 emitcode ("movx", "@dptr,a");
10255 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10256 emitcode ("inc", "dptr");
10258 _endLazyDPSEvaluation ();
10262 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10263 if (!AOP_INDPTRn(result)) {
10264 _startLazyDPSEvaluation ();
10266 aopPut (AOP(result),"dpl",0);
10267 aopPut (AOP(result),"dph",1);
10268 if (options.model == MODEL_FLAT24)
10269 aopPut (AOP(result),"dpx",2);
10271 _endLazyDPSEvaluation ();
10274 } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
10275 AOP_SIZE(right) > 1 &&
10276 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10278 size = AOP_SIZE (right) - 1;
10279 if (AOP_INDPTRn(result)) {
10280 genSetDPTR(AOP(result)->aopu.dptr);
10282 while (size--) emitcode ("lcall","__decdptr");
10283 if (AOP_INDPTRn(result)) {
10287 freeAsmop (result, NULL, ic, TRUE);
10288 freeAsmop (right, NULL, ic, TRUE);
10291 /*-----------------------------------------------------------------*/
10292 /* genGenPointerSet - set value from generic pointer space */
10293 /*-----------------------------------------------------------------*/
10295 genGenPointerSet (operand * right,
10296 operand * result, iCode * ic, iCode *pi)
10299 sym_link *retype = getSpec (operandType (right));
10300 sym_link *letype = getSpec (operandType (result));
10302 aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10304 /* if the operand is already in dptr
10305 then we do nothing else we move the value to dptr */
10306 if (AOP_TYPE (result) != AOP_STR)
10308 _startLazyDPSEvaluation ();
10309 /* if this is remateriazable */
10310 if (AOP_TYPE (result) == AOP_IMMD)
10312 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10313 if (AOP(result)->aopu.aop_immd.from_cast_remat)
10315 MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10320 "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10324 { /* we need to get it byte by byte */
10325 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10326 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10327 if (options.model == MODEL_FLAT24) {
10328 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10329 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10331 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10334 _endLazyDPSEvaluation ();
10336 /* so dptr + b now contains the address */
10338 aopOp (right, ic, FALSE, TRUE);
10342 /* if bit then unpack */
10343 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10345 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
10349 size = AOP_SIZE (right);
10352 _startLazyDPSEvaluation ();
10357 // Set two bytes at a time, passed in _AP & A.
10358 // dptr will be incremented ONCE by __gptrputWord.
10360 // Note: any change here must be coordinated
10361 // with the implementation of __gptrputWord
10362 // in device/lib/_gptrput.c
10363 emitcode("mov", "_ap, %s",
10364 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10365 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10369 emitcode ("lcall", "__gptrputWord");
10374 // Only one byte to put.
10375 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10379 emitcode ("lcall", "__gptrput");
10382 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10384 emitcode ("inc", "dptr");
10387 _endLazyDPSEvaluation ();
10390 if (pi && AOP_TYPE (result) != AOP_IMMD) {
10391 _startLazyDPSEvaluation ();
10393 aopPut (AOP(result),"dpl",0);
10394 aopPut (AOP(result),"dph",1);
10395 if (options.model == MODEL_FLAT24) {
10396 aopPut (AOP(result),"dpx",2);
10397 aopPut (AOP(result),"b",3);
10399 aopPut (AOP(result),"b",2);
10401 _endLazyDPSEvaluation ();
10404 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10405 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10407 size = AOP_SIZE (right) - 1;
10408 while (size--) emitcode ("lcall","__decdptr");
10410 freeAsmop (result, NULL, ic, TRUE);
10411 freeAsmop (right, NULL, ic, TRUE);
10414 /*-----------------------------------------------------------------*/
10415 /* genPointerSet - stores the value into a pointer location */
10416 /*-----------------------------------------------------------------*/
10418 genPointerSet (iCode * ic, iCode *pi)
10420 operand *right, *result;
10421 sym_link *type, *etype;
10424 D (emitcode (";", "genPointerSet "););
10426 right = IC_RIGHT (ic);
10427 result = IC_RESULT (ic);
10429 /* depending on the type of pointer we need to
10430 move it to the correct pointer register */
10431 type = operandType (result);
10432 etype = getSpec (type);
10433 /* if left is of type of pointer then it is simple */
10434 if (IS_PTR (type) && !IS_FUNC (type->next))
10436 p_type = DCL_TYPE (type);
10440 /* we have to go by the storage class */
10441 p_type = PTR_TYPE (SPEC_OCLS (etype));
10443 /* special case when cast remat */
10444 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10445 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10446 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10447 type = operandType (result);
10448 p_type = DCL_TYPE (type);
10451 /* now that we have the pointer type we assign
10452 the pointer values */
10458 genNearPointerSet (right, result, ic, pi);
10462 genPagedPointerSet (right, result, ic, pi);
10466 genFarPointerSet (right, result, ic, pi);
10470 genGenPointerSet (right, result, ic, pi);
10474 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10475 "genPointerSet: illegal pointer type");
10480 /*-----------------------------------------------------------------*/
10481 /* genIfx - generate code for Ifx statement */
10482 /*-----------------------------------------------------------------*/
10484 genIfx (iCode * ic, iCode * popIc)
10486 operand *cond = IC_COND (ic);
10489 D (emitcode (";", "genIfx "););
10491 aopOp (cond, ic, FALSE, FALSE);
10493 /* get the value into acc */
10494 if (AOP_TYPE (cond) != AOP_CRY)
10503 /* the result is now in the accumulator */
10504 freeAsmop (cond, NULL, ic, TRUE);
10506 /* if there was something to be popped then do it */
10510 /* if the condition is a bit variable */
10511 if (isbit && IS_ITEMP (cond) &&
10514 genIfxJump (ic, SPIL_LOC (cond)->rname);
10516 else if (isbit && !IS_ITEMP (cond))
10518 genIfxJump (ic, OP_SYMBOL (cond)->rname);
10522 genIfxJump (ic, "a");
10528 /*-----------------------------------------------------------------*/
10529 /* genAddrOf - generates code for address of */
10530 /*-----------------------------------------------------------------*/
10532 genAddrOf (iCode * ic)
10534 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10537 D (emitcode (";", "genAddrOf ");
10540 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10542 /* if the operand is on the stack then we
10543 need to get the stack offset of this
10545 if (sym->onStack) {
10547 /* if 10 bit stack */
10548 if (options.stack10bit) {
10552 tsprintf(buff, sizeof(buff),
10553 "#!constbyte",(options.stack_loc >> 16) & 0xff);
10554 /* if it has an offset then we need to compute it */
10555 /* emitcode ("subb", "a,#!constbyte", */
10556 /* -((sym->stack < 0) ? */
10557 /* ((short) (sym->stack - _G.nRegsSaved)) : */
10558 /* ((short) sym->stack)) & 0xff); */
10559 /* emitcode ("mov","b,a"); */
10560 /* emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
10561 /* ((short) (sym->stack - _G.nRegsSaved)) : */
10562 /* ((short) sym->stack)) >> 8) & 0xff); */
10564 emitcode ("mov", "a,_bpx");
10565 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
10566 ((char) (sym->stack - _G.nRegsSaved)) :
10567 ((char) sym->stack )) & 0xff);
10568 emitcode ("mov", "b,a");
10569 emitcode ("mov", "a,_bpx+1");
10571 offset = (((sym->stack < 0) ?
10572 ((short) (sym->stack - _G.nRegsSaved)) :
10573 ((short) sym->stack )) >> 8) & 0xff;
10575 emitcode ("addc","a,#!constbyte", offset);
10577 aopPut (AOP (IC_RESULT (ic)), "b", 0);
10578 aopPut (AOP (IC_RESULT (ic)), "a", 1);
10579 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10581 /* we can just move _bp */
10582 aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10583 aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10584 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10587 /* if it has an offset then we need to compute it */
10589 emitcode ("mov", "a,_bp");
10590 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10591 aopPut (AOP (IC_RESULT (ic)), "a", 0);
10593 /* we can just move _bp */
10594 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10596 /* fill the result with zero */
10597 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10600 if (options.stack10bit && size < (FPTRSIZE - 1)) {
10602 "*** warning: pointer to stack var truncated.\n");
10607 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10613 /* object not on stack then we need the name */
10614 size = AOP_SIZE (IC_RESULT (ic));
10619 char s[SDCC_NAME_MAX];
10623 tsprintf(s, sizeof(s), "#!his",sym->rname);
10626 tsprintf(s, sizeof(s), "#!hihis",sym->rname);
10629 tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
10631 default: /* should not need this (just in case) */
10632 SNPRINTF (s, sizeof(s), "#(%s >> %d)",
10639 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10642 aopPut (AOP (IC_RESULT (ic)), s, offset++);
10646 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10650 #if 0 // obsolete, and buggy for != xdata
10651 /*-----------------------------------------------------------------*/
10652 /* genArrayInit - generates code for address of */
10653 /*-----------------------------------------------------------------*/
10655 genArrayInit (iCode * ic)
10657 literalList *iLoop;
10659 int elementSize = 0, eIndex;
10660 unsigned val, lastVal;
10662 operand *left=IC_LEFT(ic);
10664 D (emitcode (";", "genArrayInit "););
10666 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10668 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10670 // Load immediate value into DPTR.
10671 emitcode("mov", "dptr, %s",
10672 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
10674 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10677 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10678 "Unexpected operand to genArrayInit.\n");
10681 // a regression because of SDCCcse.c:1.52
10682 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10683 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10684 if (options.model == MODEL_FLAT24)
10685 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10689 type = operandType(IC_LEFT(ic));
10691 if (type && type->next)
10693 elementSize = getSize(type->next);
10697 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10698 "can't determine element size in genArrayInit.\n");
10702 iLoop = IC_ARRAYILIST(ic);
10707 bool firstpass = TRUE;
10709 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
10710 iLoop->count, (int)iLoop->literalValue, elementSize);
10716 symbol *tlbl = NULL;
10718 count = ix > 256 ? 256 : ix;
10722 tlbl = newiTempLabel (NULL);
10723 if (firstpass || (count & 0xff))
10725 emitcode("mov", "b, #!constbyte", count & 0xff);
10728 emitcode ("", "!tlabeldef", tlbl->key + 100);
10733 for (eIndex = 0; eIndex < elementSize; eIndex++)
10735 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10736 if (val != lastVal)
10738 emitcode("mov", "a, #!constbyte", val);
10742 emitcode("movx", "@dptr, a");
10743 emitcode("inc", "dptr");
10748 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10754 iLoop = iLoop->next;
10757 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10761 /*-----------------------------------------------------------------*/
10762 /* genFarFarAssign - assignment when both are in far space */
10763 /*-----------------------------------------------------------------*/
10765 genFarFarAssign (operand * result, operand * right, iCode * ic)
10767 int size = AOP_SIZE (right);
10769 symbol *rSym = NULL;
10773 /* quick & easy case. */
10774 D(emitcode(";","genFarFarAssign (1 byte case)"););
10775 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
10776 freeAsmop (right, NULL, ic, FALSE);
10777 /* now assign DPTR to result */
10779 aopOp(result, ic, FALSE, FALSE);
10781 aopPut(AOP(result), "a", 0);
10782 freeAsmop(result, NULL, ic, FALSE);
10786 /* See if we've got an underlying symbol to abuse. */
10787 if (IS_SYMOP(result) && OP_SYMBOL(result))
10789 if (IS_TRUE_SYMOP(result))
10791 rSym = OP_SYMBOL(result);
10793 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10795 rSym = OP_SYMBOL(result)->usl.spillLoc;
10799 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10801 /* We can use the '390 auto-toggle feature to good effect here. */
10803 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10804 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
10805 emitcode ("mov", "dptr,#%s", rSym->rname);
10806 /* DP2 = result, DP1 = right, DP1 is current. */
10809 emitcode("movx", "a,@dptr");
10810 emitcode("movx", "@dptr,a");
10813 emitcode("inc", "dptr");
10814 emitcode("inc", "dptr");
10817 emitcode("mov", "dps,#0");
10818 freeAsmop (right, NULL, ic, FALSE);
10820 some alternative code for processors without auto-toggle
10821 no time to test now, so later well put in...kpb
10822 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10823 emitcode("mov", "dps,#1"); /* Select DPTR2. */
10824 emitcode ("mov", "dptr,#%s", rSym->rname);
10825 /* DP2 = result, DP1 = right, DP1 is current. */
10829 emitcode("movx", "a,@dptr");
10831 emitcode("inc", "dptr");
10832 emitcode("inc", "dps");
10833 emitcode("movx", "@dptr,a");
10835 emitcode("inc", "dptr");
10836 emitcode("inc", "dps");
10838 emitcode("mov", "dps,#0");
10839 freeAsmop (right, NULL, ic, FALSE);
10844 D (emitcode (";", "genFarFarAssign"););
10845 aopOp (result, ic, TRUE, TRUE);
10847 _startLazyDPSEvaluation ();
10851 aopPut (AOP (result),
10852 aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
10855 _endLazyDPSEvaluation ();
10856 freeAsmop (result, NULL, ic, FALSE);
10857 freeAsmop (right, NULL, ic, FALSE);
10861 /*-----------------------------------------------------------------*/
10862 /* genAssign - generate code for assignment */
10863 /*-----------------------------------------------------------------*/
10865 genAssign (iCode * ic)
10867 operand *result, *right;
10869 unsigned long lit = 0L;
10871 D (emitcode (";", "genAssign ");
10874 result = IC_RESULT (ic);
10875 right = IC_RIGHT (ic);
10877 /* if they are the same */
10878 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10881 aopOp (right, ic, FALSE, FALSE);
10883 emitcode (";", "genAssign: resultIsFar = %s",
10884 isOperandInFarSpace (result) ?
10887 /* special case both in far space */
10888 if ((AOP_TYPE (right) == AOP_DPTR ||
10889 AOP_TYPE (right) == AOP_DPTR2) &&
10890 /* IS_TRUE_SYMOP(result) && */
10891 isOperandInFarSpace (result))
10893 genFarFarAssign (result, right, ic);
10897 aopOp (result, ic, TRUE, FALSE);
10899 /* if they are the same registers */
10900 if (sameRegs (AOP (right), AOP (result)))
10903 /* if the result is a bit */
10904 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10906 /* if the right size is a literal then
10907 we know what the value is */
10908 if (AOP_TYPE (right) == AOP_LIT)
10910 if (((int) operandLitValue (right)))
10911 aopPut (AOP (result), one, 0);
10913 aopPut (AOP (result), zero, 0);
10917 /* the right is also a bit variable */
10918 if (AOP_TYPE (right) == AOP_CRY)
10920 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10921 aopPut (AOP (result), "c", 0);
10925 /* we need to or */
10927 aopPut (AOP (result), "a", 0);
10931 /* bit variables done */
10933 size = AOP_SIZE (result);
10935 if (AOP_TYPE (right) == AOP_LIT)
10936 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10939 (AOP_TYPE (result) != AOP_REG) &&
10940 (AOP_TYPE (right) == AOP_LIT) &&
10941 !IS_FLOAT (operandType (right)))
10943 _startLazyDPSEvaluation ();
10944 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10946 aopPut (AOP (result),
10947 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10952 /* And now fill the rest with zeros. */
10955 emitcode ("clr", "a");
10959 aopPut (AOP (result), "a", offset++);
10961 _endLazyDPSEvaluation ();
10965 _startLazyDPSEvaluation ();
10968 aopPut (AOP (result),
10969 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10973 _endLazyDPSEvaluation ();
10977 freeAsmop (right, NULL, ic, FALSE);
10978 freeAsmop (result, NULL, ic, TRUE);
10981 /*-----------------------------------------------------------------*/
10982 /* genJumpTab - generates code for jump table */
10983 /*-----------------------------------------------------------------*/
10985 genJumpTab (iCode * ic)
10990 D (emitcode (";", "genJumpTab ");
10993 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10994 /* get the condition into accumulator */
10995 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
10997 /* multiply by four! */
10998 emitcode ("add", "a,acc");
10999 emitcode ("add", "a,acc");
11000 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11002 jtab = newiTempLabel (NULL);
11003 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
11004 emitcode ("jmp", "@a+dptr");
11005 emitcode ("", "!tlabeldef", jtab->key + 100);
11006 /* now generate the jump labels */
11007 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11008 jtab = setNextItem (IC_JTLABELS (ic)))
11009 emitcode ("ljmp", "!tlabel", jtab->key + 100);
11013 /*-----------------------------------------------------------------*/
11014 /* genCast - gen code for casting */
11015 /*-----------------------------------------------------------------*/
11017 genCast (iCode * ic)
11019 operand *result = IC_RESULT (ic);
11020 sym_link *ctype = operandType (IC_LEFT (ic));
11021 sym_link *rtype = operandType (IC_RIGHT (ic));
11022 operand *right = IC_RIGHT (ic);
11025 D (emitcode (";", "genCast "););
11027 /* if they are equivalent then do nothing */
11028 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11031 aopOp (right, ic, FALSE, FALSE);
11032 aopOp (result, ic, FALSE, AOP_USESDPTR(right));
11034 /* if the result is a bit */
11035 // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
11036 if (IS_BITVAR(OP_SYMBOL(result)->type))
11038 /* if the right size is a literal then
11039 we know what the value is */
11040 if (AOP_TYPE (right) == AOP_LIT)
11042 if (((int) operandLitValue (right)))
11043 aopPut (AOP (result), one, 0);
11045 aopPut (AOP (result), zero, 0);
11050 /* the right is also a bit variable */
11051 if (AOP_TYPE (right) == AOP_CRY)
11053 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11054 aopPut (AOP (result), "c", 0);
11058 /* we need to or */
11060 aopPut (AOP (result), "a", 0);
11064 /* if they are the same size : or less */
11065 if (AOP_SIZE (result) <= AOP_SIZE (right))
11068 /* if they are in the same place */
11069 if (sameRegs (AOP (right), AOP (result)))
11072 /* if they in different places then copy */
11073 size = AOP_SIZE (result);
11075 _startLazyDPSEvaluation ();
11078 aopPut (AOP (result),
11079 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11083 _endLazyDPSEvaluation ();
11088 /* if the result is of type pointer */
11089 if (IS_PTR (ctype))
11093 sym_link *type = operandType (right);
11095 /* pointer to generic pointer */
11096 if (IS_GENPTR (ctype))
11100 p_type = DCL_TYPE (type);
11104 #if OLD_CAST_BEHAVIOR
11105 /* KV: we are converting a non-pointer type to
11106 * a generic pointer. This (ifdef'd out) code
11107 * says that the resulting generic pointer
11108 * should have the same class as the storage
11109 * location of the non-pointer variable.
11111 * For example, converting an int (which happens
11112 * to be stored in DATA space) to a pointer results
11113 * in a DATA generic pointer; if the original int
11114 * in XDATA space, so will be the resulting pointer.
11116 * I don't like that behavior, and thus this change:
11117 * all such conversions will be forced to XDATA and
11118 * throw a warning. If you want some non-XDATA
11119 * type, or you want to suppress the warning, you
11120 * must go through an intermediate cast, like so:
11122 * char _generic *gp = (char _xdata *)(intVar);
11124 sym_link *etype = getSpec (type);
11126 /* we have to go by the storage class */
11127 if (SPEC_OCLS (etype) != generic)
11129 p_type = PTR_TYPE (SPEC_OCLS (etype));
11134 /* Converting unknown class (i.e. register variable)
11135 * to generic pointer. This is not good, but
11136 * we'll make a guess (and throw a warning).
11139 werror (W_INT_TO_GEN_PTR_CAST);
11143 /* the first two bytes are known */
11144 size = GPTRSIZE - 1;
11146 _startLazyDPSEvaluation ();
11149 aopPut (AOP (result),
11150 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11154 _endLazyDPSEvaluation ();
11156 /* the last byte depending on type */
11158 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11163 // pointerTypeToGPByte will have bitched.
11167 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11168 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11173 /* just copy the pointers */
11174 size = AOP_SIZE (result);
11176 _startLazyDPSEvaluation ();
11179 aopPut (AOP (result),
11180 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11184 _endLazyDPSEvaluation ();
11188 /* so we now know that the size of destination is greater
11189 than the size of the source */
11190 /* we move to result for the size of source */
11191 size = AOP_SIZE (right);
11193 _startLazyDPSEvaluation ();
11196 aopPut (AOP (result),
11197 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11201 _endLazyDPSEvaluation ();
11203 /* now depending on the sign of the source && destination */
11204 size = AOP_SIZE (result) - AOP_SIZE (right);
11205 /* if unsigned or not an integral type */
11206 /* also, if the source is a bit, we don't need to sign extend, because
11207 * it can't possibly have set the sign bit.
11209 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
11213 aopPut (AOP (result), zero, offset++);
11218 /* we need to extend the sign :{ */
11219 MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11220 FALSE, FALSE, NULL));
11221 emitcode ("rlc", "a");
11222 emitcode ("subb", "a,acc");
11224 aopPut (AOP (result), "a", offset++);
11227 /* we are done hurray !!!! */
11230 freeAsmop (right, NULL, ic, TRUE);
11231 freeAsmop (result, NULL, ic, TRUE);
11235 /*-----------------------------------------------------------------*/
11236 /* genDjnz - generate decrement & jump if not zero instrucion */
11237 /*-----------------------------------------------------------------*/
11239 genDjnz (iCode * ic, iCode * ifx)
11241 symbol *lbl, *lbl1;
11245 /* if the if condition has a false label
11246 then we cannot save */
11247 if (IC_FALSE (ifx))
11250 /* if the minus is not of the form
11252 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11253 !IS_OP_LITERAL (IC_RIGHT (ic)))
11256 if (operandLitValue (IC_RIGHT (ic)) != 1)
11259 /* if the size of this greater than one then no
11261 if (getSize (operandType (IC_RESULT (ic))) > 1)
11264 /* otherwise we can save BIG */
11265 D(emitcode(";", "genDjnz"););
11267 lbl = newiTempLabel (NULL);
11268 lbl1 = newiTempLabel (NULL);
11270 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11272 if (AOP_NEEDSACC(IC_RESULT(ic)))
11274 /* If the result is accessed indirectly via
11275 * the accumulator, we must explicitly write
11276 * it back after the decrement.
11278 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11280 if (strcmp(rByte, "a"))
11282 /* Something is hopelessly wrong */
11283 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11284 __FILE__, __LINE__);
11285 /* We can just give up; the generated code will be inefficient,
11286 * but what the hey.
11288 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11291 emitcode ("dec", "%s", rByte);
11292 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11293 emitcode ("jnz", "!tlabel", lbl->key + 100);
11295 else if (IS_AOP_PREG (IC_RESULT (ic)))
11297 emitcode ("dec", "%s",
11298 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11299 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11300 emitcode ("jnz", "!tlabel", lbl->key + 100);
11304 emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11307 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11308 emitcode ("", "!tlabeldef", lbl->key + 100);
11309 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11310 emitcode ("", "!tlabeldef", lbl1->key + 100);
11312 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11313 ifx->generated = 1;
11317 /*-----------------------------------------------------------------*/
11318 /* genReceive - generate code for a receive iCode */
11319 /*-----------------------------------------------------------------*/
11321 genReceive (iCode * ic)
11323 int size = getSize (operandType (IC_RESULT (ic)));
11327 D (emitcode (";", "genReceive "););
11329 if (ic->argreg == 1)
11331 /* first parameter */
11332 if (AOP_IS_STR(IC_RESULT(ic)))
11334 /* Nothing to do: it's already in the proper place. */
11341 useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11342 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11343 IS_TRUE_SYMOP (IC_RESULT (ic)));
11346 aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11349 /* Sanity checking... */
11350 if (AOP_USESDPTR(IC_RESULT(ic)))
11352 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11353 "genReceive got unexpected DPTR.");
11355 assignResultValue (IC_RESULT (ic));
11360 /* second receive onwards */
11361 /* this gets a little tricky since unused recevies will be
11362 eliminated, we have saved the reg in the type field . and
11363 we use that to figure out which register to use */
11364 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11365 rb1off = ic->argreg;
11368 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11371 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11374 /*-----------------------------------------------------------------*/
11375 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
11376 /*-----------------------------------------------------------------*/
11377 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11379 operand *from , *to , *count;
11384 /* we know it has to be 3 parameters */
11385 assert (nparms == 3);
11387 rsave = newBitVect(16);
11388 /* save DPTR if it needs to be saved */
11389 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11390 if (bitVectBitValue(ic->rMask,i))
11391 rsave = bitVectSetBit(rsave,i);
11393 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11394 ds390_rUmaskForOp (IC_RESULT(ic))));
11401 aopOp (from, ic->next, FALSE, FALSE);
11403 /* get from into DPTR1 */
11404 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11405 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11406 if (options.model == MODEL_FLAT24) {
11407 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11410 freeAsmop (from, NULL, ic, FALSE);
11411 aopOp (to, ic, FALSE, FALSE);
11412 /* get "to" into DPTR */
11413 /* if the operand is already in dptr
11414 then we do nothing else we move the value to dptr */
11415 if (AOP_TYPE (to) != AOP_STR) {
11416 /* if already in DPTR then we need to push */
11417 if (AOP_TYPE(to) == AOP_DPTR) {
11418 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11419 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11420 if (options.model == MODEL_FLAT24)
11421 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11422 emitcode ("pop", "dph");
11423 emitcode ("pop", "dpl");
11425 _startLazyDPSEvaluation ();
11426 /* if this is remateriazable */
11427 if (AOP_TYPE (to) == AOP_IMMD) {
11428 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11429 } else { /* we need to get it byte by byte */
11430 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11431 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11432 if (options.model == MODEL_FLAT24) {
11433 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11436 _endLazyDPSEvaluation ();
11439 freeAsmop (to, NULL, ic, FALSE);
11440 _G.dptrInUse = _G.dptr1InUse = 1;
11441 aopOp (count, ic->next->next, FALSE,FALSE);
11442 lbl =newiTempLabel(NULL);
11444 /* now for the actual copy */
11445 if (AOP_TYPE(count) == AOP_LIT &&
11446 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11447 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11449 emitcode ("lcall","__bi_memcpyc2x_s");
11451 emitcode ("lcall","__bi_memcpyx2x_s");
11453 freeAsmop (count, NULL, ic, FALSE);
11455 symbol *lbl1 = newiTempLabel(NULL);
11457 emitcode (";"," Auto increment but no djnz");
11458 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11459 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11460 freeAsmop (count, NULL, ic, FALSE);
11461 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11462 emitcode ("","!tlabeldef",lbl->key+100);
11464 emitcode ("clr","a");
11465 emitcode ("movc", "a,@a+dptr");
11467 emitcode ("movx", "a,@dptr");
11468 emitcode ("movx", "@dptr,a");
11469 emitcode ("inc", "dptr");
11470 emitcode ("inc", "dptr");
11471 emitcode ("mov","a,b");
11472 emitcode ("orl","a,_ap");
11473 emitcode ("jz","!tlabel",lbl1->key+100);
11474 emitcode ("mov","a,_ap");
11475 emitcode ("add","a,#!constbyte",0xFF);
11476 emitcode ("mov","_ap,a");
11477 emitcode ("mov","a,b");
11478 emitcode ("addc","a,#!constbyte",0xFF);
11479 emitcode ("mov","b,a");
11480 emitcode ("sjmp","!tlabel",lbl->key+100);
11481 emitcode ("","!tlabeldef",lbl1->key+100);
11483 emitcode ("mov", "dps,#0");
11484 _G.dptrInUse = _G.dptr1InUse = 0;
11485 unsavermask(rsave);
11489 /*-----------------------------------------------------------------*/
11490 /* genMemcmpX2X - gen code for memcmp xdata to xdata */
11491 /*-----------------------------------------------------------------*/
11492 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11494 operand *from , *to , *count;
11499 /* we know it has to be 3 parameters */
11500 assert (nparms == 3);
11502 rsave = newBitVect(16);
11503 /* save DPTR if it needs to be saved */
11504 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11505 if (bitVectBitValue(ic->rMask,i))
11506 rsave = bitVectSetBit(rsave,i);
11508 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11509 ds390_rUmaskForOp (IC_RESULT(ic))));
11516 aopOp (from, ic->next, FALSE, FALSE);
11518 /* get from into DPTR1 */
11519 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11520 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11521 if (options.model == MODEL_FLAT24) {
11522 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11525 freeAsmop (from, NULL, ic, FALSE);
11526 aopOp (to, ic, FALSE, FALSE);
11527 /* get "to" into DPTR */
11528 /* if the operand is already in dptr
11529 then we do nothing else we move the value to dptr */
11530 if (AOP_TYPE (to) != AOP_STR) {
11531 /* if already in DPTR then we need to push */
11532 if (AOP_TYPE(to) == AOP_DPTR) {
11533 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11534 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11535 if (options.model == MODEL_FLAT24)
11536 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11537 emitcode ("pop", "dph");
11538 emitcode ("pop", "dpl");
11540 _startLazyDPSEvaluation ();
11541 /* if this is remateriazable */
11542 if (AOP_TYPE (to) == AOP_IMMD) {
11543 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11544 } else { /* we need to get it byte by byte */
11545 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11546 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11547 if (options.model == MODEL_FLAT24) {
11548 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11551 _endLazyDPSEvaluation ();
11554 freeAsmop (to, NULL, ic, FALSE);
11555 _G.dptrInUse = _G.dptr1InUse = 1;
11556 aopOp (count, ic->next->next, FALSE,FALSE);
11557 lbl =newiTempLabel(NULL);
11558 lbl2 =newiTempLabel(NULL);
11560 /* now for the actual compare */
11561 if (AOP_TYPE(count) == AOP_LIT &&
11562 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11563 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11565 emitcode("lcall","__bi_memcmpc2x_s");
11567 emitcode("lcall","__bi_memcmpx2x_s");
11568 freeAsmop (count, NULL, ic, FALSE);
11569 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11570 aopPut(AOP(IC_RESULT(ic)),"a",0);
11571 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11573 symbol *lbl1 = newiTempLabel(NULL);
11575 emitcode("push","ar0");
11576 emitcode (";"," Auto increment but no djnz");
11577 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11578 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11579 freeAsmop (count, NULL, ic, FALSE);
11580 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11581 emitcode ("","!tlabeldef",lbl->key+100);
11583 emitcode ("clr","a");
11584 emitcode ("movc", "a,@a+dptr");
11586 emitcode ("movx", "a,@dptr");
11587 emitcode ("mov","r0,a");
11588 emitcode ("movx", "a,@dptr");
11589 emitcode ("clr","c");
11590 emitcode ("subb","a,r0");
11591 emitcode ("jnz","!tlabel",lbl2->key+100);
11592 emitcode ("inc", "dptr");
11593 emitcode ("inc", "dptr");
11594 emitcode ("mov","a,b");
11595 emitcode ("orl","a,_ap");
11596 emitcode ("jz","!tlabel",lbl1->key+100);
11597 emitcode ("mov","a,_ap");
11598 emitcode ("add","a,#!constbyte",0xFF);
11599 emitcode ("mov","_ap,a");
11600 emitcode ("mov","a,b");
11601 emitcode ("addc","a,#!constbyte",0xFF);
11602 emitcode ("mov","b,a");
11603 emitcode ("sjmp","!tlabel",lbl->key+100);
11604 emitcode ("","!tlabeldef",lbl1->key+100);
11605 emitcode ("clr","a");
11606 emitcode ("","!tlabeldef",lbl2->key+100);
11607 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11608 aopPut(AOP(IC_RESULT(ic)),"a",0);
11609 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11610 emitcode("pop","ar0");
11611 emitcode ("mov", "dps,#0");
11613 _G.dptrInUse = _G.dptr1InUse = 0;
11614 unsavermask(rsave);
11618 /*-----------------------------------------------------------------*/
11619 /* genInp - gen code for __builtin_inp read data from a mem mapped */
11620 /* port, first parameter output area second parameter pointer to */
11621 /* port third parameter count */
11622 /*-----------------------------------------------------------------*/
11623 static void genInp( iCode *ic, int nparms, operand **parms)
11625 operand *from , *to , *count;
11630 /* we know it has to be 3 parameters */
11631 assert (nparms == 3);
11633 rsave = newBitVect(16);
11634 /* save DPTR if it needs to be saved */
11635 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11636 if (bitVectBitValue(ic->rMask,i))
11637 rsave = bitVectSetBit(rsave,i);
11639 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11640 ds390_rUmaskForOp (IC_RESULT(ic))));
11647 aopOp (from, ic->next, FALSE, FALSE);
11649 /* get from into DPTR1 */
11650 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11651 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11652 if (options.model == MODEL_FLAT24) {
11653 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11656 freeAsmop (from, NULL, ic, FALSE);
11657 aopOp (to, ic, FALSE, FALSE);
11658 /* get "to" into DPTR */
11659 /* if the operand is already in dptr
11660 then we do nothing else we move the value to dptr */
11661 if (AOP_TYPE (to) != AOP_STR) {
11662 /* if already in DPTR then we need to push */
11663 if (AOP_TYPE(to) == AOP_DPTR) {
11664 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11665 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11666 if (options.model == MODEL_FLAT24)
11667 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11668 emitcode ("pop", "dph");
11669 emitcode ("pop", "dpl");
11671 _startLazyDPSEvaluation ();
11672 /* if this is remateriazable */
11673 if (AOP_TYPE (to) == AOP_IMMD) {
11674 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11675 } else { /* we need to get it byte by byte */
11676 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11677 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11678 if (options.model == MODEL_FLAT24) {
11679 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11682 _endLazyDPSEvaluation ();
11685 freeAsmop (to, NULL, ic, FALSE);
11687 _G.dptrInUse = _G.dptr1InUse = 1;
11688 aopOp (count, ic->next->next, FALSE,FALSE);
11689 lbl =newiTempLabel(NULL);
11691 /* now for the actual copy */
11692 if (AOP_TYPE(count) == AOP_LIT &&
11693 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11694 emitcode (";","OH JOY auto increment with djnz (very fast)");
11695 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11696 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11697 freeAsmop (count, NULL, ic, FALSE);
11698 emitcode ("","!tlabeldef",lbl->key+100);
11699 emitcode ("movx", "a,@dptr"); /* read data from port */
11700 emitcode ("dec","dps"); /* switch to DPTR */
11701 emitcode ("movx", "@dptr,a"); /* save into location */
11702 emitcode ("inc", "dptr"); /* point to next area */
11703 emitcode ("inc","dps"); /* switch to DPTR2 */
11704 emitcode ("djnz","b,!tlabel",lbl->key+100);
11706 symbol *lbl1 = newiTempLabel(NULL);
11708 emitcode (";"," Auto increment but no djnz");
11709 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11710 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11711 freeAsmop (count, NULL, ic, FALSE);
11712 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11713 emitcode ("","!tlabeldef",lbl->key+100);
11714 emitcode ("movx", "a,@dptr");
11715 emitcode ("dec","dps"); /* switch to DPTR */
11716 emitcode ("movx", "@dptr,a");
11717 emitcode ("inc", "dptr");
11718 emitcode ("inc","dps"); /* switch to DPTR2 */
11719 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
11720 /* emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
11721 emitcode ("mov","a,b");
11722 emitcode ("orl","a,_ap");
11723 emitcode ("jz","!tlabel",lbl1->key+100);
11724 emitcode ("mov","a,_ap");
11725 emitcode ("add","a,#!constbyte",0xFF);
11726 emitcode ("mov","_ap,a");
11727 emitcode ("mov","a,b");
11728 emitcode ("addc","a,#!constbyte",0xFF);
11729 emitcode ("mov","b,a");
11730 emitcode ("sjmp","!tlabel",lbl->key+100);
11731 emitcode ("","!tlabeldef",lbl1->key+100);
11733 emitcode ("mov", "dps,#0");
11734 _G.dptrInUse = _G.dptr1InUse = 0;
11735 unsavermask(rsave);
11739 /*-----------------------------------------------------------------*/
11740 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
11741 /* port, first parameter output area second parameter pointer to */
11742 /* port third parameter count */
11743 /*-----------------------------------------------------------------*/
11744 static void genOutp( iCode *ic, int nparms, operand **parms)
11746 operand *from , *to , *count;
11751 /* we know it has to be 3 parameters */
11752 assert (nparms == 3);
11754 rsave = newBitVect(16);
11755 /* save DPTR if it needs to be saved */
11756 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11757 if (bitVectBitValue(ic->rMask,i))
11758 rsave = bitVectSetBit(rsave,i);
11760 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11761 ds390_rUmaskForOp (IC_RESULT(ic))));
11768 aopOp (from, ic->next, FALSE, FALSE);
11770 /* get from into DPTR1 */
11771 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11772 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11773 if (options.model == MODEL_FLAT24) {
11774 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11777 freeAsmop (from, NULL, ic, FALSE);
11778 aopOp (to, ic, FALSE, FALSE);
11779 /* get "to" into DPTR */
11780 /* if the operand is already in dptr
11781 then we do nothing else we move the value to dptr */
11782 if (AOP_TYPE (to) != AOP_STR) {
11783 /* if already in DPTR then we need to push */
11784 if (AOP_TYPE(to) == AOP_DPTR) {
11785 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11786 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11787 if (options.model == MODEL_FLAT24)
11788 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11789 emitcode ("pop", "dph");
11790 emitcode ("pop", "dpl");
11792 _startLazyDPSEvaluation ();
11793 /* if this is remateriazable */
11794 if (AOP_TYPE (to) == AOP_IMMD) {
11795 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11796 } else { /* we need to get it byte by byte */
11797 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11798 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11799 if (options.model == MODEL_FLAT24) {
11800 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11803 _endLazyDPSEvaluation ();
11806 freeAsmop (to, NULL, ic, FALSE);
11808 _G.dptrInUse = _G.dptr1InUse = 1;
11809 aopOp (count, ic->next->next, FALSE,FALSE);
11810 lbl =newiTempLabel(NULL);
11812 /* now for the actual copy */
11813 if (AOP_TYPE(count) == AOP_LIT &&
11814 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11815 emitcode (";","OH JOY auto increment with djnz (very fast)");
11816 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
11817 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11818 emitcode ("","!tlabeldef",lbl->key+100);
11819 emitcode ("movx", "a,@dptr"); /* read data from port */
11820 emitcode ("inc","dps"); /* switch to DPTR2 */
11821 emitcode ("movx", "@dptr,a"); /* save into location */
11822 emitcode ("inc", "dptr"); /* point to next area */
11823 emitcode ("dec","dps"); /* switch to DPTR */
11824 emitcode ("djnz","b,!tlabel",lbl->key+100);
11825 freeAsmop (count, NULL, ic, FALSE);
11827 symbol *lbl1 = newiTempLabel(NULL);
11829 emitcode (";"," Auto increment but no djnz");
11830 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11831 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11832 freeAsmop (count, NULL, ic, FALSE);
11833 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
11834 emitcode ("","!tlabeldef",lbl->key+100);
11835 emitcode ("movx", "a,@dptr");
11836 emitcode ("inc", "dptr");
11837 emitcode ("inc","dps"); /* switch to DPTR2 */
11838 emitcode ("movx", "@dptr,a");
11839 emitcode ("dec","dps"); /* switch to DPTR */
11840 emitcode ("mov","a,b");
11841 emitcode ("orl","a,_ap");
11842 emitcode ("jz","!tlabel",lbl1->key+100);
11843 emitcode ("mov","a,_ap");
11844 emitcode ("add","a,#!constbyte",0xFF);
11845 emitcode ("mov","_ap,a");
11846 emitcode ("mov","a,b");
11847 emitcode ("addc","a,#!constbyte",0xFF);
11848 emitcode ("mov","b,a");
11849 emitcode ("sjmp","!tlabel",lbl->key+100);
11850 emitcode ("","!tlabeldef",lbl1->key+100);
11852 emitcode ("mov", "dps,#0");
11853 _G.dptrInUse = _G.dptr1InUse = 0;
11854 unsavermask(rsave);
11858 /*-----------------------------------------------------------------*/
11859 /* genSwapW - swap lower & high order bytes */
11860 /*-----------------------------------------------------------------*/
11861 static void genSwapW(iCode *ic, int nparms, operand **parms)
11865 assert (nparms==1);
11868 dest=IC_RESULT(ic);
11870 assert(getSize(operandType(src))==2);
11872 aopOp (src, ic, FALSE, FALSE);
11873 emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
11875 MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
11877 freeAsmop (src, NULL, ic, FALSE);
11879 aopOp (dest,ic, FALSE, FALSE);
11880 aopPut(AOP(dest),"b",0);
11881 aopPut(AOP(dest),"a",1);
11882 freeAsmop (dest, NULL, ic, FALSE);
11885 /*-----------------------------------------------------------------*/
11886 /* genMemsetX - gencode for memSetX data */
11887 /*-----------------------------------------------------------------*/
11888 static void genMemsetX(iCode *ic, int nparms, operand **parms)
11890 operand *to , *val , *count;
11896 /* we know it has to be 3 parameters */
11897 assert (nparms == 3);
11903 /* save DPTR if it needs to be saved */
11904 rsave = newBitVect(16);
11905 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11906 if (bitVectBitValue(ic->rMask,i))
11907 rsave = bitVectSetBit(rsave,i);
11909 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11910 ds390_rUmaskForOp (IC_RESULT(ic))));
11913 aopOp (to, ic, FALSE, FALSE);
11914 /* get "to" into DPTR */
11915 /* if the operand is already in dptr
11916 then we do nothing else we move the value to dptr */
11917 if (AOP_TYPE (to) != AOP_STR) {
11918 /* if already in DPTR then we need to push */
11919 if (AOP_TYPE(to) == AOP_DPTR) {
11920 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11921 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11922 if (options.model == MODEL_FLAT24)
11923 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11924 emitcode ("pop", "dph");
11925 emitcode ("pop", "dpl");
11927 _startLazyDPSEvaluation ();
11928 /* if this is remateriazable */
11929 if (AOP_TYPE (to) == AOP_IMMD) {
11930 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11931 } else { /* we need to get it byte by byte */
11932 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11933 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11934 if (options.model == MODEL_FLAT24) {
11935 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11938 _endLazyDPSEvaluation ();
11941 freeAsmop (to, NULL, ic, FALSE);
11943 aopOp (val, ic->next->next, FALSE,FALSE);
11944 aopOp (count, ic->next->next, FALSE,FALSE);
11945 lbl =newiTempLabel(NULL);
11946 /* now for the actual copy */
11947 if (AOP_TYPE(count) == AOP_LIT &&
11948 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11949 l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
11950 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11952 emitcode ("","!tlabeldef",lbl->key+100);
11953 emitcode ("movx", "@dptr,a");
11954 emitcode ("inc", "dptr");
11955 emitcode ("djnz","b,!tlabel",lbl->key+100);
11957 symbol *lbl1 = newiTempLabel(NULL);
11959 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11960 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11961 emitcode ("","!tlabeldef",lbl->key+100);
11962 MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
11963 emitcode ("movx", "@dptr,a");
11964 emitcode ("inc", "dptr");
11965 emitcode ("mov","a,b");
11966 emitcode ("orl","a,_ap");
11967 emitcode ("jz","!tlabel",lbl1->key+100);
11968 emitcode ("mov","a,_ap");
11969 emitcode ("add","a,#!constbyte",0xFF);
11970 emitcode ("mov","_ap,a");
11971 emitcode ("mov","a,b");
11972 emitcode ("addc","a,#!constbyte",0xFF);
11973 emitcode ("mov","b,a");
11974 emitcode ("sjmp","!tlabel",lbl->key+100);
11975 emitcode ("","!tlabeldef",lbl1->key+100);
11977 freeAsmop (count, NULL, ic, FALSE);
11978 unsavermask(rsave);
11981 /*-----------------------------------------------------------------*/
11982 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
11983 /*-----------------------------------------------------------------*/
11984 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
11987 operand *pnum, *result;
11990 assert (nparms==1);
11991 /* save registers that need to be saved */
11992 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11993 ds390_rUmaskForOp (IC_RESULT(ic))));
11996 aopOp (pnum, ic, FALSE, FALSE);
11997 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
11998 freeAsmop (pnum, NULL, ic, FALSE);
11999 emitcode ("lcall","NatLib_LoadPrimitive");
12000 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12001 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
12002 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
12003 for (i = (size-1) ; i >= 0 ; i-- ) {
12004 emitcode ("push","a%s",javaRet[i]);
12006 for (i=0; i < size ; i++ ) {
12007 emitcode ("pop","a%s",
12008 aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
12011 for (i = 0 ; i < size ; i++ ) {
12012 aopPut(AOP(result),javaRet[i],i);
12015 freeAsmop (result, NULL, ic, FALSE);
12016 unsavermask(rsave);
12019 /*-----------------------------------------------------------------*/
12020 /* genNatLibLoadPointer - calls TINI api function to load pointer */
12021 /*-----------------------------------------------------------------*/
12022 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
12025 operand *pnum, *result;
12029 assert (nparms==1);
12030 /* save registers that need to be saved */
12031 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12032 ds390_rUmaskForOp (IC_RESULT(ic))));
12035 aopOp (pnum, ic, FALSE, FALSE);
12036 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12037 freeAsmop (pnum, NULL, ic, FALSE);
12038 emitcode ("lcall","NatLib_LoadPointer");
12039 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12040 if (AOP_TYPE(result)!=AOP_STR) {
12041 for (i = 0 ; i < size ; i++ ) {
12042 aopPut(AOP(result),fReturn[i],i);
12045 freeAsmop (result, NULL, ic, FALSE);
12046 unsavermask(rsave);
12049 /*-----------------------------------------------------------------*/
12050 /* genNatLibInstallStateBlock - */
12051 /*-----------------------------------------------------------------*/
12052 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
12053 operand **parms, const char *name)
12056 operand *psb, *handle;
12057 assert (nparms==2);
12059 /* save registers that need to be saved */
12060 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12061 ds390_rUmaskForOp (IC_RESULT(ic))));
12065 /* put pointer to state block into DPTR1 */
12066 aopOp (psb, ic, FALSE, FALSE);
12067 if (AOP_TYPE (psb) == AOP_IMMD) {
12068 emitcode ("mov","dps,#1");
12069 emitcode ("mov", "dptr,%s",
12070 aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12071 emitcode ("mov","dps,#0");
12073 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12074 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12075 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12077 freeAsmop (psb, NULL, ic, FALSE);
12079 /* put libraryID into DPTR */
12080 emitcode ("mov","dptr,#LibraryID");
12082 /* put handle into r3:r2 */
12083 aopOp (handle, ic, FALSE, FALSE);
12084 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12085 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12086 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12087 emitcode ("pop","ar3");
12088 emitcode ("pop","ar2");
12090 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12091 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12093 freeAsmop (psb, NULL, ic, FALSE);
12095 /* make the call */
12096 emitcode ("lcall","NatLib_Install%sStateBlock",name);
12098 /* put return value into place*/
12100 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12102 aopPut(AOP(IC_RESULT(ic)),"a",0);
12103 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12104 unsavermask(rsave);
12107 /*-----------------------------------------------------------------*/
12108 /* genNatLibRemoveStateBlock - */
12109 /*-----------------------------------------------------------------*/
12110 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12116 /* save registers that need to be saved */
12117 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12118 ds390_rUmaskForOp (IC_RESULT(ic))));
12120 /* put libraryID into DPTR */
12121 emitcode ("mov","dptr,#LibraryID");
12122 /* make the call */
12123 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12124 unsavermask(rsave);
12127 /*-----------------------------------------------------------------*/
12128 /* genNatLibGetStateBlock - */
12129 /*-----------------------------------------------------------------*/
12130 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12131 operand **parms,const char *name)
12134 symbol *lbl = newiTempLabel(NULL);
12137 /* save registers that need to be saved */
12138 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12139 ds390_rUmaskForOp (IC_RESULT(ic))));
12141 /* put libraryID into DPTR */
12142 emitcode ("mov","dptr,#LibraryID");
12143 /* make the call */
12144 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12145 emitcode ("jnz","!tlabel",lbl->key+100);
12147 /* put return value into place */
12148 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12149 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12150 emitcode ("push","ar3");
12151 emitcode ("push","ar2");
12152 emitcode ("pop","%s",
12153 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12154 emitcode ("pop","%s",
12155 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12157 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12158 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12160 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12161 emitcode ("","!tlabeldef",lbl->key+100);
12162 unsavermask(rsave);
12165 /*-----------------------------------------------------------------*/
12166 /* genMMMalloc - */
12167 /*-----------------------------------------------------------------*/
12168 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12169 int size, const char *name)
12174 symbol *lbl = newiTempLabel(NULL);
12176 assert (nparms == 1);
12177 /* save registers that need to be saved */
12178 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12179 ds390_rUmaskForOp (IC_RESULT(ic))));
12182 aopOp (bsize,ic,FALSE,FALSE);
12184 /* put the size in R4-R2 */
12185 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12186 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12187 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12189 emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12190 emitcode("pop","ar4");
12192 emitcode("pop","ar3");
12193 emitcode("pop","ar2");
12195 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12196 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12198 emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12201 freeAsmop (bsize, NULL, ic, FALSE);
12203 /* make the call */
12204 emitcode ("lcall","MM_%s",name);
12205 emitcode ("jz","!tlabel",lbl->key+100);
12206 emitcode ("mov","r2,#!constbyte",0xff);
12207 emitcode ("mov","r3,#!constbyte",0xff);
12208 emitcode ("","!tlabeldef",lbl->key+100);
12209 /* we don't care about the pointer : we just save the handle */
12210 rsym = OP_SYMBOL(IC_RESULT(ic));
12211 if (rsym->liveFrom != rsym->liveTo) {
12212 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12213 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12214 emitcode ("push","ar3");
12215 emitcode ("push","ar2");
12216 emitcode ("pop","%s",
12217 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12218 emitcode ("pop","%s",
12219 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12221 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12222 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12224 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12226 unsavermask(rsave);
12229 /*-----------------------------------------------------------------*/
12231 /*-----------------------------------------------------------------*/
12232 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12237 assert (nparms == 1);
12238 /* save registers that need to be saved */
12239 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12240 ds390_rUmaskForOp (IC_RESULT(ic))));
12243 aopOp (handle,ic,FALSE,FALSE);
12245 /* put the size in R4-R2 */
12246 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12247 emitcode("push","%s",
12248 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12249 emitcode("push","%s",
12250 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12251 emitcode("pop","ar3");
12252 emitcode("pop","ar2");
12254 emitcode ("mov","r2,%s",
12255 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12256 emitcode ("mov","r3,%s",
12257 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12259 freeAsmop (handle, NULL, ic, FALSE);
12261 /* make the call */
12262 emitcode ("lcall","MM_Deref");
12265 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12266 if (rsym->liveFrom != rsym->liveTo) {
12267 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12268 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12269 _startLazyDPSEvaluation ();
12271 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12272 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12273 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12275 _endLazyDPSEvaluation ();
12280 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12281 unsavermask(rsave);
12284 /*-----------------------------------------------------------------*/
12285 /* genMMUnrestrictedPersist - */
12286 /*-----------------------------------------------------------------*/
12287 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12292 assert (nparms == 1);
12293 /* save registers that need to be saved */
12294 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12295 ds390_rUmaskForOp (IC_RESULT(ic))));
12298 aopOp (handle,ic,FALSE,FALSE);
12300 /* put the size in R3-R2 */
12301 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12302 emitcode("push","%s",
12303 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12304 emitcode("push","%s",
12305 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12306 emitcode("pop","ar3");
12307 emitcode("pop","ar2");
12309 emitcode ("mov","r2,%s",
12310 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12311 emitcode ("mov","r3,%s",
12312 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12314 freeAsmop (handle, NULL, ic, FALSE);
12316 /* make the call */
12317 emitcode ("lcall","MM_UnrestrictedPersist");
12320 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12321 if (rsym->liveFrom != rsym->liveTo) {
12322 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12323 aopPut(AOP(IC_RESULT(ic)),"a",0);
12324 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12327 unsavermask(rsave);
12330 /*-----------------------------------------------------------------*/
12331 /* genSystemExecJavaProcess - */
12332 /*-----------------------------------------------------------------*/
12333 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12336 operand *handle, *pp;
12338 assert (nparms==2);
12339 /* save registers that need to be saved */
12340 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12341 ds390_rUmaskForOp (IC_RESULT(ic))));
12346 /* put the handle in R3-R2 */
12347 aopOp (handle,ic,FALSE,FALSE);
12348 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12349 emitcode("push","%s",
12350 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12351 emitcode("push","%s",
12352 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12353 emitcode("pop","ar3");
12354 emitcode("pop","ar2");
12356 emitcode ("mov","r2,%s",
12357 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12358 emitcode ("mov","r3,%s",
12359 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12361 freeAsmop (handle, NULL, ic, FALSE);
12363 /* put pointer in DPTR */
12364 aopOp (pp,ic,FALSE,FALSE);
12365 if (AOP_TYPE(pp) == AOP_IMMD) {
12366 emitcode ("mov", "dptr,%s",
12367 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12368 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12369 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12370 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12371 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12373 freeAsmop (handle, NULL, ic, FALSE);
12375 /* make the call */
12376 emitcode ("lcall","System_ExecJavaProcess");
12378 /* put result in place */
12380 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12381 if (rsym->liveFrom != rsym->liveTo) {
12382 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12383 aopPut(AOP(IC_RESULT(ic)),"a",0);
12384 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12388 unsavermask(rsave);
12391 /*-----------------------------------------------------------------*/
12392 /* genSystemRTCRegisters - */
12393 /*-----------------------------------------------------------------*/
12394 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12400 assert (nparms==1);
12401 /* save registers that need to be saved */
12402 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12403 ds390_rUmaskForOp (IC_RESULT(ic))));
12406 /* put pointer in DPTR */
12407 aopOp (pp,ic,FALSE,FALSE);
12408 if (AOP_TYPE (pp) == AOP_IMMD) {
12409 emitcode ("mov","dps,#1");
12410 emitcode ("mov", "dptr,%s",
12411 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12412 emitcode ("mov","dps,#0");
12414 emitcode ("mov","dpl1,%s",
12415 aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12416 emitcode ("mov","dph1,%s",
12417 aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12418 emitcode ("mov","dpx1,%s",
12419 aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12421 freeAsmop (pp, NULL, ic, FALSE);
12423 /* make the call */
12424 emitcode ("lcall","System_%sRTCRegisters",name);
12426 unsavermask(rsave);
12429 /*-----------------------------------------------------------------*/
12430 /* genSystemThreadSleep - */
12431 /*-----------------------------------------------------------------*/
12432 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12437 assert (nparms==1);
12438 /* save registers that need to be saved */
12439 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12440 ds390_rUmaskForOp (IC_RESULT(ic))));
12443 aopOp(to,ic,FALSE,FALSE);
12444 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12445 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12446 emitcode ("push","%s",
12447 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12448 emitcode ("push","%s",
12449 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12450 emitcode ("push","%s",
12451 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12452 emitcode ("push","%s",
12453 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12454 emitcode ("pop","ar3");
12455 emitcode ("pop","ar2");
12456 emitcode ("pop","ar1");
12457 emitcode ("pop","ar0");
12459 emitcode ("mov","r0,%s",
12460 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12461 emitcode ("mov","r1,%s",
12462 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12463 emitcode ("mov","r2,%s",
12464 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12465 emitcode ("mov","r3,%s",
12466 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12468 freeAsmop (to, NULL, ic, FALSE);
12470 /* suspend in acc */
12472 aopOp(s,ic,FALSE,FALSE);
12473 emitcode ("mov","a,%s",
12474 aopGet(AOP(s),0,FALSE,TRUE,NULL));
12475 freeAsmop (s, NULL, ic, FALSE);
12477 /* make the call */
12478 emitcode ("lcall","System_%s",name);
12480 unsavermask(rsave);
12483 /*-----------------------------------------------------------------*/
12484 /* genSystemThreadResume - */
12485 /*-----------------------------------------------------------------*/
12486 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12491 assert (nparms==2);
12492 /* save registers that need to be saved */
12493 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12494 ds390_rUmaskForOp (IC_RESULT(ic))));
12500 aopOp(pid,ic,FALSE,FALSE);
12501 emitcode ("mov","r0,%s",
12502 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12503 freeAsmop (pid, NULL, ic, FALSE);
12506 aopOp(tid,ic,FALSE,FALSE);
12507 emitcode ("mov","a,%s",
12508 aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
12509 freeAsmop (tid, NULL, ic, FALSE);
12511 emitcode ("lcall","System_ThreadResume");
12513 /* put result into place */
12515 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12516 if (rsym->liveFrom != rsym->liveTo) {
12517 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12518 aopPut(AOP(IC_RESULT(ic)),"a",0);
12519 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12522 unsavermask(rsave);
12525 /*-----------------------------------------------------------------*/
12526 /* genSystemProcessResume - */
12527 /*-----------------------------------------------------------------*/
12528 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
12533 assert (nparms==1);
12534 /* save registers that need to be saved */
12535 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12536 ds390_rUmaskForOp (IC_RESULT(ic))));
12541 aopOp(pid,ic,FALSE,FALSE);
12542 emitcode ("mov","a,%s",
12543 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12544 freeAsmop (pid, NULL, ic, FALSE);
12546 emitcode ("lcall","System_ProcessResume");
12548 unsavermask(rsave);
12551 /*-----------------------------------------------------------------*/
12553 /*-----------------------------------------------------------------*/
12554 static void genSystem (iCode *ic,int nparms,char *name)
12556 assert(nparms == 0);
12558 emitcode ("lcall","System_%s",name);
12561 /*-----------------------------------------------------------------*/
12562 /* genSystemPoll - */
12563 /*-----------------------------------------------------------------*/
12564 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
12569 assert (nparms==1);
12570 /* save registers that need to be saved */
12571 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12572 ds390_rUmaskForOp (IC_RESULT(ic))));
12575 aopOp (fp,ic,FALSE,FALSE);
12576 if (AOP_TYPE (fp) == AOP_IMMD) {
12577 emitcode ("mov", "dptr,%s",
12578 aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
12579 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
12580 emitcode ("mov","dpl,%s",
12581 aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
12582 emitcode ("mov","dph,%s",
12583 aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
12584 emitcode ("mov","dpx,%s",
12585 aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
12587 freeAsmop (fp, NULL, ic, FALSE);
12589 emitcode ("lcall","System_%sPoll",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);
12600 unsavermask(rsave);
12603 /*-----------------------------------------------------------------*/
12604 /* genSystemGetCurrentID - */
12605 /*-----------------------------------------------------------------*/
12606 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
12608 assert (nparms==0);
12610 emitcode ("lcall","System_GetCurrent%sId",name);
12611 /* put result into place */
12613 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12614 if (rsym->liveFrom != rsym->liveTo) {
12615 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12616 aopPut(AOP(IC_RESULT(ic)),"a",0);
12617 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12622 /*-----------------------------------------------------------------*/
12623 /* genDummyRead - generate code for dummy read of volatiles */
12624 /*-----------------------------------------------------------------*/
12626 genDummyRead (iCode * ic)
12631 D(emitcode("; genDummyRead",""));
12633 right = IC_RIGHT (ic);
12635 aopOp (right, ic, FALSE, FALSE);
12637 /* if the result is a bit */
12638 if (AOP_TYPE (right) == AOP_CRY)
12640 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
12644 /* bit variables done */
12646 size = AOP_SIZE (right);
12650 emitcode ("mov", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
12655 freeAsmop (right, NULL, ic, TRUE);
12658 /*-----------------------------------------------------------------*/
12659 /* genBuiltIn - calls the appropriate function to generating code */
12660 /* for a built in function */
12661 /*-----------------------------------------------------------------*/
12662 static void genBuiltIn (iCode *ic)
12664 operand *bi_parms[MAX_BUILTIN_ARGS];
12669 /* get all the arguments for a built in function */
12670 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
12672 /* which function is it */
12673 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
12674 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
12675 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
12676 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
12677 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
12678 } else if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
12679 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
12680 } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
12681 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
12682 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
12683 genMemsetX(bi_iCode,nbi_parms,bi_parms);
12684 } else if (strcmp(bif->name,"__builtin_inp")==0) {
12685 genInp(bi_iCode,nbi_parms,bi_parms);
12686 } else if (strcmp(bif->name,"__builtin_outp")==0) {
12687 genOutp(bi_iCode,nbi_parms,bi_parms);
12688 } else if (strcmp(bif->name,"__builtin_swapw")==0) {
12689 genSwapW(bi_iCode,nbi_parms,bi_parms);
12690 /* JavaNative builtIns */
12691 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
12692 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
12693 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
12694 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
12695 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
12696 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
12697 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
12698 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
12699 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
12700 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12701 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
12702 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12703 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
12704 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
12705 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
12706 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
12707 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
12708 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12709 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
12710 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12711 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
12712 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
12713 } else if (strcmp(bif->name,"MM_Malloc")==0) {
12714 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
12715 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
12716 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
12717 } else if (strcmp(bif->name,"MM_Free")==0) {
12718 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
12719 } else if (strcmp(bif->name,"MM_Deref")==0) {
12720 genMMDeref(bi_iCode,nbi_parms,bi_parms);
12721 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
12722 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
12723 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
12724 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
12725 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
12726 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
12727 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
12728 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
12729 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
12730 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
12731 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
12732 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
12733 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
12734 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
12735 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
12736 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
12737 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12738 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12739 } else if (strcmp(bif->name,"System_SaveThread")==0) {
12740 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12741 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12742 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12743 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
12744 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
12745 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
12746 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
12747 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
12748 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
12749 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
12750 genSystem(bi_iCode,nbi_parms,"ProcessYield");
12751 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
12752 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
12753 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
12754 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
12755 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
12756 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
12757 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
12758 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
12759 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
12760 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
12762 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
12768 /*-----------------------------------------------------------------*/
12769 /* gen390Code - generate code for Dallas 390 based controllers */
12770 /*-----------------------------------------------------------------*/
12772 gen390Code (iCode * lic)
12777 lineHead = lineCurr = NULL;
12778 dptrn[1][0] = "dpl1";
12779 dptrn[1][1] = "dph1";
12780 dptrn[1][2] = "dpx1";
12782 if (options.model == MODEL_FLAT24) {
12783 fReturnSizeDS390 = 5;
12784 fReturn = fReturn24;
12786 fReturnSizeDS390 = 4;
12787 fReturn = fReturn16;
12788 options.stack10bit=0;
12791 /* print the allocation information */
12792 if (allocInfo && currFunc)
12793 printAllocInfo (currFunc, codeOutFile);
12795 /* if debug information required */
12796 if (options.debug && currFunc)
12798 debugFile->writeFunction(currFunc);
12800 if (IS_STATIC (currFunc->etype))
12801 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
12803 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
12806 /* stack pointer name */
12807 if (options.useXstack)
12813 for (ic = lic; ic; ic = ic->next)
12816 if (ic->lineno && cln != ic->lineno)
12821 emitcode ("", "C$%s$%d$%d$%d ==.",
12822 FileBaseName (ic->filename), ic->lineno,
12823 ic->level, ic->block);
12826 if (!options.noCcodeInAsm) {
12827 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
12828 printCLine(ic->filename, ic->lineno));
12832 if (options.iCodeInAsm) {
12833 emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
12835 /* if the result is marked as
12836 spilt and rematerializable or code for
12837 this has already been generated then
12839 if (resultRemat (ic) || ic->generated)
12842 /* depending on the operation */
12862 /* IPOP happens only when trying to restore a
12863 spilt live range, if there is an ifx statement
12864 following this pop then the if statement might
12865 be using some of the registers being popped which
12866 would destory the contents of the register so
12867 we need to check for this condition and handle it */
12869 ic->next->op == IFX &&
12870 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
12871 genIfx (ic->next, ic);
12889 genEndFunction (ic);
12909 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
12926 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
12930 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
12937 /* note these two are xlated by algebraic equivalence
12938 during parsing SDCC.y */
12939 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12940 "got '>=' or '<=' shouldn't have come here");
12944 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
12956 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
12960 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
12964 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
12988 genRightShift (ic);
12991 case GET_VALUE_AT_ADDRESS:
12992 genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
12996 if (POINTER_SET (ic))
12997 genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
13023 if (ic->builtinSEND) genBuiltIn(ic);
13024 else addSet (&_G.sendSet, ic);
13027 case DUMMY_READ_VOLATILE:
13031 #if 0 // obsolete, and buggy for != xdata
13043 /* now we are ready to call the
13044 peep hole optimizer */
13045 if (!options.nopeep)
13046 peepHole (&lineHead);
13048 /* now do the actual printing */
13049 printLine (lineHead, codeOutFile);