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."); \
1611 /*-----------------------------------------------------------------*/
1612 /* opIsGptr: returns non-zero if the passed operand is */
1613 /* a generic pointer type. */
1614 /*-----------------------------------------------------------------*/
1616 opIsGptr (operand * op)
1618 sym_link *type = operandType (op);
1620 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1627 /*-----------------------------------------------------------------*/
1628 /* getDataSize - get the operand data size */
1629 /*-----------------------------------------------------------------*/
1631 getDataSize (operand * op)
1634 size = AOP_SIZE (op);
1635 if (size == GPTRSIZE)
1637 sym_link *type = operandType (op);
1638 if (IS_GENPTR (type))
1640 /* generic pointer; arithmetic operations
1641 * should ignore the high byte (pointer type).
1649 /*-----------------------------------------------------------------*/
1650 /* outAcc - output Acc */
1651 /*-----------------------------------------------------------------*/
1653 outAcc (operand * result)
1656 size = getDataSize (result);
1659 aopPut (AOP (result), "a", 0);
1662 /* unsigned or positive */
1665 aopPut (AOP (result), zero, offset++);
1670 /*-----------------------------------------------------------------*/
1671 /* outBitC - output a bit C */
1672 /*-----------------------------------------------------------------*/
1674 outBitC (operand * result)
1676 /* if the result is bit */
1677 if (AOP_TYPE (result) == AOP_CRY)
1679 aopPut (AOP (result), "c", 0);
1683 emitcode ("clr", "a");
1684 emitcode ("rlc", "a");
1689 /*-----------------------------------------------------------------*/
1690 /* toBoolean - emit code for orl a,operator(sizeop) */
1691 /*-----------------------------------------------------------------*/
1693 toBoolean (operand * oper)
1695 int size = AOP_SIZE (oper) - 1;
1699 /* The generic part of a generic pointer should
1700 * not participate in it's truth value.
1702 * i.e. 0x10000000 is zero.
1704 if (opIsGptr (oper))
1706 D (emitcode (";", "toBoolean: generic ptr special case."););
1710 _startLazyDPSEvaluation ();
1711 if (AOP_NEEDSACC (oper) && size)
1716 emitcode ("push", "b");
1718 MOVB (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1722 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1729 emitcode ("orl", "b,%s",
1730 aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1734 emitcode ("orl", "a,%s",
1735 aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1738 _endLazyDPSEvaluation ();
1742 emitcode ("mov", "a,b");
1745 emitcode ("pop", "b");
1752 /*-----------------------------------------------------------------*/
1753 /* genNot - generate code for ! operation */
1754 /*-----------------------------------------------------------------*/
1760 D (emitcode (";", "genNot "););
1762 /* assign asmOps to operand & result */
1763 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1764 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1766 /* if in bit space then a special case */
1767 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1769 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1770 emitcode ("cpl", "c");
1771 outBitC (IC_RESULT (ic));
1775 toBoolean (IC_LEFT (ic));
1777 tlbl = newiTempLabel (NULL);
1778 emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1779 emitcode ("", "!tlabeldef", tlbl->key + 100);
1780 outBitC (IC_RESULT (ic));
1783 /* release the aops */
1784 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1785 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1789 /*-----------------------------------------------------------------*/
1790 /* genCpl - generate code for complement */
1791 /*-----------------------------------------------------------------*/
1799 D (emitcode (";", "genCpl "););
1802 /* assign asmOps to operand & result */
1803 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1804 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1806 /* special case if in bit space */
1807 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1808 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1809 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1810 emitcode ("cpl", "c");
1811 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1814 tlbl=newiTempLabel(NULL);
1815 emitcode ("cjne", "%s,#0x01,%05d$",
1816 aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE,NULL), tlbl->key+100);
1817 emitcode ("", "%05d$:", tlbl->key+100);
1818 outBitC (IC_RESULT(ic));
1822 size = AOP_SIZE (IC_RESULT (ic));
1823 _startLazyDPSEvaluation ();
1826 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
1827 emitcode ("cpl", "a");
1828 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1830 _endLazyDPSEvaluation ();
1834 /* release the aops */
1835 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1836 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1839 /*-----------------------------------------------------------------*/
1840 /* genUminusFloat - unary minus for floating points */
1841 /*-----------------------------------------------------------------*/
1843 genUminusFloat (operand * op, operand * result)
1845 int size, offset = 0;
1847 D(emitcode (";", "genUminusFloat"););
1849 /* for this we just copy and then flip the bit */
1851 _startLazyDPSEvaluation ();
1852 size = AOP_SIZE (op) - 1;
1856 aopPut (AOP (result),
1857 aopGet (AOP (op), offset, FALSE, FALSE, NULL),
1862 MOVA(aopGet (AOP (op), offset, FALSE, FALSE, NULL));
1864 emitcode ("cpl", "acc.7");
1865 aopPut (AOP (result), "a", offset);
1866 _endLazyDPSEvaluation ();
1869 /*-----------------------------------------------------------------*/
1870 /* genUminus - unary minus code generation */
1871 /*-----------------------------------------------------------------*/
1873 genUminus (iCode * ic)
1878 D (emitcode (";", "genUminus "););
1881 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1882 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1884 /* if both in bit space then special
1886 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1887 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1890 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1891 emitcode ("cpl", "c");
1892 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1896 optype = operandType (IC_LEFT (ic));
1898 /* if float then do float stuff */
1899 if (IS_FLOAT (optype))
1901 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1905 /* otherwise subtract from zero */
1906 size = AOP_SIZE (IC_LEFT (ic));
1908 _startLazyDPSEvaluation ();
1911 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL);
1912 if (!strcmp (l, "a"))
1916 emitcode ("cpl", "a");
1917 emitcode ("addc", "a,#0");
1923 emitcode ("clr", "a");
1924 emitcode ("subb", "a,%s", l);
1926 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1928 _endLazyDPSEvaluation ();
1930 /* if any remaining bytes in the result */
1931 /* we just need to propagate the sign */
1932 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic)))) != 0)
1934 emitcode ("rlc", "a");
1935 emitcode ("subb", "a,acc");
1937 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1941 /* release the aops */
1942 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1943 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1946 /*-----------------------------------------------------------------*/
1947 /* savermask - saves registers in the mask */
1948 /*-----------------------------------------------------------------*/
1949 static void savermask(bitVect *rs_mask)
1952 if (options.useXstack) {
1953 if (bitVectBitValue (rs_mask, R0_IDX))
1954 emitcode ("mov", "b,r0");
1955 emitcode ("mov", "r0,%s", spname);
1956 for (i = 0; i < ds390_nRegs; i++) {
1957 if (bitVectBitValue (rs_mask, i)) {
1959 emitcode ("mov", "a,b");
1961 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1962 emitcode ("movx", "@r0,a");
1963 emitcode ("inc", "r0");
1966 emitcode ("mov", "%s,r0", spname);
1967 if (bitVectBitValue (rs_mask, R0_IDX))
1968 emitcode ("mov", "r0,b");
1970 for (i = 0; i < ds390_nRegs; i++) {
1971 if (bitVectBitValue (rs_mask, i))
1972 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
1977 /*-----------------------------------------------------------------*/
1978 /* saveRegisters - will look for a call and save the registers */
1979 /*-----------------------------------------------------------------*/
1981 saveRegisters (iCode * lic)
1987 for (ic = lic; ic; ic = ic->next)
1988 if (ic->op == CALL || ic->op == PCALL)
1993 fprintf (stderr, "found parameter push with no function call\n");
1997 /* if the registers have been saved already then
2000 || (IS_SYMOP(IC_LEFT(ic)) && IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))) && !TARGET_IS_DS400) )
2003 /* special case if DPTR alive across a function call then must save it
2004 even though callee saves */
2005 if (IS_SYMOP(IC_LEFT(ic)) &&
2006 IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2008 rsave = newBitVect(ic->rMask->size);
2009 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2010 if (bitVectBitValue(ic->rMask,i))
2011 rsave = bitVectSetBit(rsave,i);
2013 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2015 /* safe the registers in use at this time but skip the
2016 ones for the result */
2017 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2018 ds390_rUmaskForOp (IC_RESULT(ic)));
2024 /*-----------------------------------------------------------------*/
2025 /* usavermask - restore registers with mask */
2026 /*-----------------------------------------------------------------*/
2027 static void unsavermask(bitVect *rs_mask)
2030 if (options.useXstack) {
2031 emitcode ("mov", "r0,%s", spname);
2032 for (i = ds390_nRegs; i >= 0; i--) {
2033 if (bitVectBitValue (rs_mask, i)) {
2034 emitcode ("dec", "r0");
2035 emitcode ("movx", "a,@r0");
2037 emitcode ("mov", "b,a");
2039 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
2042 emitcode ("mov", "%s,r0", spname);
2043 if (bitVectBitValue (rs_mask, R0_IDX))
2044 emitcode ("mov", "r0,b");
2046 for (i = ds390_nRegs; i >= 0; i--) {
2047 if (bitVectBitValue (rs_mask, i))
2048 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2053 /*-----------------------------------------------------------------*/
2054 /* unsaveRegisters - pop the pushed registers */
2055 /*-----------------------------------------------------------------*/
2057 unsaveRegisters (iCode * ic)
2061 if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2063 rsave = newBitVect(ic->rMask->size);
2064 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2065 if (bitVectBitValue(ic->rMask,i))
2066 rsave = bitVectSetBit(rsave,i);
2068 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2070 /* restore the registers in use at this time but skip the
2071 ones for the result */
2072 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2073 ds390_rUmaskForOp (IC_RESULT(ic)));
2079 /*-----------------------------------------------------------------*/
2081 /*-----------------------------------------------------------------*/
2083 pushSide (operand * oper, int size)
2086 _startLazyDPSEvaluation ();
2089 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, NULL);
2090 if (AOP_TYPE (oper) != AOP_REG &&
2091 AOP_TYPE (oper) != AOP_DIR &&
2094 emitcode ("mov", "a,%s", l);
2095 emitcode ("push", "acc");
2098 emitcode ("push", "%s", l);
2100 _endLazyDPSEvaluation ();
2103 /*-----------------------------------------------------------------*/
2104 /* assignResultValue - */
2105 /*-----------------------------------------------------------------*/
2107 assignResultValue (operand * oper)
2110 int size = AOP_SIZE (oper);
2111 bool pushedAcc = FALSE;
2113 if (size == fReturnSizeDS390)
2115 /* I don't think this case can ever happen... */
2116 /* ACC is the last part of this. If writing the result
2117 * uses AC, we must preserve it.
2119 if (AOP_NEEDSACC(oper))
2121 emitcode(";", "assignResultValue special case for ACC.");
2122 emitcode("push", "acc");
2129 _startLazyDPSEvaluation ();
2132 aopPut (AOP (oper), fReturn[offset], offset);
2135 _endLazyDPSEvaluation ();
2139 emitcode("pop", "acc");
2140 aopPut(AOP(oper), "a", offset);
2145 /*-----------------------------------------------------------------*/
2146 /* genXpush - pushes onto the external stack */
2147 /*-----------------------------------------------------------------*/
2149 genXpush (iCode * ic)
2151 asmop *aop = newAsmop (0);
2153 int size, offset = 0;
2155 D (emitcode (";", "genXpush ");
2158 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2159 r = getFreePtr (ic, &aop, FALSE);
2162 emitcode ("mov", "%s,_spx", r->name);
2164 size = AOP_SIZE (IC_LEFT (ic));
2165 _startLazyDPSEvaluation ();
2169 MOVA (aopGet (AOP (IC_LEFT (ic)),
2170 offset++, FALSE, FALSE, NULL));
2171 emitcode ("movx", "@%s,a", r->name);
2172 emitcode ("inc", "%s", r->name);
2175 _endLazyDPSEvaluation ();
2178 emitcode ("mov", "_spx,%s", r->name);
2180 freeAsmop (NULL, aop, ic, TRUE);
2181 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2184 /*-----------------------------------------------------------------*/
2185 /* genIpush - generate code for pushing this gets a little complex */
2186 /*-----------------------------------------------------------------*/
2188 genIpush (iCode * ic)
2190 int size, offset = 0;
2193 D (emitcode (";", "genIpush ");
2196 /* if this is not a parm push : ie. it is spill push
2197 and spill push is always done on the local stack */
2201 /* and the item is spilt then do nothing */
2202 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2205 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2206 size = AOP_SIZE (IC_LEFT (ic));
2207 /* push it on the stack */
2208 _startLazyDPSEvaluation ();
2211 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2217 emitcode ("push", "%s", l);
2219 _endLazyDPSEvaluation ();
2223 /* this is a paramter push: in this case we call
2224 the routine to find the call and save those
2225 registers that need to be saved */
2228 /* if use external stack then call the external
2229 stack pushing routine */
2230 if (options.useXstack)
2236 /* then do the push */
2237 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2239 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2240 size = AOP_SIZE (IC_LEFT (ic));
2242 _startLazyDPSEvaluation ();
2245 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2246 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2247 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2250 emitcode ("mov", "a,%s", l);
2251 emitcode ("push", "acc");
2255 emitcode ("push", "%s", l);
2258 _endLazyDPSEvaluation ();
2260 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2263 /*-----------------------------------------------------------------*/
2264 /* genIpop - recover the registers: can happen only for spilling */
2265 /*-----------------------------------------------------------------*/
2267 genIpop (iCode * ic)
2271 D (emitcode (";", "genIpop ");
2275 /* if the temp was not pushed then */
2276 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2279 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2280 size = AOP_SIZE (IC_LEFT (ic));
2281 offset = (size - 1);
2282 _startLazyDPSEvaluation ();
2285 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2286 FALSE, TRUE, NULL));
2288 _endLazyDPSEvaluation ();
2290 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2293 /*-----------------------------------------------------------------*/
2294 /* unsaveRBank - restores the resgister bank from stack */
2295 /*-----------------------------------------------------------------*/
2297 unsaveRBank (int bank, iCode * ic, bool popPsw)
2303 if (options.useXstack)
2307 /* Assume r0 is available for use. */
2308 r = ds390_regWithIdx (R0_IDX);;
2313 r = getFreePtr (ic, &aop, FALSE);
2315 emitcode ("mov", "%s,_spx", r->name);
2320 if (options.useXstack)
2322 emitcode ("movx", "a,@%s", r->name);
2323 emitcode ("mov", "psw,a");
2324 emitcode ("dec", "%s", r->name);
2328 emitcode ("pop", "psw");
2332 for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2334 if (options.useXstack)
2336 emitcode ("movx", "a,@%s", r->name);
2337 emitcode ("mov", "(%s+%d),a",
2338 regs390[i].base, 8 * bank + regs390[i].offset);
2339 emitcode ("dec", "%s", r->name);
2343 emitcode ("pop", "(%s+%d)",
2344 regs390[i].base, 8 * bank + regs390[i].offset);
2347 if (options.useXstack)
2349 emitcode ("mov", "_spx,%s", r->name);
2354 freeAsmop (NULL, aop, ic, TRUE);
2358 /*-----------------------------------------------------------------*/
2359 /* saveRBank - saves an entire register bank on the stack */
2360 /*-----------------------------------------------------------------*/
2362 saveRBank (int bank, iCode * ic, bool pushPsw)
2368 if (options.useXstack)
2372 /* Assume r0 is available for use. */
2373 r = ds390_regWithIdx (R0_IDX);;
2378 r = getFreePtr (ic, &aop, FALSE);
2380 emitcode ("mov", "%s,_spx", r->name);
2383 for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2385 if (options.useXstack)
2387 emitcode ("inc", "%s", r->name);
2388 emitcode ("mov", "a,(%s+%d)",
2389 regs390[i].base, 8 * bank + regs390[i].offset);
2390 emitcode ("movx", "@%s,a", r->name);
2393 emitcode ("push", "(%s+%d)",
2394 regs390[i].base, 8 * bank + regs390[i].offset);
2399 if (options.useXstack)
2401 emitcode ("mov", "a,psw");
2402 emitcode ("movx", "@%s,a", r->name);
2403 emitcode ("inc", "%s", r->name);
2404 emitcode ("mov", "_spx,%s", r->name);
2408 emitcode ("push", "psw");
2411 emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2416 freeAsmop (NULL, aop, ic, TRUE);
2425 /*-----------------------------------------------------------------*/
2426 /* genSend - gen code for SEND */
2427 /*-----------------------------------------------------------------*/
2428 static void genSend(set *sendSet)
2432 static int rb1_count = 0;
2434 for (sic = setFirstItem (sendSet); sic;
2435 sic = setNextItem (sendSet)) {
2436 int size, offset = 0;
2438 size=getSize(operandType(IC_LEFT(sic)));
2439 D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2440 if (sendCount == 0) { /* first parameter */
2441 // we know that dpl(hxb) is the result, so
2443 _startLazyDPSEvaluation ();
2445 aopOp (IC_LEFT (sic), sic, FALSE,
2446 (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2448 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2451 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2452 FALSE, FALSE, NULL);
2453 if (strcmp (l, fReturn[offset])) {
2454 emitcode ("mov", "%s,%s",
2460 _endLazyDPSEvaluation ();
2461 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2463 } else { /* if more parameter in registers */
2464 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2466 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
2467 FALSE, FALSE, NULL));
2469 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2476 adjustEsp(const char *reg)
2478 emitcode ("anl","%s,#3", reg);
2479 if (TARGET_IS_DS400)
2481 emitcode ("orl","%s,#!constbyte",
2483 (options.stack_loc >> 8) & 0xff);
2487 /*-----------------------------------------------------------------*/
2488 /* genCall - generates a call statement */
2489 /*-----------------------------------------------------------------*/
2491 genCall (iCode * ic)
2494 bool restoreBank = FALSE;
2495 bool swapBanks = FALSE;
2497 D (emitcode (";", "genCall "););
2499 /* if we are calling a not _naked function that is not using
2500 the same register bank then we need to save the
2501 destination registers on the stack */
2502 dtype = operandType (IC_LEFT (ic));
2503 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2504 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2505 IFFUNC_ISISR (currFunc->type))
2509 /* This is unexpected; the bank should have been saved in
2512 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2518 /* if caller saves & we have not saved then */
2522 /* if send set is not empty the assign */
2523 /* We've saved all the registers we care about;
2524 * therefore, we may clobber any register not used
2525 * in the calling convention (i.e. anything not in
2530 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2531 genSend(reverseSet(_G.sendSet));
2533 genSend(_G.sendSet);
2540 emitcode ("mov", "psw,#!constbyte",
2541 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2545 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2546 OP_SYMBOL (IC_LEFT (ic))->rname :
2547 OP_SYMBOL (IC_LEFT (ic))->name));
2551 emitcode ("mov", "psw,#!constbyte",
2552 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2555 /* if we need assign a result value */
2556 if ((IS_ITEMP (IC_RESULT (ic)) &&
2557 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2558 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2559 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2560 IS_TRUE_SYMOP (IC_RESULT (ic)))
2562 if (isOperandInFarSpace (IC_RESULT (ic))
2563 && getSize (operandType (IC_RESULT (ic))) <= 2)
2565 int size = getSize (operandType (IC_RESULT (ic)));
2567 /* Special case for 1 or 2 byte return in far space. */
2571 emitcode ("mov", "b,%s", fReturn[1]);
2574 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2575 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2579 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2581 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2586 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2589 assignResultValue (IC_RESULT (ic));
2591 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2595 /* adjust the stack for parameters if
2597 if (ic->parmBytes) {
2599 if (options.stack10bit) {
2600 if (ic->parmBytes <= 10) {
2601 emitcode(";","stack adjustment for parms");
2602 for (i=0; i < ic->parmBytes ; i++) {
2603 emitcode("pop","acc");
2607 emitcode ("clr","c");
2608 emitcode ("mov","a,sp");
2609 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2610 emitcode ("mov","sp,a");
2611 emitcode ("mov","a,esp");
2613 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2614 emitcode ("mov","esp,a");
2618 if (ic->parmBytes > 3) {
2619 emitcode ("mov", "a,%s", spname);
2620 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2621 emitcode ("mov", "%s,a", spname);
2623 for (i = 0; i < ic->parmBytes; i++)
2624 emitcode ("dec", "%s", spname);
2628 /* if we hade saved some registers then unsave them */
2630 unsaveRegisters (ic);
2632 /* if register bank was saved then pop them */
2634 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2637 /*-----------------------------------------------------------------*/
2638 /* genPcall - generates a call by pointer statement */
2639 /*-----------------------------------------------------------------*/
2641 genPcall (iCode * ic)
2644 symbol *rlbl = newiTempLabel (NULL);
2645 bool restoreBank=FALSE;
2647 D (emitcode (";", "genPcall ");
2651 /* if caller saves & we have not saved then */
2655 /* if we are calling a function that is not using
2656 the same register bank then we need to save the
2657 destination registers on the stack */
2658 dtype = operandType (IC_LEFT (ic));
2659 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2660 IFFUNC_ISISR (currFunc->type) &&
2661 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2662 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2666 /* push the return address on to the stack */
2667 emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2668 emitcode ("push", "acc");
2669 emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2670 emitcode ("push", "acc");
2672 if (options.model == MODEL_FLAT24)
2674 emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2675 emitcode ("push", "acc");
2678 /* now push the calling address */
2679 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2681 pushSide (IC_LEFT (ic), FPTRSIZE);
2683 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2685 /* if send set is not empty the assign */
2688 genSend(reverseSet(_G.sendSet));
2692 emitcode ("ret", "");
2693 emitcode ("", "!tlabeldef", (rlbl->key + 100));
2696 /* if we need assign a result value */
2697 if ((IS_ITEMP (IC_RESULT (ic)) &&
2698 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2699 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2700 IS_TRUE_SYMOP (IC_RESULT (ic)))
2704 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2707 assignResultValue (IC_RESULT (ic));
2709 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2712 /* adjust the stack for parameters if
2717 if (options.stack10bit) {
2718 if (ic->parmBytes <= 10) {
2719 emitcode(";","stack adjustment for parms");
2720 for (i=0; i < ic->parmBytes ; i++) {
2721 emitcode("pop","acc");
2725 emitcode ("clr","c");
2726 emitcode ("mov","a,sp");
2727 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2728 emitcode ("mov","sp,a");
2729 emitcode ("mov","a,esp");
2731 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2732 emitcode ("mov","esp,a");
2736 if (ic->parmBytes > 3) {
2737 emitcode ("mov", "a,%s", spname);
2738 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2739 emitcode ("mov", "%s,a", spname);
2742 for (i = 0; i < ic->parmBytes; i++)
2743 emitcode ("dec", "%s", spname);
2747 /* if register bank was saved then unsave them */
2749 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2751 /* if we hade saved some registers then
2754 unsaveRegisters (ic);
2758 /*-----------------------------------------------------------------*/
2759 /* resultRemat - result is rematerializable */
2760 /*-----------------------------------------------------------------*/
2762 resultRemat (iCode * ic)
2764 if (SKIP_IC (ic) || ic->op == IFX)
2767 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2769 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2770 if (sym->remat && !POINTER_SET (ic))
2777 #if defined(__BORLANDC__) || defined(_MSC_VER)
2778 #define STRCASECMP stricmp
2780 #define STRCASECMP strcasecmp
2783 /*-----------------------------------------------------------------*/
2784 /* inExcludeList - return 1 if the string is in exclude Reg list */
2785 /*-----------------------------------------------------------------*/
2787 regsCmp(void *p1, void *p2)
2789 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2793 inExcludeList (char *s)
2795 const char *p = setFirstItem(options.excludeRegsSet);
2797 if (p == NULL || STRCASECMP(p, "none") == 0)
2801 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2804 /*-----------------------------------------------------------------*/
2805 /* genFunction - generated code for function entry */
2806 /*-----------------------------------------------------------------*/
2808 genFunction (iCode * ic)
2812 bool switchedPSW = FALSE;
2814 D (emitcode (";", "genFunction "););
2817 /* create the function header */
2818 emitcode (";", "-----------------------------------------");
2819 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2820 emitcode (";", "-----------------------------------------");
2822 emitcode ("", "%s:", sym->rname);
2823 ftype = operandType (IC_LEFT (ic));
2825 if (IFFUNC_ISNAKED(ftype))
2827 emitcode(";", "naked function: no prologue.");
2831 if (options.stack_probe)
2832 emitcode ("lcall","__stack_probe");
2833 /* if critical function then turn interrupts off */
2834 if (IFFUNC_ISCRITICAL (ftype))
2835 emitcode ("clr", "ea");
2837 /* here we need to generate the equates for the
2838 register bank if required */
2839 if (FUNC_REGBANK (ftype) != rbank)
2843 rbank = FUNC_REGBANK (ftype);
2844 for (i = 0; i < ds390_nRegs; i++)
2846 if (regs390[i].print) {
2847 if (strcmp (regs390[i].base, "0") == 0)
2848 emitcode ("", "%s !equ !constbyte",
2850 8 * rbank + regs390[i].offset);
2852 emitcode ("", "%s !equ %s + !constbyte",
2855 8 * rbank + regs390[i].offset);
2860 /* if this is an interrupt service routine then
2861 save acc, b, dpl, dph */
2862 if (IFFUNC_ISISR (sym->type))
2864 if (!inExcludeList ("acc"))
2865 emitcode ("push", "acc");
2866 if (!inExcludeList ("b"))
2867 emitcode ("push", "b");
2868 if (!inExcludeList ("dpl"))
2869 emitcode ("push", "dpl");
2870 if (!inExcludeList ("dph"))
2871 emitcode ("push", "dph");
2872 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2874 emitcode ("push", "dpx");
2875 /* Make sure we're using standard DPTR */
2876 emitcode ("push", "dps");
2877 emitcode ("mov", "dps,#0");
2878 if (options.stack10bit)
2880 /* This ISR could conceivably use DPTR2. Better save it. */
2881 emitcode ("push", "dpl1");
2882 emitcode ("push", "dph1");
2883 emitcode ("push", "dpx1");
2884 emitcode ("push", DP2_RESULT_REG);
2887 /* if this isr has no bank i.e. is going to
2888 run with bank 0 , then we need to save more
2890 if (!FUNC_REGBANK (sym->type))
2894 /* if this function does not call any other
2895 function then we can be economical and
2896 save only those registers that are used */
2897 if (!IFFUNC_HASFCALL(sym->type))
2900 /* if any registers used */
2903 /* save the registers used */
2904 for (i = 0; i < sym->regsUsed->size; i++)
2906 if (bitVectBitValue (sym->regsUsed, i) ||
2907 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2908 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2915 /* this function has a function call cannot
2916 determines register usage so we will have to push the
2918 saveRBank (0, ic, FALSE);
2919 if (options.parms_in_bank1) {
2920 for (i=0; i < 8 ; i++ ) {
2921 emitcode ("push","%s",rb1regs[i]);
2928 /* This ISR uses a non-zero bank.
2930 * We assume that the bank is available for our
2933 * However, if this ISR calls a function which uses some
2934 * other bank, we must save that bank entirely.
2936 unsigned long banksToSave = 0;
2938 if (IFFUNC_HASFCALL(sym->type))
2941 #define MAX_REGISTER_BANKS 4
2946 for (i = ic; i; i = i->next)
2948 if (i->op == ENDFUNCTION)
2950 /* we got to the end OK. */
2958 dtype = operandType (IC_LEFT(i));
2960 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2962 /* Mark this bank for saving. */
2963 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2965 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2969 banksToSave |= (1 << FUNC_REGBANK(dtype));
2972 /* And note that we don't need to do it in
2980 /* This is a mess; we have no idea what
2981 * register bank the called function might
2984 * The only thing I can think of to do is
2985 * throw a warning and hope.
2987 werror(W_FUNCPTR_IN_USING_ISR);
2991 if (banksToSave && options.useXstack)
2993 /* Since we aren't passing it an ic,
2994 * saveRBank will assume r0 is available to abuse.
2996 * So switch to our (trashable) bank now, so
2997 * the caller's R0 isn't trashed.
2999 emitcode ("push", "psw");
3000 emitcode ("mov", "psw,#!constbyte",
3001 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3005 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3007 if (banksToSave & (1 << ix))
3009 saveRBank(ix, NULL, FALSE);
3013 // TODO: this needs a closer look
3014 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3019 /* if callee-save to be used for this function
3020 then save the registers being used in this function */
3021 if (IFFUNC_CALLEESAVES(sym->type))
3025 /* if any registers used */
3028 /* save the registers used */
3029 for (i = 0; i < sym->regsUsed->size; i++)
3031 if (bitVectBitValue (sym->regsUsed, i) ||
3032 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3034 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3042 /* set the register bank to the desired value */
3043 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3046 emitcode ("push", "psw");
3047 emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3050 if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3051 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3052 if (options.stack10bit) {
3053 emitcode ("push","_bpx");
3054 emitcode ("push","_bpx+1");
3055 emitcode ("mov","_bpx,%s",spname);
3056 emitcode ("mov","_bpx+1,esp");
3057 adjustEsp("_bpx+1");
3059 if (options.useXstack) {
3060 emitcode ("mov", "r0,%s", spname);
3061 emitcode ("mov", "a,_bp");
3062 emitcode ("movx", "@r0,a");
3063 emitcode ("inc", "%s", spname);
3065 /* set up the stack */
3066 emitcode ("push", "_bp"); /* save the callers stack */
3068 emitcode ("mov", "_bp,%s", spname);
3072 /* adjust the stack for the function */
3075 if (options.stack10bit) {
3076 if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
3077 assert (sym->recvSize <= 4);
3078 if (sym->stack <= 8) {
3079 while (i--) emitcode ("push","acc");
3082 emitcode ("mov","a,sp");
3083 emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3084 emitcode ("mov","sp,a");
3085 emitcode ("mov","a,esp");
3087 emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3088 emitcode ("mov","esp,a");
3093 werror (W_STACK_OVERFLOW, sym->name);
3095 if (i > 3 && sym->recvSize < 4) {
3097 emitcode ("mov", "a,sp");
3098 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3099 emitcode ("mov", "sp,a");
3103 emitcode ("inc", "sp");
3110 emitcode ("mov", "a,_spx");
3111 emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3112 emitcode ("mov", "_spx,a");
3117 /*-----------------------------------------------------------------*/
3118 /* genEndFunction - generates epilogue for functions */
3119 /*-----------------------------------------------------------------*/
3121 genEndFunction (iCode * ic)
3123 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3125 D (emitcode (";", "genEndFunction "););
3127 if (IFFUNC_ISNAKED(sym->type))
3129 emitcode(";", "naked function: no epilogue.");
3133 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3134 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3136 if (options.stack10bit) {
3138 emitcode ("mov", "sp,_bpx", spname);
3139 emitcode ("mov", "esp,_bpx+1", spname);
3142 emitcode ("mov", "%s,_bp", spname);
3146 /* if use external stack but some variables were
3147 added to the local stack then decrement the
3149 if (options.useXstack && sym->stack) {
3150 emitcode ("mov", "a,sp");
3151 emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3152 emitcode ("mov", "sp,a");
3156 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3157 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3159 if (options.useXstack) {
3160 emitcode ("mov", "r0,%s", spname);
3161 emitcode ("movx", "a,@r0");
3162 emitcode ("mov", "_bp,a");
3163 emitcode ("dec", "%s", spname);
3165 if (options.stack10bit) {
3166 emitcode ("pop", "_bpx+1");
3167 emitcode ("pop", "_bpx");
3169 emitcode ("pop", "_bp");
3174 /* restore the register bank */
3175 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3177 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3178 || !options.useXstack)
3180 /* Special case of ISR using non-zero bank with useXstack
3183 emitcode ("pop", "psw");
3187 if (IFFUNC_ISISR (sym->type))
3190 /* now we need to restore the registers */
3191 /* if this isr has no bank i.e. is going to
3192 run with bank 0 , then we need to save more
3194 if (!FUNC_REGBANK (sym->type))
3197 /* if this function does not call any other
3198 function then we can be economical and
3199 save only those registers that are used */
3200 if (!IFFUNC_HASFCALL(sym->type))
3203 /* if any registers used */
3206 /* save the registers used */
3207 for (i = sym->regsUsed->size; i >= 0; i--)
3209 if (bitVectBitValue (sym->regsUsed, i) ||
3210 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3211 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3218 /* this function has a function call cannot
3219 determines register usage so we will have to pop the
3221 if (options.parms_in_bank1) {
3222 for (i = 7 ; i >= 0 ; i-- ) {
3223 emitcode ("pop","%s",rb1regs[i]);
3226 unsaveRBank (0, ic, FALSE);
3231 /* This ISR uses a non-zero bank.
3233 * Restore any register banks saved by genFunction
3236 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3239 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3241 if (savedBanks & (1 << ix))
3243 unsaveRBank(ix, NULL, FALSE);
3247 if (options.useXstack)
3249 /* Restore bank AFTER calling unsaveRBank,
3250 * since it can trash r0.
3252 emitcode ("pop", "psw");
3256 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3258 if (options.stack10bit)
3260 emitcode ("pop", DP2_RESULT_REG);
3261 emitcode ("pop", "dpx1");
3262 emitcode ("pop", "dph1");
3263 emitcode ("pop", "dpl1");
3265 emitcode ("pop", "dps");
3266 emitcode ("pop", "dpx");
3268 if (!inExcludeList ("dph"))
3269 emitcode ("pop", "dph");
3270 if (!inExcludeList ("dpl"))
3271 emitcode ("pop", "dpl");
3272 if (!inExcludeList ("b"))
3273 emitcode ("pop", "b");
3274 if (!inExcludeList ("acc"))
3275 emitcode ("pop", "acc");
3277 if (IFFUNC_ISCRITICAL (sym->type))
3278 emitcode ("setb", "ea");
3280 /* if debug then send end of function */
3281 if (options.debug && currFunc) {
3283 emitcode ("", "C$%s$%d$%d$%d ==.",
3284 FileBaseName (ic->filename), currFunc->lastLine,
3285 ic->level, ic->block);
3286 if (IS_STATIC (currFunc->etype))
3287 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3289 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3293 emitcode ("reti", "");
3297 if (IFFUNC_ISCRITICAL (sym->type))
3298 emitcode ("setb", "ea");
3300 if (IFFUNC_CALLEESAVES(sym->type))
3304 /* if any registers used */
3307 /* save the registers used */
3308 for (i = sym->regsUsed->size; i >= 0; i--)
3310 if (bitVectBitValue (sym->regsUsed, i) ||
3311 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3312 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3318 /* if debug then send end of function */
3319 if (options.debug && currFunc)
3322 emitcode ("", "C$%s$%d$%d$%d ==.",
3323 FileBaseName (ic->filename), currFunc->lastLine,
3324 ic->level, ic->block);
3325 if (IS_STATIC (currFunc->etype))
3326 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3328 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3332 emitcode ("ret", "");
3337 /*-----------------------------------------------------------------*/
3338 /* genJavaNativeRet - generate code for return JavaNative */
3339 /*-----------------------------------------------------------------*/
3340 static void genJavaNativeRet(iCode *ic)
3344 aopOp (IC_LEFT (ic), ic, FALSE,
3345 AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
3346 size = AOP_SIZE (IC_LEFT (ic));
3350 /* it is assigned to GPR0-R3 then push them */
3351 if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3352 aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3353 for (i = 0 ; i < size ; i++ ) {
3354 emitcode ("push","%s",
3355 aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3357 for (i = (size-1) ; i >= 0 ; i--) {
3358 emitcode ("pop","a%s",javaRet[i]);
3361 for (i = 0 ; i < size ; i++)
3362 emitcode ("mov","%s,%s",javaRet[i],
3363 aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3365 for (i = size ; i < 4 ; i++ )
3366 emitcode ("mov","%s,#0",javaRet[i]);
3370 /*-----------------------------------------------------------------*/
3371 /* genRet - generate code for return statement */
3372 /*-----------------------------------------------------------------*/
3376 int size, offset = 0, pushed = 0;
3378 D (emitcode (";", "genRet "););
3380 /* if we have no return value then
3381 just generate the "ret" */
3385 /* if this is a JavaNative function then return
3386 value in different register */
3387 if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3388 genJavaNativeRet(ic);
3391 /* we have something to return then
3392 move the return value into place */
3393 aopOp (IC_LEFT (ic), ic, FALSE,
3394 (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
3395 size = AOP_SIZE (IC_LEFT (ic));
3397 _startLazyDPSEvaluation ();
3401 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3403 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3405 emitcode ("push", "%s", l);
3410 /* Since A is the last element of fReturn,
3411 * is is OK to clobber it in the aopGet.
3413 l = aopGet (AOP (IC_LEFT (ic)), offset,
3414 FALSE, FALSE, NULL);
3415 if (strcmp (fReturn[offset], l))
3416 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3419 _endLazyDPSEvaluation ();
3426 if (strcmp (fReturn[pushed], "a"))
3427 emitcode ("pop", fReturn[pushed]);
3429 emitcode ("pop", "acc");
3432 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3435 /* generate a jump to the return label
3436 if the next is not the return statement */
3437 if (!(ic->next && ic->next->op == LABEL &&
3438 IC_LABEL (ic->next) == returnLabel))
3440 emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3444 /*-----------------------------------------------------------------*/
3445 /* genLabel - generates a label */
3446 /*-----------------------------------------------------------------*/
3448 genLabel (iCode * ic)
3450 /* special case never generate */
3451 if (IC_LABEL (ic) == entryLabel)
3454 D (emitcode (";", "genLabel ");
3457 emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3460 /*-----------------------------------------------------------------*/
3461 /* genGoto - generates a ljmp */
3462 /*-----------------------------------------------------------------*/
3464 genGoto (iCode * ic)
3466 D (emitcode (";", "genGoto ");
3468 emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3471 /*-----------------------------------------------------------------*/
3472 /* findLabelBackwards: walks back through the iCode chain looking */
3473 /* for the given label. Returns number of iCode instructions */
3474 /* between that label and given ic. */
3475 /* Returns zero if label not found. */
3476 /*-----------------------------------------------------------------*/
3478 findLabelBackwards (iCode * ic, int key)
3487 /* If we have any pushes or pops, we cannot predict the distance.
3488 I don't like this at all, this should be dealt with in the
3490 if (ic->op == IPUSH || ic->op == IPOP) {
3494 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3496 /* printf("findLabelBackwards = %d\n", count); */
3504 /*-----------------------------------------------------------------*/
3505 /* genPlusIncr :- does addition with increment if possible */
3506 /*-----------------------------------------------------------------*/
3508 genPlusIncr (iCode * ic)
3510 unsigned int icount;
3511 unsigned int size = getDataSize (IC_RESULT (ic));
3513 /* will try to generate an increment */
3514 /* if the right side is not a literal
3516 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3519 /* if the literal value of the right hand side
3520 is greater than 4 then it is not worth it */
3521 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3524 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3525 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3527 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
3531 /* if increment 16 bits in register */
3533 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3534 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3535 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3544 /* If the next instruction is a goto and the goto target
3545 * is <= 5 instructions previous to this, we can generate
3546 * jumps straight to that target.
3548 if (ic->next && ic->next->op == GOTO
3549 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3552 D(emitcode (";", "tail increment optimized (range %d)", labelRange););
3553 tlbl = IC_LABEL (ic->next);
3558 tlbl = newiTempLabel (NULL);
3562 l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
3563 emitcode ("inc", "%s", l);
3565 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3566 IS_AOP_PREG (IC_RESULT (ic)))
3568 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3572 emitcode ("clr", "a");
3573 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3576 l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
3577 emitcode ("inc", "%s", l);
3580 if (!strcmp(l, "acc"))
3582 emitcode("jnz", "!tlabel", tlbl->key + 100);
3584 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3585 IS_AOP_PREG (IC_RESULT (ic)))
3587 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3591 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3594 l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
3595 emitcode ("inc", "%s", l);
3599 if (!strcmp(l, "acc"))
3601 emitcode("jnz", "!tlabel", tlbl->key + 100);
3603 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3604 IS_AOP_PREG (IC_RESULT (ic)))
3606 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3610 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3613 l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
3614 emitcode ("inc", "%s", l); }
3618 emitcode ("", "!tlabeldef", tlbl->key + 100);
3623 if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3624 !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 &&
3625 options.model == MODEL_FLAT24 ) {
3629 emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, NULL));
3631 emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, NULL));
3633 emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3636 while (icount--) emitcode ("inc","dptr");
3640 if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3641 AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3643 emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3644 while (icount--) emitcode ("inc","dptr");
3645 emitcode ("mov","dps,#0");
3649 /* if the sizes are greater than 1 then we cannot */
3650 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3651 AOP_SIZE (IC_LEFT (ic)) > 1)
3654 /* we can if the aops of the left & result match or
3655 if they are in registers and the registers are the
3658 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3659 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3660 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3665 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3666 emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3667 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3672 _startLazyDPSEvaluation ();
3675 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3677 _endLazyDPSEvaluation ();
3686 /*-----------------------------------------------------------------*/
3687 /* outBitAcc - output a bit in acc */
3688 /*-----------------------------------------------------------------*/
3690 outBitAcc (operand * result)
3692 symbol *tlbl = newiTempLabel (NULL);
3693 /* if the result is a bit */
3694 if (AOP_TYPE (result) == AOP_CRY)
3696 aopPut (AOP (result), "a", 0);
3700 emitcode ("jz", "!tlabel", tlbl->key + 100);
3701 emitcode ("mov", "a,%s", one);
3702 emitcode ("", "!tlabeldef", tlbl->key + 100);
3707 /*-----------------------------------------------------------------*/
3708 /* genPlusBits - generates code for addition of two bits */
3709 /*-----------------------------------------------------------------*/
3711 genPlusBits (iCode * ic)
3713 D (emitcode (";", "genPlusBits "););
3715 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3717 symbol *lbl = newiTempLabel (NULL);
3718 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3719 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3720 emitcode ("cpl", "c");
3721 emitcode ("", "!tlabeldef", (lbl->key + 100));
3722 outBitC (IC_RESULT (ic));
3726 emitcode ("clr", "a");
3727 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3728 emitcode ("rlc", "a");
3729 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3730 emitcode ("addc", "a,#0");
3731 outAcc (IC_RESULT (ic));
3736 adjustArithmeticResult (iCode * ic)
3738 if (opIsGptr (IC_RESULT (ic)) &&
3739 opIsGptr (IC_LEFT (ic)) &&
3740 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3742 aopPut (AOP (IC_RESULT (ic)),
3743 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3747 if (opIsGptr (IC_RESULT (ic)) &&
3748 opIsGptr (IC_RIGHT (ic)) &&
3749 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3751 aopPut (AOP (IC_RESULT (ic)),
3752 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3756 if (opIsGptr (IC_RESULT (ic)) &&
3757 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3758 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3759 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3760 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3763 SNPRINTF (buff, sizeof(buff),
3764 "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3765 aopPut (AOP (IC_RESULT (ic)), buff, GPTRSIZE - 1);
3769 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
3770 // generates the result if possible. If result is generated, returns TRUE; otherwise
3771 // returns false and caller must deal with fact that result isn't aopOp'd.
3772 bool aopOp3(iCode * ic)
3774 bool dp1InUse, dp2InUse;
3777 // First, generate the right opcode. DPTR may be used if neither left nor result are
3780 // D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
3781 // AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
3782 // AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
3783 // AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
3785 // D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
3786 // AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
3787 // AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
3788 // AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
3791 // Right uses DPTR unless left or result is an AOP_STR; however,
3792 // if right is an AOP_STR, it must use DPTR regardless.
3793 if ((AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)))
3794 && !AOP_IS_STR(IC_RIGHT(ic)))
3803 aopOp (IC_RIGHT(ic),ic,FALSE, useDp2);
3805 // if the right used DPTR, left MUST use DPTR2.
3806 // if the right used DPTR2, left MUST use DPTR.
3807 // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
3808 // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
3809 // enabling us to assign DPTR to result.
3811 if (AOP_USESDPTR(IC_RIGHT(ic)))
3815 else if (AOP_USESDPTR2(IC_RIGHT(ic)))
3821 if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
3831 aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
3833 // We've op'd the left & right. So, if left or right are the same operand as result,
3834 // we know aopOp will succeed, and we can just do it & bail.
3835 if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)) ||
3836 isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
3838 // D(emitcode(";", "aopOp3: (left | right) & result equal"););
3839 aopOp(IC_RESULT(ic),ic,TRUE, FALSE);
3843 // Note which dptrs are currently in use.
3844 dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
3845 dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
3847 // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot
3849 if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
3854 // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
3855 if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
3860 // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck
3861 if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
3866 aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
3868 // Some sanity checking...
3869 if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
3872 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
3873 __FILE__, __LINE__, ic->filename, ic->lineno);
3874 emitcode(";", ">>> unexpected DPTR here.");
3877 if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
3880 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
3881 __FILE__, __LINE__, ic->filename, ic->lineno);
3882 emitcode(";", ">>> unexpected DPTR2 here.");
3888 // Macro to aopOp all three operands of an ic. If this cannot be done,
3889 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3890 // will be set TRUE. The caller must then handle the case specially, noting
3891 // that the IC_RESULT operand is not aopOp'd.
3893 #define AOP_OP_3_NOFATAL(ic, rc) \
3894 do { rc = !aopOp3(ic); } while (0)
3896 // aopOp the left & right operands of an ic.
3897 #define AOP_OP_2(ic) \
3898 aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
3899 aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
3901 // convienience macro.
3902 #define AOP_SET_LOCALS(ic) \
3903 left = IC_LEFT(ic); \
3904 right = IC_RIGHT(ic); \
3905 result = IC_RESULT(ic);
3908 // Given an integer value of pushedSize bytes on the stack,
3909 // adjust it to be resultSize bytes, either by discarding
3910 // the most significant bytes or by zero-padding.
3912 // On exit from this macro, pushedSize will have been adjusted to
3913 // equal resultSize, and ACC may be trashed.
3914 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3915 /* If the pushed data is bigger than the result, \
3916 * simply discard unused bytes. Icky, but works. \
3918 while (pushedSize > resultSize) \
3920 D (emitcode (";", "discarding unused result byte."););\
3921 emitcode ("pop", "acc"); \
3924 if (pushedSize < resultSize) \
3926 emitcode ("clr", "a"); \
3927 /* Conversly, we haven't pushed enough here. \
3928 * just zero-pad, and all is well. \
3930 while (pushedSize < resultSize) \
3932 emitcode("push", "acc"); \
3936 assert(pushedSize == resultSize);
3938 /*-----------------------------------------------------------------*/
3939 /* genPlus - generates code for addition */
3940 /*-----------------------------------------------------------------*/
3942 genPlus (iCode * ic)
3944 int size, offset = 0;
3948 D (emitcode (";", "genPlus "););
3950 /* special cases :- */
3951 if ( AOP_IS_STR(IC_LEFT(ic)) &&
3952 isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
3953 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
3954 size = (int)floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
3956 while (size--) emitcode ("inc","dptr");
3958 emitcode ("mov","a,dpl");
3959 emitcode ("add","a,#!constbyte",size & 0xff);
3960 emitcode ("mov","dpl,a");
3961 emitcode ("mov","a,dph");
3962 emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
3963 emitcode ("mov","dph,a");
3964 emitcode ("mov","a,dpx");
3965 emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
3966 emitcode ("mov","dpx,a");
3968 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
3971 if ( IS_SYMOP(IC_LEFT(ic)) &&
3972 OP_SYMBOL(IC_LEFT(ic))->remat &&
3973 isOperandInFarSpace(IC_RIGHT(ic))) {
3974 operand *op = IC_RIGHT(ic);
3975 IC_RIGHT(ic) = IC_LEFT(ic);
3979 AOP_OP_3_NOFATAL (ic, pushResult);
3983 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3988 /* if literal, literal on the right or
3989 if left requires ACC or right is already
3991 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3992 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3993 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3995 operand *t = IC_RIGHT (ic);
3996 IC_RIGHT (ic) = IC_LEFT (ic);
3998 emitcode (";", "Swapped plus args.");
4001 /* if both left & right are in bit
4003 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4004 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4010 /* if left in bit space & right literal */
4011 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4012 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4014 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4015 /* if result in bit space */
4016 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4018 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4019 emitcode ("cpl", "c");
4020 outBitC (IC_RESULT (ic));
4024 size = getDataSize (IC_RESULT (ic));
4025 _startLazyDPSEvaluation ();
4028 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4029 emitcode ("addc", "a,#0");
4030 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4032 _endLazyDPSEvaluation ();
4037 /* if I can do an increment instead
4038 of add then GOOD for ME */
4039 if (genPlusIncr (ic) == TRUE)
4041 emitcode (";", "did genPlusIncr");
4046 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4048 _startLazyDPSEvaluation ();
4051 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4053 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4055 emitcode ("add", "a,%s",
4056 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4058 emitcode ("addc", "a,%s",
4059 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4063 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4065 /* right is going to use ACC or we would have taken the
4068 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4070 D(emitcode(";", "+ AOP_ACC special case."););
4071 emitcode("xch", "a, %s", DP2_RESULT_REG);
4073 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4076 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4079 emitcode("add", "a, %s", DP2_RESULT_REG);
4083 emitcode ("add", "a,%s",
4084 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE,
4090 emitcode ("addc", "a,%s",
4091 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE,
4097 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4101 emitcode ("push", "acc");
4105 _endLazyDPSEvaluation ();
4109 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4111 size = getDataSize (IC_LEFT (ic));
4112 rSize = getDataSize (IC_RESULT (ic));
4114 ADJUST_PUSHED_RESULT(size, rSize);
4116 _startLazyDPSEvaluation ();
4119 emitcode ("pop", "acc");
4120 aopPut (AOP (IC_RESULT (ic)), "a", size);
4122 _endLazyDPSEvaluation ();
4125 adjustArithmeticResult (ic);
4128 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4129 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4130 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4133 /*-----------------------------------------------------------------*/
4134 /* genMinusDec :- does subtraction with deccrement if possible */
4135 /*-----------------------------------------------------------------*/
4137 genMinusDec (iCode * ic)
4139 unsigned int icount;
4140 unsigned int size = getDataSize (IC_RESULT (ic));
4142 /* will try to generate an increment */
4143 /* if the right side is not a literal
4145 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4148 /* if the literal value of the right hand side
4149 is greater than 4 then it is not worth it */
4150 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4153 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4154 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4156 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
4160 /* if decrement 16 bits in register */
4161 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4162 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4163 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4172 /* If the next instruction is a goto and the goto target
4173 * is <= 5 instructions previous to this, we can generate
4174 * jumps straight to that target.
4176 if (ic->next && ic->next->op == GOTO
4177 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4180 emitcode (";", "tail decrement optimized (range %d)", labelRange);
4181 tlbl = IC_LABEL (ic->next);
4186 tlbl = newiTempLabel (NULL);
4190 l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
4191 emitcode ("dec", "%s", l);
4193 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4194 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4195 IS_AOP_PREG (IC_RESULT (ic)))
4197 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4201 emitcode ("mov", "a,#!constbyte",0xff);
4202 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4204 l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
4205 emitcode ("dec", "%s", l);
4208 if (!strcmp(l, "acc"))
4210 emitcode("jnz", "!tlabel", tlbl->key + 100);
4212 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4213 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4214 IS_AOP_PREG (IC_RESULT (ic)))
4216 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4220 emitcode ("mov", "a,#!constbyte",0xff);
4221 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4223 l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
4224 emitcode ("dec", "%s", l);
4228 if (!strcmp(l, "acc"))
4230 emitcode("jnz", "!tlabel", tlbl->key + 100);
4232 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4233 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4234 IS_AOP_PREG (IC_RESULT (ic)))
4236 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4240 emitcode ("mov", "a,#!constbyte",0xff);
4241 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4243 l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
4244 emitcode ("dec", "%s", l);
4248 emitcode ("", "!tlabeldef", tlbl->key + 100);
4253 /* if the sizes are greater than 1 then we cannot */
4254 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4255 AOP_SIZE (IC_LEFT (ic)) > 1)
4258 /* we can if the aops of the left & result match or
4259 if they are in registers and the registers are the
4262 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4263 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4264 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4267 _startLazyDPSEvaluation ();
4270 emitcode ("dec", "%s",
4271 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
4273 _endLazyDPSEvaluation ();
4281 /*-----------------------------------------------------------------*/
4282 /* addSign - complete with sign */
4283 /*-----------------------------------------------------------------*/
4285 addSign (operand * result, int offset, int sign)
4287 int size = (getDataSize (result) - offset);
4290 _startLazyDPSEvaluation();
4293 emitcode ("rlc", "a");
4294 emitcode ("subb", "a,acc");
4297 aopPut (AOP (result), "a", offset++);
4304 aopPut (AOP (result), zero, offset++);
4307 _endLazyDPSEvaluation();
4311 /*-----------------------------------------------------------------*/
4312 /* genMinusBits - generates code for subtraction of two bits */
4313 /*-----------------------------------------------------------------*/
4315 genMinusBits (iCode * ic)
4317 symbol *lbl = newiTempLabel (NULL);
4319 D (emitcode (";", "genMinusBits "););
4321 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4323 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4324 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4325 emitcode ("cpl", "c");
4326 emitcode ("", "!tlabeldef", (lbl->key + 100));
4327 outBitC (IC_RESULT (ic));
4331 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4332 emitcode ("subb", "a,acc");
4333 emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4334 emitcode ("inc", "a");
4335 emitcode ("", "!tlabeldef", (lbl->key + 100));
4336 aopPut (AOP (IC_RESULT (ic)), "a", 0);
4337 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4341 /*-----------------------------------------------------------------*/
4342 /* genMinus - generates code for subtraction */
4343 /*-----------------------------------------------------------------*/
4345 genMinus (iCode * ic)
4347 int size, offset = 0;
4352 D (emitcode (";", "genMinus "););
4354 AOP_OP_3_NOFATAL(ic, pushResult);
4358 /* special cases :- */
4359 /* if both left & right are in bit space */
4360 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4361 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4367 /* if I can do an decrement instead
4368 of subtract then GOOD for ME */
4369 if (genMinusDec (ic) == TRUE)
4374 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4376 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4382 lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4387 /* if literal, add a,#-lit, else normal subb */
4388 _startLazyDPSEvaluation ();
4390 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4391 if (AOP_USESDPTR(IC_RIGHT(ic))) {
4392 emitcode ("mov","b,%s",
4393 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4394 MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4395 emitcode ("subb","a,b");
4397 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4398 emitcode ("subb", "a,%s",
4399 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE,
4403 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4404 /* first add without previous c */
4406 if (!size && lit==-1) {
4407 emitcode ("dec", "a");
4409 emitcode ("add", "a,#!constbyte",
4410 (unsigned int) (lit & 0x0FFL));
4413 emitcode ("addc", "a,#!constbyte",
4414 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4419 emitcode ("push", "acc");
4421 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4425 _endLazyDPSEvaluation ();
4429 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4431 size = getDataSize (IC_LEFT (ic));
4432 rSize = getDataSize (IC_RESULT (ic));
4434 ADJUST_PUSHED_RESULT(size, rSize);
4436 _startLazyDPSEvaluation ();
4439 emitcode ("pop", "acc");
4440 aopPut (AOP (IC_RESULT (ic)), "a", size);
4442 _endLazyDPSEvaluation ();
4445 adjustArithmeticResult (ic);
4448 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4449 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4450 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4454 /*-----------------------------------------------------------------*/
4455 /* genMultbits :- multiplication of bits */
4456 /*-----------------------------------------------------------------*/
4458 genMultbits (operand * left,
4463 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4464 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4465 aopOp(result, ic, TRUE, FALSE);
4470 /*-----------------------------------------------------------------*/
4471 /* genMultOneByte : 8*8=8/16 bit multiplication */
4472 /*-----------------------------------------------------------------*/
4474 genMultOneByte (operand * left,
4479 sym_link *opetype = operandType (result);
4483 /* (if two literals: the value is computed before) */
4484 /* if one literal, literal on the right */
4485 if (AOP_TYPE (left) == AOP_LIT)
4490 emitcode (";", "swapped left and right");
4493 if (SPEC_USIGN(opetype)
4494 // ignore the sign of left and right, what else can we do?
4495 || (SPEC_USIGN(operandType(left)) &&
4496 SPEC_USIGN(operandType(right)))) {
4497 // just an unsigned 8*8=8/16 multiply
4498 //emitcode (";","unsigned");
4499 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4500 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4501 emitcode ("mul", "ab");
4503 _G.accInUse++; _G.bInUse++;
4504 aopOp(result, ic, TRUE, FALSE);
4506 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4508 // this should never happen
4509 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4510 AOP_SIZE(result), __FILE__, lineno);
4514 aopPut (AOP (result), "a", 0);
4515 _G.accInUse--; _G.bInUse--;
4516 if (AOP_SIZE(result)==2)
4518 aopPut (AOP (result), "b", 1);
4523 // we have to do a signed multiply
4525 emitcode (";", "signed");
4526 emitcode ("clr", "F0"); // reset sign flag
4527 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4529 lbl=newiTempLabel(NULL);
4530 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4531 // left side is negative, 8-bit two's complement, this fails for -128
4532 emitcode ("setb", "F0"); // set sign flag
4533 emitcode ("cpl", "a");
4534 emitcode ("inc", "a");
4536 emitcode ("", "!tlabeldef", lbl->key+100);
4539 if (AOP_TYPE(right)==AOP_LIT) {
4540 signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
4541 /* AND literal negative */
4542 if ((int) val < 0) {
4543 emitcode ("cpl", "F0"); // complement sign flag
4544 emitcode ("mov", "b,#!constbyte", -val);
4546 emitcode ("mov", "b,#!constbyte", val);
4549 lbl=newiTempLabel(NULL);
4550 emitcode ("mov", "b,a");
4551 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4552 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4553 // right side is negative, 8-bit two's complement
4554 emitcode ("cpl", "F0"); // complement sign flag
4555 emitcode ("cpl", "a");
4556 emitcode ("inc", "a");
4557 emitcode ("", "!tlabeldef", lbl->key+100);
4559 emitcode ("mul", "ab");
4561 _G.accInUse++;_G.bInUse++;
4562 aopOp(result, ic, TRUE, FALSE);
4564 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4566 // this should never happen
4567 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4568 AOP_SIZE(result), __FILE__, lineno);
4572 lbl=newiTempLabel(NULL);
4573 emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4574 // only ONE op was negative, we have to do a 8/16-bit two's complement
4575 emitcode ("cpl", "a"); // lsb
4576 if (AOP_SIZE(result)==1) {
4577 emitcode ("inc", "a");
4579 emitcode ("add", "a,#1");
4580 emitcode ("xch", "a,b");
4581 emitcode ("cpl", "a"); // msb
4582 emitcode ("addc", "a,#0");
4583 emitcode ("xch", "a,b");
4586 emitcode ("", "!tlabeldef", lbl->key+100);
4587 aopPut (AOP (result), "a", 0);
4588 _G.accInUse--;_G.bInUse--;
4589 if (AOP_SIZE(result)==2) {
4590 aopPut (AOP (result), "b", 1);
4594 /*-----------------------------------------------------------------*/
4595 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
4596 /*-----------------------------------------------------------------*/
4597 static void genMultTwoByte (operand *left, operand *right,
4598 operand *result, iCode *ic)
4600 sym_link *retype = getSpec(operandType(right));
4601 sym_link *letype = getSpec(operandType(left));
4602 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4605 if (AOP_TYPE (left) == AOP_LIT) {
4610 /* save EA bit in F1 */
4611 lbl = newiTempLabel(NULL);
4612 emitcode ("setb","F1");
4613 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4614 emitcode ("clr","F1");
4615 emitcode("","!tlabeldef",lbl->key+100);
4617 /* load up MB with right */
4619 emitcode("clr","F0");
4620 if (AOP_TYPE(right) == AOP_LIT) {
4621 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
4623 emitcode("setb","F0");
4626 emitcode ("mov","mb,#!constbyte",val & 0xff);
4627 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4629 lbl = newiTempLabel(NULL);
4630 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4631 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4632 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4633 emitcode ("xch", "a,b");
4634 emitcode ("cpl","a");
4635 emitcode ("add", "a,#1");
4636 emitcode ("xch", "a,b");
4637 emitcode ("cpl", "a"); // msb
4638 emitcode ("addc", "a,#0");
4639 emitcode ("setb","F0");
4640 emitcode ("","!tlabeldef",lbl->key+100);
4641 emitcode ("mov","mb,b");
4642 emitcode ("mov","mb,a");
4645 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4646 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4648 /* load up MA with left */
4650 lbl = newiTempLabel(NULL);
4651 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4652 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4653 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4654 emitcode ("xch", "a,b");
4655 emitcode ("cpl","a");
4656 emitcode ("add", "a,#1");
4657 emitcode ("xch", "a,b");
4658 emitcode ("cpl", "a"); // msb
4659 emitcode ("addc","a,#0");
4660 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4661 emitcode ("setb","F0");
4662 emitcode ("","!tlabeldef",lbl->key+100);
4663 emitcode ("mov","ma,b");
4664 emitcode ("mov","ma,a");
4666 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4667 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4669 /* wait for multiplication to finish */
4670 lbl = newiTempLabel(NULL);
4671 emitcode("","!tlabeldef", lbl->key+100);
4672 emitcode("mov","a,mcnt1");
4673 emitcode("anl","a,#!constbyte",0x80);
4674 emitcode("jnz","!tlabel",lbl->key+100);
4676 freeAsmop (left, NULL, ic, TRUE);
4677 freeAsmop (right, NULL, ic,TRUE);
4678 aopOp(result, ic, TRUE, FALSE);
4680 /* if unsigned then simple */
4682 emitcode ("mov","a,ma");
4683 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4684 emitcode ("mov","a,ma");
4685 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4686 aopPut(AOP(result),"ma",1);
4687 aopPut(AOP(result),"ma",0);
4689 emitcode("push","ma");
4690 emitcode("push","ma");
4691 emitcode("push","ma");
4693 /* negate result if needed */
4694 lbl = newiTempLabel(NULL);
4695 emitcode("jnb","F0,!tlabel",lbl->key+100);
4696 emitcode("cpl","a");
4697 emitcode("add","a,#1");
4698 emitcode("","!tlabeldef", lbl->key+100);
4699 if (AOP_TYPE(result) == AOP_ACC)
4701 D(emitcode(";", "ACC special case."););
4702 /* We know result is the only live aop, and
4703 * it's obviously not a DPTR2, so AP is available.
4705 emitcode("mov", "%s,acc", DP2_RESULT_REG);
4709 aopPut(AOP(result),"a",0);
4712 emitcode("pop","acc");
4713 lbl = newiTempLabel(NULL);
4714 emitcode("jnb","F0,!tlabel",lbl->key+100);
4715 emitcode("cpl","a");
4716 emitcode("addc","a,#0");
4717 emitcode("","!tlabeldef", lbl->key+100);
4718 aopPut(AOP(result),"a",1);
4719 emitcode("pop","acc");
4720 if (AOP_SIZE(result) >= 3) {
4721 lbl = newiTempLabel(NULL);
4722 emitcode("jnb","F0,!tlabel",lbl->key+100);
4723 emitcode("cpl","a");
4724 emitcode("addc","a,#0");
4725 emitcode("","!tlabeldef", lbl->key+100);
4726 aopPut(AOP(result),"a",2);
4728 emitcode("pop","acc");
4729 if (AOP_SIZE(result) >= 4) {
4730 lbl = newiTempLabel(NULL);
4731 emitcode("jnb","F0,!tlabel",lbl->key+100);
4732 emitcode("cpl","a");
4733 emitcode("addc","a,#0");
4734 emitcode("","!tlabeldef", lbl->key+100);
4735 aopPut(AOP(result),"a",3);
4737 if (AOP_TYPE(result) == AOP_ACC)
4739 /* We stashed the result away above. */
4740 emitcode("mov", "acc,%s", DP2_RESULT_REG);
4744 freeAsmop (result, NULL, ic, TRUE);
4746 /* restore EA bit in F1 */
4747 lbl = newiTempLabel(NULL);
4748 emitcode ("jnb","F1,!tlabel",lbl->key+100);
4749 emitcode ("setb","EA");
4750 emitcode("","!tlabeldef",lbl->key+100);
4754 /*-----------------------------------------------------------------*/
4755 /* genMult - generates code for multiplication */
4756 /*-----------------------------------------------------------------*/
4758 genMult (iCode * ic)
4760 operand *left = IC_LEFT (ic);
4761 operand *right = IC_RIGHT (ic);
4762 operand *result = IC_RESULT (ic);
4764 D (emitcode (";", "genMult "););
4766 /* assign the amsops */
4769 /* special cases first */
4771 if (AOP_TYPE (left) == AOP_CRY &&
4772 AOP_TYPE (right) == AOP_CRY)
4774 genMultbits (left, right, result, ic);
4778 /* if both are of size == 1 */
4779 if (AOP_SIZE (left) == 1 &&
4780 AOP_SIZE (right) == 1)
4782 genMultOneByte (left, right, result, ic);
4786 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4787 /* use the ds390 ARITHMETIC accel UNIT */
4788 genMultTwoByte (left, right, result, ic);
4791 /* should have been converted to function call */
4795 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4796 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4797 freeAsmop (result, NULL, ic, TRUE);
4800 /*-----------------------------------------------------------------*/
4801 /* genDivbits :- division of bits */
4802 /*-----------------------------------------------------------------*/
4804 genDivbits (operand * left,
4812 /* the result must be bit */
4813 LOAD_AB_FOR_DIV (left, right, l);
4814 emitcode ("div", "ab");
4815 emitcode ("rrc", "a");
4816 aopOp(result, ic, TRUE, FALSE);
4818 aopPut (AOP (result), "c", 0);
4821 /*-----------------------------------------------------------------*/
4822 /* genDivOneByte : 8 bit division */
4823 /*-----------------------------------------------------------------*/
4825 genDivOneByte (operand * left,
4830 sym_link *opetype = operandType (result);
4836 /* signed or unsigned */
4837 if (SPEC_USIGN (opetype))
4839 /* unsigned is easy */
4840 LOAD_AB_FOR_DIV (left, right, l);
4841 emitcode ("div", "ab");
4844 aopOp(result, ic, TRUE, FALSE);
4845 aopPut (AOP (result), "a", 0);
4848 size = AOP_SIZE (result) - 1;
4852 aopPut (AOP (result), zero, offset++);
4857 /* signed is a little bit more difficult */
4859 /* save the signs of the operands */
4860 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4861 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4862 emitcode ("push", "acc"); /* save it on the stack */
4864 /* now sign adjust for both left & right */
4865 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4866 lbl = newiTempLabel (NULL);
4867 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4868 emitcode ("cpl", "a");
4869 emitcode ("inc", "a");
4870 emitcode ("", "!tlabeldef", (lbl->key + 100));
4871 emitcode ("mov", "b,a");
4873 /* sign adjust left side */
4874 MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4876 lbl = newiTempLabel (NULL);
4877 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4878 emitcode ("cpl", "a");
4879 emitcode ("inc", "a");
4880 emitcode ("", "!tlabeldef", (lbl->key + 100));
4882 /* now the division */
4883 emitcode ("nop", "; workaround for DS80C390 div bug.");
4884 emitcode ("div", "ab");
4885 /* we are interested in the lower order
4887 emitcode ("mov", "b,a");
4888 lbl = newiTempLabel (NULL);
4889 emitcode ("pop", "acc");
4890 /* if there was an over flow we don't
4891 adjust the sign of the result */
4892 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4893 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4895 emitcode ("clr", "a");
4896 emitcode ("subb", "a,b");
4897 emitcode ("mov", "b,a");
4898 emitcode ("", "!tlabeldef", (lbl->key + 100));
4900 /* now we are done */
4901 _G.accInUse++; _G.bInUse++;
4902 aopOp(result, ic, TRUE, FALSE);
4904 aopPut (AOP (result), "b", 0);
4906 size = AOP_SIZE (result) - 1;
4910 emitcode ("mov", "c,b.7");
4911 emitcode ("subb", "a,acc");
4915 aopPut (AOP (result), "a", offset++);
4917 _G.accInUse--; _G.bInUse--;
4921 /*-----------------------------------------------------------------*/
4922 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
4923 /*-----------------------------------------------------------------*/
4924 static void genDivTwoByte (operand *left, operand *right,
4925 operand *result, iCode *ic)
4927 sym_link *retype = getSpec(operandType(right));
4928 sym_link *letype = getSpec(operandType(left));
4929 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4932 /* save EA bit in F1 */
4933 lbl = newiTempLabel(NULL);
4934 emitcode ("setb","F1");
4935 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4936 emitcode ("clr","F1");
4937 emitcode("","!tlabeldef",lbl->key+100);
4939 /* load up MA with left */
4941 emitcode("clr","F0");
4942 lbl = newiTempLabel(NULL);
4943 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4944 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4945 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4946 emitcode ("xch", "a,b");
4947 emitcode ("cpl","a");
4948 emitcode ("add", "a,#1");
4949 emitcode ("xch", "a,b");
4950 emitcode ("cpl", "a"); // msb
4951 emitcode ("addc","a,#0");
4952 emitcode ("setb","F0");
4953 emitcode ("","!tlabeldef",lbl->key+100);
4954 emitcode ("mov","ma,b");
4955 emitcode ("mov","ma,a");
4957 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4958 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4961 /* load up MB with right */
4963 if (AOP_TYPE(right) == AOP_LIT) {
4964 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
4966 lbl = newiTempLabel(NULL);
4967 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4968 emitcode("setb","F0");
4969 emitcode ("","!tlabeldef",lbl->key+100);
4972 emitcode ("mov","mb,#!constbyte",val & 0xff);
4973 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4975 lbl = newiTempLabel(NULL);
4976 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4977 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4978 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4979 emitcode ("xch", "a,b");
4980 emitcode ("cpl","a");
4981 emitcode ("add", "a,#1");
4982 emitcode ("xch", "a,b");
4983 emitcode ("cpl", "a"); // msb
4984 emitcode ("addc", "a,#0");
4985 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4986 emitcode ("setb","F0");
4987 emitcode ("","!tlabeldef",lbl->key+100);
4988 emitcode ("mov","mb,b");
4989 emitcode ("mov","mb,a");
4992 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4993 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4996 /* wait for multiplication to finish */
4997 lbl = newiTempLabel(NULL);
4998 emitcode("","!tlabeldef", lbl->key+100);
4999 emitcode("mov","a,mcnt1");
5000 emitcode("anl","a,#!constbyte",0x80);
5001 emitcode("jnz","!tlabel",lbl->key+100);
5003 freeAsmop (left, NULL, ic, TRUE);
5004 freeAsmop (right, NULL, ic,TRUE);
5005 aopOp(result, ic, TRUE, FALSE);
5007 /* if unsigned then simple */
5009 aopPut(AOP(result),"ma",1);
5010 aopPut(AOP(result),"ma",0);
5012 emitcode("push","ma");
5014 /* negate result if needed */
5015 lbl = newiTempLabel(NULL);
5016 emitcode("jnb","F0,!tlabel",lbl->key+100);
5017 emitcode("cpl","a");
5018 emitcode("add","a,#1");
5019 emitcode("","!tlabeldef", lbl->key+100);
5020 aopPut(AOP(result),"a",0);
5021 emitcode("pop","acc");
5022 lbl = newiTempLabel(NULL);
5023 emitcode("jnb","F0,!tlabel",lbl->key+100);
5024 emitcode("cpl","a");
5025 emitcode("addc","a,#0");
5026 emitcode("","!tlabeldef", lbl->key+100);
5027 aopPut(AOP(result),"a",1);
5029 freeAsmop (result, NULL, ic, TRUE);
5030 /* restore EA bit in F1 */
5031 lbl = newiTempLabel(NULL);
5032 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5033 emitcode ("setb","EA");
5034 emitcode("","!tlabeldef",lbl->key+100);
5038 /*-----------------------------------------------------------------*/
5039 /* genDiv - generates code for division */
5040 /*-----------------------------------------------------------------*/
5044 operand *left = IC_LEFT (ic);
5045 operand *right = IC_RIGHT (ic);
5046 operand *result = IC_RESULT (ic);
5048 D (emitcode (";", "genDiv "););
5050 /* assign the amsops */
5053 /* special cases first */
5055 if (AOP_TYPE (left) == AOP_CRY &&
5056 AOP_TYPE (right) == AOP_CRY)
5058 genDivbits (left, right, result, ic);
5062 /* if both are of size == 1 */
5063 if (AOP_SIZE (left) == 1 &&
5064 AOP_SIZE (right) == 1)
5066 genDivOneByte (left, right, result, ic);
5070 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5071 /* use the ds390 ARITHMETIC accel UNIT */
5072 genDivTwoByte (left, right, result, ic);
5075 /* should have been converted to function call */
5078 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5079 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5080 freeAsmop (result, NULL, ic, TRUE);
5083 /*-----------------------------------------------------------------*/
5084 /* genModbits :- modulus of bits */
5085 /*-----------------------------------------------------------------*/
5087 genModbits (operand * left,
5095 /* the result must be bit */
5096 LOAD_AB_FOR_DIV (left, right, l);
5097 emitcode ("div", "ab");
5098 emitcode ("mov", "a,b");
5099 emitcode ("rrc", "a");
5100 aopOp(result, ic, TRUE, FALSE);
5101 aopPut (AOP (result), "c", 0);
5104 /*-----------------------------------------------------------------*/
5105 /* genModOneByte : 8 bit modulus */
5106 /*-----------------------------------------------------------------*/
5108 genModOneByte (operand * left,
5113 sym_link *opetype = operandType (result);
5117 /* signed or unsigned */
5118 if (SPEC_USIGN (opetype))
5120 /* unsigned is easy */
5121 LOAD_AB_FOR_DIV (left, right, l);
5122 emitcode ("div", "ab");
5123 aopOp(result, ic, TRUE, FALSE);
5124 aopPut (AOP (result), "b", 0);
5128 /* signed is a little bit more difficult */
5130 /* save the signs of the operands */
5131 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5133 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
5134 emitcode ("push", "acc"); /* save it on the stack */
5136 /* now sign adjust for both left & right */
5137 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5139 lbl = newiTempLabel (NULL);
5140 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5141 emitcode ("cpl", "a");
5142 emitcode ("inc", "a");
5143 emitcode ("", "!tlabeldef", (lbl->key + 100));
5144 emitcode ("mov", "b,a");
5146 /* sign adjust left side */
5147 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5149 lbl = newiTempLabel (NULL);
5150 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5151 emitcode ("cpl", "a");
5152 emitcode ("inc", "a");
5153 emitcode ("", "!tlabeldef", (lbl->key + 100));
5155 /* now the multiplication */
5156 emitcode ("nop", "; workaround for DS80C390 div bug.");
5157 emitcode ("div", "ab");
5158 /* we are interested in the lower order
5160 lbl = newiTempLabel (NULL);
5161 emitcode ("pop", "acc");
5162 /* if there was an over flow we don't
5163 adjust the sign of the result */
5164 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
5165 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5167 emitcode ("clr", "a");
5168 emitcode ("subb", "a,b");
5169 emitcode ("mov", "b,a");
5170 emitcode ("", "!tlabeldef", (lbl->key + 100));
5173 /* now we are done */
5174 aopOp(result, ic, TRUE, FALSE);
5175 aopPut (AOP (result), "b", 0);
5180 /*-----------------------------------------------------------------*/
5181 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
5182 /*-----------------------------------------------------------------*/
5183 static void genModTwoByte (operand *left, operand *right,
5184 operand *result, iCode *ic)
5186 sym_link *retype = getSpec(operandType(right));
5187 sym_link *letype = getSpec(operandType(left));
5188 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5191 /* load up MA with left */
5192 /* save EA bit in F1 */
5193 lbl = newiTempLabel(NULL);
5194 emitcode ("setb","F1");
5195 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5196 emitcode ("clr","F1");
5197 emitcode("","!tlabeldef",lbl->key+100);
5200 lbl = newiTempLabel(NULL);
5201 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5202 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5203 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5204 emitcode ("xch", "a,b");
5205 emitcode ("cpl","a");
5206 emitcode ("add", "a,#1");
5207 emitcode ("xch", "a,b");
5208 emitcode ("cpl", "a"); // msb
5209 emitcode ("addc","a,#0");
5210 emitcode ("","!tlabeldef",lbl->key+100);
5211 emitcode ("mov","ma,b");
5212 emitcode ("mov","ma,a");
5214 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5215 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5218 /* load up MB with right */
5220 if (AOP_TYPE(right) == AOP_LIT) {
5221 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5225 emitcode ("mov","mb,#!constbyte",val & 0xff);
5226 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5228 lbl = newiTempLabel(NULL);
5229 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5230 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5231 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5232 emitcode ("xch", "a,b");
5233 emitcode ("cpl","a");
5234 emitcode ("add", "a,#1");
5235 emitcode ("xch", "a,b");
5236 emitcode ("cpl", "a"); // msb
5237 emitcode ("addc", "a,#0");
5238 emitcode ("","!tlabeldef",lbl->key+100);
5239 emitcode ("mov","mb,b");
5240 emitcode ("mov","mb,a");
5243 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5244 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5247 /* wait for multiplication to finish */
5248 lbl = newiTempLabel(NULL);
5249 emitcode("","!tlabeldef", lbl->key+100);
5250 emitcode("mov","a,mcnt1");
5251 emitcode("anl","a,#!constbyte",0x80);
5252 emitcode("jnz","!tlabel",lbl->key+100);
5254 freeAsmop (left, NULL, ic, TRUE);
5255 freeAsmop (right, NULL, ic,TRUE);
5256 aopOp(result, ic, TRUE, FALSE);
5258 aopPut(AOP(result),"mb",1);
5259 aopPut(AOP(result),"mb",0);
5260 freeAsmop (result, NULL, ic, TRUE);
5262 /* restore EA bit in F1 */
5263 lbl = newiTempLabel(NULL);
5264 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5265 emitcode ("setb","EA");
5266 emitcode("","!tlabeldef",lbl->key+100);
5270 /*-----------------------------------------------------------------*/
5271 /* genMod - generates code for division */
5272 /*-----------------------------------------------------------------*/
5276 operand *left = IC_LEFT (ic);
5277 operand *right = IC_RIGHT (ic);
5278 operand *result = IC_RESULT (ic);
5280 D (emitcode (";", "genMod "); );
5282 /* assign the amsops */
5285 /* special cases first */
5287 if (AOP_TYPE (left) == AOP_CRY &&
5288 AOP_TYPE (right) == AOP_CRY)
5290 genModbits (left, right, result, ic);
5294 /* if both are of size == 1 */
5295 if (AOP_SIZE (left) == 1 &&
5296 AOP_SIZE (right) == 1)
5298 genModOneByte (left, right, result, ic);
5302 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5303 /* use the ds390 ARITHMETIC accel UNIT */
5304 genModTwoByte (left, right, result, ic);
5308 /* should have been converted to function call */
5312 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5313 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5314 freeAsmop (result, NULL, ic, TRUE);
5317 /*-----------------------------------------------------------------*/
5318 /* genIfxJump :- will create a jump depending on the ifx */
5319 /*-----------------------------------------------------------------*/
5321 genIfxJump (iCode * ic, char *jval)
5324 symbol *tlbl = newiTempLabel (NULL);
5327 D (emitcode (";", "genIfxJump"););
5329 /* if true label then we jump if condition
5333 jlbl = IC_TRUE (ic);
5334 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5335 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5339 /* false label is present */
5340 jlbl = IC_FALSE (ic);
5341 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5342 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5344 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5345 emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5347 emitcode (inst, "!tlabel", tlbl->key + 100);
5348 emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5349 emitcode ("", "!tlabeldef", tlbl->key + 100);
5351 /* mark the icode as generated */
5355 /*-----------------------------------------------------------------*/
5356 /* genCmp :- greater or less than comparison */
5357 /*-----------------------------------------------------------------*/
5359 genCmp (operand * left, operand * right,
5360 iCode * ic, iCode * ifx, int sign)
5362 int size, offset = 0;
5363 unsigned long lit = 0L;
5366 D (emitcode (";", "genCmp"););
5368 result = IC_RESULT (ic);
5370 /* if left & right are bit variables */
5371 if (AOP_TYPE (left) == AOP_CRY &&
5372 AOP_TYPE (right) == AOP_CRY)
5374 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5375 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5379 /* subtract right from left if at the
5380 end the carry flag is set then we know that
5381 left is greater than right */
5382 size = max (AOP_SIZE (left), AOP_SIZE (right));
5384 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5385 if ((size == 1) && !sign
5386 && (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5388 symbol *lbl = newiTempLabel (NULL);
5389 emitcode ("cjne", "%s,%s,!tlabel",
5390 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
5391 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5393 emitcode ("", "!tlabeldef", lbl->key + 100);
5397 if (AOP_TYPE (right) == AOP_LIT)
5399 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5400 /* optimize if(x < 0) or if(x >= 0) */
5409 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
5411 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5412 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5414 aopOp (result, ic, FALSE, FALSE);
5416 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5418 freeAsmop (result, NULL, ic, TRUE);
5419 genIfxJump (ifx, "acc.7");
5424 emitcode ("rlc", "a");
5426 goto release_freedLR;
5434 // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5435 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5436 // emitcode (";", "genCmp #2");
5437 if (sign && (size == 0))
5439 // emitcode (";", "genCmp #3");
5440 emitcode ("xrl", "a,#!constbyte",0x80);
5441 if (AOP_TYPE (right) == AOP_LIT)
5443 unsigned long lit = (unsigned long)
5444 floatFromVal (AOP (right)->aopu.aop_lit);
5445 // emitcode (";", "genCmp #3.1");
5446 emitcode ("subb", "a,#!constbyte",
5447 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5451 // emitcode (";", "genCmp #3.2");
5453 MOVB(aopGet (AOP (right), offset++, FALSE, FALSE, "b"));
5454 saveAccWarn = DEFAULT_ACC_WARNING;
5455 emitcode ("xrl", "b,#!constbyte",0x80);
5456 emitcode ("subb", "a,b");
5463 // emitcode (";", "genCmp #4");
5465 s = aopGet (AOP (right), offset++, FALSE, FALSE, "b");
5466 saveAccWarn = DEFAULT_ACC_WARNING;
5468 emitcode ("subb", "a,%s", s);
5475 /* Don't need the left & right operands any more; do need the result. */
5476 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5477 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5479 aopOp (result, ic, FALSE, FALSE);
5483 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5489 /* if the result is used in the next
5490 ifx conditional branch then generate
5491 code a little differently */
5494 genIfxJump (ifx, "c");
5500 /* leave the result in acc */
5502 freeAsmop (result, NULL, ic, TRUE);
5505 /*-----------------------------------------------------------------*/
5506 /* genCmpGt :- greater than comparison */
5507 /*-----------------------------------------------------------------*/
5509 genCmpGt (iCode * ic, iCode * ifx)
5511 operand *left, *right;
5512 sym_link *letype, *retype;
5515 D (emitcode (";", "genCmpGt ");
5518 left = IC_LEFT (ic);
5519 right = IC_RIGHT (ic);
5521 letype = getSpec (operandType (left));
5522 retype = getSpec (operandType (right));
5523 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5525 /* assign the left & right amsops */
5528 genCmp (right, left, ic, ifx, sign);
5531 /*-----------------------------------------------------------------*/
5532 /* genCmpLt - less than comparisons */
5533 /*-----------------------------------------------------------------*/
5535 genCmpLt (iCode * ic, iCode * ifx)
5537 operand *left, *right;
5538 sym_link *letype, *retype;
5541 D (emitcode (";", "genCmpLt "););
5543 left = IC_LEFT (ic);
5544 right = IC_RIGHT (ic);
5546 letype = getSpec (operandType (left));
5547 retype = getSpec (operandType (right));
5548 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5550 /* assign the left & right amsops */
5553 genCmp (left, right, ic, ifx, sign);
5556 /*-----------------------------------------------------------------*/
5557 /* gencjneshort - compare and jump if not equal */
5558 /*-----------------------------------------------------------------*/
5560 gencjneshort (operand * left, operand * right, symbol * lbl)
5562 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5564 unsigned long lit = 0L;
5566 D (emitcode (";", "gencjneshort");
5569 /* if the left side is a literal or
5570 if the right is in a pointer register and left
5572 if ((AOP_TYPE (left) == AOP_LIT) ||
5573 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5580 if (AOP_TYPE (right) == AOP_LIT)
5581 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5583 if (opIsGptr (left) || opIsGptr (right))
5585 /* We are comparing a generic pointer to something.
5586 * Exclude the generic type byte from the comparison.
5589 D (emitcode (";", "cjneshort: generic ptr special case."););
5593 /* if the right side is a literal then anything goes */
5594 if (AOP_TYPE (right) == AOP_LIT &&
5595 AOP_TYPE (left) != AOP_DIR)
5599 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5600 emitcode ("cjne", "a,%s,!tlabel",
5601 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5607 /* if the right side is in a register or in direct space or
5608 if the left is a pointer register & right is not */
5609 else if (AOP_TYPE (right) == AOP_REG ||
5610 AOP_TYPE (right) == AOP_DIR ||
5611 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5612 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5616 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5617 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5618 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5619 emitcode ("jnz", "!tlabel", lbl->key + 100);
5621 emitcode ("cjne", "a,%s,!tlabel",
5622 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
5629 /* right is a pointer reg need both a & b */
5632 MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5633 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
5634 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5640 /*-----------------------------------------------------------------*/
5641 /* gencjne - compare and jump if not equal */
5642 /*-----------------------------------------------------------------*/
5644 gencjne (operand * left, operand * right, symbol * lbl)
5646 symbol *tlbl = newiTempLabel (NULL);
5648 D (emitcode (";", "gencjne");
5651 gencjneshort (left, right, lbl);
5653 emitcode ("mov", "a,%s", one);
5654 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5655 emitcode ("", "!tlabeldef", lbl->key + 100);
5656 emitcode ("clr", "a");
5657 emitcode ("", "!tlabeldef", tlbl->key + 100);
5660 /*-----------------------------------------------------------------*/
5661 /* genCmpEq - generates code for equal to */
5662 /*-----------------------------------------------------------------*/
5664 genCmpEq (iCode * ic, iCode * ifx)
5666 operand *left, *right, *result;
5668 D (emitcode (";", "genCmpEq ");
5672 AOP_SET_LOCALS (ic);
5674 /* if literal, literal on the right or
5675 if the right is in a pointer register and left
5677 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5678 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5680 operand *t = IC_RIGHT (ic);
5681 IC_RIGHT (ic) = IC_LEFT (ic);
5685 if (ifx && /* !AOP_SIZE(result) */
5686 OP_SYMBOL (result) &&
5687 OP_SYMBOL (result)->regType == REG_CND)
5690 /* if they are both bit variables */
5691 if (AOP_TYPE (left) == AOP_CRY &&
5692 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5694 if (AOP_TYPE (right) == AOP_LIT)
5696 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5699 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5700 emitcode ("cpl", "c");
5704 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5708 emitcode ("clr", "c");
5710 /* AOP_TYPE(right) == AOP_CRY */
5714 symbol *lbl = newiTempLabel (NULL);
5715 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5716 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5717 emitcode ("cpl", "c");
5718 emitcode ("", "!tlabeldef", (lbl->key + 100));
5720 /* if true label then we jump if condition
5722 tlbl = newiTempLabel (NULL);
5725 emitcode ("jnc", "!tlabel", tlbl->key + 100);
5726 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5730 emitcode ("jc", "!tlabel", tlbl->key + 100);
5731 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5733 emitcode ("", "!tlabeldef", tlbl->key + 100);
5737 tlbl = newiTempLabel (NULL);
5738 gencjneshort (left, right, tlbl);
5741 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5742 emitcode ("", "!tlabeldef", tlbl->key + 100);
5746 symbol *lbl = newiTempLabel (NULL);
5747 emitcode ("sjmp", "!tlabel", lbl->key + 100);
5748 emitcode ("", "!tlabeldef", tlbl->key + 100);
5749 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5750 emitcode ("", "!tlabeldef", lbl->key + 100);
5753 /* mark the icode as generated */
5756 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5757 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5761 /* if they are both bit variables */
5762 if (AOP_TYPE (left) == AOP_CRY &&
5763 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5765 if (AOP_TYPE (right) == AOP_LIT)
5767 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5770 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5771 emitcode ("cpl", "c");
5775 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5779 emitcode ("clr", "c");
5781 /* AOP_TYPE(right) == AOP_CRY */
5785 symbol *lbl = newiTempLabel (NULL);
5786 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5787 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5788 emitcode ("cpl", "c");
5789 emitcode ("", "!tlabeldef", (lbl->key + 100));
5792 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5793 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5795 aopOp (result, ic, TRUE, FALSE);
5798 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5805 genIfxJump (ifx, "c");
5808 /* if the result is used in an arithmetic operation
5809 then put the result in place */
5814 gencjne (left, right, newiTempLabel (NULL));
5816 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5817 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5819 aopOp (result, ic, TRUE, FALSE);
5821 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5823 aopPut (AOP (result), "a", 0);
5828 genIfxJump (ifx, "a");
5831 /* if the result is used in an arithmetic operation
5832 then put the result in place */
5833 if (AOP_TYPE (result) != AOP_CRY)
5835 /* leave the result in acc */
5839 freeAsmop (result, NULL, ic, TRUE);
5842 /*-----------------------------------------------------------------*/
5843 /* ifxForOp - returns the icode containing the ifx for operand */
5844 /*-----------------------------------------------------------------*/
5846 ifxForOp (operand * op, iCode * ic)
5848 /* if true symbol then needs to be assigned */
5849 if (IS_TRUE_SYMOP (op))
5852 /* if this has register type condition and
5853 the next instruction is ifx with the same operand
5854 and live to of the operand is upto the ifx only then */
5856 ic->next->op == IFX &&
5857 IC_COND (ic->next)->key == op->key &&
5858 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5863 /*-----------------------------------------------------------------*/
5864 /* hasInc - operand is incremented before any other use */
5865 /*-----------------------------------------------------------------*/
5867 hasInc (operand *op, iCode *ic, int osize)
5869 sym_link *type = operandType(op);
5870 sym_link *retype = getSpec (type);
5871 iCode *lic = ic->next;
5874 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5875 if (!IS_SYMOP(op)) return NULL;
5877 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5878 if (IS_AGGREGATE(type->next)) return NULL;
5879 if (osize != (isize = getSize(type->next))) return NULL;
5882 /* if operand of the form op = op + <sizeof *op> */
5883 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5884 isOperandEqual(IC_RESULT(lic),op) &&
5885 isOperandLiteral(IC_RIGHT(lic)) &&
5886 operandLitValue(IC_RIGHT(lic)) == isize) {
5889 /* if the operand used or deffed */
5890 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5893 /* if GOTO or IFX */
5894 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5900 /*-----------------------------------------------------------------*/
5901 /* genAndOp - for && operation */
5902 /*-----------------------------------------------------------------*/
5904 genAndOp (iCode * ic)
5906 operand *left, *right, *result;
5909 D (emitcode (";", "genAndOp "););
5911 /* note here that && operations that are in an
5912 if statement are taken away by backPatchLabels
5913 only those used in arthmetic operations remain */
5915 AOP_SET_LOCALS (ic);
5917 /* if both are bit variables */
5918 if (AOP_TYPE (left) == AOP_CRY &&
5919 AOP_TYPE (right) == AOP_CRY)
5921 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5922 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5923 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5924 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5926 aopOp (result,ic,FALSE, FALSE);
5931 tlbl = newiTempLabel (NULL);
5933 emitcode ("jz", "!tlabel", tlbl->key + 100);
5935 emitcode ("", "!tlabeldef", tlbl->key + 100);
5936 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5937 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5939 aopOp (result,ic,FALSE, FALSE);
5942 freeAsmop (result, NULL, ic, TRUE);
5946 /*-----------------------------------------------------------------*/
5947 /* genOrOp - for || operation */
5948 /*-----------------------------------------------------------------*/
5950 genOrOp (iCode * ic)
5952 operand *left, *right, *result;
5955 D (emitcode (";", "genOrOp "););
5957 /* note here that || operations that are in an
5958 if statement are taken away by backPatchLabels
5959 only those used in arthmetic operations remain */
5961 AOP_SET_LOCALS (ic);
5963 /* if both are bit variables */
5964 if (AOP_TYPE (left) == AOP_CRY &&
5965 AOP_TYPE (right) == AOP_CRY)
5967 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5968 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5969 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5970 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5972 aopOp (result,ic,FALSE, FALSE);
5978 tlbl = newiTempLabel (NULL);
5980 emitcode ("jnz", "!tlabel", tlbl->key + 100);
5982 emitcode ("", "!tlabeldef", tlbl->key + 100);
5983 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5984 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5986 aopOp (result,ic,FALSE, FALSE);
5991 freeAsmop (result, NULL, ic, TRUE);
5994 /*-----------------------------------------------------------------*/
5995 /* isLiteralBit - test if lit == 2^n */
5996 /*-----------------------------------------------------------------*/
5998 isLiteralBit (unsigned long lit)
6000 unsigned long pw[32] =
6001 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6002 0x100L, 0x200L, 0x400L, 0x800L,
6003 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6004 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6005 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6006 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6007 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6010 for (idx = 0; idx < 32; idx++)
6016 /*-----------------------------------------------------------------*/
6017 /* continueIfTrue - */
6018 /*-----------------------------------------------------------------*/
6020 continueIfTrue (iCode * ic)
6023 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6027 /*-----------------------------------------------------------------*/
6029 /*-----------------------------------------------------------------*/
6031 jumpIfTrue (iCode * ic)
6034 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6038 /*-----------------------------------------------------------------*/
6039 /* jmpTrueOrFalse - */
6040 /*-----------------------------------------------------------------*/
6042 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6044 // ugly but optimized by peephole
6047 symbol *nlbl = newiTempLabel (NULL);
6048 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6049 emitcode ("", "!tlabeldef", tlbl->key + 100);
6050 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6051 emitcode ("", "!tlabeldef", nlbl->key + 100);
6055 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6056 emitcode ("", "!tlabeldef", tlbl->key + 100);
6061 // Generate code to perform a bit-wise logic operation
6062 // on two operands in far space (assumed to already have been
6063 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6064 // in far space. This requires pushing the result on the stack
6065 // then popping it into the result.
6067 genFarFarLogicOp(iCode *ic, char *logicOp)
6069 int size, resultSize, compSize;
6073 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6074 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
6075 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6077 _startLazyDPSEvaluation();
6078 for (size = compSize; (size--); offset++)
6080 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6081 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6082 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6084 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6085 emitcode ("push", "acc");
6087 _endLazyDPSEvaluation();
6089 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6090 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6091 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6093 resultSize = AOP_SIZE(IC_RESULT(ic));
6095 ADJUST_PUSHED_RESULT(compSize, resultSize);
6097 _startLazyDPSEvaluation();
6100 emitcode ("pop", "acc");
6101 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6103 _endLazyDPSEvaluation();
6104 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6108 /*-----------------------------------------------------------------*/
6109 /* genAnd - code for and */
6110 /*-----------------------------------------------------------------*/
6112 genAnd (iCode * ic, iCode * ifx)
6114 operand *left, *right, *result;
6115 int size, offset = 0;
6116 unsigned long lit = 0L;
6121 D (emitcode (";", "genAnd "););
6123 AOP_OP_3_NOFATAL (ic, pushResult);
6124 AOP_SET_LOCALS (ic);
6128 genFarFarLogicOp(ic, "anl");
6133 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6135 AOP_TYPE (left), AOP_TYPE (right));
6136 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6138 AOP_SIZE (left), AOP_SIZE (right));
6141 /* if left is a literal & right is not then exchange them */
6142 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6143 #ifdef LOGIC_OPS_BROKEN
6144 || AOP_NEEDSACC (left)
6148 operand *tmp = right;
6153 /* if result = right then exchange them */
6154 if (sameRegs (AOP (result), AOP (right)))
6156 operand *tmp = right;
6161 /* if right is bit then exchange them */
6162 if (AOP_TYPE (right) == AOP_CRY &&
6163 AOP_TYPE (left) != AOP_CRY)
6165 operand *tmp = right;
6169 if (AOP_TYPE (right) == AOP_LIT)
6170 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6172 size = AOP_SIZE (result);
6175 // result = bit & yy;
6176 if (AOP_TYPE (left) == AOP_CRY)
6178 // c = bit & literal;
6179 if (AOP_TYPE (right) == AOP_LIT)
6183 if (size && sameRegs (AOP (result), AOP (left)))
6186 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6191 if (size && (AOP_TYPE (result) == AOP_CRY))
6193 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6196 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6201 emitcode ("clr", "c");
6206 if (AOP_TYPE (right) == AOP_CRY)
6209 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6210 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6215 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6217 emitcode ("rrc", "a");
6218 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6226 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6227 genIfxJump (ifx, "c");
6231 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6232 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6233 if ((AOP_TYPE (right) == AOP_LIT) &&
6234 (AOP_TYPE (result) == AOP_CRY) &&
6235 (AOP_TYPE (left) != AOP_CRY))
6237 int posbit = isLiteralBit (lit);
6242 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6245 emitcode ("mov", "c,acc.%d", posbit & 0x07);
6251 SNPRINTF (buff, sizeof(buff),
6252 "acc.%d", posbit & 0x07);
6253 genIfxJump (ifx, buff);
6257 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6264 symbol *tlbl = newiTempLabel (NULL);
6265 int sizel = AOP_SIZE (left);
6267 emitcode ("setb", "c");
6270 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6272 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6274 if ((posbit = isLiteralBit (bytelit)) != 0)
6275 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6278 if (bytelit != 0x0FFL)
6279 emitcode ("anl", "a,%s",
6280 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6281 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6286 // bit = left & literal
6289 emitcode ("clr", "c");
6290 emitcode ("", "!tlabeldef", tlbl->key + 100);
6292 // if(left & literal)
6296 jmpTrueOrFalse (ifx, tlbl);
6304 /* if left is same as result */
6305 if (sameRegs (AOP (result), AOP (left)))
6307 for (; size--; offset++)
6309 if (AOP_TYPE (right) == AOP_LIT)
6311 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6313 else if (bytelit == 0)
6314 aopPut (AOP (result), zero, offset);
6315 else if (IS_AOP_PREG (result))
6317 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6318 emitcode ("anl", "a,%s",
6319 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6320 aopPut (AOP (result), "a", offset);
6323 emitcode ("anl", "%s,%s",
6324 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6325 aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6329 if (AOP_TYPE (left) == AOP_ACC)
6330 emitcode ("anl", "a,%s",
6331 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6334 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6335 if (IS_AOP_PREG (result))
6337 emitcode ("anl", "a,%s",
6338 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6339 aopPut (AOP (result), "a", offset);
6342 emitcode ("anl", "%s,a",
6343 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6350 // left & result in different registers
6351 if (AOP_TYPE (result) == AOP_CRY)
6354 // if(size), result in bit
6355 // if(!size && ifx), conditional oper: if(left & right)
6356 symbol *tlbl = newiTempLabel (NULL);
6357 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6359 emitcode ("setb", "c");
6362 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6363 emitcode ("anl", "a,%s",
6364 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6366 if (AOP_TYPE(left)==AOP_ACC) {
6367 emitcode("mov", "b,a");
6368 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6369 emitcode("anl", "a,b");
6371 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6372 emitcode ("anl", "a,%s",
6373 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6376 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6382 emitcode ("", "!tlabeldef", tlbl->key + 100);
6386 jmpTrueOrFalse (ifx, tlbl);
6390 for (; (size--); offset++)
6393 // result = left & right
6394 if (AOP_TYPE (right) == AOP_LIT)
6396 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6398 aopPut (AOP (result),
6399 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6403 else if (bytelit == 0)
6405 aopPut (AOP (result), zero, offset);
6408 D (emitcode (";", "better literal AND."););
6409 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6410 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6411 FALSE, FALSE, DP2_RESULT_REG));
6416 // faster than result <- left, anl result,right
6417 // and better if result is SFR
6418 if (AOP_TYPE (left) == AOP_ACC)
6420 emitcode ("anl", "a,%s",
6421 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6425 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6426 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6428 emitcode("mov", "b,a");
6432 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6433 emitcode ("anl", "a,%s", rOp);
6436 aopPut (AOP (result), "a", offset);
6442 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6443 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6444 freeAsmop (result, NULL, ic, TRUE);
6448 /*-----------------------------------------------------------------*/
6449 /* genOr - code for or */
6450 /*-----------------------------------------------------------------*/
6452 genOr (iCode * ic, iCode * ifx)
6454 operand *left, *right, *result;
6455 int size, offset = 0;
6456 unsigned long lit = 0L;
6459 D (emitcode (";", "genOr "););
6461 AOP_OP_3_NOFATAL (ic, pushResult);
6462 AOP_SET_LOCALS (ic);
6466 genFarFarLogicOp(ic, "orl");
6472 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6474 AOP_TYPE (left), AOP_TYPE (right));
6475 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6477 AOP_SIZE (left), AOP_SIZE (right));
6480 /* if left is a literal & right is not then exchange them */
6481 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6482 #ifdef LOGIC_OPS_BROKEN
6483 || AOP_NEEDSACC (left) // I think this is a net loss now.
6487 operand *tmp = right;
6492 /* if result = right then exchange them */
6493 if (sameRegs (AOP (result), AOP (right)))
6495 operand *tmp = right;
6500 /* if right is bit then exchange them */
6501 if (AOP_TYPE (right) == AOP_CRY &&
6502 AOP_TYPE (left) != AOP_CRY)
6504 operand *tmp = right;
6508 if (AOP_TYPE (right) == AOP_LIT)
6509 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6511 size = AOP_SIZE (result);
6515 if (AOP_TYPE (left) == AOP_CRY)
6517 if (AOP_TYPE (right) == AOP_LIT)
6519 // c = bit & literal;
6522 // lit != 0 => result = 1
6523 if (AOP_TYPE (result) == AOP_CRY)
6526 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6528 continueIfTrue (ifx);
6531 emitcode ("setb", "c");
6535 // lit == 0 => result = left
6536 if (size && sameRegs (AOP (result), AOP (left)))
6538 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6543 if (AOP_TYPE (right) == AOP_CRY)
6546 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6547 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6552 symbol *tlbl = newiTempLabel (NULL);
6553 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6554 emitcode ("setb", "c");
6555 emitcode ("jb", "%s,!tlabel",
6556 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6558 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6559 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6561 jmpTrueOrFalse (ifx, tlbl);
6567 emitcode ("", "!tlabeldef", tlbl->key + 100);
6576 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6577 genIfxJump (ifx, "c");
6581 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6582 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6583 if ((AOP_TYPE (right) == AOP_LIT) &&
6584 (AOP_TYPE (result) == AOP_CRY) &&
6585 (AOP_TYPE (left) != AOP_CRY))
6591 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6593 continueIfTrue (ifx);
6598 // lit = 0, result = boolean(left)
6600 emitcode ("setb", "c");
6604 symbol *tlbl = newiTempLabel (NULL);
6605 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6607 emitcode ("", "!tlabeldef", tlbl->key + 100);
6611 genIfxJump (ifx, "a");
6619 /* if left is same as result */
6620 if (sameRegs (AOP (result), AOP (left)))
6622 for (; size--; offset++)
6624 if (AOP_TYPE (right) == AOP_LIT)
6626 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6632 if (IS_AOP_PREG (left))
6634 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6635 emitcode ("orl", "a,%s",
6636 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6637 aopPut (AOP (result), "a", offset);
6641 emitcode ("orl", "%s,%s",
6642 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6643 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6649 if (AOP_TYPE (left) == AOP_ACC)
6651 emitcode ("orl", "a,%s",
6652 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6656 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6657 if (IS_AOP_PREG (left))
6659 emitcode ("orl", "a,%s",
6660 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6661 aopPut (AOP (result), "a", offset);
6665 emitcode ("orl", "%s,a",
6666 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6674 // left & result in different registers
6675 if (AOP_TYPE (result) == AOP_CRY)
6678 // if(size), result in bit
6679 // if(!size && ifx), conditional oper: if(left | right)
6680 symbol *tlbl = newiTempLabel (NULL);
6681 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6683 emitcode ("setb", "c");
6686 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6687 emitcode ("orl", "a,%s",
6688 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6690 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6691 emitcode ("orl", "a,%s",
6692 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6694 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6700 emitcode ("", "!tlabeldef", tlbl->key + 100);
6704 jmpTrueOrFalse (ifx, tlbl);
6708 _startLazyDPSEvaluation();
6709 for (; (size--); offset++)
6712 // result = left & right
6713 if (AOP_TYPE (right) == AOP_LIT)
6715 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6717 aopPut (AOP (result),
6718 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6722 D (emitcode (";", "better literal OR."););
6723 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6724 emitcode ("orl", "a, %s",
6725 aopGet (AOP (right), offset,
6726 FALSE, FALSE, DP2_RESULT_REG));
6731 // faster than result <- left, anl result,right
6732 // and better if result is SFR
6733 if (AOP_TYPE (left) == AOP_ACC)
6735 emitcode ("orl", "a,%s",
6736 aopGet (AOP (right), offset,
6737 FALSE, FALSE, DP2_RESULT_REG));
6741 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6743 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6745 emitcode("mov", "b,a");
6749 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6750 emitcode ("orl", "a,%s", rOp);
6753 aopPut (AOP (result), "a", offset);
6755 _endLazyDPSEvaluation();
6760 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6761 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6762 freeAsmop (result, NULL, ic, TRUE);
6765 /*-----------------------------------------------------------------*/
6766 /* genXor - code for xclusive or */
6767 /*-----------------------------------------------------------------*/
6769 genXor (iCode * ic, iCode * ifx)
6771 operand *left, *right, *result;
6772 int size, offset = 0;
6773 unsigned long lit = 0L;
6776 D (emitcode (";", "genXor "););
6778 AOP_OP_3_NOFATAL (ic, pushResult);
6779 AOP_SET_LOCALS (ic);
6783 genFarFarLogicOp(ic, "xrl");
6788 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6790 AOP_TYPE (left), AOP_TYPE (right));
6791 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6793 AOP_SIZE (left), AOP_SIZE (right));
6796 /* if left is a literal & right is not ||
6797 if left needs acc & right does not */
6798 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6799 #ifdef LOGIC_OPS_BROKEN
6800 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6804 operand *tmp = right;
6809 /* if result = right then exchange them */
6810 if (sameRegs (AOP (result), AOP (right)))
6812 operand *tmp = right;
6817 /* if right is bit then exchange them */
6818 if (AOP_TYPE (right) == AOP_CRY &&
6819 AOP_TYPE (left) != AOP_CRY)
6821 operand *tmp = right;
6825 if (AOP_TYPE (right) == AOP_LIT)
6826 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6828 size = AOP_SIZE (result);
6832 if (AOP_TYPE (left) == AOP_CRY)
6834 if (AOP_TYPE (right) == AOP_LIT)
6836 // c = bit & literal;
6839 // lit>>1 != 0 => result = 1
6840 if (AOP_TYPE (result) == AOP_CRY)
6843 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6845 continueIfTrue (ifx);
6848 emitcode ("setb", "c");
6855 // lit == 0, result = left
6856 if (size && sameRegs (AOP (result), AOP (left)))
6858 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6862 // lit == 1, result = not(left)
6863 if (size && sameRegs (AOP (result), AOP (left)))
6865 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6870 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6871 emitcode ("cpl", "c");
6880 symbol *tlbl = newiTempLabel (NULL);
6881 if (AOP_TYPE (right) == AOP_CRY)
6884 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6888 int sizer = AOP_SIZE (right);
6890 // if val>>1 != 0, result = 1
6891 emitcode ("setb", "c");
6894 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
6896 // test the msb of the lsb
6897 emitcode ("anl", "a,#!constbyte",0xfe);
6898 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6902 emitcode ("rrc", "a");
6904 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6905 emitcode ("cpl", "c");
6906 emitcode ("", "!tlabeldef", (tlbl->key + 100));
6913 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6914 genIfxJump (ifx, "c");
6918 if (sameRegs (AOP (result), AOP (left)))
6920 /* if left is same as result */
6921 for (; size--; offset++)
6923 if (AOP_TYPE (right) == AOP_LIT)
6925 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6927 else if (IS_AOP_PREG (left))
6929 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6930 emitcode ("xrl", "a,%s",
6931 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6932 aopPut (AOP (result), "a", offset);
6935 emitcode ("xrl", "%s,%s",
6936 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6937 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6941 if (AOP_TYPE (left) == AOP_ACC)
6942 emitcode ("xrl", "a,%s",
6943 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6946 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6947 if (IS_AOP_PREG (left))
6949 emitcode ("xrl", "a,%s",
6950 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6951 aopPut (AOP (result), "a", offset);
6954 emitcode ("xrl", "%s,a",
6955 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6962 // left & result in different registers
6963 if (AOP_TYPE (result) == AOP_CRY)
6966 // if(size), result in bit
6967 // if(!size && ifx), conditional oper: if(left ^ right)
6968 symbol *tlbl = newiTempLabel (NULL);
6969 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6972 emitcode ("setb", "c");
6975 if ((AOP_TYPE (right) == AOP_LIT) &&
6976 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6978 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6982 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6983 emitcode ("xrl", "a,%s",
6984 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6986 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6987 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6989 emitcode("mov", "b,a");
6993 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6994 emitcode ("xrl", "a,%s", rOp);
6997 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7003 emitcode ("", "!tlabeldef", tlbl->key + 100);
7007 jmpTrueOrFalse (ifx, tlbl);
7011 for (; (size--); offset++)
7014 // result = left & right
7015 if (AOP_TYPE (right) == AOP_LIT)
7017 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7019 aopPut (AOP (result),
7020 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7024 D (emitcode (";", "better literal XOR."););
7025 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7026 emitcode ("xrl", "a, %s",
7027 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7031 // faster than result <- left, anl result,right
7032 // and better if result is SFR
7033 if (AOP_TYPE (left) == AOP_ACC)
7035 emitcode ("xrl", "a,%s",
7036 aopGet (AOP (right), offset,
7037 FALSE, FALSE, DP2_RESULT_REG));
7041 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7042 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7044 emitcode("mov", "b,a");
7048 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7049 emitcode ("xrl", "a,%s", rOp);
7052 aopPut (AOP (result), "a", offset);
7059 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7060 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7061 freeAsmop (result, NULL, ic, TRUE);
7064 /*-----------------------------------------------------------------*/
7065 /* genInline - write the inline code out */
7066 /*-----------------------------------------------------------------*/
7068 genInline (iCode * ic)
7070 char *buffer, *bp, *bp1;
7072 D (emitcode (";", "genInline "); );
7074 _G.inLine += (!options.asmpeep);
7076 buffer = Safe_strdup(IC_INLINE(ic));
7080 /* emit each line as a code */
7105 /* emitcode("",buffer); */
7106 _G.inLine -= (!options.asmpeep);
7109 /*-----------------------------------------------------------------*/
7110 /* genRRC - rotate right with carry */
7111 /*-----------------------------------------------------------------*/
7115 operand *left, *result;
7118 D (emitcode (";", "genRRC "););
7120 /* rotate right with carry */
7121 left = IC_LEFT (ic);
7122 result = IC_RESULT (ic);
7123 aopOp (left, ic, FALSE, FALSE);
7124 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7126 /* move it to the result */
7127 size = AOP_SIZE (result);
7131 _startLazyDPSEvaluation ();
7134 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7135 emitcode ("rrc", "a");
7136 if (AOP_SIZE (result) > 1)
7137 aopPut (AOP (result), "a", offset--);
7139 _endLazyDPSEvaluation ();
7141 /* now we need to put the carry into the
7142 highest order byte of the result */
7143 if (AOP_SIZE (result) > 1)
7145 MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7147 emitcode ("mov", "acc.7,c");
7148 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7149 freeAsmop (left, NULL, ic, TRUE);
7150 freeAsmop (result, NULL, ic, TRUE);
7153 /*-----------------------------------------------------------------*/
7154 /* genRLC - generate code for rotate left with carry */
7155 /*-----------------------------------------------------------------*/
7159 operand *left, *result;
7163 D (emitcode (";", "genRLC "););
7165 /* rotate right with carry */
7166 left = IC_LEFT (ic);
7167 result = IC_RESULT (ic);
7168 aopOp (left, ic, FALSE, FALSE);
7169 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7171 /* move it to the result */
7172 size = AOP_SIZE (result);
7176 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7178 emitcode ("add", "a,acc");
7179 if (AOP_SIZE (result) > 1)
7181 aopPut (AOP (result), "a", offset++);
7184 _startLazyDPSEvaluation ();
7187 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7189 emitcode ("rlc", "a");
7190 if (AOP_SIZE (result) > 1)
7191 aopPut (AOP (result), "a", offset++);
7193 _endLazyDPSEvaluation ();
7195 /* now we need to put the carry into the
7196 highest order byte of the result */
7197 if (AOP_SIZE (result) > 1)
7199 l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7202 emitcode ("mov", "acc.0,c");
7203 aopPut (AOP (result), "a", 0);
7204 freeAsmop (left, NULL, ic, TRUE);
7205 freeAsmop (result, NULL, ic, TRUE);
7208 /*-----------------------------------------------------------------*/
7209 /* genGetHbit - generates code get highest order bit */
7210 /*-----------------------------------------------------------------*/
7212 genGetHbit (iCode * ic)
7214 operand *left, *result;
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 D (emitcode (";", "genGetHbit "););
7222 /* get the highest order byte into a */
7223 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7224 if (AOP_TYPE (result) == AOP_CRY)
7226 emitcode ("rlc", "a");
7231 emitcode ("rl", "a");
7232 emitcode ("anl", "a,#1");
7237 freeAsmop (left, NULL, ic, TRUE);
7238 freeAsmop (result, NULL, ic, TRUE);
7241 /*-----------------------------------------------------------------*/
7242 /* AccRol - rotate left accumulator by known count */
7243 /*-----------------------------------------------------------------*/
7245 AccRol (int shCount)
7247 shCount &= 0x0007; // shCount : 0..7
7254 emitcode ("rl", "a");
7257 emitcode ("rl", "a");
7258 emitcode ("rl", "a");
7261 emitcode ("swap", "a");
7262 emitcode ("rr", "a");
7265 emitcode ("swap", "a");
7268 emitcode ("swap", "a");
7269 emitcode ("rl", "a");
7272 emitcode ("rr", "a");
7273 emitcode ("rr", "a");
7276 emitcode ("rr", "a");
7281 /*-----------------------------------------------------------------*/
7282 /* AccLsh - left shift accumulator by known count */
7283 /*-----------------------------------------------------------------*/
7285 AccLsh (int shCount)
7290 emitcode ("add", "a,acc");
7291 else if (shCount == 2)
7293 emitcode ("add", "a,acc");
7294 emitcode ("add", "a,acc");
7298 /* rotate left accumulator */
7300 /* and kill the lower order bits */
7301 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7306 /*-----------------------------------------------------------------*/
7307 /* AccRsh - right shift accumulator by known count */
7308 /*-----------------------------------------------------------------*/
7310 AccRsh (int shCount)
7317 emitcode ("rrc", "a");
7321 /* rotate right accumulator */
7322 AccRol (8 - shCount);
7323 /* and kill the higher order bits */
7324 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7329 #ifdef BETTER_LITERAL_SHIFT
7330 /*-----------------------------------------------------------------*/
7331 /* AccSRsh - signed right shift accumulator by known count */
7332 /*-----------------------------------------------------------------*/
7334 AccSRsh (int shCount)
7341 emitcode ("mov", "c,acc.7");
7342 emitcode ("rrc", "a");
7344 else if (shCount == 2)
7346 emitcode ("mov", "c,acc.7");
7347 emitcode ("rrc", "a");
7348 emitcode ("mov", "c,acc.7");
7349 emitcode ("rrc", "a");
7353 tlbl = newiTempLabel (NULL);
7354 /* rotate right accumulator */
7355 AccRol (8 - shCount);
7356 /* and kill the higher order bits */
7357 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7358 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7359 emitcode ("orl", "a,#!constbyte",
7360 (unsigned char) ~SRMask[shCount]);
7361 emitcode ("", "!tlabeldef", tlbl->key + 100);
7367 #ifdef BETTER_LITERAL_SHIFT
7368 /*-----------------------------------------------------------------*/
7369 /* shiftR1Left2Result - shift right one byte from left to result */
7370 /*-----------------------------------------------------------------*/
7372 shiftR1Left2Result (operand * left, int offl,
7373 operand * result, int offr,
7374 int shCount, int sign)
7376 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7377 /* shift right accumulator */
7382 aopPut (AOP (result), "a", offr);
7386 #ifdef BETTER_LITERAL_SHIFT
7387 /*-----------------------------------------------------------------*/
7388 /* shiftL1Left2Result - shift left one byte from left to result */
7389 /*-----------------------------------------------------------------*/
7391 shiftL1Left2Result (operand * left, int offl,
7392 operand * result, int offr, int shCount)
7394 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7395 /* shift left accumulator */
7397 aopPut (AOP (result), "a", offr);
7401 #ifdef BETTER_LITERAL_SHIFT
7402 /*-----------------------------------------------------------------*/
7403 /* movLeft2Result - move byte from left to result */
7404 /*-----------------------------------------------------------------*/
7406 movLeft2Result (operand * left, int offl,
7407 operand * result, int offr, int sign)
7410 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7412 l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
7414 if (*l == '@' && (IS_AOP_PREG (result)))
7416 emitcode ("mov", "a,%s", l);
7417 aopPut (AOP (result), "a", offr);
7423 aopPut (AOP (result), l, offr);
7427 /* MSB sign in acc.7 ! */
7428 if (getDataSize (left) == offl + 1)
7430 emitcode ("mov", "a,%s", l);
7431 aopPut (AOP (result), "a", offr);
7439 #ifdef BETTER_LITERAL_SHIFT
7440 /*-----------------------------------------------------------------*/
7441 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7442 /*-----------------------------------------------------------------*/
7446 emitcode ("rrc", "a");
7447 emitcode ("xch", "a,%s", x);
7448 emitcode ("rrc", "a");
7449 emitcode ("xch", "a,%s", x);
7453 #ifdef BETTER_LITERAL_SHIFT
7455 /*-----------------------------------------------------------------*/
7456 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7457 /*-----------------------------------------------------------------*/
7461 emitcode ("xch", "a,%s", x);
7462 emitcode ("rlc", "a");
7463 emitcode ("xch", "a,%s", x);
7464 emitcode ("rlc", "a");
7468 #ifdef BETTER_LITERAL_SHIFT
7469 /*-----------------------------------------------------------------*/
7470 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7471 /*-----------------------------------------------------------------*/
7475 emitcode ("xch", "a,%s", x);
7476 emitcode ("add", "a,acc");
7477 emitcode ("xch", "a,%s", x);
7478 emitcode ("rlc", "a");
7482 #ifdef BETTER_LITERAL_SHIFT
7483 /*-----------------------------------------------------------------*/
7484 /* AccAXLsh - left shift a:x by known count (0..7) */
7485 /*-----------------------------------------------------------------*/
7487 AccAXLsh (char *x, int shCount)
7502 case 5: // AAAAABBB:CCCCCDDD
7504 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7506 emitcode ("anl", "a,#!constbyte",
7507 SLMask[shCount]); // BBB00000:CCCCCDDD
7509 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7511 AccRol (shCount); // DDDCCCCC:BBB00000
7513 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7515 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7517 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7519 emitcode ("anl", "a,#!constbyte",
7520 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7522 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7524 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7527 case 6: // AAAAAABB:CCCCCCDD
7528 emitcode ("anl", "a,#!constbyte",
7529 SRMask[shCount]); // 000000BB:CCCCCCDD
7530 emitcode ("mov", "c,acc.0"); // c = B
7531 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7533 AccAXRrl1 (x); // BCCCCCCD:D000000B
7534 AccAXRrl1 (x); // BBCCCCCC:DD000000
7536 emitcode("rrc","a");
7537 emitcode("xch","a,%s", x);
7538 emitcode("rrc","a");
7539 emitcode("mov","c,acc.0"); //<< get correct bit
7540 emitcode("xch","a,%s", x);
7542 emitcode("rrc","a");
7543 emitcode("xch","a,%s", x);
7544 emitcode("rrc","a");
7545 emitcode("xch","a,%s", x);
7548 case 7: // a:x <<= 7
7550 emitcode ("anl", "a,#!constbyte",
7551 SRMask[shCount]); // 0000000B:CCCCCCCD
7553 emitcode ("mov", "c,acc.0"); // c = B
7555 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7557 AccAXRrl1 (x); // BCCCCCCC:D0000000
7566 #ifdef BETTER_LITERAL_SHIFT
7568 /*-----------------------------------------------------------------*/
7569 /* AccAXRsh - right shift a:x known count (0..7) */
7570 /*-----------------------------------------------------------------*/
7572 AccAXRsh (char *x, int shCount)
7580 AccAXRrl1 (x); // 0->a:x
7585 AccAXRrl1 (x); // 0->a:x
7588 AccAXRrl1 (x); // 0->a:x
7593 case 5: // AAAAABBB:CCCCCDDD = a:x
7595 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7597 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7599 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7601 emitcode ("anl", "a,#!constbyte",
7602 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7604 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7606 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7608 emitcode ("anl", "a,#!constbyte",
7609 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7611 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7613 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7615 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7618 case 6: // AABBBBBB:CCDDDDDD
7620 emitcode ("mov", "c,acc.7");
7621 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7623 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7625 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7627 emitcode ("anl", "a,#!constbyte",
7628 SRMask[shCount]); // 000000AA:BBBBBBCC
7631 case 7: // ABBBBBBB:CDDDDDDD
7633 emitcode ("mov", "c,acc.7"); // c = A
7635 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7637 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7639 emitcode ("anl", "a,#!constbyte",
7640 SRMask[shCount]); // 0000000A:BBBBBBBC
7649 #ifdef BETTER_LITERAL_SHIFT
7650 /*-----------------------------------------------------------------*/
7651 /* AccAXRshS - right shift signed a:x known count (0..7) */
7652 /*-----------------------------------------------------------------*/
7654 AccAXRshS (char *x, int shCount)
7662 emitcode ("mov", "c,acc.7");
7663 AccAXRrl1 (x); // s->a:x
7667 emitcode ("mov", "c,acc.7");
7668 AccAXRrl1 (x); // s->a:x
7670 emitcode ("mov", "c,acc.7");
7671 AccAXRrl1 (x); // s->a:x
7676 case 5: // AAAAABBB:CCCCCDDD = a:x
7678 tlbl = newiTempLabel (NULL);
7679 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7681 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7683 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7685 emitcode ("anl", "a,#!constbyte",
7686 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7688 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7690 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7692 emitcode ("anl", "a,#!constbyte",
7693 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7695 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7697 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7699 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7701 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7702 emitcode ("orl", "a,#!constbyte",
7703 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7705 emitcode ("", "!tlabeldef", tlbl->key + 100);
7706 break; // SSSSAAAA:BBBCCCCC
7708 case 6: // AABBBBBB:CCDDDDDD
7710 tlbl = newiTempLabel (NULL);
7711 emitcode ("mov", "c,acc.7");
7712 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7714 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7716 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7718 emitcode ("anl", "a,#!constbyte",
7719 SRMask[shCount]); // 000000AA:BBBBBBCC
7721 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7722 emitcode ("orl", "a,#!constbyte",
7723 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7725 emitcode ("", "!tlabeldef", tlbl->key + 100);
7727 case 7: // ABBBBBBB:CDDDDDDD
7729 tlbl = newiTempLabel (NULL);
7730 emitcode ("mov", "c,acc.7"); // c = A
7732 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7734 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7736 emitcode ("anl", "a,#!constbyte",
7737 SRMask[shCount]); // 0000000A:BBBBBBBC
7739 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7740 emitcode ("orl", "a,#!constbyte",
7741 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7743 emitcode ("", "!tlabeldef", tlbl->key + 100);
7751 #ifdef BETTER_LITERAL_SHIFT
7753 _loadLeftIntoAx(char **lsb,
7759 // Get the initial value from left into a pair of registers.
7760 // MSB must be in A, LSB can be any register.
7762 // If the result is held in registers, it is an optimization
7763 // if the LSB can be held in the register which will hold the,
7764 // result LSB since this saves us from having to copy it into
7765 // the result following AccAXLsh.
7767 // If the result is addressed indirectly, this is not a gain.
7768 if (AOP_NEEDSACC(result))
7772 _startLazyDPSEvaluation();
7773 if (AOP_TYPE(left) == AOP_DPTR2)
7776 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
7777 // get LSB in DP2_RESULT_REG.
7778 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
7779 assert(!strcmp(leftByte, DP2_RESULT_REG));
7783 // get LSB into DP2_RESULT_REG
7784 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
7785 if (strcmp(leftByte, DP2_RESULT_REG))
7788 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7791 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
7792 assert(strcmp(leftByte, DP2_RESULT_REG));
7795 _endLazyDPSEvaluation();
7796 *lsb = DP2_RESULT_REG;
7800 if (sameRegs (AOP (result), AOP (left)) &&
7801 ((offl + MSB16) == offr))
7803 /* don't crash result[offr] */
7804 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
7805 emitcode ("xch", "a,%s",
7806 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
7810 movLeft2Result (left, offl, result, offr, 0);
7811 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
7813 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
7814 assert(strcmp(*lsb,"a"));
7819 _storeAxResults(char *lsb,
7823 _startLazyDPSEvaluation();
7824 if (AOP_NEEDSACC(result))
7826 /* We have to explicitly update the result LSB.
7828 emitcode("xch","a,%s", lsb);
7829 aopPut(AOP(result), "a", offr);
7830 emitcode("mov","a,%s", lsb);
7832 if (getDataSize (result) > 1)
7834 aopPut (AOP (result), "a", offr + MSB16);
7836 _endLazyDPSEvaluation();
7839 /*-----------------------------------------------------------------*/
7840 /* shiftL2Left2Result - shift left two bytes from left to result */
7841 /*-----------------------------------------------------------------*/
7843 shiftL2Left2Result (operand * left, int offl,
7844 operand * result, int offr, int shCount)
7848 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7850 AccAXLsh (lsb, shCount);
7852 _storeAxResults(lsb, result, offr);
7856 #ifdef BETTER_LITERAL_SHIFT
7857 /*-----------------------------------------------------------------*/
7858 /* shiftR2Left2Result - shift right two bytes from left to result */
7859 /*-----------------------------------------------------------------*/
7861 shiftR2Left2Result (operand * left, int offl,
7862 operand * result, int offr,
7863 int shCount, int sign)
7867 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7869 /* a:x >> shCount (x = lsb(result)) */
7872 AccAXRshS(lsb, shCount);
7876 AccAXRsh(lsb, shCount);
7879 _storeAxResults(lsb, result, offr);
7883 /*-----------------------------------------------------------------*/
7884 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7885 /*-----------------------------------------------------------------*/
7887 shiftLLeftOrResult (operand * left, int offl,
7888 operand * result, int offr, int shCount)
7890 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7891 /* shift left accumulator */
7893 /* or with result */
7894 emitcode ("orl", "a,%s",
7895 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7896 /* back to result */
7897 aopPut (AOP (result), "a", offr);
7902 /*-----------------------------------------------------------------*/
7903 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7904 /*-----------------------------------------------------------------*/
7906 shiftRLeftOrResult (operand * left, int offl,
7907 operand * result, int offr, int shCount)
7909 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7910 /* shift right accumulator */
7912 /* or with result */
7913 emitcode ("orl", "a,%s",
7914 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7915 /* back to result */
7916 aopPut (AOP (result), "a", offr);
7920 #ifdef BETTER_LITERAL_SHIFT
7921 /*-----------------------------------------------------------------*/
7922 /* genlshOne - left shift a one byte quantity by known count */
7923 /*-----------------------------------------------------------------*/
7925 genlshOne (operand * result, operand * left, int shCount)
7927 D (emitcode (";", "genlshOne "););
7928 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7932 #ifdef BETTER_LITERAL_SHIFT
7933 /*-----------------------------------------------------------------*/
7934 /* genlshTwo - left shift two bytes by known amount != 0 */
7935 /*-----------------------------------------------------------------*/
7937 genlshTwo (operand * result, operand * left, int shCount)
7941 D (emitcode (";", "genlshTwo "););
7943 size = getDataSize (result);
7945 /* if shCount >= 8 */
7950 _startLazyDPSEvaluation();
7956 _endLazyDPSEvaluation();
7957 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7958 aopPut (AOP (result), zero, LSB);
7962 movLeft2Result (left, LSB, result, MSB16, 0);
7963 aopPut (AOP (result), zero, LSB);
7964 _endLazyDPSEvaluation();
7969 aopPut (AOP (result), zero, LSB);
7970 _endLazyDPSEvaluation();
7974 /* 1 <= shCount <= 7 */
7979 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7983 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7991 /*-----------------------------------------------------------------*/
7992 /* shiftLLong - shift left one long from left to result */
7993 /* offl = LSB or MSB16 */
7994 /*-----------------------------------------------------------------*/
7996 shiftLLong (operand * left, operand * result, int offr)
7999 int size = AOP_SIZE (result);
8001 if (size >= LSB + offr)
8003 l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8005 emitcode ("add", "a,acc");
8006 if (sameRegs (AOP (left), AOP (result)) &&
8007 size >= MSB16 + offr && offr != LSB)
8008 emitcode ("xch", "a,%s",
8009 aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8011 aopPut (AOP (result), "a", LSB + offr);
8014 if (size >= MSB16 + offr)
8016 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8018 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8020 emitcode ("rlc", "a");
8021 if (sameRegs (AOP (left), AOP (result)) &&
8022 size >= MSB24 + offr && offr != LSB)
8023 emitcode ("xch", "a,%s",
8024 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8026 aopPut (AOP (result), "a", MSB16 + offr);
8029 if (size >= MSB24 + offr)
8031 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8033 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8035 emitcode ("rlc", "a");
8036 if (sameRegs (AOP (left), AOP (result)) &&
8037 size >= MSB32 + offr && offr != LSB)
8038 emitcode ("xch", "a,%s",
8039 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8041 aopPut (AOP (result), "a", MSB24 + offr);
8044 if (size > MSB32 + offr)
8046 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8048 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8050 emitcode ("rlc", "a");
8051 aopPut (AOP (result), "a", MSB32 + offr);
8054 aopPut (AOP (result), zero, LSB);
8060 /*-----------------------------------------------------------------*/
8061 /* genlshFour - shift four byte by a known amount != 0 */
8062 /*-----------------------------------------------------------------*/
8064 genlshFour (operand * result, operand * left, int shCount)
8068 D (emitcode (";", "genlshFour ");
8071 size = AOP_SIZE (result);
8073 /* if shifting more that 3 bytes */
8078 /* lowest order of left goes to the highest
8079 order of the destination */
8080 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8082 movLeft2Result (left, LSB, result, MSB32, 0);
8083 aopPut (AOP (result), zero, LSB);
8084 aopPut (AOP (result), zero, MSB16);
8085 aopPut (AOP (result), zero, MSB24);
8089 /* more than two bytes */
8090 else if (shCount >= 16)
8092 /* lower order two bytes goes to higher order two bytes */
8094 /* if some more remaining */
8096 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8099 movLeft2Result (left, MSB16, result, MSB32, 0);
8100 movLeft2Result (left, LSB, result, MSB24, 0);
8102 aopPut (AOP (result), zero, MSB16);
8103 aopPut (AOP (result), zero, LSB);
8107 /* if more than 1 byte */
8108 else if (shCount >= 8)
8110 /* lower order three bytes goes to higher order three bytes */
8115 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8117 movLeft2Result (left, LSB, result, MSB16, 0);
8123 movLeft2Result (left, MSB24, result, MSB32, 0);
8124 movLeft2Result (left, MSB16, result, MSB24, 0);
8125 movLeft2Result (left, LSB, result, MSB16, 0);
8126 aopPut (AOP (result), zero, LSB);
8128 else if (shCount == 1)
8129 shiftLLong (left, result, MSB16);
8132 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8133 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8134 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8135 aopPut (AOP (result), zero, LSB);
8140 /* 1 <= shCount <= 7 */
8141 else if (shCount <= 2)
8143 shiftLLong (left, result, LSB);
8145 shiftLLong (result, result, LSB);
8147 /* 3 <= shCount <= 7, optimize */
8150 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8151 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8152 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8157 #ifdef BETTER_LITERAL_SHIFT
8158 /*-----------------------------------------------------------------*/
8159 /* genLeftShiftLiteral - left shifting by known count */
8160 /*-----------------------------------------------------------------*/
8162 genLeftShiftLiteral (operand * left,
8167 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8170 size = getSize (operandType (result));
8172 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8174 /* We only handle certain easy cases so far. */
8176 && (shCount < (size * 8))
8180 D(emitcode (";", "genLeftShiftLiteral wimping out"););
8184 freeAsmop (right, NULL, ic, TRUE);
8186 aopOp(left, ic, FALSE, FALSE);
8187 aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8190 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8192 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8193 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8195 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8198 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8200 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8201 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8203 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8209 emitcode ("; shift left ", "result %d, left %d", size,
8213 /* I suppose that the left size >= result size */
8216 _startLazyDPSEvaluation();
8219 movLeft2Result (left, size, result, size, 0);
8221 _endLazyDPSEvaluation();
8223 else if (shCount >= (size * 8))
8225 _startLazyDPSEvaluation();
8228 aopPut (AOP (result), zero, size);
8230 _endLazyDPSEvaluation();
8237 genlshOne (result, left, shCount);
8241 genlshTwo (result, left, shCount);
8245 genlshFour (result, left, shCount);
8249 fprintf(stderr, "*** ack! mystery literal shift!\n");
8253 freeAsmop (left, NULL, ic, TRUE);
8254 freeAsmop (result, NULL, ic, TRUE);
8259 /*-----------------------------------------------------------------*/
8260 /* genLeftShift - generates code for left shifting */
8261 /*-----------------------------------------------------------------*/
8263 genLeftShift (iCode * ic)
8265 operand *left, *right, *result;
8268 symbol *tlbl, *tlbl1;
8270 D (emitcode (";", "genLeftShift "););
8272 right = IC_RIGHT (ic);
8273 left = IC_LEFT (ic);
8274 result = IC_RESULT (ic);
8276 aopOp (right, ic, FALSE, FALSE);
8279 #ifdef BETTER_LITERAL_SHIFT
8280 /* if the shift count is known then do it
8281 as efficiently as possible */
8282 if (AOP_TYPE (right) == AOP_LIT)
8284 if (genLeftShiftLiteral (left, right, result, ic))
8291 /* shift count is unknown then we have to form
8292 a loop get the loop count in B : Note: we take
8293 only the lower order byte since shifting
8294 more that 32 bits make no sense anyway, ( the
8295 largest size of an object can be only 32 bits ) */
8297 if (AOP_TYPE (right) == AOP_LIT)
8299 /* Really should be handled by genLeftShiftLiteral,
8300 * but since I'm too lazy to fix that today, at least we can make
8301 * some small improvement.
8303 emitcode("mov", "b,#!constbyte",
8304 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8308 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8309 emitcode ("inc", "b");
8311 freeAsmop (right, NULL, ic, TRUE);
8312 aopOp (left, ic, FALSE, FALSE);
8313 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8315 /* now move the left to the result if they are not the
8317 if (!sameRegs (AOP (left), AOP (result)) &&
8318 AOP_SIZE (result) > 1)
8321 size = AOP_SIZE (result);
8323 _startLazyDPSEvaluation ();
8326 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8327 if (*l == '@' && (IS_AOP_PREG (result)))
8330 emitcode ("mov", "a,%s", l);
8331 aopPut (AOP (result), "a", offset);
8334 aopPut (AOP (result), l, offset);
8337 _endLazyDPSEvaluation ();
8340 tlbl = newiTempLabel (NULL);
8341 size = AOP_SIZE (result);
8343 tlbl1 = newiTempLabel (NULL);
8345 /* if it is only one byte then */
8348 symbol *tlbl1 = newiTempLabel (NULL);
8350 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8351 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8352 emitcode ("", "!tlabeldef", tlbl->key + 100);
8353 emitcode ("add", "a,acc");
8354 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8355 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8356 aopPut (AOP (result), "a", 0);
8360 reAdjustPreg (AOP (result));
8362 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8363 emitcode ("", "!tlabeldef", tlbl->key + 100);
8364 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8365 emitcode ("add", "a,acc");
8366 aopPut (AOP (result), "a", offset++);
8367 _startLazyDPSEvaluation ();
8370 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8371 emitcode ("rlc", "a");
8372 aopPut (AOP (result), "a", offset++);
8374 _endLazyDPSEvaluation ();
8375 reAdjustPreg (AOP (result));
8377 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8378 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8380 freeAsmop (left, NULL, ic, TRUE);
8381 freeAsmop (result, NULL, ic, TRUE);
8384 #ifdef BETTER_LITERAL_SHIFT
8385 /*-----------------------------------------------------------------*/
8386 /* genrshOne - right shift a one byte quantity by known count */
8387 /*-----------------------------------------------------------------*/
8389 genrshOne (operand * result, operand * left,
8390 int shCount, int sign)
8392 D (emitcode (";", "genrshOne"););
8393 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8397 #ifdef BETTER_LITERAL_SHIFT
8398 /*-----------------------------------------------------------------*/
8399 /* genrshTwo - right shift two bytes by known amount != 0 */
8400 /*-----------------------------------------------------------------*/
8402 genrshTwo (operand * result, operand * left,
8403 int shCount, int sign)
8405 D (emitcode (";", "genrshTwo"););
8407 /* if shCount >= 8 */
8411 _startLazyDPSEvaluation();
8414 shiftR1Left2Result (left, MSB16, result, LSB,
8419 movLeft2Result (left, MSB16, result, LSB, sign);
8421 addSign (result, MSB16, sign);
8422 _endLazyDPSEvaluation();
8425 /* 1 <= shCount <= 7 */
8428 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8433 /*-----------------------------------------------------------------*/
8434 /* shiftRLong - shift right one long from left to result */
8435 /* offl = LSB or MSB16 */
8436 /*-----------------------------------------------------------------*/
8438 shiftRLong (operand * left, int offl,
8439 operand * result, int sign)
8441 int isSameRegs=sameRegs(AOP(left),AOP(result));
8443 if (isSameRegs && offl>1) {
8444 // we are in big trouble, but this shouldn't happen
8445 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8448 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8453 emitcode ("rlc", "a");
8454 emitcode ("subb", "a,acc");
8455 emitcode ("xch", "a,%s",
8456 aopGet(AOP(left), MSB32, FALSE, FALSE, DP2_RESULT_REG));
8458 aopPut (AOP(result), zero, MSB32);
8463 emitcode ("clr", "c");
8465 emitcode ("mov", "c,acc.7");
8468 emitcode ("rrc", "a");
8470 if (isSameRegs && offl==MSB16) {
8472 "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE, DP2_RESULT_REG));
8474 aopPut (AOP (result), "a", MSB32);
8475 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8478 emitcode ("rrc", "a");
8479 if (isSameRegs && offl==1) {
8480 emitcode ("xch", "a,%s",
8481 aopGet (AOP (left), MSB16, FALSE, FALSE, DP2_RESULT_REG));
8483 aopPut (AOP (result), "a", MSB24);
8484 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, NULL));
8486 emitcode ("rrc", "a");
8487 aopPut (AOP (result), "a", MSB16 - offl);
8491 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, NULL));
8492 emitcode ("rrc", "a");
8493 aopPut (AOP (result), "a", LSB);
8497 /*-----------------------------------------------------------------*/
8498 /* genrshFour - shift four byte by a known amount != 0 */
8499 /*-----------------------------------------------------------------*/
8501 genrshFour (operand * result, operand * left,
8502 int shCount, int sign)
8504 D (emitcode (";", "genrshFour"););
8506 /* if shifting more that 3 bytes */
8510 _startLazyDPSEvaluation();
8512 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8514 movLeft2Result (left, MSB32, result, LSB, sign);
8515 addSign (result, MSB16, sign);
8516 _endLazyDPSEvaluation();
8518 else if (shCount >= 16)
8521 _startLazyDPSEvaluation();
8523 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8526 movLeft2Result (left, MSB24, result, LSB, 0);
8527 movLeft2Result (left, MSB32, result, MSB16, sign);
8529 addSign (result, MSB24, sign);
8530 _endLazyDPSEvaluation();
8532 else if (shCount >= 8)
8535 _startLazyDPSEvaluation();
8538 shiftRLong (left, MSB16, result, sign);
8540 else if (shCount == 0)
8542 movLeft2Result (left, MSB16, result, LSB, 0);
8543 movLeft2Result (left, MSB24, result, MSB16, 0);
8544 movLeft2Result (left, MSB32, result, MSB24, sign);
8545 addSign (result, MSB32, sign);
8549 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8550 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8551 /* the last shift is signed */
8552 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8553 addSign (result, MSB32, sign);
8555 _endLazyDPSEvaluation();
8559 /* 1 <= shCount <= 7 */
8562 shiftRLong (left, LSB, result, sign);
8564 shiftRLong (result, LSB, result, sign);
8568 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8569 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8570 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8575 #ifdef BETTER_LITERAL_SHIFT
8576 /*-----------------------------------------------------------------*/
8577 /* genRightShiftLiteral - right shifting by known count */
8578 /*-----------------------------------------------------------------*/
8580 genRightShiftLiteral (operand * left,
8586 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8589 size = getSize (operandType (result));
8591 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8593 /* We only handle certain easy cases so far. */
8595 && (shCount < (size * 8))
8600 D(emitcode (";", "genRightShiftLiteral wimping out"););
8604 freeAsmop (right, NULL, ic, TRUE);
8606 aopOp (left, ic, FALSE, FALSE);
8607 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8610 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8614 /* test the LEFT size !!! */
8616 /* I suppose that the left size >= result size */
8619 size = getDataSize (result);
8620 _startLazyDPSEvaluation();
8623 movLeft2Result (left, size, result, size, 0);
8625 _endLazyDPSEvaluation();
8627 else if (shCount >= (size * 8))
8631 /* get sign in acc.7 */
8632 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
8634 addSign (result, LSB, sign);
8641 genrshOne (result, left, shCount, sign);
8645 genrshTwo (result, left, shCount, sign);
8649 genrshFour (result, left, shCount, sign);
8656 freeAsmop (left, NULL, ic, TRUE);
8657 freeAsmop (result, NULL, ic, TRUE);
8663 /*-----------------------------------------------------------------*/
8664 /* genSignedRightShift - right shift of signed number */
8665 /*-----------------------------------------------------------------*/
8667 genSignedRightShift (iCode * ic)
8669 operand *right, *left, *result;
8672 symbol *tlbl, *tlbl1;
8674 D (emitcode (";", "genSignedRightShift "););
8676 /* we do it the hard way put the shift count in b
8677 and loop thru preserving the sign */
8679 right = IC_RIGHT (ic);
8680 left = IC_LEFT (ic);
8681 result = IC_RESULT (ic);
8683 aopOp (right, ic, FALSE, FALSE);
8685 #ifdef BETTER_LITERAL_SHIFT
8686 if (AOP_TYPE (right) == AOP_LIT)
8688 if (genRightShiftLiteral (left, right, result, ic, 1))
8694 /* shift count is unknown then we have to form
8695 a loop get the loop count in B : Note: we take
8696 only the lower order byte since shifting
8697 more that 32 bits make no sense anyway, ( the
8698 largest size of an object can be only 32 bits ) */
8700 if (AOP_TYPE (right) == AOP_LIT)
8702 /* Really should be handled by genRightShiftLiteral,
8703 * but since I'm too lazy to fix that today, at least we can make
8704 * some small improvement.
8706 emitcode("mov", "b,#!constbyte",
8707 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8711 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8712 emitcode ("inc", "b");
8714 freeAsmop (right, NULL, ic, TRUE);
8715 aopOp (left, ic, FALSE, FALSE);
8716 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8718 /* now move the left to the result if they are not the
8720 if (!sameRegs (AOP (left), AOP (result)) &&
8721 AOP_SIZE (result) > 1)
8724 size = AOP_SIZE (result);
8726 _startLazyDPSEvaluation ();
8729 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8730 if (*l == '@' && IS_AOP_PREG (result))
8733 emitcode ("mov", "a,%s", l);
8734 aopPut (AOP (result), "a", offset);
8737 aopPut (AOP (result), l, offset);
8740 _endLazyDPSEvaluation ();
8743 /* mov the highest order bit to OVR */
8744 tlbl = newiTempLabel (NULL);
8745 tlbl1 = newiTempLabel (NULL);
8747 size = AOP_SIZE (result);
8749 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
8750 emitcode ("rlc", "a");
8751 emitcode ("mov", "ov,c");
8752 /* if it is only one byte then */
8755 MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8756 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8757 emitcode ("", "!tlabeldef", tlbl->key + 100);
8758 emitcode ("mov", "c,ov");
8759 emitcode ("rrc", "a");
8760 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8761 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8762 aopPut (AOP (result), "a", 0);
8766 reAdjustPreg (AOP (result));
8767 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8768 emitcode ("", "!tlabeldef", tlbl->key + 100);
8769 emitcode ("mov", "c,ov");
8770 _startLazyDPSEvaluation ();
8773 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8774 emitcode ("rrc", "a");
8775 aopPut (AOP (result), "a", offset--);
8777 _endLazyDPSEvaluation ();
8778 reAdjustPreg (AOP (result));
8779 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8780 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8783 freeAsmop (left, NULL, ic, TRUE);
8784 freeAsmop (result, NULL, ic, TRUE);
8787 /*-----------------------------------------------------------------*/
8788 /* genRightShift - generate code for right shifting */
8789 /*-----------------------------------------------------------------*/
8791 genRightShift (iCode * ic)
8793 operand *right, *left, *result;
8797 symbol *tlbl, *tlbl1;
8799 D (emitcode (";", "genRightShift "););
8801 /* if signed then we do it the hard way preserve the
8802 sign bit moving it inwards */
8803 retype = getSpec (operandType (IC_RESULT (ic)));
8805 if (!SPEC_USIGN (retype))
8807 genSignedRightShift (ic);
8811 /* signed & unsigned types are treated the same : i.e. the
8812 signed is NOT propagated inwards : quoting from the
8813 ANSI - standard : "for E1 >> E2, is equivalent to division
8814 by 2**E2 if unsigned or if it has a non-negative value,
8815 otherwise the result is implementation defined ", MY definition
8816 is that the sign does not get propagated */
8818 right = IC_RIGHT (ic);
8819 left = IC_LEFT (ic);
8820 result = IC_RESULT (ic);
8822 aopOp (right, ic, FALSE, FALSE);
8824 #ifdef BETTER_LITERAL_SHIFT
8825 /* if the shift count is known then do it
8826 as efficiently as possible */
8827 if (AOP_TYPE (right) == AOP_LIT)
8829 if (genRightShiftLiteral (left, right, result, ic, 0))
8836 /* shift count is unknown then we have to form
8837 a loop get the loop count in B : Note: we take
8838 only the lower order byte since shifting
8839 more that 32 bits make no sense anyway, ( the
8840 largest size of an object can be only 32 bits ) */
8842 if (AOP_TYPE (right) == AOP_LIT)
8844 /* Really should be handled by genRightShiftLiteral,
8845 * but since I'm too lazy to fix that today, at least we can make
8846 * some small improvement.
8848 emitcode("mov", "b,#!constbyte",
8849 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8853 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8854 emitcode ("inc", "b");
8856 freeAsmop (right, NULL, ic, TRUE);
8857 aopOp (left, ic, FALSE, FALSE);
8858 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8860 /* now move the left to the result if they are not the
8862 if (!sameRegs (AOP (left), AOP (result)) &&
8863 AOP_SIZE (result) > 1)
8866 size = AOP_SIZE (result);
8868 _startLazyDPSEvaluation ();
8871 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8872 if (*l == '@' && IS_AOP_PREG (result))
8875 emitcode ("mov", "a,%s", l);
8876 aopPut (AOP (result), "a", offset);
8879 aopPut (AOP (result), l, offset);
8882 _endLazyDPSEvaluation ();
8885 tlbl = newiTempLabel (NULL);
8886 tlbl1 = newiTempLabel (NULL);
8887 size = AOP_SIZE (result);
8890 /* if it is only one byte then */
8893 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8894 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8895 emitcode ("", "!tlabeldef", tlbl->key + 100);
8897 emitcode ("rrc", "a");
8898 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8899 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8900 aopPut (AOP (result), "a", 0);
8904 reAdjustPreg (AOP (result));
8905 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8906 emitcode ("", "!tlabeldef", tlbl->key + 100);
8908 _startLazyDPSEvaluation ();
8911 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8912 emitcode ("rrc", "a");
8913 aopPut (AOP (result), "a", offset--);
8915 _endLazyDPSEvaluation ();
8916 reAdjustPreg (AOP (result));
8918 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8919 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8922 freeAsmop (left, NULL, ic, TRUE);
8923 freeAsmop (result, NULL, ic, TRUE);
8927 /*-----------------------------------------------------------------*/
8928 /* emitPtrByteGet - emits code to get a byte into A through a */
8929 /* pointer register (R0, R1, or DPTR). The */
8930 /* original value of A can be preserved in B. */
8931 /*-----------------------------------------------------------------*/
8933 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
8940 emitcode ("mov", "b,a");
8941 emitcode ("mov", "a,@%s", rname);
8946 emitcode ("mov", "b,a");
8947 emitcode ("movx", "a,@%s", rname);
8952 emitcode ("mov", "b,a");
8953 emitcode ("movx", "a,@dptr");
8958 emitcode ("mov", "b,a");
8959 emitcode ("clr", "a");
8960 emitcode ("movc", "a,@a+dptr");
8966 emitcode ("push", "b");
8967 emitcode ("push", "acc");
8969 emitcode ("lcall", "__gptrget");
8971 emitcode ("pop", "b");
8976 /*-----------------------------------------------------------------*/
8977 /* emitPtrByteSet - emits code to set a byte from src through a */
8978 /* pointer register (R0, R1, or DPTR). */
8979 /*-----------------------------------------------------------------*/
8981 emitPtrByteSet (char *rname, int p_type, char *src)
8990 emitcode ("mov", "@%s,a", rname);
8993 emitcode ("mov", "@%s,%s", rname, src);
8998 emitcode ("movx", "@%s,a", rname);
9003 emitcode ("movx", "@dptr,a");
9008 emitcode ("lcall", "__gptrput");
9013 /*-----------------------------------------------------------------*/
9014 /* genUnpackBits - generates code for unpacking bits */
9015 /*-----------------------------------------------------------------*/
9017 genUnpackBits (operand * result, char *rname, int ptype)
9019 int offset = 0; /* result byte offset */
9020 int rsize; /* result size */
9021 int rlen = 0; /* remaining bitfield length */
9022 sym_link *etype; /* bitfield type information */
9023 int blen; /* bitfield length */
9024 int bstr; /* bitfield starting bit within byte */
9026 D(emitcode ("; genUnpackBits",""));
9028 etype = getSpec (operandType (result));
9029 rsize = getSize (operandType (result));
9030 blen = SPEC_BLEN (etype);
9031 bstr = SPEC_BSTR (etype);
9033 /* If the bitfield length is less than a byte */
9036 emitPtrByteGet (rname, ptype, FALSE);
9038 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
9039 aopPut (AOP (result), "a", offset++);
9043 /* Bit field did not fit in a byte. Copy all
9044 but the partial byte at the end. */
9045 for (rlen=blen;rlen>=8;rlen-=8)
9047 emitPtrByteGet (rname, ptype, FALSE);
9048 aopPut (AOP (result), "a", offset++);
9050 emitcode ("inc", "%s", rname);
9053 /* Handle the partial byte at the end */
9056 emitPtrByteGet (rname, ptype, FALSE);
9057 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
9058 aopPut (AOP (result), "a", offset++);
9066 aopPut (AOP (result), zero, offset++);
9071 /*-----------------------------------------------------------------*/
9072 /* genDataPointerGet - generates code when ptr offset is known */
9073 /*-----------------------------------------------------------------*/
9075 genDataPointerGet (operand * left,
9081 int size, offset = 0;
9082 aopOp (result, ic, TRUE, FALSE);
9084 /* get the string representation of the name */
9085 l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9086 size = AOP_SIZE (result);
9087 _startLazyDPSEvaluation ();
9092 SNPRINTF (buff, sizeof(buff),
9093 "(%s + %d)", l + 1, offset);
9097 SNPRINTF (buff, sizeof(buff),
9100 aopPut (AOP (result), buff, offset++);
9102 _endLazyDPSEvaluation ();
9104 freeAsmop (left, NULL, ic, TRUE);
9105 freeAsmop (result, NULL, ic, TRUE);
9108 /*-----------------------------------------------------------------*/
9109 /* genNearPointerGet - emitcode for near pointer fetch */
9110 /*-----------------------------------------------------------------*/
9112 genNearPointerGet (operand * left,
9120 sym_link *rtype, *retype, *letype;
9121 sym_link *ltype = operandType (left);
9124 rtype = operandType (result);
9125 retype = getSpec (rtype);
9126 letype = getSpec (ltype);
9128 aopOp (left, ic, FALSE, FALSE);
9130 /* if left is rematerialisable and
9131 result is not bit variable type and
9132 the left is pointer to data space i.e
9133 lower 128 bytes of space */
9134 if (AOP_TYPE (left) == AOP_IMMD &&
9135 !IS_BITVAR (retype) &&
9136 !IS_BITVAR (letype) &&
9137 DCL_TYPE (ltype) == POINTER)
9139 genDataPointerGet (left, result, ic);
9143 /* if the value is already in a pointer register
9144 then don't need anything more */
9145 if (!AOP_INPREG (AOP (left)))
9147 /* otherwise get a free pointer register */
9149 preg = getFreePtr (ic, &aop, FALSE);
9150 emitcode ("mov", "%s,%s",
9152 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9156 rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9158 freeAsmop (left, NULL, ic, TRUE);
9159 aopOp (result, ic, FALSE, FALSE);
9161 /* if bitfield then unpack the bits */
9162 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9163 genUnpackBits (result, rname, POINTER);
9166 /* we have can just get the values */
9167 int size = AOP_SIZE (result);
9172 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9175 emitcode ("mov", "a,@%s", rname);
9176 aopPut (AOP (result), "a", offset);
9180 SNPRINTF (buff, sizeof(buff), "@%s", rname);
9181 aopPut (AOP (result), buff, offset);
9186 emitcode ("inc", "%s", rname);
9191 /* now some housekeeping stuff */
9194 /* we had to allocate for this iCode */
9195 if (pi) { /* post increment present */
9196 aopPut(AOP ( left ),rname,0);
9198 freeAsmop (NULL, aop, ic, TRUE);
9202 /* we did not allocate which means left
9203 already in a pointer register, then
9204 if size > 0 && this could be used again
9205 we have to point it back to where it
9207 if (AOP_SIZE (result) > 1 &&
9208 !OP_SYMBOL (left)->remat &&
9209 (OP_SYMBOL (left)->liveTo > ic->seq ||
9213 int size = AOP_SIZE (result) - 1;
9215 emitcode ("dec", "%s", rname);
9220 freeAsmop (result, NULL, ic, TRUE);
9221 if (pi) pi->generated = 1;
9224 /*-----------------------------------------------------------------*/
9225 /* genPagedPointerGet - emitcode for paged pointer fetch */
9226 /*-----------------------------------------------------------------*/
9228 genPagedPointerGet (operand * left,
9236 sym_link *rtype, *retype, *letype;
9238 rtype = operandType (result);
9239 retype = getSpec (rtype);
9240 letype = getSpec (operandType (left));
9241 aopOp (left, ic, FALSE, FALSE);
9243 /* if the value is already in a pointer register
9244 then don't need anything more */
9245 if (!AOP_INPREG (AOP (left)))
9247 /* otherwise get a free pointer register */
9249 preg = getFreePtr (ic, &aop, FALSE);
9250 emitcode ("mov", "%s,%s",
9252 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9256 rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9258 freeAsmop (left, NULL, ic, TRUE);
9259 aopOp (result, ic, FALSE, FALSE);
9261 /* if bitfield then unpack the bits */
9262 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9263 genUnpackBits (result, rname, PPOINTER);
9266 /* we have can just get the values */
9267 int size = AOP_SIZE (result);
9273 emitcode ("movx", "a,@%s", rname);
9274 aopPut (AOP (result), "a", offset);
9279 emitcode ("inc", "%s", rname);
9283 /* now some housekeeping stuff */
9286 /* we had to allocate for this iCode */
9287 if (pi) aopPut ( AOP (left), rname, 0);
9288 freeAsmop (NULL, aop, ic, TRUE);
9292 /* we did not allocate which means left
9293 already in a pointer register, then
9294 if size > 0 && this could be used again
9295 we have to point it back to where it
9297 if (AOP_SIZE (result) > 1 &&
9298 !OP_SYMBOL (left)->remat &&
9299 (OP_SYMBOL (left)->liveTo > ic->seq ||
9303 int size = AOP_SIZE (result) - 1;
9305 emitcode ("dec", "%s", rname);
9310 freeAsmop (result, NULL, ic, TRUE);
9311 if (pi) pi->generated = 1;
9314 /*-----------------------------------------------------------------*/
9315 /* genFarPointerGet - gget value from far space */
9316 /*-----------------------------------------------------------------*/
9318 genFarPointerGet (operand * left,
9319 operand * result, iCode * ic, iCode *pi)
9321 int size, offset, dopi=1;
9322 sym_link *retype = getSpec (operandType (result));
9323 sym_link *letype = getSpec (operandType (left));
9324 D (emitcode (";", "genFarPointerGet"););
9326 aopOp (left, ic, FALSE, FALSE);
9328 /* if the operand is already in dptr
9329 then we do nothing else we move the value to dptr */
9330 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9332 /* if this is remateriazable */
9333 if (AOP_TYPE (left) == AOP_IMMD)
9335 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9339 /* we need to get it byte by byte */
9340 _startLazyDPSEvaluation ();
9341 if (AOP_TYPE (left) != AOP_DPTR)
9343 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9344 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9345 if (options.model == MODEL_FLAT24)
9346 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9350 /* We need to generate a load to DPTR indirect through DPTR. */
9351 D (emitcode (";", "genFarPointerGet -- indirection special case."););
9352 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9353 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9354 if (options.model == MODEL_FLAT24)
9355 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9356 emitcode ("pop", "dph");
9357 emitcode ("pop", "dpl");
9360 _endLazyDPSEvaluation ();
9363 /* so dptr know contains the address */
9364 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9366 /* if bit then unpack */
9367 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9368 if (AOP_INDPTRn(left)) {
9369 genSetDPTR(AOP(left)->aopu.dptr);
9371 genUnpackBits (result, "dptr", FPOINTER);
9372 if (AOP_INDPTRn(left)) {
9377 size = AOP_SIZE (result);
9380 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9382 genSetDPTR(AOP(left)->aopu.dptr);
9383 emitcode ("movx", "a,@dptr");
9384 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9385 emitcode ("inc", "dptr");
9387 aopPut (AOP (result), "a", offset++);
9390 _startLazyDPSEvaluation ();
9392 if (AOP_INDPTRn(left)) {
9393 genSetDPTR(AOP(left)->aopu.dptr);
9399 emitcode ("movx", "a,@dptr");
9400 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9401 emitcode ("inc", "dptr");
9403 aopPut (AOP (result), "a", offset++);
9405 _endLazyDPSEvaluation ();
9408 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9409 if (!AOP_INDPTRn(left)) {
9410 _startLazyDPSEvaluation ();
9411 aopPut ( AOP (left), "dpl", 0);
9412 aopPut ( AOP (left), "dph", 1);
9413 if (options.model == MODEL_FLAT24)
9414 aopPut ( AOP (left), "dpx", 2);
9415 _endLazyDPSEvaluation ();
9418 } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) &&
9419 AOP_SIZE(result) > 1 &&
9421 (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
9423 size = AOP_SIZE (result) - 1;
9424 if (AOP_INDPTRn(left)) {
9425 genSetDPTR(AOP(left)->aopu.dptr);
9427 while (size--) emitcode ("lcall","__decdptr");
9428 if (AOP_INDPTRn(left)) {
9433 freeAsmop (left, NULL, ic, TRUE);
9434 freeAsmop (result, NULL, ic, TRUE);
9437 /*-----------------------------------------------------------------*/
9438 /* genCodePointerGet - get value from code space */
9439 /*-----------------------------------------------------------------*/
9441 genCodePointerGet (operand * left,
9442 operand * result, iCode * ic, iCode *pi)
9444 int size, offset, dopi=1;
9445 sym_link *retype = getSpec (operandType (result));
9447 aopOp (left, ic, FALSE, FALSE);
9449 /* if the operand is already in dptr
9450 then we do nothing else we move the value to dptr */
9451 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
9453 /* if this is remateriazable */
9454 if (AOP_TYPE (left) == AOP_IMMD)
9456 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9459 { /* we need to get it byte by byte */
9460 _startLazyDPSEvaluation ();
9461 if (AOP_TYPE (left) != AOP_DPTR)
9463 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9464 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9465 if (options.model == MODEL_FLAT24)
9466 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9470 /* We need to generate a load to DPTR indirect through DPTR. */
9471 D (emitcode (";", "gencodePointerGet -- indirection special case."););
9472 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9473 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9474 if (options.model == MODEL_FLAT24)
9475 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9476 emitcode ("pop", "dph");
9477 emitcode ("pop", "dpl");
9480 _endLazyDPSEvaluation ();
9483 /* so dptr know contains the address */
9484 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9486 /* if bit then unpack */
9487 if (IS_BITVAR (retype)) {
9488 if (AOP_INDPTRn(left)) {
9489 genSetDPTR(AOP(left)->aopu.dptr);
9491 genUnpackBits (result, "dptr", CPOINTER);
9492 if (AOP_INDPTRn(left)) {
9497 size = AOP_SIZE (result);
9499 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9501 genSetDPTR(AOP(left)->aopu.dptr);
9502 emitcode ("clr", "a");
9503 emitcode ("movc", "a,@a+dptr");
9504 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9505 emitcode ("inc", "dptr");
9507 aopPut (AOP (result), "a", offset++);
9510 _startLazyDPSEvaluation ();
9513 if (AOP_INDPTRn(left)) {
9514 genSetDPTR(AOP(left)->aopu.dptr);
9520 emitcode ("clr", "a");
9521 emitcode ("movc", "a,@a+dptr");
9522 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9523 emitcode ("inc", "dptr");
9524 aopPut (AOP (result), "a", offset++);
9526 _endLazyDPSEvaluation ();
9529 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9530 if (!AOP_INDPTRn(left)) {
9531 _startLazyDPSEvaluation ();
9533 aopPut ( AOP (left), "dpl", 0);
9534 aopPut ( AOP (left), "dph", 1);
9535 if (options.model == MODEL_FLAT24)
9536 aopPut ( AOP (left), "dpx", 2);
9538 _endLazyDPSEvaluation ();
9541 } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
9542 AOP_SIZE(result) > 1 &&
9543 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9545 size = AOP_SIZE (result) - 1;
9546 if (AOP_INDPTRn(left)) {
9547 genSetDPTR(AOP(left)->aopu.dptr);
9549 while (size--) emitcode ("lcall","__decdptr");
9550 if (AOP_INDPTRn(left)) {
9555 freeAsmop (left, NULL, ic, TRUE);
9556 freeAsmop (result, NULL, ic, TRUE);
9559 /*-----------------------------------------------------------------*/
9560 /* genGenPointerGet - gget value from generic pointer space */
9561 /*-----------------------------------------------------------------*/
9563 genGenPointerGet (operand * left,
9564 operand * result, iCode * ic, iCode * pi)
9567 sym_link *retype = getSpec (operandType (result));
9568 sym_link *letype = getSpec (operandType (left));
9570 D (emitcode (";", "genGenPointerGet "); );
9572 aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
9574 /* if the operand is already in dptr
9575 then we do nothing else we move the value to dptr */
9576 if (AOP_TYPE (left) != AOP_STR)
9578 /* if this is remateriazable */
9579 if (AOP_TYPE (left) == AOP_IMMD)
9581 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9582 if (AOP(left)->aopu.aop_immd.from_cast_remat)
9584 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
9588 emitcode ("mov", "b,#%d", pointerCode (retype));
9592 { /* we need to get it byte by byte */
9593 _startLazyDPSEvaluation ();
9594 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
9595 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
9596 if (options.model == MODEL_FLAT24) {
9597 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9598 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
9600 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9602 _endLazyDPSEvaluation ();
9606 /* so dptr-b now contains the address */
9608 aopOp (result, ic, FALSE, TRUE);
9611 /* if bit then unpack */
9612 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9614 genUnpackBits (result, "dptr", GPOINTER);
9618 size = AOP_SIZE (result);
9625 // Get two bytes at a time, results in _AP & A.
9626 // dptr will be incremented ONCE by __gptrgetWord.
9628 // Note: any change here must be coordinated
9629 // with the implementation of __gptrgetWord
9630 // in device/lib/_gptrget.c
9631 emitcode ("lcall", "__gptrgetWord");
9632 aopPut (AOP (result), DP2_RESULT_REG, offset++);
9633 aopPut (AOP (result), "a", offset++);
9638 // Only one byte to get.
9639 emitcode ("lcall", "__gptrget");
9640 aopPut (AOP (result), "a", offset++);
9643 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9645 emitcode ("inc", "dptr");
9650 if (pi && AOP_TYPE (left) != AOP_IMMD) {
9651 _startLazyDPSEvaluation ();
9653 aopPut ( AOP (left), "dpl", 0);
9654 aopPut ( AOP (left), "dph", 1);
9655 if (options.model == MODEL_FLAT24) {
9656 aopPut ( AOP (left), "dpx", 2);
9657 aopPut ( AOP (left), "b", 3);
9658 } else aopPut ( AOP (left), "b", 2);
9660 _endLazyDPSEvaluation ();
9663 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9664 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9666 size = AOP_SIZE (result) - 1;
9667 while (size--) emitcode ("lcall","__decdptr");
9670 freeAsmop (left, NULL, ic, TRUE);
9671 freeAsmop (result, NULL, ic, TRUE);
9674 /*-----------------------------------------------------------------*/
9675 /* genPointerGet - generate code for pointer get */
9676 /*-----------------------------------------------------------------*/
9678 genPointerGet (iCode * ic, iCode *pi)
9680 operand *left, *result;
9681 sym_link *type, *etype;
9684 D (emitcode (";", "genPointerGet ");
9687 left = IC_LEFT (ic);
9688 result = IC_RESULT (ic);
9690 /* depending on the type of pointer we need to
9691 move it to the correct pointer register */
9692 type = operandType (left);
9693 etype = getSpec (type);
9694 /* if left is of type of pointer then it is simple */
9695 if (IS_PTR (type) && !IS_FUNC (type->next))
9696 p_type = DCL_TYPE (type);
9699 /* we have to go by the storage class */
9700 p_type = PTR_TYPE (SPEC_OCLS (etype));
9702 /* special case when cast remat */
9703 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9704 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9705 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9706 type = operandType (left);
9707 p_type = DCL_TYPE (type);
9709 /* now that we have the pointer type we assign
9710 the pointer values */
9716 genNearPointerGet (left, result, ic, pi);
9720 genPagedPointerGet (left, result, ic, pi);
9724 genFarPointerGet (left, result, ic, pi);
9728 genCodePointerGet (left, result, ic, pi);
9732 genGenPointerGet (left, result, ic, pi);
9738 /*-----------------------------------------------------------------*/
9739 /* genPackBits - generates code for packed bit storage */
9740 /*-----------------------------------------------------------------*/
9742 genPackBits (sym_link * etype,
9744 char *rname, int p_type)
9746 int offset = 0; /* source byte offset */
9747 int rlen = 0; /* remaining bitfield length */
9748 int blen; /* bitfield length */
9749 int bstr; /* bitfield starting bit within byte */
9750 int litval; /* source literal value (if AOP_LIT) */
9751 unsigned char mask; /* bitmask within current byte */
9753 D(emitcode ("; genPackBits",""));
9755 blen = SPEC_BLEN (etype);
9756 bstr = SPEC_BSTR (etype);
9758 /* If the bitfield length is less than a byte */
9761 mask = ((unsigned char) (0xFF << (blen + bstr)) |
9762 (unsigned char) (0xFF >> (8 - bstr)));
9764 if (AOP_TYPE (right) == AOP_LIT)
9766 /* Case with a bitfield length <8 and literal source
9768 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9770 litval &= (~mask) & 0xff;
9771 emitPtrByteGet (rname, p_type, FALSE);
9772 if ((mask|litval)!=0xff)
9773 emitcode ("anl","a,#!constbyte", mask);
9775 emitcode ("orl","a,#!constbyte", litval);
9779 if ((blen==1) && (p_type!=GPOINTER))
9781 /* Case with a bitfield length == 1 and no generic pointer
9783 if (AOP_TYPE (right) == AOP_CRY)
9784 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9787 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
9788 emitcode ("rrc","a");
9790 emitPtrByteGet (rname, p_type, FALSE);
9791 emitcode ("mov","acc.%d,c",bstr);
9795 /* Case with a bitfield length < 8 and arbitrary source
9797 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
9798 /* shift and mask source value */
9800 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
9802 /* transfer A to B and get next byte */
9803 emitPtrByteGet (rname, p_type, TRUE);
9805 emitcode ("anl", "a,#!constbyte", mask);
9806 emitcode ("orl", "a,b");
9807 if (p_type == GPOINTER)
9808 emitcode ("pop", "b");
9812 emitPtrByteSet (rname, p_type, "a");
9816 /* Bit length is greater than 7 bits. In this case, copy */
9817 /* all except the partial byte at the end */
9818 for (rlen=blen;rlen>=8;rlen-=8)
9820 emitPtrByteSet (rname, p_type,
9821 aopGet (AOP (right), offset++, FALSE, TRUE, NULL) );
9823 emitcode ("inc", "%s", rname);
9826 /* If there was a partial byte at the end */
9829 mask = (((unsigned char) -1 << rlen) & 0xff);
9831 if (AOP_TYPE (right) == AOP_LIT)
9833 /* Case with partial byte and literal source
9835 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9836 litval >>= (blen-rlen);
9837 litval &= (~mask) & 0xff;
9838 emitPtrByteGet (rname, p_type, FALSE);
9839 if ((mask|litval)!=0xff)
9840 emitcode ("anl","a,#!constbyte", mask);
9842 emitcode ("orl","a,#!constbyte", litval);
9846 /* Case with partial byte and arbitrary source
9848 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9849 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
9851 /* transfer A to B and get next byte */
9852 emitPtrByteGet (rname, p_type, TRUE);
9854 emitcode ("anl", "a,#!constbyte", mask);
9855 emitcode ("orl", "a,b");
9856 if (p_type == GPOINTER)
9857 emitcode ("pop", "b");
9859 emitPtrByteSet (rname, p_type, "a");
9865 /*-----------------------------------------------------------------*/
9866 /* genDataPointerSet - remat pointer to data space */
9867 /*-----------------------------------------------------------------*/
9869 genDataPointerSet (operand * right,
9873 int size, offset = 0;
9876 aopOp (right, ic, FALSE, FALSE);
9878 l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
9879 size = AOP_SIZE (right);
9884 SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
9888 SNPRINTF (buff, sizeof(buff), "%s", l + 1);
9891 emitcode ("mov", "%s,%s", buff,
9892 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9895 freeAsmop (right, NULL, ic, TRUE);
9896 freeAsmop (result, NULL, ic, TRUE);
9899 /*-----------------------------------------------------------------*/
9900 /* genNearPointerSet - emitcode for near pointer put */
9901 /*-----------------------------------------------------------------*/
9903 genNearPointerSet (operand * right,
9910 sym_link *retype, *letype;
9911 sym_link *ptype = operandType (result);
9913 retype = getSpec (operandType (right));
9914 letype = getSpec (ptype);
9916 aopOp (result, ic, FALSE, FALSE);
9918 /* if the result is rematerializable &
9919 in data space & not a bit variable */
9920 if (AOP_TYPE (result) == AOP_IMMD &&
9921 DCL_TYPE (ptype) == POINTER &&
9922 !IS_BITVAR (retype) &&
9923 !IS_BITVAR (letype))
9925 genDataPointerSet (right, result, ic);
9929 /* if the value is already in a pointer register
9930 then don't need anything more */
9931 if (!AOP_INPREG (AOP (result)))
9933 /* otherwise get a free pointer register */
9937 preg = getFreePtr (ic, &aop, FALSE);
9938 emitcode ("mov", "%s,%s",
9940 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
9944 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
9946 aopOp (right, ic, FALSE, FALSE);
9948 /* if bitfield then unpack the bits */
9949 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9950 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9953 /* we have can just get the values */
9954 int size = AOP_SIZE (right);
9959 l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
9963 emitcode ("mov", "@%s,a", rname);
9966 emitcode ("mov", "@%s,%s", rname, l);
9968 emitcode ("inc", "%s", rname);
9973 /* now some housekeeping stuff */
9976 /* we had to allocate for this iCode */
9977 if (pi) aopPut (AOP (result),rname,0);
9978 freeAsmop (NULL, aop, ic, TRUE);
9982 /* we did not allocate which means left
9983 already in a pointer register, then
9984 if size > 0 && this could be used again
9985 we have to point it back to where it
9987 if (AOP_SIZE (right) > 1 &&
9988 !OP_SYMBOL (result)->remat &&
9989 (OP_SYMBOL (result)->liveTo > ic->seq ||
9993 int size = AOP_SIZE (right) - 1;
9995 emitcode ("dec", "%s", rname);
10000 if (pi) pi->generated = 1;
10001 freeAsmop (result, NULL, ic, TRUE);
10002 freeAsmop (right, NULL, ic, TRUE);
10007 /*-----------------------------------------------------------------*/
10008 /* genPagedPointerSet - emitcode for Paged pointer put */
10009 /*-----------------------------------------------------------------*/
10011 genPagedPointerSet (operand * right,
10018 sym_link *retype, *letype;
10020 retype = getSpec (operandType (right));
10021 letype = getSpec (operandType (result));
10023 aopOp (result, ic, FALSE, FALSE);
10025 /* if the value is already in a pointer register
10026 then don't need anything more */
10027 if (!AOP_INPREG (AOP (result)))
10029 /* otherwise get a free pointer register */
10032 aop = newAsmop (0);
10033 preg = getFreePtr (ic, &aop, FALSE);
10034 emitcode ("mov", "%s,%s",
10036 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10037 rname = preg->name;
10040 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10042 aopOp (right, ic, FALSE, FALSE);
10044 /* if bitfield then unpack the bits */
10045 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10046 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
10049 /* we have can just get the values */
10050 int size = AOP_SIZE (right);
10055 MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10057 emitcode ("movx", "@%s,a", rname);
10060 emitcode ("inc", "%s", rname);
10066 /* now some housekeeping stuff */
10069 if (pi) aopPut (AOP (result),rname,0);
10070 /* we had to allocate for this iCode */
10071 freeAsmop (NULL, aop, ic, TRUE);
10075 /* we did not allocate which means left
10076 already in a pointer register, then
10077 if size > 0 && this could be used again
10078 we have to point it back to where it
10080 if (AOP_SIZE (right) > 1 &&
10081 !OP_SYMBOL (result)->remat &&
10082 (OP_SYMBOL (result)->liveTo > ic->seq ||
10086 int size = AOP_SIZE (right) - 1;
10088 emitcode ("dec", "%s", rname);
10093 if (pi) pi->generated = 1;
10094 freeAsmop (result, NULL, ic, TRUE);
10095 freeAsmop (right, NULL, ic, TRUE);
10100 /*-----------------------------------------------------------------*/
10101 /* genFarPointerSet - set value from far space */
10102 /*-----------------------------------------------------------------*/
10104 genFarPointerSet (operand * right,
10105 operand * result, iCode * ic, iCode *pi)
10107 int size, offset, dopi=1;
10108 sym_link *retype = getSpec (operandType (right));
10109 sym_link *letype = getSpec (operandType (result));
10111 aopOp (result, ic, FALSE, FALSE);
10113 /* if the operand is already in dptr
10114 then we do nothing else we move the value to dptr */
10115 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10117 /* if this is remateriazable */
10118 if (AOP_TYPE (result) == AOP_IMMD)
10119 emitcode ("mov", "dptr,%s",
10120 aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10123 /* we need to get it byte by byte */
10124 _startLazyDPSEvaluation ();
10125 if (AOP_TYPE (result) != AOP_DPTR)
10127 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10128 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10129 if (options.model == MODEL_FLAT24)
10130 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10134 /* We need to generate a load to DPTR indirect through DPTR. */
10135 D (emitcode (";", "genFarPointerSet -- indirection special case."););
10137 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10138 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10139 if (options.model == MODEL_FLAT24)
10140 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10141 emitcode ("pop", "dph");
10142 emitcode ("pop", "dpl");
10145 _endLazyDPSEvaluation ();
10148 /* so dptr know contains the address */
10149 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10151 /* if bit then unpack */
10152 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
10153 if (AOP_INDPTRn(result)) {
10154 genSetDPTR(AOP(result)->aopu.dptr);
10156 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
10157 if (AOP_INDPTRn(result)) {
10161 size = AOP_SIZE (right);
10163 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10165 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10167 genSetDPTR(AOP(result)->aopu.dptr);
10168 emitcode ("movx", "@dptr,a");
10169 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10170 emitcode ("inc", "dptr");
10174 _startLazyDPSEvaluation ();
10176 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10178 if (AOP_INDPTRn(result)) {
10179 genSetDPTR(AOP(result)->aopu.dptr);
10185 emitcode ("movx", "@dptr,a");
10186 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10187 emitcode ("inc", "dptr");
10189 _endLazyDPSEvaluation ();
10193 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10194 if (!AOP_INDPTRn(result)) {
10195 _startLazyDPSEvaluation ();
10197 aopPut (AOP(result),"dpl",0);
10198 aopPut (AOP(result),"dph",1);
10199 if (options.model == MODEL_FLAT24)
10200 aopPut (AOP(result),"dpx",2);
10202 _endLazyDPSEvaluation ();
10205 } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
10206 AOP_SIZE(right) > 1 &&
10207 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10209 size = AOP_SIZE (right) - 1;
10210 if (AOP_INDPTRn(result)) {
10211 genSetDPTR(AOP(result)->aopu.dptr);
10213 while (size--) emitcode ("lcall","__decdptr");
10214 if (AOP_INDPTRn(result)) {
10218 freeAsmop (result, NULL, ic, TRUE);
10219 freeAsmop (right, NULL, ic, TRUE);
10222 /*-----------------------------------------------------------------*/
10223 /* genGenPointerSet - set value from generic pointer space */
10224 /*-----------------------------------------------------------------*/
10226 genGenPointerSet (operand * right,
10227 operand * result, iCode * ic, iCode *pi)
10230 sym_link *retype = getSpec (operandType (right));
10231 sym_link *letype = getSpec (operandType (result));
10233 aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10235 /* if the operand is already in dptr
10236 then we do nothing else we move the value to dptr */
10237 if (AOP_TYPE (result) != AOP_STR)
10239 _startLazyDPSEvaluation ();
10240 /* if this is remateriazable */
10241 if (AOP_TYPE (result) == AOP_IMMD)
10243 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10244 if (AOP(result)->aopu.aop_immd.from_cast_remat)
10246 MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10251 "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10255 { /* we need to get it byte by byte */
10256 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10257 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10258 if (options.model == MODEL_FLAT24) {
10259 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10260 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10262 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10265 _endLazyDPSEvaluation ();
10267 /* so dptr + b now contains the address */
10269 aopOp (right, ic, FALSE, TRUE);
10273 /* if bit then unpack */
10274 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10276 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
10280 size = AOP_SIZE (right);
10283 _startLazyDPSEvaluation ();
10288 // Set two bytes at a time, passed in _AP & A.
10289 // dptr will be incremented ONCE by __gptrputWord.
10291 // Note: any change here must be coordinated
10292 // with the implementation of __gptrputWord
10293 // in device/lib/_gptrput.c
10294 emitcode("mov", "_ap, %s",
10295 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10296 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10300 emitcode ("lcall", "__gptrputWord");
10305 // Only one byte to put.
10306 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10310 emitcode ("lcall", "__gptrput");
10313 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10315 emitcode ("inc", "dptr");
10318 _endLazyDPSEvaluation ();
10321 if (pi && AOP_TYPE (result) != AOP_IMMD) {
10322 _startLazyDPSEvaluation ();
10324 aopPut (AOP(result),"dpl",0);
10325 aopPut (AOP(result),"dph",1);
10326 if (options.model == MODEL_FLAT24) {
10327 aopPut (AOP(result),"dpx",2);
10328 aopPut (AOP(result),"b",3);
10330 aopPut (AOP(result),"b",2);
10332 _endLazyDPSEvaluation ();
10335 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10336 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10338 size = AOP_SIZE (right) - 1;
10339 while (size--) emitcode ("lcall","__decdptr");
10341 freeAsmop (result, NULL, ic, TRUE);
10342 freeAsmop (right, NULL, ic, TRUE);
10345 /*-----------------------------------------------------------------*/
10346 /* genPointerSet - stores the value into a pointer location */
10347 /*-----------------------------------------------------------------*/
10349 genPointerSet (iCode * ic, iCode *pi)
10351 operand *right, *result;
10352 sym_link *type, *etype;
10355 D (emitcode (";", "genPointerSet "););
10357 right = IC_RIGHT (ic);
10358 result = IC_RESULT (ic);
10360 /* depending on the type of pointer we need to
10361 move it to the correct pointer register */
10362 type = operandType (result);
10363 etype = getSpec (type);
10364 /* if left is of type of pointer then it is simple */
10365 if (IS_PTR (type) && !IS_FUNC (type->next))
10367 p_type = DCL_TYPE (type);
10371 /* we have to go by the storage class */
10372 p_type = PTR_TYPE (SPEC_OCLS (etype));
10374 /* special case when cast remat */
10375 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10376 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10377 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10378 type = operandType (result);
10379 p_type = DCL_TYPE (type);
10382 /* now that we have the pointer type we assign
10383 the pointer values */
10389 genNearPointerSet (right, result, ic, pi);
10393 genPagedPointerSet (right, result, ic, pi);
10397 genFarPointerSet (right, result, ic, pi);
10401 genGenPointerSet (right, result, ic, pi);
10405 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10406 "genPointerSet: illegal pointer type");
10411 /*-----------------------------------------------------------------*/
10412 /* genIfx - generate code for Ifx statement */
10413 /*-----------------------------------------------------------------*/
10415 genIfx (iCode * ic, iCode * popIc)
10417 operand *cond = IC_COND (ic);
10420 D (emitcode (";", "genIfx "););
10422 aopOp (cond, ic, FALSE, FALSE);
10424 /* get the value into acc */
10425 if (AOP_TYPE (cond) != AOP_CRY)
10434 /* the result is now in the accumulator */
10435 freeAsmop (cond, NULL, ic, TRUE);
10437 /* if there was something to be popped then do it */
10441 /* if the condition is a bit variable */
10442 if (isbit && IS_ITEMP (cond) &&
10445 genIfxJump (ic, SPIL_LOC (cond)->rname);
10447 else if (isbit && !IS_ITEMP (cond))
10449 genIfxJump (ic, OP_SYMBOL (cond)->rname);
10453 genIfxJump (ic, "a");
10459 /*-----------------------------------------------------------------*/
10460 /* genAddrOf - generates code for address of */
10461 /*-----------------------------------------------------------------*/
10463 genAddrOf (iCode * ic)
10465 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10468 D (emitcode (";", "genAddrOf ");
10471 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10473 /* if the operand is on the stack then we
10474 need to get the stack offset of this
10476 if (sym->onStack) {
10478 /* if 10 bit stack */
10479 if (options.stack10bit) {
10483 tsprintf(buff, sizeof(buff),
10484 "#!constbyte",(options.stack_loc >> 16) & 0xff);
10485 /* if it has an offset then we need to compute it */
10486 /* emitcode ("subb", "a,#!constbyte", */
10487 /* -((sym->stack < 0) ? */
10488 /* ((short) (sym->stack - _G.nRegsSaved)) : */
10489 /* ((short) sym->stack)) & 0xff); */
10490 /* emitcode ("mov","b,a"); */
10491 /* emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
10492 /* ((short) (sym->stack - _G.nRegsSaved)) : */
10493 /* ((short) sym->stack)) >> 8) & 0xff); */
10495 emitcode ("mov", "a,_bpx");
10496 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
10497 ((char) (sym->stack - _G.nRegsSaved)) :
10498 ((char) sym->stack )) & 0xff);
10499 emitcode ("mov", "b,a");
10500 emitcode ("mov", "a,_bpx+1");
10502 offset = (((sym->stack < 0) ?
10503 ((short) (sym->stack - _G.nRegsSaved)) :
10504 ((short) sym->stack )) >> 8) & 0xff;
10506 emitcode ("addc","a,#!constbyte", offset);
10508 aopPut (AOP (IC_RESULT (ic)), "b", 0);
10509 aopPut (AOP (IC_RESULT (ic)), "a", 1);
10510 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10512 /* we can just move _bp */
10513 aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10514 aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10515 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10518 /* if it has an offset then we need to compute it */
10520 emitcode ("mov", "a,_bp");
10521 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10522 aopPut (AOP (IC_RESULT (ic)), "a", 0);
10524 /* we can just move _bp */
10525 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10527 /* fill the result with zero */
10528 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10531 if (options.stack10bit && size < (FPTRSIZE - 1)) {
10533 "*** warning: pointer to stack var truncated.\n");
10538 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10544 /* object not on stack then we need the name */
10545 size = AOP_SIZE (IC_RESULT (ic));
10550 char s[SDCC_NAME_MAX];
10554 tsprintf(s, sizeof(s), "#!his",sym->rname);
10557 tsprintf(s, sizeof(s), "#!hihis",sym->rname);
10560 tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
10562 default: /* should not need this (just in case) */
10563 SNPRINTF (s, sizeof(s), "#(%s >> %d)",
10570 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10573 aopPut (AOP (IC_RESULT (ic)), s, offset++);
10577 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10581 #if 0 // obsolete, and buggy for != xdata
10582 /*-----------------------------------------------------------------*/
10583 /* genArrayInit - generates code for address of */
10584 /*-----------------------------------------------------------------*/
10586 genArrayInit (iCode * ic)
10588 literalList *iLoop;
10590 int elementSize = 0, eIndex;
10591 unsigned val, lastVal;
10593 operand *left=IC_LEFT(ic);
10595 D (emitcode (";", "genArrayInit "););
10597 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10599 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10601 // Load immediate value into DPTR.
10602 emitcode("mov", "dptr, %s",
10603 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
10605 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10608 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10609 "Unexpected operand to genArrayInit.\n");
10612 // a regression because of SDCCcse.c:1.52
10613 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10614 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10615 if (options.model == MODEL_FLAT24)
10616 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10620 type = operandType(IC_LEFT(ic));
10622 if (type && type->next)
10624 elementSize = getSize(type->next);
10628 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10629 "can't determine element size in genArrayInit.\n");
10633 iLoop = IC_ARRAYILIST(ic);
10638 bool firstpass = TRUE;
10640 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
10641 iLoop->count, (int)iLoop->literalValue, elementSize);
10647 symbol *tlbl = NULL;
10649 count = ix > 256 ? 256 : ix;
10653 tlbl = newiTempLabel (NULL);
10654 if (firstpass || (count & 0xff))
10656 emitcode("mov", "b, #!constbyte", count & 0xff);
10659 emitcode ("", "!tlabeldef", tlbl->key + 100);
10664 for (eIndex = 0; eIndex < elementSize; eIndex++)
10666 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10667 if (val != lastVal)
10669 emitcode("mov", "a, #!constbyte", val);
10673 emitcode("movx", "@dptr, a");
10674 emitcode("inc", "dptr");
10679 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10685 iLoop = iLoop->next;
10688 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10692 /*-----------------------------------------------------------------*/
10693 /* genFarFarAssign - assignment when both are in far space */
10694 /*-----------------------------------------------------------------*/
10696 genFarFarAssign (operand * result, operand * right, iCode * ic)
10698 int size = AOP_SIZE (right);
10700 symbol *rSym = NULL;
10704 /* quick & easy case. */
10705 D(emitcode(";","genFarFarAssign (1 byte case)"););
10706 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
10707 freeAsmop (right, NULL, ic, FALSE);
10708 /* now assign DPTR to result */
10710 aopOp(result, ic, FALSE, FALSE);
10712 aopPut(AOP(result), "a", 0);
10713 freeAsmop(result, NULL, ic, FALSE);
10717 /* See if we've got an underlying symbol to abuse. */
10718 if (IS_SYMOP(result) && OP_SYMBOL(result))
10720 if (IS_TRUE_SYMOP(result))
10722 rSym = OP_SYMBOL(result);
10724 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10726 rSym = OP_SYMBOL(result)->usl.spillLoc;
10730 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10732 /* We can use the '390 auto-toggle feature to good effect here. */
10734 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10735 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
10736 emitcode ("mov", "dptr,#%s", rSym->rname);
10737 /* DP2 = result, DP1 = right, DP1 is current. */
10740 emitcode("movx", "a,@dptr");
10741 emitcode("movx", "@dptr,a");
10744 emitcode("inc", "dptr");
10745 emitcode("inc", "dptr");
10748 emitcode("mov", "dps,#0");
10749 freeAsmop (right, NULL, ic, FALSE);
10751 some alternative code for processors without auto-toggle
10752 no time to test now, so later well put in...kpb
10753 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10754 emitcode("mov", "dps,#1"); /* Select DPTR2. */
10755 emitcode ("mov", "dptr,#%s", rSym->rname);
10756 /* DP2 = result, DP1 = right, DP1 is current. */
10760 emitcode("movx", "a,@dptr");
10762 emitcode("inc", "dptr");
10763 emitcode("inc", "dps");
10764 emitcode("movx", "@dptr,a");
10766 emitcode("inc", "dptr");
10767 emitcode("inc", "dps");
10769 emitcode("mov", "dps,#0");
10770 freeAsmop (right, NULL, ic, FALSE);
10775 D (emitcode (";", "genFarFarAssign"););
10776 aopOp (result, ic, TRUE, TRUE);
10778 _startLazyDPSEvaluation ();
10782 aopPut (AOP (result),
10783 aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
10786 _endLazyDPSEvaluation ();
10787 freeAsmop (result, NULL, ic, FALSE);
10788 freeAsmop (right, NULL, ic, FALSE);
10792 /*-----------------------------------------------------------------*/
10793 /* genAssign - generate code for assignment */
10794 /*-----------------------------------------------------------------*/
10796 genAssign (iCode * ic)
10798 operand *result, *right;
10800 unsigned long lit = 0L;
10802 D (emitcode (";", "genAssign ");
10805 result = IC_RESULT (ic);
10806 right = IC_RIGHT (ic);
10808 /* if they are the same */
10809 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10812 aopOp (right, ic, FALSE, FALSE);
10814 emitcode (";", "genAssign: resultIsFar = %s",
10815 isOperandInFarSpace (result) ?
10818 /* special case both in far space */
10819 if ((AOP_TYPE (right) == AOP_DPTR ||
10820 AOP_TYPE (right) == AOP_DPTR2) &&
10821 /* IS_TRUE_SYMOP(result) && */
10822 isOperandInFarSpace (result))
10824 genFarFarAssign (result, right, ic);
10828 aopOp (result, ic, TRUE, FALSE);
10830 /* if they are the same registers */
10831 if (sameRegs (AOP (right), AOP (result)))
10834 /* if the result is a bit */
10835 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10837 /* if the right size is a literal then
10838 we know what the value is */
10839 if (AOP_TYPE (right) == AOP_LIT)
10841 if (((int) operandLitValue (right)))
10842 aopPut (AOP (result), one, 0);
10844 aopPut (AOP (result), zero, 0);
10848 /* the right is also a bit variable */
10849 if (AOP_TYPE (right) == AOP_CRY)
10851 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10852 aopPut (AOP (result), "c", 0);
10856 /* we need to or */
10858 aopPut (AOP (result), "a", 0);
10862 /* bit variables done */
10864 size = AOP_SIZE (result);
10866 if (AOP_TYPE (right) == AOP_LIT)
10867 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10870 (AOP_TYPE (result) != AOP_REG) &&
10871 (AOP_TYPE (right) == AOP_LIT) &&
10872 !IS_FLOAT (operandType (right)))
10874 _startLazyDPSEvaluation ();
10875 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10877 aopPut (AOP (result),
10878 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10883 /* And now fill the rest with zeros. */
10886 emitcode ("clr", "a");
10890 aopPut (AOP (result), "a", offset++);
10892 _endLazyDPSEvaluation ();
10896 _startLazyDPSEvaluation ();
10899 aopPut (AOP (result),
10900 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10904 _endLazyDPSEvaluation ();
10908 freeAsmop (right, NULL, ic, FALSE);
10909 freeAsmop (result, NULL, ic, TRUE);
10912 /*-----------------------------------------------------------------*/
10913 /* genJumpTab - generates code for jump table */
10914 /*-----------------------------------------------------------------*/
10916 genJumpTab (iCode * ic)
10921 D (emitcode (";", "genJumpTab ");
10924 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10925 /* get the condition into accumulator */
10926 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
10928 /* multiply by four! */
10929 emitcode ("add", "a,acc");
10930 emitcode ("add", "a,acc");
10931 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10933 jtab = newiTempLabel (NULL);
10934 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
10935 emitcode ("jmp", "@a+dptr");
10936 emitcode ("", "!tlabeldef", jtab->key + 100);
10937 /* now generate the jump labels */
10938 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10939 jtab = setNextItem (IC_JTLABELS (ic)))
10940 emitcode ("ljmp", "!tlabel", jtab->key + 100);
10944 /*-----------------------------------------------------------------*/
10945 /* genCast - gen code for casting */
10946 /*-----------------------------------------------------------------*/
10948 genCast (iCode * ic)
10950 operand *result = IC_RESULT (ic);
10951 sym_link *ctype = operandType (IC_LEFT (ic));
10952 sym_link *rtype = operandType (IC_RIGHT (ic));
10953 operand *right = IC_RIGHT (ic);
10956 D (emitcode (";", "genCast "););
10958 /* if they are equivalent then do nothing */
10959 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10962 aopOp (right, ic, FALSE, FALSE);
10963 aopOp (result, ic, FALSE, AOP_USESDPTR(right));
10965 /* if the result is a bit */
10966 if (IS_BITVAR (OP_SYMBOL (result)->type)
10967 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
10969 /* if the right size is a literal then
10970 we know what the value is */
10971 if (AOP_TYPE (right) == AOP_LIT)
10973 if (((int) operandLitValue (right)))
10974 aopPut (AOP (result), one, 0);
10976 aopPut (AOP (result), zero, 0);
10981 /* the right is also a bit variable */
10982 if (AOP_TYPE (right) == AOP_CRY)
10984 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10985 aopPut (AOP (result), "c", 0);
10989 /* we need to or */
10991 aopPut (AOP (result), "a", 0);
10995 /* if they are the same size : or less */
10996 if (AOP_SIZE (result) <= AOP_SIZE (right))
10999 /* if they are in the same place */
11000 if (sameRegs (AOP (right), AOP (result)))
11003 /* if they in different places then copy */
11004 size = AOP_SIZE (result);
11006 _startLazyDPSEvaluation ();
11009 aopPut (AOP (result),
11010 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11014 _endLazyDPSEvaluation ();
11019 /* if the result is of type pointer */
11020 if (IS_PTR (ctype))
11024 sym_link *type = operandType (right);
11026 /* pointer to generic pointer */
11027 if (IS_GENPTR (ctype))
11031 p_type = DCL_TYPE (type);
11035 #if OLD_CAST_BEHAVIOR
11036 /* KV: we are converting a non-pointer type to
11037 * a generic pointer. This (ifdef'd out) code
11038 * says that the resulting generic pointer
11039 * should have the same class as the storage
11040 * location of the non-pointer variable.
11042 * For example, converting an int (which happens
11043 * to be stored in DATA space) to a pointer results
11044 * in a DATA generic pointer; if the original int
11045 * in XDATA space, so will be the resulting pointer.
11047 * I don't like that behavior, and thus this change:
11048 * all such conversions will be forced to XDATA and
11049 * throw a warning. If you want some non-XDATA
11050 * type, or you want to suppress the warning, you
11051 * must go through an intermediate cast, like so:
11053 * char _generic *gp = (char _xdata *)(intVar);
11055 sym_link *etype = getSpec (type);
11057 /* we have to go by the storage class */
11058 if (SPEC_OCLS (etype) != generic)
11060 p_type = PTR_TYPE (SPEC_OCLS (etype));
11065 /* Converting unknown class (i.e. register variable)
11066 * to generic pointer. This is not good, but
11067 * we'll make a guess (and throw a warning).
11070 werror (W_INT_TO_GEN_PTR_CAST);
11074 /* the first two bytes are known */
11075 size = GPTRSIZE - 1;
11077 _startLazyDPSEvaluation ();
11080 aopPut (AOP (result),
11081 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11085 _endLazyDPSEvaluation ();
11087 /* the last byte depending on type */
11089 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11094 // pointerTypeToGPByte will have bitched.
11098 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11099 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11104 /* just copy the pointers */
11105 size = AOP_SIZE (result);
11107 _startLazyDPSEvaluation ();
11110 aopPut (AOP (result),
11111 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11115 _endLazyDPSEvaluation ();
11119 /* so we now know that the size of destination is greater
11120 than the size of the source */
11121 /* we move to result for the size of source */
11122 size = AOP_SIZE (right);
11124 _startLazyDPSEvaluation ();
11127 aopPut (AOP (result),
11128 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11132 _endLazyDPSEvaluation ();
11134 /* now depending on the sign of the source && destination */
11135 size = AOP_SIZE (result) - AOP_SIZE (right);
11136 /* if unsigned or not an integral type */
11137 /* also, if the source is a bit, we don't need to sign extend, because
11138 * it can't possibly have set the sign bit.
11140 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
11144 aopPut (AOP (result), zero, offset++);
11149 /* we need to extend the sign :{ */
11150 MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11151 FALSE, FALSE, NULL));
11152 emitcode ("rlc", "a");
11153 emitcode ("subb", "a,acc");
11155 aopPut (AOP (result), "a", offset++);
11158 /* we are done hurray !!!! */
11161 freeAsmop (right, NULL, ic, TRUE);
11162 freeAsmop (result, NULL, ic, TRUE);
11166 /*-----------------------------------------------------------------*/
11167 /* genDjnz - generate decrement & jump if not zero instrucion */
11168 /*-----------------------------------------------------------------*/
11170 genDjnz (iCode * ic, iCode * ifx)
11172 symbol *lbl, *lbl1;
11176 /* if the if condition has a false label
11177 then we cannot save */
11178 if (IC_FALSE (ifx))
11181 /* if the minus is not of the form
11183 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11184 !IS_OP_LITERAL (IC_RIGHT (ic)))
11187 if (operandLitValue (IC_RIGHT (ic)) != 1)
11190 /* if the size of this greater than one then no
11192 if (getSize (operandType (IC_RESULT (ic))) > 1)
11195 /* otherwise we can save BIG */
11196 D(emitcode(";", "genDjnz"););
11198 lbl = newiTempLabel (NULL);
11199 lbl1 = newiTempLabel (NULL);
11201 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11203 if (AOP_NEEDSACC(IC_RESULT(ic)))
11205 /* If the result is accessed indirectly via
11206 * the accumulator, we must explicitly write
11207 * it back after the decrement.
11209 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11211 if (strcmp(rByte, "a"))
11213 /* Something is hopelessly wrong */
11214 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11215 __FILE__, __LINE__);
11216 /* We can just give up; the generated code will be inefficient,
11217 * but what the hey.
11219 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11222 emitcode ("dec", "%s", rByte);
11223 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11224 emitcode ("jnz", "!tlabel", lbl->key + 100);
11226 else if (IS_AOP_PREG (IC_RESULT (ic)))
11228 emitcode ("dec", "%s",
11229 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11230 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11231 emitcode ("jnz", "!tlabel", lbl->key + 100);
11235 emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11238 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11239 emitcode ("", "!tlabeldef", lbl->key + 100);
11240 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11241 emitcode ("", "!tlabeldef", lbl1->key + 100);
11243 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11244 ifx->generated = 1;
11248 /*-----------------------------------------------------------------*/
11249 /* genReceive - generate code for a receive iCode */
11250 /*-----------------------------------------------------------------*/
11252 genReceive (iCode * ic)
11254 int size = getSize (operandType (IC_RESULT (ic)));
11258 D (emitcode (";", "genReceive "););
11260 if (ic->argreg == 1)
11262 /* first parameter */
11263 if (AOP_IS_STR(IC_RESULT(ic)))
11265 /* Nothing to do: it's already in the proper place. */
11272 useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11273 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11274 IS_TRUE_SYMOP (IC_RESULT (ic)));
11277 aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11280 /* Sanity checking... */
11281 if (AOP_USESDPTR(IC_RESULT(ic)))
11283 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11284 "genReceive got unexpected DPTR.");
11286 assignResultValue (IC_RESULT (ic));
11291 /* second receive onwards */
11292 /* this gets a little tricky since unused recevies will be
11293 eliminated, we have saved the reg in the type field . and
11294 we use that to figure out which register to use */
11295 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11296 rb1off = ic->argreg;
11299 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11302 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11305 /*-----------------------------------------------------------------*/
11306 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
11307 /*-----------------------------------------------------------------*/
11308 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11310 operand *from , *to , *count;
11315 /* we know it has to be 3 parameters */
11316 assert (nparms == 3);
11318 rsave = newBitVect(16);
11319 /* save DPTR if it needs to be saved */
11320 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11321 if (bitVectBitValue(ic->rMask,i))
11322 rsave = bitVectSetBit(rsave,i);
11324 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11325 ds390_rUmaskForOp (IC_RESULT(ic))));
11332 aopOp (from, ic->next, FALSE, FALSE);
11334 /* get from into DPTR1 */
11335 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11336 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11337 if (options.model == MODEL_FLAT24) {
11338 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11341 freeAsmop (from, NULL, ic, FALSE);
11342 aopOp (to, ic, FALSE, FALSE);
11343 /* get "to" into DPTR */
11344 /* if the operand is already in dptr
11345 then we do nothing else we move the value to dptr */
11346 if (AOP_TYPE (to) != AOP_STR) {
11347 /* if already in DPTR then we need to push */
11348 if (AOP_TYPE(to) == AOP_DPTR) {
11349 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11350 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11351 if (options.model == MODEL_FLAT24)
11352 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11353 emitcode ("pop", "dph");
11354 emitcode ("pop", "dpl");
11356 _startLazyDPSEvaluation ();
11357 /* if this is remateriazable */
11358 if (AOP_TYPE (to) == AOP_IMMD) {
11359 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11360 } else { /* we need to get it byte by byte */
11361 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11362 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11363 if (options.model == MODEL_FLAT24) {
11364 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11367 _endLazyDPSEvaluation ();
11370 freeAsmop (to, NULL, ic, FALSE);
11371 _G.dptrInUse = _G.dptr1InUse = 1;
11372 aopOp (count, ic->next->next, FALSE,FALSE);
11373 lbl =newiTempLabel(NULL);
11375 /* now for the actual copy */
11376 if (AOP_TYPE(count) == AOP_LIT &&
11377 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11378 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11380 emitcode ("lcall","__bi_memcpyc2x_s");
11382 emitcode ("lcall","__bi_memcpyx2x_s");
11384 freeAsmop (count, NULL, ic, FALSE);
11386 symbol *lbl1 = newiTempLabel(NULL);
11388 emitcode (";"," Auto increment but no djnz");
11389 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11390 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11391 freeAsmop (count, NULL, ic, FALSE);
11392 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11393 emitcode ("","!tlabeldef",lbl->key+100);
11395 emitcode ("clr","a");
11396 emitcode ("movc", "a,@a+dptr");
11398 emitcode ("movx", "a,@dptr");
11399 emitcode ("movx", "@dptr,a");
11400 emitcode ("inc", "dptr");
11401 emitcode ("inc", "dptr");
11402 emitcode ("mov","a,b");
11403 emitcode ("orl","a,_ap");
11404 emitcode ("jz","!tlabel",lbl1->key+100);
11405 emitcode ("mov","a,_ap");
11406 emitcode ("add","a,#!constbyte",0xFF);
11407 emitcode ("mov","_ap,a");
11408 emitcode ("mov","a,b");
11409 emitcode ("addc","a,#!constbyte",0xFF);
11410 emitcode ("mov","b,a");
11411 emitcode ("sjmp","!tlabel",lbl->key+100);
11412 emitcode ("","!tlabeldef",lbl1->key+100);
11414 emitcode ("mov", "dps,#0");
11415 _G.dptrInUse = _G.dptr1InUse = 0;
11416 unsavermask(rsave);
11420 /*-----------------------------------------------------------------*/
11421 /* genMemcmpX2X - gen code for memcmp xdata to xdata */
11422 /*-----------------------------------------------------------------*/
11423 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11425 operand *from , *to , *count;
11430 /* we know it has to be 3 parameters */
11431 assert (nparms == 3);
11433 rsave = newBitVect(16);
11434 /* save DPTR if it needs to be saved */
11435 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11436 if (bitVectBitValue(ic->rMask,i))
11437 rsave = bitVectSetBit(rsave,i);
11439 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11440 ds390_rUmaskForOp (IC_RESULT(ic))));
11447 aopOp (from, ic->next, FALSE, FALSE);
11449 /* get from into DPTR1 */
11450 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11451 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11452 if (options.model == MODEL_FLAT24) {
11453 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11456 freeAsmop (from, NULL, ic, FALSE);
11457 aopOp (to, ic, FALSE, FALSE);
11458 /* get "to" into DPTR */
11459 /* if the operand is already in dptr
11460 then we do nothing else we move the value to dptr */
11461 if (AOP_TYPE (to) != AOP_STR) {
11462 /* if already in DPTR then we need to push */
11463 if (AOP_TYPE(to) == AOP_DPTR) {
11464 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11465 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11466 if (options.model == MODEL_FLAT24)
11467 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11468 emitcode ("pop", "dph");
11469 emitcode ("pop", "dpl");
11471 _startLazyDPSEvaluation ();
11472 /* if this is remateriazable */
11473 if (AOP_TYPE (to) == AOP_IMMD) {
11474 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11475 } else { /* we need to get it byte by byte */
11476 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11477 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11478 if (options.model == MODEL_FLAT24) {
11479 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11482 _endLazyDPSEvaluation ();
11485 freeAsmop (to, NULL, ic, FALSE);
11486 _G.dptrInUse = _G.dptr1InUse = 1;
11487 aopOp (count, ic->next->next, FALSE,FALSE);
11488 lbl =newiTempLabel(NULL);
11489 lbl2 =newiTempLabel(NULL);
11491 /* now for the actual compare */
11492 if (AOP_TYPE(count) == AOP_LIT &&
11493 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11494 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11496 emitcode("lcall","__bi_memcmpc2x_s");
11498 emitcode("lcall","__bi_memcmpx2x_s");
11499 freeAsmop (count, NULL, ic, FALSE);
11500 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11501 aopPut(AOP(IC_RESULT(ic)),"a",0);
11502 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11504 symbol *lbl1 = newiTempLabel(NULL);
11506 emitcode("push","ar0");
11507 emitcode (";"," Auto increment but no djnz");
11508 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11509 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11510 freeAsmop (count, NULL, ic, FALSE);
11511 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11512 emitcode ("","!tlabeldef",lbl->key+100);
11514 emitcode ("clr","a");
11515 emitcode ("movc", "a,@a+dptr");
11517 emitcode ("movx", "a,@dptr");
11518 emitcode ("mov","r0,a");
11519 emitcode ("movx", "a,@dptr");
11520 emitcode ("clr","c");
11521 emitcode ("subb","a,r0");
11522 emitcode ("jnz","!tlabel",lbl2->key+100);
11523 emitcode ("inc", "dptr");
11524 emitcode ("inc", "dptr");
11525 emitcode ("mov","a,b");
11526 emitcode ("orl","a,_ap");
11527 emitcode ("jz","!tlabel",lbl1->key+100);
11528 emitcode ("mov","a,_ap");
11529 emitcode ("add","a,#!constbyte",0xFF);
11530 emitcode ("mov","_ap,a");
11531 emitcode ("mov","a,b");
11532 emitcode ("addc","a,#!constbyte",0xFF);
11533 emitcode ("mov","b,a");
11534 emitcode ("sjmp","!tlabel",lbl->key+100);
11535 emitcode ("","!tlabeldef",lbl1->key+100);
11536 emitcode ("clr","a");
11537 emitcode ("","!tlabeldef",lbl2->key+100);
11538 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11539 aopPut(AOP(IC_RESULT(ic)),"a",0);
11540 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11541 emitcode("pop","ar0");
11542 emitcode ("mov", "dps,#0");
11544 _G.dptrInUse = _G.dptr1InUse = 0;
11545 unsavermask(rsave);
11549 /*-----------------------------------------------------------------*/
11550 /* genInp - gen code for __builtin_inp read data from a mem mapped */
11551 /* port, first parameter output area second parameter pointer to */
11552 /* port third parameter count */
11553 /*-----------------------------------------------------------------*/
11554 static void genInp( iCode *ic, int nparms, operand **parms)
11556 operand *from , *to , *count;
11561 /* we know it has to be 3 parameters */
11562 assert (nparms == 3);
11564 rsave = newBitVect(16);
11565 /* save DPTR if it needs to be saved */
11566 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11567 if (bitVectBitValue(ic->rMask,i))
11568 rsave = bitVectSetBit(rsave,i);
11570 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11571 ds390_rUmaskForOp (IC_RESULT(ic))));
11578 aopOp (from, ic->next, FALSE, FALSE);
11580 /* get from into DPTR1 */
11581 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11582 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11583 if (options.model == MODEL_FLAT24) {
11584 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11587 freeAsmop (from, NULL, ic, FALSE);
11588 aopOp (to, ic, FALSE, FALSE);
11589 /* get "to" into DPTR */
11590 /* if the operand is already in dptr
11591 then we do nothing else we move the value to dptr */
11592 if (AOP_TYPE (to) != AOP_STR) {
11593 /* if already in DPTR then we need to push */
11594 if (AOP_TYPE(to) == AOP_DPTR) {
11595 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11596 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11597 if (options.model == MODEL_FLAT24)
11598 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11599 emitcode ("pop", "dph");
11600 emitcode ("pop", "dpl");
11602 _startLazyDPSEvaluation ();
11603 /* if this is remateriazable */
11604 if (AOP_TYPE (to) == AOP_IMMD) {
11605 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11606 } else { /* we need to get it byte by byte */
11607 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11608 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11609 if (options.model == MODEL_FLAT24) {
11610 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11613 _endLazyDPSEvaluation ();
11616 freeAsmop (to, NULL, ic, FALSE);
11618 _G.dptrInUse = _G.dptr1InUse = 1;
11619 aopOp (count, ic->next->next, FALSE,FALSE);
11620 lbl =newiTempLabel(NULL);
11622 /* now for the actual copy */
11623 if (AOP_TYPE(count) == AOP_LIT &&
11624 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11625 emitcode (";","OH JOY auto increment with djnz (very fast)");
11626 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11627 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11628 freeAsmop (count, NULL, ic, FALSE);
11629 emitcode ("","!tlabeldef",lbl->key+100);
11630 emitcode ("movx", "a,@dptr"); /* read data from port */
11631 emitcode ("dec","dps"); /* switch to DPTR */
11632 emitcode ("movx", "@dptr,a"); /* save into location */
11633 emitcode ("inc", "dptr"); /* point to next area */
11634 emitcode ("inc","dps"); /* switch to DPTR2 */
11635 emitcode ("djnz","b,!tlabel",lbl->key+100);
11637 symbol *lbl1 = newiTempLabel(NULL);
11639 emitcode (";"," Auto increment but no djnz");
11640 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11641 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11642 freeAsmop (count, NULL, ic, FALSE);
11643 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11644 emitcode ("","!tlabeldef",lbl->key+100);
11645 emitcode ("movx", "a,@dptr");
11646 emitcode ("dec","dps"); /* switch to DPTR */
11647 emitcode ("movx", "@dptr,a");
11648 emitcode ("inc", "dptr");
11649 emitcode ("inc","dps"); /* switch to DPTR2 */
11650 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
11651 /* emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
11652 emitcode ("mov","a,b");
11653 emitcode ("orl","a,_ap");
11654 emitcode ("jz","!tlabel",lbl1->key+100);
11655 emitcode ("mov","a,_ap");
11656 emitcode ("add","a,#!constbyte",0xFF);
11657 emitcode ("mov","_ap,a");
11658 emitcode ("mov","a,b");
11659 emitcode ("addc","a,#!constbyte",0xFF);
11660 emitcode ("mov","b,a");
11661 emitcode ("sjmp","!tlabel",lbl->key+100);
11662 emitcode ("","!tlabeldef",lbl1->key+100);
11664 emitcode ("mov", "dps,#0");
11665 _G.dptrInUse = _G.dptr1InUse = 0;
11666 unsavermask(rsave);
11670 /*-----------------------------------------------------------------*/
11671 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
11672 /* port, first parameter output area second parameter pointer to */
11673 /* port third parameter count */
11674 /*-----------------------------------------------------------------*/
11675 static void genOutp( iCode *ic, int nparms, operand **parms)
11677 operand *from , *to , *count;
11682 /* we know it has to be 3 parameters */
11683 assert (nparms == 3);
11685 rsave = newBitVect(16);
11686 /* save DPTR if it needs to be saved */
11687 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11688 if (bitVectBitValue(ic->rMask,i))
11689 rsave = bitVectSetBit(rsave,i);
11691 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11692 ds390_rUmaskForOp (IC_RESULT(ic))));
11699 aopOp (from, ic->next, FALSE, FALSE);
11701 /* get from into DPTR1 */
11702 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11703 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11704 if (options.model == MODEL_FLAT24) {
11705 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11708 freeAsmop (from, NULL, ic, FALSE);
11709 aopOp (to, ic, FALSE, FALSE);
11710 /* get "to" into DPTR */
11711 /* if the operand is already in dptr
11712 then we do nothing else we move the value to dptr */
11713 if (AOP_TYPE (to) != AOP_STR) {
11714 /* if already in DPTR then we need to push */
11715 if (AOP_TYPE(to) == AOP_DPTR) {
11716 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11717 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11718 if (options.model == MODEL_FLAT24)
11719 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11720 emitcode ("pop", "dph");
11721 emitcode ("pop", "dpl");
11723 _startLazyDPSEvaluation ();
11724 /* if this is remateriazable */
11725 if (AOP_TYPE (to) == AOP_IMMD) {
11726 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11727 } else { /* we need to get it byte by byte */
11728 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11729 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11730 if (options.model == MODEL_FLAT24) {
11731 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11734 _endLazyDPSEvaluation ();
11737 freeAsmop (to, NULL, ic, FALSE);
11739 _G.dptrInUse = _G.dptr1InUse = 1;
11740 aopOp (count, ic->next->next, FALSE,FALSE);
11741 lbl =newiTempLabel(NULL);
11743 /* now for the actual copy */
11744 if (AOP_TYPE(count) == AOP_LIT &&
11745 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11746 emitcode (";","OH JOY auto increment with djnz (very fast)");
11747 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
11748 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11749 emitcode ("","!tlabeldef",lbl->key+100);
11750 emitcode ("movx", "a,@dptr"); /* read data from port */
11751 emitcode ("inc","dps"); /* switch to DPTR2 */
11752 emitcode ("movx", "@dptr,a"); /* save into location */
11753 emitcode ("inc", "dptr"); /* point to next area */
11754 emitcode ("dec","dps"); /* switch to DPTR */
11755 emitcode ("djnz","b,!tlabel",lbl->key+100);
11756 freeAsmop (count, NULL, ic, FALSE);
11758 symbol *lbl1 = newiTempLabel(NULL);
11760 emitcode (";"," Auto increment but no djnz");
11761 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11762 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11763 freeAsmop (count, NULL, ic, FALSE);
11764 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
11765 emitcode ("","!tlabeldef",lbl->key+100);
11766 emitcode ("movx", "a,@dptr");
11767 emitcode ("inc", "dptr");
11768 emitcode ("inc","dps"); /* switch to DPTR2 */
11769 emitcode ("movx", "@dptr,a");
11770 emitcode ("dec","dps"); /* switch to DPTR */
11771 emitcode ("mov","a,b");
11772 emitcode ("orl","a,_ap");
11773 emitcode ("jz","!tlabel",lbl1->key+100);
11774 emitcode ("mov","a,_ap");
11775 emitcode ("add","a,#!constbyte",0xFF);
11776 emitcode ("mov","_ap,a");
11777 emitcode ("mov","a,b");
11778 emitcode ("addc","a,#!constbyte",0xFF);
11779 emitcode ("mov","b,a");
11780 emitcode ("sjmp","!tlabel",lbl->key+100);
11781 emitcode ("","!tlabeldef",lbl1->key+100);
11783 emitcode ("mov", "dps,#0");
11784 _G.dptrInUse = _G.dptr1InUse = 0;
11785 unsavermask(rsave);
11789 /*-----------------------------------------------------------------*/
11790 /* genSwapW - swap lower & high order bytes */
11791 /*-----------------------------------------------------------------*/
11792 static void genSwapW(iCode *ic, int nparms, operand **parms)
11796 assert (nparms==1);
11799 dest=IC_RESULT(ic);
11801 assert(getSize(operandType(src))==2);
11803 aopOp (src, ic, FALSE, FALSE);
11804 emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
11806 MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
11808 freeAsmop (src, NULL, ic, FALSE);
11810 aopOp (dest,ic, FALSE, FALSE);
11811 aopPut(AOP(dest),"b",0);
11812 aopPut(AOP(dest),"a",1);
11813 freeAsmop (dest, NULL, ic, FALSE);
11816 /*-----------------------------------------------------------------*/
11817 /* genMemsetX - gencode for memSetX data */
11818 /*-----------------------------------------------------------------*/
11819 static void genMemsetX(iCode *ic, int nparms, operand **parms)
11821 operand *to , *val , *count;
11827 /* we know it has to be 3 parameters */
11828 assert (nparms == 3);
11834 /* save DPTR if it needs to be saved */
11835 rsave = newBitVect(16);
11836 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11837 if (bitVectBitValue(ic->rMask,i))
11838 rsave = bitVectSetBit(rsave,i);
11840 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11841 ds390_rUmaskForOp (IC_RESULT(ic))));
11844 aopOp (to, ic, FALSE, FALSE);
11845 /* get "to" into DPTR */
11846 /* if the operand is already in dptr
11847 then we do nothing else we move the value to dptr */
11848 if (AOP_TYPE (to) != AOP_STR) {
11849 /* if already in DPTR then we need to push */
11850 if (AOP_TYPE(to) == AOP_DPTR) {
11851 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11852 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11853 if (options.model == MODEL_FLAT24)
11854 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11855 emitcode ("pop", "dph");
11856 emitcode ("pop", "dpl");
11858 _startLazyDPSEvaluation ();
11859 /* if this is remateriazable */
11860 if (AOP_TYPE (to) == AOP_IMMD) {
11861 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11862 } else { /* we need to get it byte by byte */
11863 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11864 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11865 if (options.model == MODEL_FLAT24) {
11866 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11869 _endLazyDPSEvaluation ();
11872 freeAsmop (to, NULL, ic, FALSE);
11874 aopOp (val, ic->next->next, FALSE,FALSE);
11875 aopOp (count, ic->next->next, FALSE,FALSE);
11876 lbl =newiTempLabel(NULL);
11877 /* now for the actual copy */
11878 if (AOP_TYPE(count) == AOP_LIT &&
11879 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11880 l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
11881 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11883 emitcode ("","!tlabeldef",lbl->key+100);
11884 emitcode ("movx", "@dptr,a");
11885 emitcode ("inc", "dptr");
11886 emitcode ("djnz","b,!tlabel",lbl->key+100);
11888 symbol *lbl1 = newiTempLabel(NULL);
11890 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11891 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11892 emitcode ("","!tlabeldef",lbl->key+100);
11893 MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
11894 emitcode ("movx", "@dptr,a");
11895 emitcode ("inc", "dptr");
11896 emitcode ("mov","a,b");
11897 emitcode ("orl","a,_ap");
11898 emitcode ("jz","!tlabel",lbl1->key+100);
11899 emitcode ("mov","a,_ap");
11900 emitcode ("add","a,#!constbyte",0xFF);
11901 emitcode ("mov","_ap,a");
11902 emitcode ("mov","a,b");
11903 emitcode ("addc","a,#!constbyte",0xFF);
11904 emitcode ("mov","b,a");
11905 emitcode ("sjmp","!tlabel",lbl->key+100);
11906 emitcode ("","!tlabeldef",lbl1->key+100);
11908 freeAsmop (count, NULL, ic, FALSE);
11909 unsavermask(rsave);
11912 /*-----------------------------------------------------------------*/
11913 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
11914 /*-----------------------------------------------------------------*/
11915 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
11918 operand *pnum, *result;
11921 assert (nparms==1);
11922 /* save registers that need to be saved */
11923 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11924 ds390_rUmaskForOp (IC_RESULT(ic))));
11927 aopOp (pnum, ic, FALSE, FALSE);
11928 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
11929 freeAsmop (pnum, NULL, ic, FALSE);
11930 emitcode ("lcall","NatLib_LoadPrimitive");
11931 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11932 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
11933 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
11934 for (i = (size-1) ; i >= 0 ; i-- ) {
11935 emitcode ("push","a%s",javaRet[i]);
11937 for (i=0; i < size ; i++ ) {
11938 emitcode ("pop","a%s",
11939 aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
11942 for (i = 0 ; i < size ; i++ ) {
11943 aopPut(AOP(result),javaRet[i],i);
11946 freeAsmop (result, NULL, ic, FALSE);
11947 unsavermask(rsave);
11950 /*-----------------------------------------------------------------*/
11951 /* genNatLibLoadPointer - calls TINI api function to load pointer */
11952 /*-----------------------------------------------------------------*/
11953 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
11956 operand *pnum, *result;
11960 assert (nparms==1);
11961 /* save registers that need to be saved */
11962 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11963 ds390_rUmaskForOp (IC_RESULT(ic))));
11966 aopOp (pnum, ic, FALSE, FALSE);
11967 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
11968 freeAsmop (pnum, NULL, ic, FALSE);
11969 emitcode ("lcall","NatLib_LoadPointer");
11970 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11971 if (AOP_TYPE(result)!=AOP_STR) {
11972 for (i = 0 ; i < size ; i++ ) {
11973 aopPut(AOP(result),fReturn[i],i);
11976 freeAsmop (result, NULL, ic, FALSE);
11977 unsavermask(rsave);
11980 /*-----------------------------------------------------------------*/
11981 /* genNatLibInstallStateBlock - */
11982 /*-----------------------------------------------------------------*/
11983 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
11984 operand **parms, const char *name)
11987 operand *psb, *handle;
11988 assert (nparms==2);
11990 /* save registers that need to be saved */
11991 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11992 ds390_rUmaskForOp (IC_RESULT(ic))));
11996 /* put pointer to state block into DPTR1 */
11997 aopOp (psb, ic, FALSE, FALSE);
11998 if (AOP_TYPE (psb) == AOP_IMMD) {
11999 emitcode ("mov","dps,#1");
12000 emitcode ("mov", "dptr,%s",
12001 aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12002 emitcode ("mov","dps,#0");
12004 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12005 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12006 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12008 freeAsmop (psb, NULL, ic, FALSE);
12010 /* put libraryID into DPTR */
12011 emitcode ("mov","dptr,#LibraryID");
12013 /* put handle into r3:r2 */
12014 aopOp (handle, ic, FALSE, FALSE);
12015 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12016 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12017 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12018 emitcode ("pop","ar3");
12019 emitcode ("pop","ar2");
12021 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12022 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12024 freeAsmop (psb, NULL, ic, FALSE);
12026 /* make the call */
12027 emitcode ("lcall","NatLib_Install%sStateBlock",name);
12029 /* put return value into place*/
12031 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12033 aopPut(AOP(IC_RESULT(ic)),"a",0);
12034 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12035 unsavermask(rsave);
12038 /*-----------------------------------------------------------------*/
12039 /* genNatLibRemoveStateBlock - */
12040 /*-----------------------------------------------------------------*/
12041 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12047 /* save registers that need to be saved */
12048 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12049 ds390_rUmaskForOp (IC_RESULT(ic))));
12051 /* put libraryID into DPTR */
12052 emitcode ("mov","dptr,#LibraryID");
12053 /* make the call */
12054 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12055 unsavermask(rsave);
12058 /*-----------------------------------------------------------------*/
12059 /* genNatLibGetStateBlock - */
12060 /*-----------------------------------------------------------------*/
12061 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12062 operand **parms,const char *name)
12065 symbol *lbl = newiTempLabel(NULL);
12068 /* save registers that need to be saved */
12069 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12070 ds390_rUmaskForOp (IC_RESULT(ic))));
12072 /* put libraryID into DPTR */
12073 emitcode ("mov","dptr,#LibraryID");
12074 /* make the call */
12075 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12076 emitcode ("jnz","!tlabel",lbl->key+100);
12078 /* put return value into place */
12079 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12080 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12081 emitcode ("push","ar3");
12082 emitcode ("push","ar2");
12083 emitcode ("pop","%s",
12084 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12085 emitcode ("pop","%s",
12086 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12088 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12089 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12091 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12092 emitcode ("","!tlabeldef",lbl->key+100);
12093 unsavermask(rsave);
12096 /*-----------------------------------------------------------------*/
12097 /* genMMMalloc - */
12098 /*-----------------------------------------------------------------*/
12099 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12100 int size, const char *name)
12105 symbol *lbl = newiTempLabel(NULL);
12107 assert (nparms == 1);
12108 /* save registers that need to be saved */
12109 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12110 ds390_rUmaskForOp (IC_RESULT(ic))));
12113 aopOp (bsize,ic,FALSE,FALSE);
12115 /* put the size in R4-R2 */
12116 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12117 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12118 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12120 emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12121 emitcode("pop","ar4");
12123 emitcode("pop","ar3");
12124 emitcode("pop","ar2");
12126 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12127 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12129 emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12132 freeAsmop (bsize, NULL, ic, FALSE);
12134 /* make the call */
12135 emitcode ("lcall","MM_%s",name);
12136 emitcode ("jz","!tlabel",lbl->key+100);
12137 emitcode ("mov","r2,#!constbyte",0xff);
12138 emitcode ("mov","r3,#!constbyte",0xff);
12139 emitcode ("","!tlabeldef",lbl->key+100);
12140 /* we don't care about the pointer : we just save the handle */
12141 rsym = OP_SYMBOL(IC_RESULT(ic));
12142 if (rsym->liveFrom != rsym->liveTo) {
12143 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12144 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12145 emitcode ("push","ar3");
12146 emitcode ("push","ar2");
12147 emitcode ("pop","%s",
12148 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12149 emitcode ("pop","%s",
12150 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12152 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12153 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12155 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12157 unsavermask(rsave);
12160 /*-----------------------------------------------------------------*/
12162 /*-----------------------------------------------------------------*/
12163 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12168 assert (nparms == 1);
12169 /* save registers that need to be saved */
12170 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12171 ds390_rUmaskForOp (IC_RESULT(ic))));
12174 aopOp (handle,ic,FALSE,FALSE);
12176 /* put the size in R4-R2 */
12177 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12178 emitcode("push","%s",
12179 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12180 emitcode("push","%s",
12181 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12182 emitcode("pop","ar3");
12183 emitcode("pop","ar2");
12185 emitcode ("mov","r2,%s",
12186 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12187 emitcode ("mov","r3,%s",
12188 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12190 freeAsmop (handle, NULL, ic, FALSE);
12192 /* make the call */
12193 emitcode ("lcall","MM_Deref");
12196 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12197 if (rsym->liveFrom != rsym->liveTo) {
12198 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12199 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12200 _startLazyDPSEvaluation ();
12202 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12203 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12204 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12206 _endLazyDPSEvaluation ();
12211 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12212 unsavermask(rsave);
12215 /*-----------------------------------------------------------------*/
12216 /* genMMUnrestrictedPersist - */
12217 /*-----------------------------------------------------------------*/
12218 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12223 assert (nparms == 1);
12224 /* save registers that need to be saved */
12225 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12226 ds390_rUmaskForOp (IC_RESULT(ic))));
12229 aopOp (handle,ic,FALSE,FALSE);
12231 /* put the size in R3-R2 */
12232 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12233 emitcode("push","%s",
12234 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12235 emitcode("push","%s",
12236 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12237 emitcode("pop","ar3");
12238 emitcode("pop","ar2");
12240 emitcode ("mov","r2,%s",
12241 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12242 emitcode ("mov","r3,%s",
12243 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12245 freeAsmop (handle, NULL, ic, FALSE);
12247 /* make the call */
12248 emitcode ("lcall","MM_UnrestrictedPersist");
12251 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12252 if (rsym->liveFrom != rsym->liveTo) {
12253 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12254 aopPut(AOP(IC_RESULT(ic)),"a",0);
12255 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12258 unsavermask(rsave);
12261 /*-----------------------------------------------------------------*/
12262 /* genSystemExecJavaProcess - */
12263 /*-----------------------------------------------------------------*/
12264 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12267 operand *handle, *pp;
12269 assert (nparms==2);
12270 /* save registers that need to be saved */
12271 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12272 ds390_rUmaskForOp (IC_RESULT(ic))));
12277 /* put the handle in R3-R2 */
12278 aopOp (handle,ic,FALSE,FALSE);
12279 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12280 emitcode("push","%s",
12281 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12282 emitcode("push","%s",
12283 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12284 emitcode("pop","ar3");
12285 emitcode("pop","ar2");
12287 emitcode ("mov","r2,%s",
12288 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12289 emitcode ("mov","r3,%s",
12290 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12292 freeAsmop (handle, NULL, ic, FALSE);
12294 /* put pointer in DPTR */
12295 aopOp (pp,ic,FALSE,FALSE);
12296 if (AOP_TYPE(pp) == AOP_IMMD) {
12297 emitcode ("mov", "dptr,%s",
12298 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12299 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12300 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12301 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12302 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12304 freeAsmop (handle, NULL, ic, FALSE);
12306 /* make the call */
12307 emitcode ("lcall","System_ExecJavaProcess");
12309 /* put result in place */
12311 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12312 if (rsym->liveFrom != rsym->liveTo) {
12313 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12314 aopPut(AOP(IC_RESULT(ic)),"a",0);
12315 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12319 unsavermask(rsave);
12322 /*-----------------------------------------------------------------*/
12323 /* genSystemRTCRegisters - */
12324 /*-----------------------------------------------------------------*/
12325 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12331 assert (nparms==1);
12332 /* save registers that need to be saved */
12333 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12334 ds390_rUmaskForOp (IC_RESULT(ic))));
12337 /* put pointer in DPTR */
12338 aopOp (pp,ic,FALSE,FALSE);
12339 if (AOP_TYPE (pp) == AOP_IMMD) {
12340 emitcode ("mov","dps,#1");
12341 emitcode ("mov", "dptr,%s",
12342 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12343 emitcode ("mov","dps,#0");
12345 emitcode ("mov","dpl1,%s",
12346 aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12347 emitcode ("mov","dph1,%s",
12348 aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12349 emitcode ("mov","dpx1,%s",
12350 aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12352 freeAsmop (pp, NULL, ic, FALSE);
12354 /* make the call */
12355 emitcode ("lcall","System_%sRTCRegisters",name);
12357 unsavermask(rsave);
12360 /*-----------------------------------------------------------------*/
12361 /* genSystemThreadSleep - */
12362 /*-----------------------------------------------------------------*/
12363 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12368 assert (nparms==1);
12369 /* save registers that need to be saved */
12370 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12371 ds390_rUmaskForOp (IC_RESULT(ic))));
12374 aopOp(to,ic,FALSE,FALSE);
12375 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12376 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12377 emitcode ("push","%s",
12378 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12379 emitcode ("push","%s",
12380 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12381 emitcode ("push","%s",
12382 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12383 emitcode ("push","%s",
12384 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12385 emitcode ("pop","ar3");
12386 emitcode ("pop","ar2");
12387 emitcode ("pop","ar1");
12388 emitcode ("pop","ar0");
12390 emitcode ("mov","r0,%s",
12391 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12392 emitcode ("mov","r1,%s",
12393 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12394 emitcode ("mov","r2,%s",
12395 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12396 emitcode ("mov","r3,%s",
12397 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12399 freeAsmop (to, NULL, ic, FALSE);
12401 /* suspend in acc */
12403 aopOp(s,ic,FALSE,FALSE);
12404 emitcode ("mov","a,%s",
12405 aopGet(AOP(s),0,FALSE,TRUE,NULL));
12406 freeAsmop (s, NULL, ic, FALSE);
12408 /* make the call */
12409 emitcode ("lcall","System_%s",name);
12411 unsavermask(rsave);
12414 /*-----------------------------------------------------------------*/
12415 /* genSystemThreadResume - */
12416 /*-----------------------------------------------------------------*/
12417 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12422 assert (nparms==2);
12423 /* save registers that need to be saved */
12424 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12425 ds390_rUmaskForOp (IC_RESULT(ic))));
12431 aopOp(pid,ic,FALSE,FALSE);
12432 emitcode ("mov","r0,%s",
12433 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12434 freeAsmop (pid, NULL, ic, FALSE);
12437 aopOp(tid,ic,FALSE,FALSE);
12438 emitcode ("mov","a,%s",
12439 aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
12440 freeAsmop (tid, NULL, ic, FALSE);
12442 emitcode ("lcall","System_ThreadResume");
12444 /* put result into place */
12446 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12447 if (rsym->liveFrom != rsym->liveTo) {
12448 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12449 aopPut(AOP(IC_RESULT(ic)),"a",0);
12450 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12453 unsavermask(rsave);
12456 /*-----------------------------------------------------------------*/
12457 /* genSystemProcessResume - */
12458 /*-----------------------------------------------------------------*/
12459 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
12464 assert (nparms==1);
12465 /* save registers that need to be saved */
12466 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12467 ds390_rUmaskForOp (IC_RESULT(ic))));
12472 aopOp(pid,ic,FALSE,FALSE);
12473 emitcode ("mov","a,%s",
12474 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12475 freeAsmop (pid, NULL, ic, FALSE);
12477 emitcode ("lcall","System_ProcessResume");
12479 unsavermask(rsave);
12482 /*-----------------------------------------------------------------*/
12484 /*-----------------------------------------------------------------*/
12485 static void genSystem (iCode *ic,int nparms,char *name)
12487 assert(nparms == 0);
12489 emitcode ("lcall","System_%s",name);
12492 /*-----------------------------------------------------------------*/
12493 /* genSystemPoll - */
12494 /*-----------------------------------------------------------------*/
12495 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
12500 assert (nparms==1);
12501 /* save registers that need to be saved */
12502 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12503 ds390_rUmaskForOp (IC_RESULT(ic))));
12506 aopOp (fp,ic,FALSE,FALSE);
12507 if (AOP_TYPE (fp) == AOP_IMMD) {
12508 emitcode ("mov", "dptr,%s",
12509 aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
12510 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
12511 emitcode ("mov","dpl,%s",
12512 aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
12513 emitcode ("mov","dph,%s",
12514 aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
12515 emitcode ("mov","dpx,%s",
12516 aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
12518 freeAsmop (fp, NULL, ic, FALSE);
12520 emitcode ("lcall","System_%sPoll",name);
12522 /* put result into place */
12524 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12525 if (rsym->liveFrom != rsym->liveTo) {
12526 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12527 aopPut(AOP(IC_RESULT(ic)),"a",0);
12528 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12531 unsavermask(rsave);
12534 /*-----------------------------------------------------------------*/
12535 /* genSystemGetCurrentID - */
12536 /*-----------------------------------------------------------------*/
12537 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
12539 assert (nparms==0);
12541 emitcode ("lcall","System_GetCurrent%sId",name);
12542 /* put result into place */
12544 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12545 if (rsym->liveFrom != rsym->liveTo) {
12546 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12547 aopPut(AOP(IC_RESULT(ic)),"a",0);
12548 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12553 /*-----------------------------------------------------------------*/
12554 /* genDummyRead - generate code for dummy read of volatiles */
12555 /*-----------------------------------------------------------------*/
12557 genDummyRead (iCode * ic)
12562 D(emitcode("; genDummyRead",""));
12564 right = IC_RIGHT (ic);
12566 aopOp (right, ic, FALSE, FALSE);
12568 /* if the result is a bit */
12569 if (AOP_TYPE (right) == AOP_CRY)
12571 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
12575 /* bit variables done */
12577 size = AOP_SIZE (right);
12581 emitcode ("mov", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
12586 freeAsmop (right, NULL, ic, TRUE);
12589 /*-----------------------------------------------------------------*/
12590 /* genBuiltIn - calls the appropriate function to generating code */
12591 /* for a built in function */
12592 /*-----------------------------------------------------------------*/
12593 static void genBuiltIn (iCode *ic)
12595 operand *bi_parms[MAX_BUILTIN_ARGS];
12600 /* get all the arguments for a built in function */
12601 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
12603 /* which function is it */
12604 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
12605 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
12606 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
12607 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
12608 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
12609 } else if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
12610 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
12611 } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
12612 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
12613 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
12614 genMemsetX(bi_iCode,nbi_parms,bi_parms);
12615 } else if (strcmp(bif->name,"__builtin_inp")==0) {
12616 genInp(bi_iCode,nbi_parms,bi_parms);
12617 } else if (strcmp(bif->name,"__builtin_outp")==0) {
12618 genOutp(bi_iCode,nbi_parms,bi_parms);
12619 } else if (strcmp(bif->name,"__builtin_swapw")==0) {
12620 genSwapW(bi_iCode,nbi_parms,bi_parms);
12621 /* JavaNative builtIns */
12622 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
12623 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
12624 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
12625 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
12626 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
12627 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
12628 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
12629 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
12630 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
12631 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12632 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
12633 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12634 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
12635 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
12636 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
12637 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
12638 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
12639 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12640 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
12641 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12642 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
12643 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
12644 } else if (strcmp(bif->name,"MM_Malloc")==0) {
12645 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
12646 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
12647 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
12648 } else if (strcmp(bif->name,"MM_Free")==0) {
12649 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
12650 } else if (strcmp(bif->name,"MM_Deref")==0) {
12651 genMMDeref(bi_iCode,nbi_parms,bi_parms);
12652 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
12653 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
12654 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
12655 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
12656 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
12657 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
12658 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
12659 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
12660 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
12661 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
12662 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
12663 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
12664 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
12665 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
12666 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
12667 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
12668 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12669 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12670 } else if (strcmp(bif->name,"System_SaveThread")==0) {
12671 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12672 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12673 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12674 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
12675 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
12676 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
12677 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
12678 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
12679 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
12680 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
12681 genSystem(bi_iCode,nbi_parms,"ProcessYield");
12682 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
12683 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
12684 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
12685 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
12686 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
12687 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
12688 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
12689 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
12690 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
12691 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
12693 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
12699 /*-----------------------------------------------------------------*/
12700 /* gen390Code - generate code for Dallas 390 based controllers */
12701 /*-----------------------------------------------------------------*/
12703 gen390Code (iCode * lic)
12708 lineHead = lineCurr = NULL;
12709 dptrn[1][0] = "dpl1";
12710 dptrn[1][1] = "dph1";
12711 dptrn[1][2] = "dpx1";
12713 if (options.model == MODEL_FLAT24) {
12714 fReturnSizeDS390 = 5;
12715 fReturn = fReturn24;
12717 fReturnSizeDS390 = 4;
12718 fReturn = fReturn16;
12719 options.stack10bit=0;
12722 /* print the allocation information */
12723 if (allocInfo && currFunc)
12724 printAllocInfo (currFunc, codeOutFile);
12726 /* if debug information required */
12727 if (options.debug && currFunc)
12729 debugFile->writeFunction(currFunc);
12731 if (IS_STATIC (currFunc->etype))
12732 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
12734 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
12737 /* stack pointer name */
12738 if (options.useXstack)
12744 for (ic = lic; ic; ic = ic->next)
12747 if (ic->lineno && cln != ic->lineno)
12752 emitcode ("", "C$%s$%d$%d$%d ==.",
12753 FileBaseName (ic->filename), ic->lineno,
12754 ic->level, ic->block);
12757 if (!options.noCcodeInAsm) {
12758 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
12759 printCLine(ic->filename, ic->lineno));
12763 if (options.iCodeInAsm) {
12764 emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
12766 /* if the result is marked as
12767 spilt and rematerializable or code for
12768 this has already been generated then
12770 if (resultRemat (ic) || ic->generated)
12773 /* depending on the operation */
12793 /* IPOP happens only when trying to restore a
12794 spilt live range, if there is an ifx statement
12795 following this pop then the if statement might
12796 be using some of the registers being popped which
12797 would destory the contents of the register so
12798 we need to check for this condition and handle it */
12800 ic->next->op == IFX &&
12801 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
12802 genIfx (ic->next, ic);
12820 genEndFunction (ic);
12840 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
12857 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
12861 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
12868 /* note these two are xlated by algebraic equivalence
12869 during parsing SDCC.y */
12870 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12871 "got '>=' or '<=' shouldn't have come here");
12875 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
12887 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
12891 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
12895 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
12919 genRightShift (ic);
12922 case GET_VALUE_AT_ADDRESS:
12923 genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
12927 if (POINTER_SET (ic))
12928 genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
12954 if (ic->builtinSEND) genBuiltIn(ic);
12955 else addSet (&_G.sendSet, ic);
12958 case DUMMY_READ_VOLATILE:
12962 #if 0 // obsolete, and buggy for != xdata
12974 /* now we are ready to call the
12975 peep hole optimizer */
12976 if (!options.nopeep)
12977 peepHole (&lineHead);
12979 /* now do the actual printing */
12980 printLine (lineHead, codeOutFile);