1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for DS80C390
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7 DS390 adaptation by Kevin Vigor <kevin@vigor.nu>
9 This program is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 2, or (at your option) any
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 In other words, you are welcome to use, share and improve this program.
24 You are forbidden to forbid anyone else to use, share and improve
25 what you give them. Help stamp out software-hoarding!
26 -------------------------------------------------------------------------*/
36 #include "SDCCglobl.h"
39 #define BETTER_LITERAL_SHIFT
41 char *aopLiteral (value * val, int offset);
44 /* this is the down and dirty file with all kinds of
45 kludgy & hacky stuff. This is what it is all about
46 CODE GENERATION for a specific MCU . some of the
47 routines may be reusable, will have to see */
49 static char *zero = "#0";
50 static char *one = "#1";
55 #define TR_DPTR(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_DPTR1 %s ", s); }
56 #define TR_AP(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_AP %s ", s); }
58 unsigned fReturnSizeDS390 = 5; /* shared with ralloc.c */
59 static char *fReturn24[] =
60 {"dpl", "dph", "dpx", "b", "a"};
61 static char *fReturn16[] =
62 {"dpl", "dph", "b", "a"};
63 static char **fReturn = fReturn24;
64 static char *accUse[] =
66 static char *dptrn[2][3];
67 static char *javaRet[] = { "r0","r1","r2","r3"};
68 static short rbank = -1;
85 static char *rb1regs[] = {
86 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
89 static void saveRBank (int, iCode *, bool);
91 #define RESULTONSTACK(x) \
92 (IC_RESULT(x) && IC_RESULT(x)->aop && \
93 IC_RESULT(x)->aop->type == AOP_STK )
95 #define MOVA(x) _movA(x)
96 #define MOVB(x) _movB(x)
98 #define CLRC emitcode("clr","c")
99 #define SETC emitcode("setb","c")
101 // A scratch register which will be used to hold
102 // result bytes from operands in far space via DPTR2.
103 #define DP2_RESULT_REG "_ap"
105 static lineNode *lineHead = NULL;
106 static lineNode *lineCurr = NULL;
108 static unsigned char SLMask[] =
109 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
110 0xE0, 0xC0, 0x80, 0x00};
111 static unsigned char SRMask[] =
112 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
113 0x07, 0x03, 0x01, 0x00};
119 #define PROTECT_SP {if (options.protect_sp_update) { \
120 symbol *lbl = newiTempLabel(NULL); \
121 emitcode ("setb","F1"); \
122 emitcode ("jbc","EA,!tlabel",lbl->key+100); \
123 emitcode ("clr","F1"); \
124 emitcode ("","!tlabeldef",lbl->key+100); \
126 #define UNPROTECT_SP { if (options.protect_sp_update) { \
127 symbol *lbl = newiTempLabel(NULL); \
128 emitcode ("jnb","F1,!tlabel",lbl->key+100); \
129 emitcode ("setb","EA"); \
130 emitcode ("","!tlabeldef",lbl->key+100); \
134 /*-----------------------------------------------------------------*/
135 /* emitcode - writes the code into a file : for now it is simple */
136 /*-----------------------------------------------------------------*/
138 emitcode (char *inst, char *fmt,...)
141 char lb[INITIAL_INLINEASM];
150 SNPRINTF (lb, sizeof(lb), "%s\t", inst);
154 SNPRINTF (lb, sizeof(lb), "%s", inst);
157 tvsprintf (lb + strlen(lb), sizeof(lb) - strlen(lb),
162 tvsprintf (lb, sizeof(lb), fmt, ap);
166 while (isspace (*lbp))
173 lineCurr = (lineCurr ?
174 connectLine (lineCurr, newLineNode (lb)) :
175 (lineHead = newLineNode (lb)));
178 lineCurr->isInline = _G.inLine;
179 lineCurr->isDebug = _G.debugLine;
184 // Move the passed value into A unless it is already there.
189 if (strcmp(s,"a") && strcmp(s,"acc"))
191 emitcode("mov","a,%s",s);
196 // Move the passed value into B unless it is already there.
203 emitcode("mov","b,%s",s);
207 /*-----------------------------------------------------------------*/
208 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
209 /*-----------------------------------------------------------------*/
211 getFreePtr (iCode * ic, asmop ** aopp, bool result)
216 /* the logic: if r0 & r1 used in the instruction
217 then we are in trouble otherwise */
219 /* first check if r0 & r1 are used by this
220 instruction, in which case we are in trouble */
221 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
222 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
227 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
228 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
230 /* if no usage of r0 then return it */
233 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
234 (*aopp)->type = AOP_R0;
236 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
239 /* if no usage of r1 then return it */
242 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
243 (*aopp)->type = AOP_R1;
245 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
248 /* now we know they both have usage */
249 /* if r0 not used in this instruction */
252 /* push it if not already pushed */
255 emitcode ("push", "%s",
256 ds390_regWithIdx (R0_IDX)->dname);
260 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
261 (*aopp)->type = AOP_R0;
263 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
266 /* if r1 not used then */
270 /* push it if not already pushed */
273 emitcode ("push", "%s",
274 ds390_regWithIdx (R1_IDX)->dname);
278 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
279 (*aopp)->type = AOP_R1;
280 return ds390_regWithIdx (R1_IDX);
284 /* I said end of world but not quite end of world yet */
285 /* if this is a result then we can push it on the stack */
288 (*aopp)->type = AOP_STK;
292 /* other wise this is true end of the world */
293 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
294 "getFreePtr should never reach here");
297 return NULL; // notreached, but makes compiler happy.
300 /*-----------------------------------------------------------------*/
301 /* newAsmop - creates a new asmOp */
302 /*-----------------------------------------------------------------*/
304 newAsmop (short type)
308 aop = Safe_calloc (1, sizeof (asmop));
313 static int _currentDPS; /* Current processor DPS. */
314 static int _desiredDPS; /* DPS value compiler thinks we should be using. */
315 static int _lazyDPS = 0; /* if non-zero, we are doing lazy evaluation of DPS changes. */
317 /*-----------------------------------------------------------------*/
318 /* genSetDPTR: generate code to select which DPTR is in use (zero */
319 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390 */
320 /* alternate DPTR (DPL1/DPH1/DPX1). */
321 /*-----------------------------------------------------------------*/
326 /* If we are doing lazy evaluation, simply note the desired
327 * change, but don't emit any code yet.
337 emitcode ("mov", "dps,#0");
342 emitcode ("mov", "dps,#1");
346 /*-----------------------------------------------------------------*/
347 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
349 /* Any code that operates on DPTR (NB: not on the individual */
350 /* components, like DPH) *must* call _flushLazyDPS() before using */
351 /* DPTR within a lazy DPS evaluation block. */
353 /* Note that aopPut and aopGet already contain the proper calls to */
354 /* _flushLazyDPS, so it is safe to use these calls within a lazy */
355 /* DPS evaluation block. */
357 /* Also, _flushLazyDPS must be called before any flow control */
358 /* operations that could potentially branch out of the block. */
360 /* Lazy DPS evaluation is simply an optimization (though an */
361 /* important one), so if in doubt, leave it out. */
362 /*-----------------------------------------------------------------*/
364 _startLazyDPSEvaluation (void)
368 #ifdef BETTER_LITERAL_SHIFT
375 /*-----------------------------------------------------------------*/
376 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
377 /* desired one. Call before using DPTR within a lazy DPS evaluation */
379 /*-----------------------------------------------------------------*/
389 if (_desiredDPS != _currentDPS)
393 emitcode ("inc", "dps");
397 emitcode ("dec", "dps");
399 _currentDPS = _desiredDPS;
403 /*-----------------------------------------------------------------*/
404 /* _endLazyDPSEvaluation: end lazy DPS evaluation block. */
406 /* Forces us back to the safe state (standard DPTR selected). */
407 /*-----------------------------------------------------------------*/
409 _endLazyDPSEvaluation (void)
411 #ifdef BETTER_LITERAL_SHIFT
430 /*-----------------------------------------------------------------*/
431 /* pointerCode - returns the code for a pointer type */
432 /*-----------------------------------------------------------------*/
434 pointerCode (sym_link * etype)
437 return PTR_TYPE (SPEC_OCLS (etype));
441 /*-----------------------------------------------------------------*/
442 /* aopForSym - for a true symbol */
443 /*-----------------------------------------------------------------*/
445 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
448 memmap *space = SPEC_OCLS (sym->etype);
450 /* if already has one */
454 /* assign depending on the storage class */
455 /* if it is on the stack or indirectly addressable */
456 /* space we need to assign either r0 or r1 to it */
457 if ((sym->onStack && !options.stack10bit) || sym->iaccess)
459 sym->aop = aop = newAsmop (0);
460 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
461 aop->size = getSize (sym->type);
463 /* now assign the address of the variable to
464 the pointer register */
465 if (aop->type != AOP_STK)
471 emitcode ("push", "acc");
474 emitcode ("push", "b");
476 emitcode ("mov", "a,_bp");
477 emitcode ("add", "a,#!constbyte",
479 ((char) (sym->stack - _G.nRegsSaved)) :
480 ((char) sym->stack)) & 0xff);
481 emitcode ("mov", "%s,a",
482 aop->aopu.aop_ptr->name);
485 emitcode ("pop", "b");
488 emitcode ("pop", "acc");
491 emitcode ("mov", "%s,#%s",
492 aop->aopu.aop_ptr->name,
494 aop->paged = space->paged;
497 aop->aopu.aop_stk = sym->stack;
501 if (sym->onStack && options.stack10bit)
503 short stack_val = -((sym->stack < 0) ?
504 ((short) (sym->stack - _G.nRegsSaved)) :
505 ((short) sym->stack)) ;
506 if (useDP2 && _G.dptr1InUse) {
507 emitcode ("push","dpl1");
508 emitcode ("push","dph1");
509 emitcode ("push","dpx1");
510 } else if (_G.dptrInUse ) {
511 emitcode ("push","dpl");
512 emitcode ("push","dph");
513 emitcode ("push","dpx");
515 /* It's on the 10 bit stack, which is located in
518 if (stack_val < 0 && stack_val > -5) { /* between -5 & -1 */
520 if (options.model == MODEL_FLAT24)
522 emitcode ("mov", "dpx1,#!constbyte",
523 (options.stack_loc >> 16) & 0xff);
525 emitcode ("mov", "dph1,_bpx+1");
527 emitcode ("mov", "dpl1,_bpx");
528 emitcode ("mov","dps,#1");
530 if (options.model == MODEL_FLAT24)
532 emitcode ("mov", "dpx,#!constbyte",
533 (options.stack_loc >> 16) & 0xff);
535 emitcode ("mov", "dph,_bpx+1");
536 emitcode ("mov", "dpl,_bpx");
538 stack_val = -stack_val;
539 while (stack_val--) {
540 emitcode ("inc","dptr");
543 emitcode("mov","dps,#0");
547 emitcode ("push", "acc");
550 emitcode ("push", "b");
552 emitcode ("mov", "a,_bpx");
553 emitcode ("clr","c");
554 emitcode ("subb", "a,#!constbyte", stack_val & 0xff);
555 emitcode ("mov","b,a");
556 emitcode ("mov","a,_bpx+1");
557 emitcode ("subb","a,#!constbyte",(stack_val >> 8) & 0xff);
559 if (options.model == MODEL_FLAT24)
561 emitcode ("mov", "dpx1,#!constbyte",
562 (options.stack_loc >> 16) & 0xff);
564 emitcode ("mov", "dph1,a");
565 emitcode ("mov", "dpl1,b");
567 if (options.model == MODEL_FLAT24)
569 emitcode ("mov", "dpx,#!constbyte",
570 (options.stack_loc >> 16) & 0xff);
572 emitcode ("mov", "dph,a");
573 emitcode ("mov", "dpl,b");
577 emitcode ("pop", "b");
580 emitcode ("pop", "acc");
582 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
583 aop->size = getSize (sym->type);
587 /* if in bit space */
588 if (IN_BITSPACE (space))
590 sym->aop = aop = newAsmop (AOP_CRY);
591 aop->aopu.aop_dir = sym->rname;
592 aop->size = getSize (sym->type);
595 /* if it is in direct space */
596 if (IN_DIRSPACE (space))
598 sym->aop = aop = newAsmop (AOP_DIR);
599 aop->aopu.aop_dir = sym->rname;
600 aop->size = getSize (sym->type);
604 /* special case for a function */
605 if (IS_FUNC (sym->type) && !(sym->isitmp))
607 sym->aop = aop = newAsmop (AOP_IMMD);
608 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
609 aop->size = FPTRSIZE;
613 /* only remaining is far space */
614 /* in which case DPTR gets the address */
615 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
620 emitcode ("mov", "dptr,#%s", sym->rname);
625 emitcode ("mov", "dptr,#%s", sym->rname);
627 aop->size = getSize (sym->type);
629 /* if it is in code space */
630 if (IN_CODESPACE (space))
636 /*-----------------------------------------------------------------*/
637 /* aopForRemat - rematerialzes an object */
638 /*-----------------------------------------------------------------*/
640 aopForRemat (symbol * sym)
642 iCode *ic = sym->rematiCode;
643 asmop *aop = newAsmop (AOP_IMMD);
650 val += (int) operandLitValue (IC_RIGHT (ic));
651 else if (ic->op == '-')
652 val -= (int) operandLitValue (IC_RIGHT (ic));
653 else if (IS_CAST_ICODE(ic)) {
654 sym_link *from_type = operandType(IC_RIGHT(ic));
655 aop->aopu.aop_immd.from_cast_remat = 1;
656 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
657 ptr_type = DCL_TYPE(from_type);
658 if (ptr_type == IPOINTER) {
665 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
670 SNPRINTF (buffer, sizeof(buffer),
672 OP_SYMBOL (IC_LEFT (ic))->rname,
673 val >= 0 ? '+' : '-',
674 abs (val) & 0xffffff);
678 if (IS_ASSIGN_ICODE(ic) && isOperandLiteral(IC_RIGHT(ic)))
680 SNPRINTF(buffer, sizeof(buffer),
681 "0x%x",(int) operandLitValue (IC_RIGHT (ic)));
685 strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
689 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);
690 /* set immd2 field if required */
691 if (aop->aopu.aop_immd.from_cast_remat)
693 tsprintf(buffer, sizeof(buffer), "#!constbyte",ptr_type);
694 aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
700 /*-----------------------------------------------------------------*/
701 /* aopHasRegs - returns true if aop has regs between from-to */
702 /*-----------------------------------------------------------------*/
703 static int aopHasRegs(asmop *aop, int from, int to)
707 if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
709 for (; size < aop->size ; size++) {
711 for (reg = from ; reg <= to ; reg++)
712 if (aop->aopu.aop_reg[size] == ds390_regWithIdx(reg)) return 1;
717 /*-----------------------------------------------------------------*/
718 /* regsInCommon - two operands have some registers in common */
719 /*-----------------------------------------------------------------*/
721 regsInCommon (operand * op1, operand * op2)
726 /* if they have registers in common */
727 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
730 sym1 = OP_SYMBOL (op1);
731 sym2 = OP_SYMBOL (op2);
733 if (sym1->nRegs == 0 || sym2->nRegs == 0)
736 for (i = 0; i < sym1->nRegs; i++)
742 for (j = 0; j < sym2->nRegs; j++)
747 if (sym2->regs[j] == sym1->regs[i])
755 /*-----------------------------------------------------------------*/
756 /* operandsEqu - equivalent */
757 /*-----------------------------------------------------------------*/
759 operandsEqu (operand * op1, operand * op2)
763 /* if they not symbols */
764 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
767 sym1 = OP_SYMBOL (op1);
768 sym2 = OP_SYMBOL (op2);
770 /* if both are itemps & one is spilt
771 and the other is not then false */
772 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
773 sym1->isspilt != sym2->isspilt)
776 /* if they are the same */
780 if (strcmp (sym1->rname, sym2->rname) == 0)
784 /* if left is a tmp & right is not */
785 if (IS_ITEMP (op1) &&
788 (sym1->usl.spillLoc == sym2))
791 if (IS_ITEMP (op2) &&
795 (sym2->usl.spillLoc == sym1))
801 /*-----------------------------------------------------------------*/
802 /* sameRegs - two asmops have the same registers */
803 /*-----------------------------------------------------------------*/
805 sameRegs (asmop * aop1, asmop * aop2)
811 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
818 if (aop1->type != AOP_REG ||
819 aop2->type != AOP_REG)
822 if (aop1->size != aop2->size)
825 for (i = 0; i < aop1->size; i++)
826 if (aop1->aopu.aop_reg[i] !=
827 aop2->aopu.aop_reg[i])
833 /*-----------------------------------------------------------------*/
834 /* aopOp - allocates an asmop for an operand : */
835 /*-----------------------------------------------------------------*/
837 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
846 /* if this a literal */
847 if (IS_OP_LITERAL (op))
849 op->aop = aop = newAsmop (AOP_LIT);
850 aop->aopu.aop_lit = op->operand.valOperand;
851 aop->size = getSize (operandType (op));
855 /* if already has a asmop then continue */
859 /* if the underlying symbol has a aop */
860 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
862 op->aop = OP_SYMBOL (op)->aop;
866 /* if this is a true symbol */
867 if (IS_TRUE_SYMOP (op))
869 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
873 /* this is a temporary : this has
879 e) can be a return use only */
881 sym = OP_SYMBOL (op);
884 /* if the type is a conditional */
885 if (sym->regType == REG_CND)
887 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
892 /* if it is spilt then two situations
894 b) has a spill location */
895 if (sym->isspilt || sym->nRegs == 0)
898 /* rematerialize it NOW */
901 sym->aop = op->aop = aop =
903 aop->size = getSize (sym->type);
910 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
911 aop->size = getSize (sym->type);
912 for (i = 0; i < 2; i++)
913 aop->aopu.aop_str[i] = accUse[i];
923 /* a AOP_STR uses DPTR, but DPTR is already in use;
926 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"AOP_STR with DPTR in use!");
929 aop = op->aop = sym->aop = newAsmop (AOP_STR);
930 aop->size = getSize (sym->type);
931 for (i = 0; i < (int) fReturnSizeDS390; i++)
932 aop->aopu.aop_str[i] = fReturn[i];
936 if (sym->dptr) { /* has been allocated to a DPTRn */
937 aop = op->aop = sym->aop = newAsmop (AOP_DPTRn);
938 aop->size = getSize (sym->type);
939 aop->aopu.dptr = sym->dptr;
942 /* else spill location */
943 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
944 /* force a new aop if sizes differ */
945 sym->usl.spillLoc->aop = NULL;
947 sym->aop = op->aop = aop =
948 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
949 aop->size = getSize (sym->type);
953 /* must be in a register */
954 sym->aop = op->aop = aop = newAsmop (AOP_REG);
955 aop->size = sym->nRegs;
956 for (i = 0; i < sym->nRegs; i++)
957 aop->aopu.aop_reg[i] = sym->regs[i];
960 /*-----------------------------------------------------------------*/
961 /* freeAsmop - free up the asmop given to an operand */
962 /*----------------------------------------------------------------*/
964 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
981 /* depending on the asmop type only three cases need work AOP_RO
982 , AOP_R1 && AOP_STK */
990 emitcode ("pop", "ar0");
994 bitVectUnSetBit (ic->rUsed, R0_IDX);
1002 emitcode ("pop", "ar1");
1006 bitVectUnSetBit (ic->rUsed, R1_IDX);
1012 int stk = aop->aopu.aop_stk + aop->size;
1013 bitVectUnSetBit (ic->rUsed, R0_IDX);
1014 bitVectUnSetBit (ic->rUsed, R1_IDX);
1016 getFreePtr (ic, &aop, FALSE);
1018 if (options.stack10bit)
1020 /* I'm not sure what to do here yet... */
1023 "*** Warning: probably generating bad code for "
1024 "10 bit stack mode.\n");
1029 emitcode ("mov", "a,_bp");
1030 emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
1031 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1035 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1040 emitcode ("pop", "acc");
1041 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1044 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1047 freeAsmop (op, NULL, ic, TRUE);
1050 emitcode ("pop", "ar0");
1056 emitcode ("pop", "ar1");
1061 if (_G.dptr1InUse) {
1062 emitcode ("pop","dpx1");
1063 emitcode ("pop","dph1");
1064 emitcode ("pop","dpl1");
1069 emitcode ("pop","dpx");
1070 emitcode ("pop","dph");
1071 emitcode ("pop","dpl");
1076 /* all other cases just dealloc */
1082 OP_SYMBOL (op)->aop = NULL;
1083 /* if the symbol has a spill */
1085 SPIL_LOC (op)->aop = NULL;
1090 #define DEFAULT_ACC_WARNING 0
1091 static int saveAccWarn = DEFAULT_ACC_WARNING;
1093 /*-------------------------------------------------------------------*/
1094 /* aopGet - for fetching value of the aop */
1096 /* Set saveAcc to NULL if you are sure it is OK to clobber the value */
1097 /* in the accumulator. Set it to the name of a free register */
1098 /* if acc must be preserved; the register will be used to preserve */
1099 /* acc temporarily and to return the result byte. */
1100 /*-------------------------------------------------------------------*/
1109 /* offset is greater than
1111 if (offset > (aop->size - 1) &&
1112 aop->type != AOP_LIT)
1115 /* depending on type */
1121 /* if we need to increment it */
1122 while (offset > aop->coff)
1124 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1128 while (offset < aop->coff)
1130 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1137 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1138 return (dname ? "acc" : "a");
1140 SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1141 return Safe_strdup(buffer);
1144 assert(offset <= 3);
1145 return dptrn[aop->aopu.dptr][offset];
1150 if (aop->type == AOP_DPTR2)
1158 // if (aop->type != AOP_DPTR2)
1160 // if (saveAccWarn) { fprintf(stderr, "saveAcc for DPTR...\n"); }
1161 // emitcode(";", "spanky: saveAcc for DPTR");
1164 emitcode ("xch", "a, %s", saveAcc);
1169 while (offset > aop->coff)
1171 emitcode ("inc", "dptr");
1175 while (offset < aop->coff)
1177 emitcode ("lcall", "__decdptr");
1184 emitcode ("clr", "a");
1185 emitcode ("movc", "a,@a+dptr");
1189 emitcode ("movx", "a,@dptr");
1192 if (aop->type == AOP_DPTR2)
1200 emitcode ("xch", "a, %s", saveAcc);
1201 // if (strcmp(saveAcc, "_ap"))
1203 // emitcode(";", "spiffy: non _ap return from aopGet.");
1208 return (dname ? "acc" : "a");
1211 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1213 SNPRINTF(buffer, sizeof(buffer),
1214 "%s",aop->aopu.aop_immd.aop_immd2);
1218 SNPRINTF(buffer, sizeof(buffer),
1219 "#%s", aop->aopu.aop_immd.aop_immd1);
1225 tsprintf(buffer, sizeof(buffer),
1226 "#!his",aop->aopu.aop_immd.aop_immd1);
1229 tsprintf(buffer, sizeof(buffer),
1230 "#!hihis",aop->aopu.aop_immd.aop_immd1);
1233 tsprintf(buffer, sizeof(buffer),
1234 "#!hihihis",aop->aopu.aop_immd.aop_immd1);
1236 default: /* should not need this (just in case) */
1237 SNPRINTF (buffer, sizeof(buffer),
1239 aop->aopu.aop_immd.aop_immd1,
1245 SNPRINTF (buffer, sizeof(buffer),
1246 "#%s", aop->aopu.aop_immd.aop_immd1);
1248 return Safe_strdup(buffer);
1253 SNPRINTF (buffer, sizeof(buffer),
1260 SNPRINTF(buffer, sizeof(buffer),
1261 "%s", aop->aopu.aop_dir);
1264 return Safe_strdup(buffer);
1268 return aop->aopu.aop_reg[offset]->dname;
1270 return aop->aopu.aop_reg[offset]->name;
1273 emitcode ("clr", "a");
1274 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1275 emitcode ("rlc", "a");
1276 return (dname ? "acc" : "a");
1279 if (!offset && dname)
1281 return aop->aopu.aop_str[offset];
1284 return aopLiteral (aop->aopu.aop_lit, offset);
1288 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1292 return aop->aopu.aop_str[offset];
1296 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1297 "aopget got unsupported aop->type");
1300 return NULL; // not reached, but makes compiler happy.
1302 /*-----------------------------------------------------------------*/
1303 /* aopPut - puts a string for a aop */
1304 /*-----------------------------------------------------------------*/
1306 aopPut (asmop * aop, char *s, int offset)
1308 if (aop->size && offset > (aop->size - 1))
1310 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1311 "aopPut got offset > aop->size");
1315 /* will assign value to value */
1316 /* depending on where it is ofcourse */
1322 SNPRINTF (buffer, sizeof(buffer),
1324 aop->aopu.aop_dir, offset);
1328 SNPRINTF (buffer, sizeof(buffer),
1329 "%s", aop->aopu.aop_dir);
1333 if (strcmp (buffer, s))
1335 emitcode ("mov", "%s,%s", buffer, s);
1340 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1341 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1344 strcmp (s, "r0") == 0 ||
1345 strcmp (s, "r1") == 0 ||
1346 strcmp (s, "r2") == 0 ||
1347 strcmp (s, "r3") == 0 ||
1348 strcmp (s, "r4") == 0 ||
1349 strcmp (s, "r5") == 0 ||
1350 strcmp (s, "r6") == 0 ||
1351 strcmp (s, "r7") == 0)
1353 emitcode ("mov", "%s,%s",
1354 aop->aopu.aop_reg[offset]->dname, s);
1358 emitcode ("mov", "%s,%s",
1359 aop->aopu.aop_reg[offset]->name, s);
1365 emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1371 if (aop->type == AOP_DPTR2)
1379 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1380 "aopPut writting to code space");
1384 while (offset > aop->coff)
1387 emitcode ("inc", "dptr");
1390 while (offset < aop->coff)
1393 emitcode ("lcall", "__decdptr");
1398 /* if not in accumulater */
1401 emitcode ("movx", "@dptr,a");
1403 if (aop->type == AOP_DPTR2)
1411 while (offset > aop->coff)
1414 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1416 while (offset < aop->coff)
1419 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1426 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1432 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1434 else if (strcmp (s, "r0") == 0 ||
1435 strcmp (s, "r1") == 0 ||
1436 strcmp (s, "r2") == 0 ||
1437 strcmp (s, "r3") == 0 ||
1438 strcmp (s, "r4") == 0 ||
1439 strcmp (s, "r5") == 0 ||
1440 strcmp (s, "r6") == 0 ||
1441 strcmp (s, "r7") == 0)
1444 SNPRINTF(buff, sizeof(buff),
1446 emitcode ("mov", "@%s,%s",
1447 aop->aopu.aop_ptr->name, buff);
1451 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1456 if (strcmp (s, "a") == 0)
1457 emitcode ("push", "acc");
1461 emitcode ("push", "acc");
1463 emitcode ("push", s);
1469 /* if bit variable */
1470 if (!aop->aopu.aop_dir)
1472 emitcode ("clr", "a");
1473 emitcode ("rlc", "a");
1478 emitcode ("clr", "%s", aop->aopu.aop_dir);
1480 emitcode ("setb", "%s", aop->aopu.aop_dir);
1481 else if (!strcmp (s, "c"))
1482 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1485 if (strcmp (s, "a"))
1490 /* set C, if a >= 1 */
1491 emitcode ("add", "a,#!constbyte",0xff);
1492 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1500 if (strcmp (aop->aopu.aop_str[offset], s))
1501 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1506 if (!offset && (strcmp (s, "acc") == 0))
1509 if (strcmp (aop->aopu.aop_str[offset], s))
1510 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1514 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1515 "aopPut got unsupported aop->type");
1522 /*--------------------------------------------------------------------*/
1523 /* reAdjustPreg - points a register back to where it should (coff==0) */
1524 /*--------------------------------------------------------------------*/
1526 reAdjustPreg (asmop * aop)
1528 if ((aop->coff==0) || (aop->size <= 1)) {
1537 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1541 if (aop->type == AOP_DPTR2)
1548 emitcode ("lcall", "__decdptr");
1551 if (aop->type == AOP_DPTR2)
1561 #define AOP(op) op->aop
1562 #define AOP_TYPE(op) AOP(op)->type
1563 #define AOP_SIZE(op) AOP(op)->size
1564 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1565 AOP_TYPE(x) == AOP_R0))
1567 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1568 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1571 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1572 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1573 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1574 #define AOP_INDPTRn(x) (AOP_TYPE(x) == AOP_DPTRn)
1575 #define AOP_USESDPTR(x) ((AOP_TYPE(x) == AOP_DPTR) || (AOP_TYPE(x) == AOP_STR))
1576 #define AOP_USESDPTR2(x) ((AOP_TYPE(x) == AOP_DPTR2) || (AOP_TYPE(x) == AOP_DPTRn))
1578 // The following two macros can be used even if the aop has not yet been aopOp'd.
1579 #define AOP_IS_STR(x) (IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
1580 #define AOP_IS_DPTRn(x) (IS_SYMOP(x) && OP_SYMBOL(x)->dptr)
1582 /* Workaround for DS80C390 bug: div ab may return bogus results
1583 * if A is accessed in instruction immediately before the div.
1585 * Will be fixed in B4 rev of processor, Dallas claims.
1588 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1589 if (!AOP_NEEDSACC(RIGHT)) \
1591 /* We can load A first, then B, since \
1592 * B (the RIGHT operand) won't clobber A, \
1593 * thus avoiding touching A right before the div. \
1595 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1596 L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL); \
1598 L = aopGet(AOP(RIGHT),0,FALSE,FALSE,"b"); \
1603 /* Just stuff in a nop after loading A. */ \
1604 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,NULL));\
1605 L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL); \
1607 emitcode("nop", "; workaround for DS80C390 div bug."); \
1610 /*-----------------------------------------------------------------*/
1611 /* genNotFloat - generates not for float operations */
1612 /*-----------------------------------------------------------------*/
1614 genNotFloat (operand * op, operand * res)
1619 D (emitcode (";", "genNotFloat "););
1621 /* we will put 127 in the first byte of
1623 aopPut (AOP (res), "#127", 0);
1624 size = AOP_SIZE (op) - 1;
1627 _startLazyDPSEvaluation ();
1628 MOVA(aopGet(op->aop, offset++, FALSE, FALSE, NULL));
1632 emitcode ("orl", "a,%s",
1634 offset++, FALSE, FALSE,
1637 _endLazyDPSEvaluation ();
1639 tlbl = newiTempLabel (NULL);
1640 aopPut (res->aop, one, 1);
1641 emitcode ("jz", "!tlabel", (tlbl->key + 100));
1642 aopPut (res->aop, zero, 1);
1643 emitcode ("", "!tlabeldef", (tlbl->key + 100));
1645 size = res->aop->size - 2;
1647 /* put zeros in the rest */
1649 aopPut (res->aop, zero, offset++);
1652 /*-----------------------------------------------------------------*/
1653 /* opIsGptr: returns non-zero if the passed operand is */
1654 /* a generic pointer type. */
1655 /*-----------------------------------------------------------------*/
1657 opIsGptr (operand * op)
1659 sym_link *type = operandType (op);
1661 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1668 /*-----------------------------------------------------------------*/
1669 /* getDataSize - get the operand data size */
1670 /*-----------------------------------------------------------------*/
1672 getDataSize (operand * op)
1675 size = AOP_SIZE (op);
1676 if (size == GPTRSIZE)
1678 sym_link *type = operandType (op);
1679 if (IS_GENPTR (type))
1681 /* generic pointer; arithmetic operations
1682 * should ignore the high byte (pointer type).
1690 /*-----------------------------------------------------------------*/
1691 /* outAcc - output Acc */
1692 /*-----------------------------------------------------------------*/
1694 outAcc (operand * result)
1697 size = getDataSize (result);
1700 aopPut (AOP (result), "a", 0);
1703 /* unsigned or positive */
1706 aopPut (AOP (result), zero, offset++);
1711 /*-----------------------------------------------------------------*/
1712 /* outBitC - output a bit C */
1713 /*-----------------------------------------------------------------*/
1715 outBitC (operand * result)
1717 /* if the result is bit */
1718 if (AOP_TYPE (result) == AOP_CRY)
1720 aopPut (AOP (result), "c", 0);
1724 emitcode ("clr", "a");
1725 emitcode ("rlc", "a");
1730 /*-----------------------------------------------------------------*/
1731 /* toBoolean - emit code for orl a,operator(sizeop) */
1732 /*-----------------------------------------------------------------*/
1734 toBoolean (operand * oper)
1736 int size = AOP_SIZE (oper) - 1;
1740 /* The generic part of a generic pointer should
1741 * not participate in it's truth value.
1743 * i.e. 0x10000000 is zero.
1745 if (opIsGptr (oper))
1747 D (emitcode (";", "toBoolean: generic ptr special case."););
1751 _startLazyDPSEvaluation ();
1752 if (AOP_NEEDSACC (oper) && size)
1757 emitcode ("push", "b");
1759 MOVB (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1763 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1770 emitcode ("orl", "b,%s",
1771 aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1775 emitcode ("orl", "a,%s",
1776 aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1779 _endLazyDPSEvaluation ();
1783 emitcode ("mov", "a,b");
1786 emitcode ("pop", "b");
1793 /*-----------------------------------------------------------------*/
1794 /* genNot - generate code for ! operation */
1795 /*-----------------------------------------------------------------*/
1800 sym_link *optype = operandType (IC_LEFT (ic));
1802 D (emitcode (";", "genNot "););
1804 /* assign asmOps to operand & result */
1805 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1806 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1808 /* if in bit space then a special case */
1809 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1811 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1812 emitcode ("cpl", "c");
1813 outBitC (IC_RESULT (ic));
1817 /* if type float then do float */
1818 if (IS_FLOAT (optype))
1820 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1824 toBoolean (IC_LEFT (ic));
1826 tlbl = newiTempLabel (NULL);
1827 emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1828 emitcode ("", "!tlabeldef", tlbl->key + 100);
1829 outBitC (IC_RESULT (ic));
1832 /* release the aops */
1833 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1834 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1838 /*-----------------------------------------------------------------*/
1839 /* genCpl - generate code for complement */
1840 /*-----------------------------------------------------------------*/
1848 D (emitcode (";", "genCpl "););
1851 /* assign asmOps to operand & result */
1852 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1853 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1855 /* special case if in bit space */
1856 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1857 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1858 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1859 emitcode ("cpl", "c");
1860 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1863 tlbl=newiTempLabel(NULL);
1864 emitcode ("cjne", "%s,#0x01,%05d$",
1865 aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE,NULL), tlbl->key+100);
1866 emitcode ("", "%05d$:", tlbl->key+100);
1867 outBitC (IC_RESULT(ic));
1871 size = AOP_SIZE (IC_RESULT (ic));
1872 _startLazyDPSEvaluation ();
1875 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
1876 emitcode ("cpl", "a");
1877 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1879 _endLazyDPSEvaluation ();
1883 /* release the aops */
1884 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1885 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1888 /*-----------------------------------------------------------------*/
1889 /* genUminusFloat - unary minus for floating points */
1890 /*-----------------------------------------------------------------*/
1892 genUminusFloat (operand * op, operand * result)
1894 int size, offset = 0;
1896 D(emitcode (";", "genUminusFloat"););
1898 /* for this we just copy and then flip the bit */
1900 _startLazyDPSEvaluation ();
1901 size = AOP_SIZE (op) - 1;
1905 aopPut (AOP (result),
1906 aopGet (AOP (op), offset, FALSE, FALSE, NULL),
1911 MOVA(aopGet (AOP (op), offset, FALSE, FALSE, NULL));
1913 emitcode ("cpl", "acc.7");
1914 aopPut (AOP (result), "a", offset);
1915 _endLazyDPSEvaluation ();
1918 /*-----------------------------------------------------------------*/
1919 /* genUminus - unary minus code generation */
1920 /*-----------------------------------------------------------------*/
1922 genUminus (iCode * ic)
1927 D (emitcode (";", "genUminus "););
1930 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1931 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1933 /* if both in bit space then special
1935 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1936 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1939 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1940 emitcode ("cpl", "c");
1941 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1945 optype = operandType (IC_LEFT (ic));
1947 /* if float then do float stuff */
1948 if (IS_FLOAT (optype))
1950 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1954 /* otherwise subtract from zero */
1955 size = AOP_SIZE (IC_LEFT (ic));
1957 _startLazyDPSEvaluation ();
1960 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL);
1961 if (!strcmp (l, "a"))
1965 emitcode ("cpl", "a");
1966 emitcode ("addc", "a,#0");
1972 emitcode ("clr", "a");
1973 emitcode ("subb", "a,%s", l);
1975 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1977 _endLazyDPSEvaluation ();
1979 /* if any remaining bytes in the result */
1980 /* we just need to propagate the sign */
1981 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic)))) != 0)
1983 emitcode ("rlc", "a");
1984 emitcode ("subb", "a,acc");
1986 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1990 /* release the aops */
1991 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1992 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1995 /*-----------------------------------------------------------------*/
1996 /* savermask - saves registers in the mask */
1997 /*-----------------------------------------------------------------*/
1998 static void savermask(bitVect *rs_mask)
2001 if (options.useXstack) {
2002 if (bitVectBitValue (rs_mask, R0_IDX))
2003 emitcode ("mov", "b,r0");
2004 emitcode ("mov", "r0,%s", spname);
2005 for (i = 0; i < ds390_nRegs; i++) {
2006 if (bitVectBitValue (rs_mask, i)) {
2008 emitcode ("mov", "a,b");
2010 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
2011 emitcode ("movx", "@r0,a");
2012 emitcode ("inc", "r0");
2015 emitcode ("mov", "%s,r0", spname);
2016 if (bitVectBitValue (rs_mask, R0_IDX))
2017 emitcode ("mov", "r0,b");
2019 for (i = 0; i < ds390_nRegs; i++) {
2020 if (bitVectBitValue (rs_mask, i))
2021 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2026 /*-----------------------------------------------------------------*/
2027 /* saveRegisters - will look for a call and save the registers */
2028 /*-----------------------------------------------------------------*/
2030 saveRegisters (iCode * lic)
2036 for (ic = lic; ic; ic = ic->next)
2037 if (ic->op == CALL || ic->op == PCALL)
2042 fprintf (stderr, "found parameter push with no function call\n");
2046 /* if the registers have been saved already then
2049 || (IS_SYMOP(IC_LEFT(ic)) && IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))) && !TARGET_IS_DS400) )
2052 /* special case if DPTR alive across a function call then must save it
2053 even though callee saves */
2054 if (IS_SYMOP(IC_LEFT(ic)) &&
2055 IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2057 rsave = newBitVect(ic->rMask->size);
2058 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2059 if (bitVectBitValue(ic->rMask,i))
2060 rsave = bitVectSetBit(rsave,i);
2062 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2064 /* safe the registers in use at this time but skip the
2065 ones for the result */
2066 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2067 ds390_rUmaskForOp (IC_RESULT(ic)));
2073 /*-----------------------------------------------------------------*/
2074 /* usavermask - restore registers with mask */
2075 /*-----------------------------------------------------------------*/
2076 static void unsavermask(bitVect *rs_mask)
2079 if (options.useXstack) {
2080 emitcode ("mov", "r0,%s", spname);
2081 for (i = ds390_nRegs; i >= 0; i--) {
2082 if (bitVectBitValue (rs_mask, i)) {
2083 emitcode ("dec", "r0");
2084 emitcode ("movx", "a,@r0");
2086 emitcode ("mov", "b,a");
2088 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
2091 emitcode ("mov", "%s,r0", spname);
2092 if (bitVectBitValue (rs_mask, R0_IDX))
2093 emitcode ("mov", "r0,b");
2095 for (i = ds390_nRegs; i >= 0; i--) {
2096 if (bitVectBitValue (rs_mask, i))
2097 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2102 /*-----------------------------------------------------------------*/
2103 /* unsaveRegisters - pop the pushed registers */
2104 /*-----------------------------------------------------------------*/
2106 unsaveRegisters (iCode * ic)
2110 if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2112 rsave = newBitVect(ic->rMask->size);
2113 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2114 if (bitVectBitValue(ic->rMask,i))
2115 rsave = bitVectSetBit(rsave,i);
2117 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2119 /* restore the registers in use at this time but skip the
2120 ones for the result */
2121 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2122 ds390_rUmaskForOp (IC_RESULT(ic)));
2128 /*-----------------------------------------------------------------*/
2130 /*-----------------------------------------------------------------*/
2132 pushSide (operand * oper, int size)
2135 _startLazyDPSEvaluation ();
2138 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, NULL);
2139 if (AOP_TYPE (oper) != AOP_REG &&
2140 AOP_TYPE (oper) != AOP_DIR &&
2143 emitcode ("mov", "a,%s", l);
2144 emitcode ("push", "acc");
2147 emitcode ("push", "%s", l);
2149 _endLazyDPSEvaluation ();
2152 /*-----------------------------------------------------------------*/
2153 /* assignResultValue - */
2154 /*-----------------------------------------------------------------*/
2156 assignResultValue (operand * oper)
2159 int size = AOP_SIZE (oper);
2160 bool pushedAcc = FALSE;
2162 if (size == fReturnSizeDS390)
2164 /* I don't think this case can ever happen... */
2165 /* ACC is the last part of this. If writing the result
2166 * uses AC, we must preserve it.
2168 if (AOP_NEEDSACC(oper))
2170 emitcode(";", "assignResultValue special case for ACC.");
2171 emitcode("push", "acc");
2178 _startLazyDPSEvaluation ();
2181 aopPut (AOP (oper), fReturn[offset], offset);
2184 _endLazyDPSEvaluation ();
2188 emitcode("pop", "acc");
2189 aopPut(AOP(oper), "a", offset);
2194 /*-----------------------------------------------------------------*/
2195 /* genXpush - pushes onto the external stack */
2196 /*-----------------------------------------------------------------*/
2198 genXpush (iCode * ic)
2200 asmop *aop = newAsmop (0);
2202 int size, offset = 0;
2204 D (emitcode (";", "genXpush ");
2207 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2208 r = getFreePtr (ic, &aop, FALSE);
2211 emitcode ("mov", "%s,_spx", r->name);
2213 size = AOP_SIZE (IC_LEFT (ic));
2214 _startLazyDPSEvaluation ();
2218 MOVA (aopGet (AOP (IC_LEFT (ic)),
2219 offset++, FALSE, FALSE, NULL));
2220 emitcode ("movx", "@%s,a", r->name);
2221 emitcode ("inc", "%s", r->name);
2224 _endLazyDPSEvaluation ();
2227 emitcode ("mov", "_spx,%s", r->name);
2229 freeAsmop (NULL, aop, ic, TRUE);
2230 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2233 /*-----------------------------------------------------------------*/
2234 /* genIpush - generate code for pushing this gets a little complex */
2235 /*-----------------------------------------------------------------*/
2237 genIpush (iCode * ic)
2239 int size, offset = 0;
2242 D (emitcode (";", "genIpush ");
2245 /* if this is not a parm push : ie. it is spill push
2246 and spill push is always done on the local stack */
2250 /* and the item is spilt then do nothing */
2251 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2254 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2255 size = AOP_SIZE (IC_LEFT (ic));
2256 /* push it on the stack */
2257 _startLazyDPSEvaluation ();
2260 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2266 emitcode ("push", "%s", l);
2268 _endLazyDPSEvaluation ();
2272 /* this is a paramter push: in this case we call
2273 the routine to find the call and save those
2274 registers that need to be saved */
2277 /* if use external stack then call the external
2278 stack pushing routine */
2279 if (options.useXstack)
2285 /* then do the push */
2286 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2288 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2289 size = AOP_SIZE (IC_LEFT (ic));
2291 _startLazyDPSEvaluation ();
2294 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2295 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2296 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2299 emitcode ("mov", "a,%s", l);
2300 emitcode ("push", "acc");
2304 emitcode ("push", "%s", l);
2307 _endLazyDPSEvaluation ();
2309 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2312 /*-----------------------------------------------------------------*/
2313 /* genIpop - recover the registers: can happen only for spilling */
2314 /*-----------------------------------------------------------------*/
2316 genIpop (iCode * ic)
2320 D (emitcode (";", "genIpop ");
2324 /* if the temp was not pushed then */
2325 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2328 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2329 size = AOP_SIZE (IC_LEFT (ic));
2330 offset = (size - 1);
2331 _startLazyDPSEvaluation ();
2334 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2335 FALSE, TRUE, NULL));
2337 _endLazyDPSEvaluation ();
2339 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2342 /*-----------------------------------------------------------------*/
2343 /* unsaveRBank - restores the resgister bank from stack */
2344 /*-----------------------------------------------------------------*/
2346 unsaveRBank (int bank, iCode * ic, bool popPsw)
2352 if (options.useXstack)
2356 /* Assume r0 is available for use. */
2357 r = ds390_regWithIdx (R0_IDX);;
2362 r = getFreePtr (ic, &aop, FALSE);
2364 emitcode ("mov", "%s,_spx", r->name);
2369 if (options.useXstack)
2371 emitcode ("movx", "a,@%s", r->name);
2372 emitcode ("mov", "psw,a");
2373 emitcode ("dec", "%s", r->name);
2377 emitcode ("pop", "psw");
2381 for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2383 if (options.useXstack)
2385 emitcode ("movx", "a,@%s", r->name);
2386 emitcode ("mov", "(%s+%d),a",
2387 regs390[i].base, 8 * bank + regs390[i].offset);
2388 emitcode ("dec", "%s", r->name);
2392 emitcode ("pop", "(%s+%d)",
2393 regs390[i].base, 8 * bank + regs390[i].offset);
2396 if (options.useXstack)
2398 emitcode ("mov", "_spx,%s", r->name);
2403 freeAsmop (NULL, aop, ic, TRUE);
2407 /*-----------------------------------------------------------------*/
2408 /* saveRBank - saves an entire register bank on the stack */
2409 /*-----------------------------------------------------------------*/
2411 saveRBank (int bank, iCode * ic, bool pushPsw)
2417 if (options.useXstack)
2421 /* Assume r0 is available for use. */
2422 r = ds390_regWithIdx (R0_IDX);;
2427 r = getFreePtr (ic, &aop, FALSE);
2429 emitcode ("mov", "%s,_spx", r->name);
2432 for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2434 if (options.useXstack)
2436 emitcode ("inc", "%s", r->name);
2437 emitcode ("mov", "a,(%s+%d)",
2438 regs390[i].base, 8 * bank + regs390[i].offset);
2439 emitcode ("movx", "@%s,a", r->name);
2442 emitcode ("push", "(%s+%d)",
2443 regs390[i].base, 8 * bank + regs390[i].offset);
2448 if (options.useXstack)
2450 emitcode ("mov", "a,psw");
2451 emitcode ("movx", "@%s,a", r->name);
2452 emitcode ("inc", "%s", r->name);
2453 emitcode ("mov", "_spx,%s", r->name);
2457 emitcode ("push", "psw");
2460 emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2465 freeAsmop (NULL, aop, ic, TRUE);
2474 /*-----------------------------------------------------------------*/
2475 /* genSend - gen code for SEND */
2476 /*-----------------------------------------------------------------*/
2477 static void genSend(set *sendSet)
2481 static int rb1_count = 0;
2483 for (sic = setFirstItem (sendSet); sic;
2484 sic = setNextItem (sendSet)) {
2485 int size, offset = 0;
2487 size=getSize(operandType(IC_LEFT(sic)));
2488 D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2489 if (sendCount == 0) { /* first parameter */
2490 // we know that dpl(hxb) is the result, so
2492 _startLazyDPSEvaluation ();
2494 aopOp (IC_LEFT (sic), sic, FALSE,
2495 (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2497 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2500 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2501 FALSE, FALSE, NULL);
2502 if (strcmp (l, fReturn[offset])) {
2503 emitcode ("mov", "%s,%s",
2509 _endLazyDPSEvaluation ();
2510 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2512 } else { /* if more parameter in registers */
2513 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2515 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
2516 FALSE, FALSE, NULL));
2518 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2525 adjustEsp(const char *reg)
2527 emitcode ("anl","%s,#3", reg);
2528 if (TARGET_IS_DS400)
2530 emitcode ("orl","%s,#!constbyte",
2532 (options.stack_loc >> 8) & 0xff);
2536 /*-----------------------------------------------------------------*/
2537 /* genCall - generates a call statement */
2538 /*-----------------------------------------------------------------*/
2540 genCall (iCode * ic)
2543 bool restoreBank = FALSE;
2544 bool swapBanks = FALSE;
2546 D (emitcode (";", "genCall "););
2548 /* if we are calling a not _naked function that is not using
2549 the same register bank then we need to save the
2550 destination registers on the stack */
2551 dtype = operandType (IC_LEFT (ic));
2552 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2553 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2554 IFFUNC_ISISR (currFunc->type))
2558 /* This is unexpected; the bank should have been saved in
2561 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2567 /* if caller saves & we have not saved then */
2571 /* if send set is not empty the assign */
2572 /* We've saved all the registers we care about;
2573 * therefore, we may clobber any register not used
2574 * in the calling convention (i.e. anything not in
2579 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2580 genSend(reverseSet(_G.sendSet));
2582 genSend(_G.sendSet);
2589 emitcode ("mov", "psw,#!constbyte",
2590 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2594 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2595 OP_SYMBOL (IC_LEFT (ic))->rname :
2596 OP_SYMBOL (IC_LEFT (ic))->name));
2600 emitcode ("mov", "psw,#!constbyte",
2601 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2604 /* if we need assign a result value */
2605 if ((IS_ITEMP (IC_RESULT (ic)) &&
2606 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2607 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2608 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2609 IS_TRUE_SYMOP (IC_RESULT (ic)))
2611 if (isOperandInFarSpace (IC_RESULT (ic))
2612 && getSize (operandType (IC_RESULT (ic))) <= 2)
2614 int size = getSize (operandType (IC_RESULT (ic)));
2616 /* Special case for 1 or 2 byte return in far space. */
2620 emitcode ("mov", "b,%s", fReturn[1]);
2623 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2624 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2628 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2630 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2635 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2638 assignResultValue (IC_RESULT (ic));
2640 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2644 /* adjust the stack for parameters if
2646 if (ic->parmBytes) {
2648 if (options.stack10bit) {
2649 if (ic->parmBytes <= 10) {
2650 emitcode(";","stack adjustment for parms");
2651 for (i=0; i < ic->parmBytes ; i++) {
2652 emitcode("pop","acc");
2656 emitcode ("clr","c");
2657 emitcode ("mov","a,sp");
2658 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2659 emitcode ("mov","sp,a");
2660 emitcode ("mov","a,esp");
2662 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2663 emitcode ("mov","esp,a");
2667 if (ic->parmBytes > 3) {
2668 emitcode ("mov", "a,%s", spname);
2669 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2670 emitcode ("mov", "%s,a", spname);
2672 for (i = 0; i < ic->parmBytes; i++)
2673 emitcode ("dec", "%s", spname);
2677 /* if we hade saved some registers then unsave them */
2679 unsaveRegisters (ic);
2681 /* if register bank was saved then pop them */
2683 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2686 /*-----------------------------------------------------------------*/
2687 /* genPcall - generates a call by pointer statement */
2688 /*-----------------------------------------------------------------*/
2690 genPcall (iCode * ic)
2693 symbol *rlbl = newiTempLabel (NULL);
2694 bool restoreBank=FALSE;
2696 D (emitcode (";", "genPcall ");
2700 /* if caller saves & we have not saved then */
2704 /* if we are calling a function that is not using
2705 the same register bank then we need to save the
2706 destination registers on the stack */
2707 dtype = operandType (IC_LEFT (ic));
2708 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2709 IFFUNC_ISISR (currFunc->type) &&
2710 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2711 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2715 /* push the return address on to the stack */
2716 emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2717 emitcode ("push", "acc");
2718 emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2719 emitcode ("push", "acc");
2721 if (options.model == MODEL_FLAT24)
2723 emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2724 emitcode ("push", "acc");
2727 /* now push the calling address */
2728 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2730 pushSide (IC_LEFT (ic), FPTRSIZE);
2732 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2734 /* if send set is not empty the assign */
2737 genSend(reverseSet(_G.sendSet));
2741 emitcode ("ret", "");
2742 emitcode ("", "!tlabeldef", (rlbl->key + 100));
2745 /* if we need assign a result value */
2746 if ((IS_ITEMP (IC_RESULT (ic)) &&
2747 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2748 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2749 IS_TRUE_SYMOP (IC_RESULT (ic)))
2753 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2756 assignResultValue (IC_RESULT (ic));
2758 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2761 /* adjust the stack for parameters if
2766 if (options.stack10bit) {
2767 if (ic->parmBytes <= 10) {
2768 emitcode(";","stack adjustment for parms");
2769 for (i=0; i < ic->parmBytes ; i++) {
2770 emitcode("pop","acc");
2774 emitcode ("clr","c");
2775 emitcode ("mov","a,sp");
2776 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2777 emitcode ("mov","sp,a");
2778 emitcode ("mov","a,esp");
2780 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2781 emitcode ("mov","esp,a");
2785 if (ic->parmBytes > 3) {
2786 emitcode ("mov", "a,%s", spname);
2787 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2788 emitcode ("mov", "%s,a", spname);
2791 for (i = 0; i < ic->parmBytes; i++)
2792 emitcode ("dec", "%s", spname);
2796 /* if register bank was saved then unsave them */
2798 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2800 /* if we hade saved some registers then
2803 unsaveRegisters (ic);
2807 /*-----------------------------------------------------------------*/
2808 /* resultRemat - result is rematerializable */
2809 /*-----------------------------------------------------------------*/
2811 resultRemat (iCode * ic)
2813 if (SKIP_IC (ic) || ic->op == IFX)
2816 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2818 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2819 if (sym->remat && !POINTER_SET (ic))
2826 #if defined(__BORLANDC__) || defined(_MSC_VER)
2827 #define STRCASECMP stricmp
2829 #define STRCASECMP strcasecmp
2832 /*-----------------------------------------------------------------*/
2833 /* inExcludeList - return 1 if the string is in exclude Reg list */
2834 /*-----------------------------------------------------------------*/
2836 regsCmp(void *p1, void *p2)
2838 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2842 inExcludeList (char *s)
2844 const char *p = setFirstItem(options.excludeRegsSet);
2846 if (p == NULL || STRCASECMP(p, "none") == 0)
2850 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2853 /*-----------------------------------------------------------------*/
2854 /* genFunction - generated code for function entry */
2855 /*-----------------------------------------------------------------*/
2857 genFunction (iCode * ic)
2861 bool switchedPSW = FALSE;
2863 D (emitcode (";", "genFunction "););
2866 /* create the function header */
2867 emitcode (";", "-----------------------------------------");
2868 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2869 emitcode (";", "-----------------------------------------");
2871 emitcode ("", "%s:", sym->rname);
2872 ftype = operandType (IC_LEFT (ic));
2874 if (IFFUNC_ISNAKED(ftype))
2876 emitcode(";", "naked function: no prologue.");
2880 if (options.stack_probe)
2881 emitcode ("lcall","__stack_probe");
2882 /* if critical function then turn interrupts off */
2883 if (IFFUNC_ISCRITICAL (ftype))
2884 emitcode ("clr", "ea");
2886 /* here we need to generate the equates for the
2887 register bank if required */
2888 if (FUNC_REGBANK (ftype) != rbank)
2892 rbank = FUNC_REGBANK (ftype);
2893 for (i = 0; i < ds390_nRegs; i++)
2895 if (regs390[i].print) {
2896 if (strcmp (regs390[i].base, "0") == 0)
2897 emitcode ("", "%s !equ !constbyte",
2899 8 * rbank + regs390[i].offset);
2901 emitcode ("", "%s !equ %s + !constbyte",
2904 8 * rbank + regs390[i].offset);
2909 /* if this is an interrupt service routine then
2910 save acc, b, dpl, dph */
2911 if (IFFUNC_ISISR (sym->type))
2913 if (!inExcludeList ("acc"))
2914 emitcode ("push", "acc");
2915 if (!inExcludeList ("b"))
2916 emitcode ("push", "b");
2917 if (!inExcludeList ("dpl"))
2918 emitcode ("push", "dpl");
2919 if (!inExcludeList ("dph"))
2920 emitcode ("push", "dph");
2921 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2923 emitcode ("push", "dpx");
2924 /* Make sure we're using standard DPTR */
2925 emitcode ("push", "dps");
2926 emitcode ("mov", "dps,#0");
2927 if (options.stack10bit)
2929 /* This ISR could conceivably use DPTR2. Better save it. */
2930 emitcode ("push", "dpl1");
2931 emitcode ("push", "dph1");
2932 emitcode ("push", "dpx1");
2933 emitcode ("push", DP2_RESULT_REG);
2936 /* if this isr has no bank i.e. is going to
2937 run with bank 0 , then we need to save more
2939 if (!FUNC_REGBANK (sym->type))
2943 /* if this function does not call any other
2944 function then we can be economical and
2945 save only those registers that are used */
2946 if (!IFFUNC_HASFCALL(sym->type))
2949 /* if any registers used */
2952 /* save the registers used */
2953 for (i = 0; i < sym->regsUsed->size; i++)
2955 if (bitVectBitValue (sym->regsUsed, i) ||
2956 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2957 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2964 /* this function has a function call cannot
2965 determines register usage so we will have to push the
2967 saveRBank (0, ic, FALSE);
2968 if (options.parms_in_bank1) {
2969 for (i=0; i < 8 ; i++ ) {
2970 emitcode ("push","%s",rb1regs[i]);
2977 /* This ISR uses a non-zero bank.
2979 * We assume that the bank is available for our
2982 * However, if this ISR calls a function which uses some
2983 * other bank, we must save that bank entirely.
2985 unsigned long banksToSave = 0;
2987 if (IFFUNC_HASFCALL(sym->type))
2990 #define MAX_REGISTER_BANKS 4
2995 for (i = ic; i; i = i->next)
2997 if (i->op == ENDFUNCTION)
2999 /* we got to the end OK. */
3007 dtype = operandType (IC_LEFT(i));
3009 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3011 /* Mark this bank for saving. */
3012 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3014 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3018 banksToSave |= (1 << FUNC_REGBANK(dtype));
3021 /* And note that we don't need to do it in
3029 /* This is a mess; we have no idea what
3030 * register bank the called function might
3033 * The only thing I can think of to do is
3034 * throw a warning and hope.
3036 werror(W_FUNCPTR_IN_USING_ISR);
3040 if (banksToSave && options.useXstack)
3042 /* Since we aren't passing it an ic,
3043 * saveRBank will assume r0 is available to abuse.
3045 * So switch to our (trashable) bank now, so
3046 * the caller's R0 isn't trashed.
3048 emitcode ("push", "psw");
3049 emitcode ("mov", "psw,#!constbyte",
3050 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3054 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3056 if (banksToSave & (1 << ix))
3058 saveRBank(ix, NULL, FALSE);
3062 // TODO: this needs a closer look
3063 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3068 /* if callee-save to be used for this function
3069 then save the registers being used in this function */
3070 if (IFFUNC_CALLEESAVES(sym->type))
3074 /* if any registers used */
3077 /* save the registers used */
3078 for (i = 0; i < sym->regsUsed->size; i++)
3080 if (bitVectBitValue (sym->regsUsed, i) ||
3081 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3083 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3091 /* set the register bank to the desired value */
3092 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3095 emitcode ("push", "psw");
3096 emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3099 if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3100 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3101 if (options.stack10bit) {
3102 emitcode ("push","_bpx");
3103 emitcode ("push","_bpx+1");
3104 emitcode ("mov","_bpx,%s",spname);
3105 emitcode ("mov","_bpx+1,esp");
3106 adjustEsp("_bpx+1");
3108 if (options.useXstack) {
3109 emitcode ("mov", "r0,%s", spname);
3110 emitcode ("mov", "a,_bp");
3111 emitcode ("movx", "@r0,a");
3112 emitcode ("inc", "%s", spname);
3114 /* set up the stack */
3115 emitcode ("push", "_bp"); /* save the callers stack */
3117 emitcode ("mov", "_bp,%s", spname);
3121 /* adjust the stack for the function */
3124 if (options.stack10bit) {
3125 if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
3126 assert (sym->recvSize <= 4);
3127 if (sym->stack <= 8) {
3128 while (i--) emitcode ("push","acc");
3131 emitcode ("mov","a,sp");
3132 emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3133 emitcode ("mov","sp,a");
3134 emitcode ("mov","a,esp");
3136 emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3137 emitcode ("mov","esp,a");
3142 werror (W_STACK_OVERFLOW, sym->name);
3144 if (i > 3 && sym->recvSize < 4) {
3146 emitcode ("mov", "a,sp");
3147 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3148 emitcode ("mov", "sp,a");
3152 emitcode ("inc", "sp");
3159 emitcode ("mov", "a,_spx");
3160 emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3161 emitcode ("mov", "_spx,a");
3166 /*-----------------------------------------------------------------*/
3167 /* genEndFunction - generates epilogue for functions */
3168 /*-----------------------------------------------------------------*/
3170 genEndFunction (iCode * ic)
3172 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3174 D (emitcode (";", "genEndFunction "););
3176 if (IFFUNC_ISNAKED(sym->type))
3178 emitcode(";", "naked function: no epilogue.");
3182 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3183 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3185 if (options.stack10bit) {
3187 emitcode ("mov", "sp,_bpx", spname);
3188 emitcode ("mov", "esp,_bpx+1", spname);
3191 emitcode ("mov", "%s,_bp", spname);
3195 /* if use external stack but some variables were
3196 added to the local stack then decrement the
3198 if (options.useXstack && sym->stack) {
3199 emitcode ("mov", "a,sp");
3200 emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3201 emitcode ("mov", "sp,a");
3205 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3206 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3208 if (options.useXstack) {
3209 emitcode ("mov", "r0,%s", spname);
3210 emitcode ("movx", "a,@r0");
3211 emitcode ("mov", "_bp,a");
3212 emitcode ("dec", "%s", spname);
3214 if (options.stack10bit) {
3215 emitcode ("pop", "_bpx+1");
3216 emitcode ("pop", "_bpx");
3218 emitcode ("pop", "_bp");
3223 /* restore the register bank */
3224 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3226 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3227 || !options.useXstack)
3229 /* Special case of ISR using non-zero bank with useXstack
3232 emitcode ("pop", "psw");
3236 if (IFFUNC_ISISR (sym->type))
3239 /* now we need to restore the registers */
3240 /* if this isr has no bank i.e. is going to
3241 run with bank 0 , then we need to save more
3243 if (!FUNC_REGBANK (sym->type))
3246 /* if this function does not call any other
3247 function then we can be economical and
3248 save only those registers that are used */
3249 if (!IFFUNC_HASFCALL(sym->type))
3252 /* if any registers used */
3255 /* save the registers used */
3256 for (i = sym->regsUsed->size; i >= 0; i--)
3258 if (bitVectBitValue (sym->regsUsed, i) ||
3259 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3260 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3267 /* this function has a function call cannot
3268 determines register usage so we will have to pop the
3270 if (options.parms_in_bank1) {
3271 for (i = 7 ; i >= 0 ; i-- ) {
3272 emitcode ("pop","%s",rb1regs[i]);
3275 unsaveRBank (0, ic, FALSE);
3280 /* This ISR uses a non-zero bank.
3282 * Restore any register banks saved by genFunction
3285 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3288 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3290 if (savedBanks & (1 << ix))
3292 unsaveRBank(ix, NULL, FALSE);
3296 if (options.useXstack)
3298 /* Restore bank AFTER calling unsaveRBank,
3299 * since it can trash r0.
3301 emitcode ("pop", "psw");
3305 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3307 if (options.stack10bit)
3309 emitcode ("pop", DP2_RESULT_REG);
3310 emitcode ("pop", "dpx1");
3311 emitcode ("pop", "dph1");
3312 emitcode ("pop", "dpl1");
3314 emitcode ("pop", "dps");
3315 emitcode ("pop", "dpx");
3317 if (!inExcludeList ("dph"))
3318 emitcode ("pop", "dph");
3319 if (!inExcludeList ("dpl"))
3320 emitcode ("pop", "dpl");
3321 if (!inExcludeList ("b"))
3322 emitcode ("pop", "b");
3323 if (!inExcludeList ("acc"))
3324 emitcode ("pop", "acc");
3326 if (IFFUNC_ISCRITICAL (sym->type))
3327 emitcode ("setb", "ea");
3329 /* if debug then send end of function */
3330 if (options.debug && currFunc) {
3332 emitcode ("", "C$%s$%d$%d$%d ==.",
3333 FileBaseName (ic->filename), currFunc->lastLine,
3334 ic->level, ic->block);
3335 if (IS_STATIC (currFunc->etype))
3336 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3338 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3342 emitcode ("reti", "");
3346 if (IFFUNC_ISCRITICAL (sym->type))
3347 emitcode ("setb", "ea");
3349 if (IFFUNC_CALLEESAVES(sym->type))
3353 /* if any registers used */
3356 /* save the registers used */
3357 for (i = sym->regsUsed->size; i >= 0; i--)
3359 if (bitVectBitValue (sym->regsUsed, i) ||
3360 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3361 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3367 /* if debug then send end of function */
3368 if (options.debug && currFunc)
3371 emitcode ("", "C$%s$%d$%d$%d ==.",
3372 FileBaseName (ic->filename), currFunc->lastLine,
3373 ic->level, ic->block);
3374 if (IS_STATIC (currFunc->etype))
3375 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3377 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3381 emitcode ("ret", "");
3386 /*-----------------------------------------------------------------*/
3387 /* genJavaNativeRet - generate code for return JavaNative */
3388 /*-----------------------------------------------------------------*/
3389 static void genJavaNativeRet(iCode *ic)
3393 aopOp (IC_LEFT (ic), ic, FALSE,
3394 AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
3395 size = AOP_SIZE (IC_LEFT (ic));
3399 /* it is assigned to GPR0-R3 then push them */
3400 if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3401 aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3402 for (i = 0 ; i < size ; i++ ) {
3403 emitcode ("push","%s",
3404 aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3406 for (i = (size-1) ; i >= 0 ; i--) {
3407 emitcode ("pop","a%s",javaRet[i]);
3410 for (i = 0 ; i < size ; i++)
3411 emitcode ("mov","%s,%s",javaRet[i],
3412 aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3414 for (i = size ; i < 4 ; i++ )
3415 emitcode ("mov","%s,#0",javaRet[i]);
3419 /*-----------------------------------------------------------------*/
3420 /* genRet - generate code for return statement */
3421 /*-----------------------------------------------------------------*/
3425 int size, offset = 0, pushed = 0;
3427 D (emitcode (";", "genRet "););
3429 /* if we have no return value then
3430 just generate the "ret" */
3434 /* if this is a JavaNative function then return
3435 value in different register */
3436 if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3437 genJavaNativeRet(ic);
3440 /* we have something to return then
3441 move the return value into place */
3442 aopOp (IC_LEFT (ic), ic, FALSE,
3443 (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
3444 size = AOP_SIZE (IC_LEFT (ic));
3446 _startLazyDPSEvaluation ();
3450 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3452 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3454 emitcode ("push", "%s", l);
3459 /* Since A is the last element of fReturn,
3460 * is is OK to clobber it in the aopGet.
3462 l = aopGet (AOP (IC_LEFT (ic)), offset,
3463 FALSE, FALSE, NULL);
3464 if (strcmp (fReturn[offset], l))
3465 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3468 _endLazyDPSEvaluation ();
3475 if (strcmp (fReturn[pushed], "a"))
3476 emitcode ("pop", fReturn[pushed]);
3478 emitcode ("pop", "acc");
3481 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3484 /* generate a jump to the return label
3485 if the next is not the return statement */
3486 if (!(ic->next && ic->next->op == LABEL &&
3487 IC_LABEL (ic->next) == returnLabel))
3489 emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3493 /*-----------------------------------------------------------------*/
3494 /* genLabel - generates a label */
3495 /*-----------------------------------------------------------------*/
3497 genLabel (iCode * ic)
3499 /* special case never generate */
3500 if (IC_LABEL (ic) == entryLabel)
3503 D (emitcode (";", "genLabel ");
3506 emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3509 /*-----------------------------------------------------------------*/
3510 /* genGoto - generates a ljmp */
3511 /*-----------------------------------------------------------------*/
3513 genGoto (iCode * ic)
3515 D (emitcode (";", "genGoto ");
3517 emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3520 /*-----------------------------------------------------------------*/
3521 /* findLabelBackwards: walks back through the iCode chain looking */
3522 /* for the given label. Returns number of iCode instructions */
3523 /* between that label and given ic. */
3524 /* Returns zero if label not found. */
3525 /*-----------------------------------------------------------------*/
3527 findLabelBackwards (iCode * ic, int key)
3536 /* If we have any pushes or pops, we cannot predict the distance.
3537 I don't like this at all, this should be dealt with in the
3539 if (ic->op == IPUSH || ic->op == IPOP) {
3543 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3545 /* printf("findLabelBackwards = %d\n", count); */
3553 /*-----------------------------------------------------------------*/
3554 /* genPlusIncr :- does addition with increment if possible */
3555 /*-----------------------------------------------------------------*/
3557 genPlusIncr (iCode * ic)
3559 unsigned int icount;
3560 unsigned int size = getDataSize (IC_RESULT (ic));
3562 /* will try to generate an increment */
3563 /* if the right side is not a literal
3565 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3568 /* if the literal value of the right hand side
3569 is greater than 4 then it is not worth it */
3570 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3573 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3574 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3576 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
3580 /* if increment 16 bits in register */
3582 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3583 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3584 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3593 /* If the next instruction is a goto and the goto target
3594 * is <= 5 instructions previous to this, we can generate
3595 * jumps straight to that target.
3597 if (ic->next && ic->next->op == GOTO
3598 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3601 D(emitcode (";", "tail increment optimized (range %d)", labelRange););
3602 tlbl = IC_LABEL (ic->next);
3607 tlbl = newiTempLabel (NULL);
3611 l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
3612 emitcode ("inc", "%s", l);
3614 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3615 IS_AOP_PREG (IC_RESULT (ic)))
3617 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3621 emitcode ("clr", "a");
3622 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3625 l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
3626 emitcode ("inc", "%s", l);
3629 if (!strcmp(l, "acc"))
3631 emitcode("jnz", "!tlabel", tlbl->key + 100);
3633 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3634 IS_AOP_PREG (IC_RESULT (ic)))
3636 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3640 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3643 l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
3644 emitcode ("inc", "%s", l);
3648 if (!strcmp(l, "acc"))
3650 emitcode("jnz", "!tlabel", tlbl->key + 100);
3652 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3653 IS_AOP_PREG (IC_RESULT (ic)))
3655 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3659 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3662 l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
3663 emitcode ("inc", "%s", l); }
3667 emitcode ("", "!tlabeldef", tlbl->key + 100);
3672 if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3673 !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 &&
3674 options.model == MODEL_FLAT24 ) {
3678 emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, NULL));
3680 emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, NULL));
3682 emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3685 while (icount--) emitcode ("inc","dptr");
3689 if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3690 AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3692 emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3693 while (icount--) emitcode ("inc","dptr");
3694 emitcode ("mov","dps,#0");
3698 /* if the sizes are greater than 1 then we cannot */
3699 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3700 AOP_SIZE (IC_LEFT (ic)) > 1)
3703 /* we can if the aops of the left & result match or
3704 if they are in registers and the registers are the
3707 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3708 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3709 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3714 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3715 emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3716 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3721 _startLazyDPSEvaluation ();
3724 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3726 _endLazyDPSEvaluation ();
3735 /*-----------------------------------------------------------------*/
3736 /* outBitAcc - output a bit in acc */
3737 /*-----------------------------------------------------------------*/
3739 outBitAcc (operand * result)
3741 symbol *tlbl = newiTempLabel (NULL);
3742 /* if the result is a bit */
3743 if (AOP_TYPE (result) == AOP_CRY)
3745 aopPut (AOP (result), "a", 0);
3749 emitcode ("jz", "!tlabel", tlbl->key + 100);
3750 emitcode ("mov", "a,%s", one);
3751 emitcode ("", "!tlabeldef", tlbl->key + 100);
3756 /*-----------------------------------------------------------------*/
3757 /* genPlusBits - generates code for addition of two bits */
3758 /*-----------------------------------------------------------------*/
3760 genPlusBits (iCode * ic)
3762 D (emitcode (";", "genPlusBits "););
3764 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3766 symbol *lbl = newiTempLabel (NULL);
3767 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3768 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3769 emitcode ("cpl", "c");
3770 emitcode ("", "!tlabeldef", (lbl->key + 100));
3771 outBitC (IC_RESULT (ic));
3775 emitcode ("clr", "a");
3776 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3777 emitcode ("rlc", "a");
3778 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3779 emitcode ("addc", "a,#0");
3780 outAcc (IC_RESULT (ic));
3785 adjustArithmeticResult (iCode * ic)
3787 if (opIsGptr (IC_RESULT (ic)) &&
3788 opIsGptr (IC_LEFT (ic)) &&
3789 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3791 aopPut (AOP (IC_RESULT (ic)),
3792 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3796 if (opIsGptr (IC_RESULT (ic)) &&
3797 opIsGptr (IC_RIGHT (ic)) &&
3798 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3800 aopPut (AOP (IC_RESULT (ic)),
3801 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3805 if (opIsGptr (IC_RESULT (ic)) &&
3806 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3807 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3808 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3809 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3812 SNPRINTF (buff, sizeof(buff),
3813 "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3814 aopPut (AOP (IC_RESULT (ic)), buff, GPTRSIZE - 1);
3818 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
3819 // generates the result if possible. If result is generated, returns TRUE; otherwise
3820 // returns false and caller must deal with fact that result isn't aopOp'd.
3821 bool aopOp3(iCode * ic)
3823 bool dp1InUse, dp2InUse;
3826 // First, generate the right opcode. DPTR may be used if neither left nor result are
3829 // D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
3830 // AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
3831 // AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
3832 // AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
3834 // D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
3835 // AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
3836 // AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
3837 // AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
3840 // Right uses DPTR unless left or result is an AOP_STR; however,
3841 // if right is an AOP_STR, it must use DPTR regardless.
3842 if ((AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)))
3843 && !AOP_IS_STR(IC_RIGHT(ic)))
3852 aopOp (IC_RIGHT(ic),ic,FALSE, useDp2);
3854 // if the right used DPTR, left MUST use DPTR2.
3855 // if the right used DPTR2, left MUST use DPTR.
3856 // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
3857 // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
3858 // enabling us to assign DPTR to result.
3860 if (AOP_USESDPTR(IC_RIGHT(ic)))
3864 else if (AOP_USESDPTR2(IC_RIGHT(ic)))
3870 if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
3880 aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
3882 // We've op'd the left & right. So, if left or right are the same operand as result,
3883 // we know aopOp will succeed, and we can just do it & bail.
3884 if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)) ||
3885 isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
3887 // D(emitcode(";", "aopOp3: (left | right) & result equal"););
3888 aopOp(IC_RESULT(ic),ic,TRUE, FALSE);
3892 // Note which dptrs are currently in use.
3893 dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
3894 dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
3896 // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot
3898 if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
3903 // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
3904 if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
3909 // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck
3910 if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
3915 aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
3917 // Some sanity checking...
3918 if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
3921 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
3922 __FILE__, __LINE__, ic->filename, ic->lineno);
3923 emitcode(";", ">>> unexpected DPTR here.");
3926 if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
3929 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
3930 __FILE__, __LINE__, ic->filename, ic->lineno);
3931 emitcode(";", ">>> unexpected DPTR2 here.");
3937 // Macro to aopOp all three operands of an ic. If this cannot be done,
3938 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3939 // will be set TRUE. The caller must then handle the case specially, noting
3940 // that the IC_RESULT operand is not aopOp'd.
3942 #define AOP_OP_3_NOFATAL(ic, rc) \
3943 do { rc = !aopOp3(ic); } while (0)
3945 // aopOp the left & right operands of an ic.
3946 #define AOP_OP_2(ic) \
3947 aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
3948 aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
3950 // convienience macro.
3951 #define AOP_SET_LOCALS(ic) \
3952 left = IC_LEFT(ic); \
3953 right = IC_RIGHT(ic); \
3954 result = IC_RESULT(ic);
3957 // Given an integer value of pushedSize bytes on the stack,
3958 // adjust it to be resultSize bytes, either by discarding
3959 // the most significant bytes or by zero-padding.
3961 // On exit from this macro, pushedSize will have been adjusted to
3962 // equal resultSize, and ACC may be trashed.
3963 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3964 /* If the pushed data is bigger than the result, \
3965 * simply discard unused bytes. Icky, but works. \
3967 while (pushedSize > resultSize) \
3969 D (emitcode (";", "discarding unused result byte."););\
3970 emitcode ("pop", "acc"); \
3973 if (pushedSize < resultSize) \
3975 emitcode ("clr", "a"); \
3976 /* Conversly, we haven't pushed enough here. \
3977 * just zero-pad, and all is well. \
3979 while (pushedSize < resultSize) \
3981 emitcode("push", "acc"); \
3985 assert(pushedSize == resultSize);
3987 /*-----------------------------------------------------------------*/
3988 /* genPlus - generates code for addition */
3989 /*-----------------------------------------------------------------*/
3991 genPlus (iCode * ic)
3993 int size, offset = 0;
3997 D (emitcode (";", "genPlus "););
3999 /* special cases :- */
4000 if ( AOP_IS_STR(IC_LEFT(ic)) &&
4001 isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
4002 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
4003 size = (int)floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
4005 while (size--) emitcode ("inc","dptr");
4007 emitcode ("mov","a,dpl");
4008 emitcode ("add","a,#!constbyte",size & 0xff);
4009 emitcode ("mov","dpl,a");
4010 emitcode ("mov","a,dph");
4011 emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
4012 emitcode ("mov","dph,a");
4013 emitcode ("mov","a,dpx");
4014 emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
4015 emitcode ("mov","dpx,a");
4017 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
4020 if ( IS_SYMOP(IC_LEFT(ic)) &&
4021 OP_SYMBOL(IC_LEFT(ic))->remat &&
4022 isOperandInFarSpace(IC_RIGHT(ic))) {
4023 operand *op = IC_RIGHT(ic);
4024 IC_RIGHT(ic) = IC_LEFT(ic);
4028 AOP_OP_3_NOFATAL (ic, pushResult);
4032 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
4037 /* if literal, literal on the right or
4038 if left requires ACC or right is already
4040 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4041 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
4042 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4044 operand *t = IC_RIGHT (ic);
4045 IC_RIGHT (ic) = IC_LEFT (ic);
4047 emitcode (";", "Swapped plus args.");
4050 /* if both left & right are in bit
4052 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4053 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4059 /* if left in bit space & right literal */
4060 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4061 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4063 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4064 /* if result in bit space */
4065 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4067 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4068 emitcode ("cpl", "c");
4069 outBitC (IC_RESULT (ic));
4073 size = getDataSize (IC_RESULT (ic));
4074 _startLazyDPSEvaluation ();
4077 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4078 emitcode ("addc", "a,#0");
4079 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4081 _endLazyDPSEvaluation ();
4086 /* if I can do an increment instead
4087 of add then GOOD for ME */
4088 if (genPlusIncr (ic) == TRUE)
4090 emitcode (";", "did genPlusIncr");
4095 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4097 _startLazyDPSEvaluation ();
4100 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4102 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4104 emitcode ("add", "a,%s",
4105 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4107 emitcode ("addc", "a,%s",
4108 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4112 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4114 /* right is going to use ACC or we would have taken the
4117 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4119 D(emitcode(";", "+ AOP_ACC special case."););
4120 emitcode("xch", "a, %s", DP2_RESULT_REG);
4122 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4125 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4128 emitcode("add", "a, %s", DP2_RESULT_REG);
4132 emitcode ("add", "a,%s",
4133 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE,
4139 emitcode ("addc", "a,%s",
4140 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE,
4146 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4150 emitcode ("push", "acc");
4154 _endLazyDPSEvaluation ();
4158 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4160 size = getDataSize (IC_LEFT (ic));
4161 rSize = getDataSize (IC_RESULT (ic));
4163 ADJUST_PUSHED_RESULT(size, rSize);
4165 _startLazyDPSEvaluation ();
4168 emitcode ("pop", "acc");
4169 aopPut (AOP (IC_RESULT (ic)), "a", size);
4171 _endLazyDPSEvaluation ();
4174 adjustArithmeticResult (ic);
4177 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4178 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4179 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4182 /*-----------------------------------------------------------------*/
4183 /* genMinusDec :- does subtraction with deccrement if possible */
4184 /*-----------------------------------------------------------------*/
4186 genMinusDec (iCode * ic)
4188 unsigned int icount;
4189 unsigned int size = getDataSize (IC_RESULT (ic));
4191 /* will try to generate an increment */
4192 /* if the right side is not a literal
4194 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4197 /* if the literal value of the right hand side
4198 is greater than 4 then it is not worth it */
4199 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4202 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4203 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4205 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
4209 /* if decrement 16 bits in register */
4210 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4211 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4212 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4221 /* If the next instruction is a goto and the goto target
4222 * is <= 5 instructions previous to this, we can generate
4223 * jumps straight to that target.
4225 if (ic->next && ic->next->op == GOTO
4226 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4229 emitcode (";", "tail decrement optimized (range %d)", labelRange);
4230 tlbl = IC_LABEL (ic->next);
4235 tlbl = newiTempLabel (NULL);
4239 l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
4240 emitcode ("dec", "%s", l);
4242 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4243 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4244 IS_AOP_PREG (IC_RESULT (ic)))
4246 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4250 emitcode ("mov", "a,#!constbyte",0xff);
4251 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4253 l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
4254 emitcode ("dec", "%s", l);
4257 if (!strcmp(l, "acc"))
4259 emitcode("jnz", "!tlabel", tlbl->key + 100);
4261 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4262 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4263 IS_AOP_PREG (IC_RESULT (ic)))
4265 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4269 emitcode ("mov", "a,#!constbyte",0xff);
4270 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4272 l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
4273 emitcode ("dec", "%s", l);
4277 if (!strcmp(l, "acc"))
4279 emitcode("jnz", "!tlabel", tlbl->key + 100);
4281 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4282 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4283 IS_AOP_PREG (IC_RESULT (ic)))
4285 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4289 emitcode ("mov", "a,#!constbyte",0xff);
4290 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4292 l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
4293 emitcode ("dec", "%s", l);
4297 emitcode ("", "!tlabeldef", tlbl->key + 100);
4302 /* if the sizes are greater than 1 then we cannot */
4303 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4304 AOP_SIZE (IC_LEFT (ic)) > 1)
4307 /* we can if the aops of the left & result match or
4308 if they are in registers and the registers are the
4311 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4312 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4313 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4316 _startLazyDPSEvaluation ();
4319 emitcode ("dec", "%s",
4320 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
4322 _endLazyDPSEvaluation ();
4330 /*-----------------------------------------------------------------*/
4331 /* addSign - complete with sign */
4332 /*-----------------------------------------------------------------*/
4334 addSign (operand * result, int offset, int sign)
4336 int size = (getDataSize (result) - offset);
4339 _startLazyDPSEvaluation();
4342 emitcode ("rlc", "a");
4343 emitcode ("subb", "a,acc");
4346 aopPut (AOP (result), "a", offset++);
4353 aopPut (AOP (result), zero, offset++);
4356 _endLazyDPSEvaluation();
4360 /*-----------------------------------------------------------------*/
4361 /* genMinusBits - generates code for subtraction of two bits */
4362 /*-----------------------------------------------------------------*/
4364 genMinusBits (iCode * ic)
4366 symbol *lbl = newiTempLabel (NULL);
4368 D (emitcode (";", "genMinusBits "););
4370 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4372 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4373 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4374 emitcode ("cpl", "c");
4375 emitcode ("", "!tlabeldef", (lbl->key + 100));
4376 outBitC (IC_RESULT (ic));
4380 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4381 emitcode ("subb", "a,acc");
4382 emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4383 emitcode ("inc", "a");
4384 emitcode ("", "!tlabeldef", (lbl->key + 100));
4385 aopPut (AOP (IC_RESULT (ic)), "a", 0);
4386 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4390 /*-----------------------------------------------------------------*/
4391 /* genMinus - generates code for subtraction */
4392 /*-----------------------------------------------------------------*/
4394 genMinus (iCode * ic)
4396 int size, offset = 0;
4401 D (emitcode (";", "genMinus "););
4403 AOP_OP_3_NOFATAL(ic, pushResult);
4407 /* special cases :- */
4408 /* if both left & right are in bit space */
4409 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4410 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4416 /* if I can do an decrement instead
4417 of subtract then GOOD for ME */
4418 if (genMinusDec (ic) == TRUE)
4423 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4425 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4431 lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4436 /* if literal, add a,#-lit, else normal subb */
4437 _startLazyDPSEvaluation ();
4439 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4440 if (AOP_USESDPTR(IC_RIGHT(ic))) {
4441 emitcode ("mov","b,%s",
4442 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4443 MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4444 emitcode ("subb","a,b");
4446 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4447 emitcode ("subb", "a,%s",
4448 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE,
4452 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4453 /* first add without previous c */
4455 if (!size && lit==-1) {
4456 emitcode ("dec", "a");
4458 emitcode ("add", "a,#!constbyte",
4459 (unsigned int) (lit & 0x0FFL));
4462 emitcode ("addc", "a,#!constbyte",
4463 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4468 emitcode ("push", "acc");
4470 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4474 _endLazyDPSEvaluation ();
4478 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4480 size = getDataSize (IC_LEFT (ic));
4481 rSize = getDataSize (IC_RESULT (ic));
4483 ADJUST_PUSHED_RESULT(size, rSize);
4485 _startLazyDPSEvaluation ();
4488 emitcode ("pop", "acc");
4489 aopPut (AOP (IC_RESULT (ic)), "a", size);
4491 _endLazyDPSEvaluation ();
4494 adjustArithmeticResult (ic);
4497 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4498 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4499 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4503 /*-----------------------------------------------------------------*/
4504 /* genMultbits :- multiplication of bits */
4505 /*-----------------------------------------------------------------*/
4507 genMultbits (operand * left,
4512 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4513 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4514 aopOp(result, ic, TRUE, FALSE);
4519 /*-----------------------------------------------------------------*/
4520 /* genMultOneByte : 8*8=8/16 bit multiplication */
4521 /*-----------------------------------------------------------------*/
4523 genMultOneByte (operand * left,
4528 sym_link *opetype = operandType (result);
4532 /* (if two literals: the value is computed before) */
4533 /* if one literal, literal on the right */
4534 if (AOP_TYPE (left) == AOP_LIT)
4539 emitcode (";", "swapped left and right");
4542 if (SPEC_USIGN(opetype)
4543 // ignore the sign of left and right, what else can we do?
4544 || (SPEC_USIGN(operandType(left)) &&
4545 SPEC_USIGN(operandType(right)))) {
4546 // just an unsigned 8*8=8/16 multiply
4547 //emitcode (";","unsigned");
4548 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4549 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4550 emitcode ("mul", "ab");
4552 _G.accInUse++; _G.bInUse++;
4553 aopOp(result, ic, TRUE, FALSE);
4555 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4557 // this should never happen
4558 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4559 AOP_SIZE(result), __FILE__, lineno);
4563 aopPut (AOP (result), "a", 0);
4564 _G.accInUse--; _G.bInUse--;
4565 if (AOP_SIZE(result)==2)
4567 aopPut (AOP (result), "b", 1);
4572 // we have to do a signed multiply
4574 emitcode (";", "signed");
4575 emitcode ("clr", "F0"); // reset sign flag
4576 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4578 lbl=newiTempLabel(NULL);
4579 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4580 // left side is negative, 8-bit two's complement, this fails for -128
4581 emitcode ("setb", "F0"); // set sign flag
4582 emitcode ("cpl", "a");
4583 emitcode ("inc", "a");
4585 emitcode ("", "!tlabeldef", lbl->key+100);
4588 if (AOP_TYPE(right)==AOP_LIT) {
4589 signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
4590 /* AND literal negative */
4591 if ((int) val < 0) {
4592 emitcode ("cpl", "F0"); // complement sign flag
4593 emitcode ("mov", "b,#!constbyte", -val);
4595 emitcode ("mov", "b,#!constbyte", val);
4598 lbl=newiTempLabel(NULL);
4599 emitcode ("mov", "b,a");
4600 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4601 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4602 // right side is negative, 8-bit two's complement
4603 emitcode ("cpl", "F0"); // complement sign flag
4604 emitcode ("cpl", "a");
4605 emitcode ("inc", "a");
4606 emitcode ("", "!tlabeldef", lbl->key+100);
4608 emitcode ("mul", "ab");
4610 _G.accInUse++;_G.bInUse++;
4611 aopOp(result, ic, TRUE, FALSE);
4613 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4615 // this should never happen
4616 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4617 AOP_SIZE(result), __FILE__, lineno);
4621 lbl=newiTempLabel(NULL);
4622 emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4623 // only ONE op was negative, we have to do a 8/16-bit two's complement
4624 emitcode ("cpl", "a"); // lsb
4625 if (AOP_SIZE(result)==1) {
4626 emitcode ("inc", "a");
4628 emitcode ("add", "a,#1");
4629 emitcode ("xch", "a,b");
4630 emitcode ("cpl", "a"); // msb
4631 emitcode ("addc", "a,#0");
4632 emitcode ("xch", "a,b");
4635 emitcode ("", "!tlabeldef", lbl->key+100);
4636 aopPut (AOP (result), "a", 0);
4637 _G.accInUse--;_G.bInUse--;
4638 if (AOP_SIZE(result)==2) {
4639 aopPut (AOP (result), "b", 1);
4643 /*-----------------------------------------------------------------*/
4644 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
4645 /*-----------------------------------------------------------------*/
4646 static void genMultTwoByte (operand *left, operand *right,
4647 operand *result, iCode *ic)
4649 sym_link *retype = getSpec(operandType(right));
4650 sym_link *letype = getSpec(operandType(left));
4651 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4654 if (AOP_TYPE (left) == AOP_LIT) {
4659 /* save EA bit in F1 */
4660 lbl = newiTempLabel(NULL);
4661 emitcode ("setb","F1");
4662 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4663 emitcode ("clr","F1");
4664 emitcode("","!tlabeldef",lbl->key+100);
4666 /* load up MB with right */
4668 emitcode("clr","F0");
4669 if (AOP_TYPE(right) == AOP_LIT) {
4670 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
4672 emitcode("setb","F0");
4675 emitcode ("mov","mb,#!constbyte",val & 0xff);
4676 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4678 lbl = newiTempLabel(NULL);
4679 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4680 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4681 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4682 emitcode ("xch", "a,b");
4683 emitcode ("cpl","a");
4684 emitcode ("add", "a,#1");
4685 emitcode ("xch", "a,b");
4686 emitcode ("cpl", "a"); // msb
4687 emitcode ("addc", "a,#0");
4688 emitcode ("setb","F0");
4689 emitcode ("","!tlabeldef",lbl->key+100);
4690 emitcode ("mov","mb,b");
4691 emitcode ("mov","mb,a");
4694 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4695 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4697 /* load up MA with left */
4699 lbl = newiTempLabel(NULL);
4700 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4701 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4702 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4703 emitcode ("xch", "a,b");
4704 emitcode ("cpl","a");
4705 emitcode ("add", "a,#1");
4706 emitcode ("xch", "a,b");
4707 emitcode ("cpl", "a"); // msb
4708 emitcode ("addc","a,#0");
4709 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4710 emitcode ("setb","F0");
4711 emitcode ("","!tlabeldef",lbl->key+100);
4712 emitcode ("mov","ma,b");
4713 emitcode ("mov","ma,a");
4715 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4716 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4718 /* wait for multiplication to finish */
4719 lbl = newiTempLabel(NULL);
4720 emitcode("","!tlabeldef", lbl->key+100);
4721 emitcode("mov","a,mcnt1");
4722 emitcode("anl","a,#!constbyte",0x80);
4723 emitcode("jnz","!tlabel",lbl->key+100);
4725 freeAsmop (left, NULL, ic, TRUE);
4726 freeAsmop (right, NULL, ic,TRUE);
4727 aopOp(result, ic, TRUE, FALSE);
4729 /* if unsigned then simple */
4731 emitcode ("mov","a,ma");
4732 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4733 emitcode ("mov","a,ma");
4734 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4735 aopPut(AOP(result),"ma",1);
4736 aopPut(AOP(result),"ma",0);
4738 emitcode("push","ma");
4739 emitcode("push","ma");
4740 emitcode("push","ma");
4742 /* negate result if needed */
4743 lbl = newiTempLabel(NULL);
4744 emitcode("jnb","F0,!tlabel",lbl->key+100);
4745 emitcode("cpl","a");
4746 emitcode("add","a,#1");
4747 emitcode("","!tlabeldef", lbl->key+100);
4748 if (AOP_TYPE(result) == AOP_ACC)
4750 D(emitcode(";", "ACC special case."););
4751 /* We know result is the only live aop, and
4752 * it's obviously not a DPTR2, so AP is available.
4754 emitcode("mov", "%s,acc", DP2_RESULT_REG);
4758 aopPut(AOP(result),"a",0);
4761 emitcode("pop","acc");
4762 lbl = newiTempLabel(NULL);
4763 emitcode("jnb","F0,!tlabel",lbl->key+100);
4764 emitcode("cpl","a");
4765 emitcode("addc","a,#0");
4766 emitcode("","!tlabeldef", lbl->key+100);
4767 aopPut(AOP(result),"a",1);
4768 emitcode("pop","acc");
4769 if (AOP_SIZE(result) >= 3) {
4770 lbl = newiTempLabel(NULL);
4771 emitcode("jnb","F0,!tlabel",lbl->key+100);
4772 emitcode("cpl","a");
4773 emitcode("addc","a,#0");
4774 emitcode("","!tlabeldef", lbl->key+100);
4775 aopPut(AOP(result),"a",2);
4777 emitcode("pop","acc");
4778 if (AOP_SIZE(result) >= 4) {
4779 lbl = newiTempLabel(NULL);
4780 emitcode("jnb","F0,!tlabel",lbl->key+100);
4781 emitcode("cpl","a");
4782 emitcode("addc","a,#0");
4783 emitcode("","!tlabeldef", lbl->key+100);
4784 aopPut(AOP(result),"a",3);
4786 if (AOP_TYPE(result) == AOP_ACC)
4788 /* We stashed the result away above. */
4789 emitcode("mov", "acc,%s", DP2_RESULT_REG);
4793 freeAsmop (result, NULL, ic, TRUE);
4795 /* restore EA bit in F1 */
4796 lbl = newiTempLabel(NULL);
4797 emitcode ("jnb","F1,!tlabel",lbl->key+100);
4798 emitcode ("setb","EA");
4799 emitcode("","!tlabeldef",lbl->key+100);
4803 /*-----------------------------------------------------------------*/
4804 /* genMult - generates code for multiplication */
4805 /*-----------------------------------------------------------------*/
4807 genMult (iCode * ic)
4809 operand *left = IC_LEFT (ic);
4810 operand *right = IC_RIGHT (ic);
4811 operand *result = IC_RESULT (ic);
4813 D (emitcode (";", "genMult "););
4815 /* assign the amsops */
4818 /* special cases first */
4820 if (AOP_TYPE (left) == AOP_CRY &&
4821 AOP_TYPE (right) == AOP_CRY)
4823 genMultbits (left, right, result, ic);
4827 /* if both are of size == 1 */
4828 if (AOP_SIZE (left) == 1 &&
4829 AOP_SIZE (right) == 1)
4831 genMultOneByte (left, right, result, ic);
4835 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4836 /* use the ds390 ARITHMETIC accel UNIT */
4837 genMultTwoByte (left, right, result, ic);
4840 /* should have been converted to function call */
4844 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4845 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4846 freeAsmop (result, NULL, ic, TRUE);
4849 /*-----------------------------------------------------------------*/
4850 /* genDivbits :- division of bits */
4851 /*-----------------------------------------------------------------*/
4853 genDivbits (operand * left,
4861 /* the result must be bit */
4862 LOAD_AB_FOR_DIV (left, right, l);
4863 emitcode ("div", "ab");
4864 emitcode ("rrc", "a");
4865 aopOp(result, ic, TRUE, FALSE);
4867 aopPut (AOP (result), "c", 0);
4870 /*-----------------------------------------------------------------*/
4871 /* genDivOneByte : 8 bit division */
4872 /*-----------------------------------------------------------------*/
4874 genDivOneByte (operand * left,
4879 sym_link *opetype = operandType (result);
4885 /* signed or unsigned */
4886 if (SPEC_USIGN (opetype))
4888 /* unsigned is easy */
4889 LOAD_AB_FOR_DIV (left, right, l);
4890 emitcode ("div", "ab");
4893 aopOp(result, ic, TRUE, FALSE);
4894 aopPut (AOP (result), "a", 0);
4897 size = AOP_SIZE (result) - 1;
4901 aopPut (AOP (result), zero, offset++);
4906 /* signed is a little bit more difficult */
4908 /* save the signs of the operands */
4909 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4910 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4911 emitcode ("push", "acc"); /* save it on the stack */
4913 /* now sign adjust for both left & right */
4914 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4915 lbl = newiTempLabel (NULL);
4916 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4917 emitcode ("cpl", "a");
4918 emitcode ("inc", "a");
4919 emitcode ("", "!tlabeldef", (lbl->key + 100));
4920 emitcode ("mov", "b,a");
4922 /* sign adjust left side */
4923 MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4925 lbl = newiTempLabel (NULL);
4926 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4927 emitcode ("cpl", "a");
4928 emitcode ("inc", "a");
4929 emitcode ("", "!tlabeldef", (lbl->key + 100));
4931 /* now the division */
4932 emitcode ("nop", "; workaround for DS80C390 div bug.");
4933 emitcode ("div", "ab");
4934 /* we are interested in the lower order
4936 emitcode ("mov", "b,a");
4937 lbl = newiTempLabel (NULL);
4938 emitcode ("pop", "acc");
4939 /* if there was an over flow we don't
4940 adjust the sign of the result */
4941 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4942 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4944 emitcode ("clr", "a");
4945 emitcode ("subb", "a,b");
4946 emitcode ("mov", "b,a");
4947 emitcode ("", "!tlabeldef", (lbl->key + 100));
4949 /* now we are done */
4950 _G.accInUse++; _G.bInUse++;
4951 aopOp(result, ic, TRUE, FALSE);
4953 aopPut (AOP (result), "b", 0);
4955 size = AOP_SIZE (result) - 1;
4959 emitcode ("mov", "c,b.7");
4960 emitcode ("subb", "a,acc");
4964 aopPut (AOP (result), "a", offset++);
4966 _G.accInUse--; _G.bInUse--;
4970 /*-----------------------------------------------------------------*/
4971 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
4972 /*-----------------------------------------------------------------*/
4973 static void genDivTwoByte (operand *left, operand *right,
4974 operand *result, iCode *ic)
4976 sym_link *retype = getSpec(operandType(right));
4977 sym_link *letype = getSpec(operandType(left));
4978 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4981 /* save EA bit in F1 */
4982 lbl = newiTempLabel(NULL);
4983 emitcode ("setb","F1");
4984 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4985 emitcode ("clr","F1");
4986 emitcode("","!tlabeldef",lbl->key+100);
4988 /* load up MA with left */
4990 emitcode("clr","F0");
4991 lbl = newiTempLabel(NULL);
4992 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4993 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4994 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4995 emitcode ("xch", "a,b");
4996 emitcode ("cpl","a");
4997 emitcode ("add", "a,#1");
4998 emitcode ("xch", "a,b");
4999 emitcode ("cpl", "a"); // msb
5000 emitcode ("addc","a,#0");
5001 emitcode ("setb","F0");
5002 emitcode ("","!tlabeldef",lbl->key+100);
5003 emitcode ("mov","ma,b");
5004 emitcode ("mov","ma,a");
5006 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5007 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5010 /* load up MB with right */
5012 if (AOP_TYPE(right) == AOP_LIT) {
5013 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5015 lbl = newiTempLabel(NULL);
5016 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5017 emitcode("setb","F0");
5018 emitcode ("","!tlabeldef",lbl->key+100);
5021 emitcode ("mov","mb,#!constbyte",val & 0xff);
5022 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5024 lbl = newiTempLabel(NULL);
5025 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5026 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5027 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5028 emitcode ("xch", "a,b");
5029 emitcode ("cpl","a");
5030 emitcode ("add", "a,#1");
5031 emitcode ("xch", "a,b");
5032 emitcode ("cpl", "a"); // msb
5033 emitcode ("addc", "a,#0");
5034 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5035 emitcode ("setb","F0");
5036 emitcode ("","!tlabeldef",lbl->key+100);
5037 emitcode ("mov","mb,b");
5038 emitcode ("mov","mb,a");
5041 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5042 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5045 /* wait for multiplication to finish */
5046 lbl = newiTempLabel(NULL);
5047 emitcode("","!tlabeldef", lbl->key+100);
5048 emitcode("mov","a,mcnt1");
5049 emitcode("anl","a,#!constbyte",0x80);
5050 emitcode("jnz","!tlabel",lbl->key+100);
5052 freeAsmop (left, NULL, ic, TRUE);
5053 freeAsmop (right, NULL, ic,TRUE);
5054 aopOp(result, ic, TRUE, FALSE);
5056 /* if unsigned then simple */
5058 aopPut(AOP(result),"ma",1);
5059 aopPut(AOP(result),"ma",0);
5061 emitcode("push","ma");
5063 /* negate result if needed */
5064 lbl = newiTempLabel(NULL);
5065 emitcode("jnb","F0,!tlabel",lbl->key+100);
5066 emitcode("cpl","a");
5067 emitcode("add","a,#1");
5068 emitcode("","!tlabeldef", lbl->key+100);
5069 aopPut(AOP(result),"a",0);
5070 emitcode("pop","acc");
5071 lbl = newiTempLabel(NULL);
5072 emitcode("jnb","F0,!tlabel",lbl->key+100);
5073 emitcode("cpl","a");
5074 emitcode("addc","a,#0");
5075 emitcode("","!tlabeldef", lbl->key+100);
5076 aopPut(AOP(result),"a",1);
5078 freeAsmop (result, NULL, ic, TRUE);
5079 /* restore EA bit in F1 */
5080 lbl = newiTempLabel(NULL);
5081 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5082 emitcode ("setb","EA");
5083 emitcode("","!tlabeldef",lbl->key+100);
5087 /*-----------------------------------------------------------------*/
5088 /* genDiv - generates code for division */
5089 /*-----------------------------------------------------------------*/
5093 operand *left = IC_LEFT (ic);
5094 operand *right = IC_RIGHT (ic);
5095 operand *result = IC_RESULT (ic);
5097 D (emitcode (";", "genDiv "););
5099 /* assign the amsops */
5102 /* special cases first */
5104 if (AOP_TYPE (left) == AOP_CRY &&
5105 AOP_TYPE (right) == AOP_CRY)
5107 genDivbits (left, right, result, ic);
5111 /* if both are of size == 1 */
5112 if (AOP_SIZE (left) == 1 &&
5113 AOP_SIZE (right) == 1)
5115 genDivOneByte (left, right, result, ic);
5119 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5120 /* use the ds390 ARITHMETIC accel UNIT */
5121 genDivTwoByte (left, right, result, ic);
5124 /* should have been converted to function call */
5127 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5128 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5129 freeAsmop (result, NULL, ic, TRUE);
5132 /*-----------------------------------------------------------------*/
5133 /* genModbits :- modulus of bits */
5134 /*-----------------------------------------------------------------*/
5136 genModbits (operand * left,
5144 /* the result must be bit */
5145 LOAD_AB_FOR_DIV (left, right, l);
5146 emitcode ("div", "ab");
5147 emitcode ("mov", "a,b");
5148 emitcode ("rrc", "a");
5149 aopOp(result, ic, TRUE, FALSE);
5150 aopPut (AOP (result), "c", 0);
5153 /*-----------------------------------------------------------------*/
5154 /* genModOneByte : 8 bit modulus */
5155 /*-----------------------------------------------------------------*/
5157 genModOneByte (operand * left,
5162 sym_link *opetype = operandType (result);
5166 /* signed or unsigned */
5167 if (SPEC_USIGN (opetype))
5169 /* unsigned is easy */
5170 LOAD_AB_FOR_DIV (left, right, l);
5171 emitcode ("div", "ab");
5172 aopOp(result, ic, TRUE, FALSE);
5173 aopPut (AOP (result), "b", 0);
5177 /* signed is a little bit more difficult */
5179 /* save the signs of the operands */
5180 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5182 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
5183 emitcode ("push", "acc"); /* save it on the stack */
5185 /* now sign adjust for both left & right */
5186 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5188 lbl = newiTempLabel (NULL);
5189 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5190 emitcode ("cpl", "a");
5191 emitcode ("inc", "a");
5192 emitcode ("", "!tlabeldef", (lbl->key + 100));
5193 emitcode ("mov", "b,a");
5195 /* sign adjust left side */
5196 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5198 lbl = newiTempLabel (NULL);
5199 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5200 emitcode ("cpl", "a");
5201 emitcode ("inc", "a");
5202 emitcode ("", "!tlabeldef", (lbl->key + 100));
5204 /* now the multiplication */
5205 emitcode ("nop", "; workaround for DS80C390 div bug.");
5206 emitcode ("div", "ab");
5207 /* we are interested in the lower order
5209 lbl = newiTempLabel (NULL);
5210 emitcode ("pop", "acc");
5211 /* if there was an over flow we don't
5212 adjust the sign of the result */
5213 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
5214 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5216 emitcode ("clr", "a");
5217 emitcode ("subb", "a,b");
5218 emitcode ("mov", "b,a");
5219 emitcode ("", "!tlabeldef", (lbl->key + 100));
5222 /* now we are done */
5223 aopOp(result, ic, TRUE, FALSE);
5224 aopPut (AOP (result), "b", 0);
5229 /*-----------------------------------------------------------------*/
5230 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
5231 /*-----------------------------------------------------------------*/
5232 static void genModTwoByte (operand *left, operand *right,
5233 operand *result, iCode *ic)
5235 sym_link *retype = getSpec(operandType(right));
5236 sym_link *letype = getSpec(operandType(left));
5237 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5240 /* load up MA with left */
5241 /* save EA bit in F1 */
5242 lbl = newiTempLabel(NULL);
5243 emitcode ("setb","F1");
5244 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5245 emitcode ("clr","F1");
5246 emitcode("","!tlabeldef",lbl->key+100);
5249 lbl = newiTempLabel(NULL);
5250 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5251 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5252 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5253 emitcode ("xch", "a,b");
5254 emitcode ("cpl","a");
5255 emitcode ("add", "a,#1");
5256 emitcode ("xch", "a,b");
5257 emitcode ("cpl", "a"); // msb
5258 emitcode ("addc","a,#0");
5259 emitcode ("","!tlabeldef",lbl->key+100);
5260 emitcode ("mov","ma,b");
5261 emitcode ("mov","ma,a");
5263 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5264 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5267 /* load up MB with right */
5269 if (AOP_TYPE(right) == AOP_LIT) {
5270 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5274 emitcode ("mov","mb,#!constbyte",val & 0xff);
5275 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5277 lbl = newiTempLabel(NULL);
5278 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5279 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5280 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5281 emitcode ("xch", "a,b");
5282 emitcode ("cpl","a");
5283 emitcode ("add", "a,#1");
5284 emitcode ("xch", "a,b");
5285 emitcode ("cpl", "a"); // msb
5286 emitcode ("addc", "a,#0");
5287 emitcode ("","!tlabeldef",lbl->key+100);
5288 emitcode ("mov","mb,b");
5289 emitcode ("mov","mb,a");
5292 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5293 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5296 /* wait for multiplication to finish */
5297 lbl = newiTempLabel(NULL);
5298 emitcode("","!tlabeldef", lbl->key+100);
5299 emitcode("mov","a,mcnt1");
5300 emitcode("anl","a,#!constbyte",0x80);
5301 emitcode("jnz","!tlabel",lbl->key+100);
5303 freeAsmop (left, NULL, ic, TRUE);
5304 freeAsmop (right, NULL, ic,TRUE);
5305 aopOp(result, ic, TRUE, FALSE);
5307 aopPut(AOP(result),"mb",1);
5308 aopPut(AOP(result),"mb",0);
5309 freeAsmop (result, NULL, ic, TRUE);
5311 /* restore EA bit in F1 */
5312 lbl = newiTempLabel(NULL);
5313 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5314 emitcode ("setb","EA");
5315 emitcode("","!tlabeldef",lbl->key+100);
5319 /*-----------------------------------------------------------------*/
5320 /* genMod - generates code for division */
5321 /*-----------------------------------------------------------------*/
5325 operand *left = IC_LEFT (ic);
5326 operand *right = IC_RIGHT (ic);
5327 operand *result = IC_RESULT (ic);
5329 D (emitcode (";", "genMod "); );
5331 /* assign the amsops */
5334 /* special cases first */
5336 if (AOP_TYPE (left) == AOP_CRY &&
5337 AOP_TYPE (right) == AOP_CRY)
5339 genModbits (left, right, result, ic);
5343 /* if both are of size == 1 */
5344 if (AOP_SIZE (left) == 1 &&
5345 AOP_SIZE (right) == 1)
5347 genModOneByte (left, right, result, ic);
5351 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5352 /* use the ds390 ARITHMETIC accel UNIT */
5353 genModTwoByte (left, right, result, ic);
5357 /* should have been converted to function call */
5361 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5362 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5363 freeAsmop (result, NULL, ic, TRUE);
5366 /*-----------------------------------------------------------------*/
5367 /* genIfxJump :- will create a jump depending on the ifx */
5368 /*-----------------------------------------------------------------*/
5370 genIfxJump (iCode * ic, char *jval)
5373 symbol *tlbl = newiTempLabel (NULL);
5376 D (emitcode (";", "genIfxJump"););
5378 /* if true label then we jump if condition
5382 jlbl = IC_TRUE (ic);
5383 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5384 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5388 /* false label is present */
5389 jlbl = IC_FALSE (ic);
5390 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5391 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5393 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5394 emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5396 emitcode (inst, "!tlabel", tlbl->key + 100);
5397 emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5398 emitcode ("", "!tlabeldef", tlbl->key + 100);
5400 /* mark the icode as generated */
5404 /*-----------------------------------------------------------------*/
5405 /* genCmp :- greater or less than comparison */
5406 /*-----------------------------------------------------------------*/
5408 genCmp (operand * left, operand * right,
5409 iCode * ic, iCode * ifx, int sign)
5411 int size, offset = 0;
5412 unsigned long lit = 0L;
5415 D (emitcode (";", "genCmp"););
5417 result = IC_RESULT (ic);
5419 /* if left & right are bit variables */
5420 if (AOP_TYPE (left) == AOP_CRY &&
5421 AOP_TYPE (right) == AOP_CRY)
5423 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5424 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5428 /* subtract right from left if at the
5429 end the carry flag is set then we know that
5430 left is greater than right */
5431 size = max (AOP_SIZE (left), AOP_SIZE (right));
5433 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5434 if ((size == 1) && !sign
5435 && (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5437 symbol *lbl = newiTempLabel (NULL);
5438 emitcode ("cjne", "%s,%s,!tlabel",
5439 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
5440 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5442 emitcode ("", "!tlabeldef", lbl->key + 100);
5446 if (AOP_TYPE (right) == AOP_LIT)
5448 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5449 /* optimize if(x < 0) or if(x >= 0) */
5458 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
5460 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5461 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5463 aopOp (result, ic, FALSE, FALSE);
5465 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5467 freeAsmop (result, NULL, ic, TRUE);
5468 genIfxJump (ifx, "acc.7");
5473 emitcode ("rlc", "a");
5475 goto release_freedLR;
5483 // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5484 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5485 // emitcode (";", "genCmp #2");
5486 if (sign && (size == 0))
5488 // emitcode (";", "genCmp #3");
5489 emitcode ("xrl", "a,#!constbyte",0x80);
5490 if (AOP_TYPE (right) == AOP_LIT)
5492 unsigned long lit = (unsigned long)
5493 floatFromVal (AOP (right)->aopu.aop_lit);
5494 // emitcode (";", "genCmp #3.1");
5495 emitcode ("subb", "a,#!constbyte",
5496 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5500 // emitcode (";", "genCmp #3.2");
5502 MOVB(aopGet (AOP (right), offset++, FALSE, FALSE, "b"));
5503 saveAccWarn = DEFAULT_ACC_WARNING;
5504 emitcode ("xrl", "b,#!constbyte",0x80);
5505 emitcode ("subb", "a,b");
5512 // emitcode (";", "genCmp #4");
5514 s = aopGet (AOP (right), offset++, FALSE, FALSE, "b");
5515 saveAccWarn = DEFAULT_ACC_WARNING;
5517 emitcode ("subb", "a,%s", s);
5524 /* Don't need the left & right operands any more; do need the result. */
5525 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5526 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5528 aopOp (result, ic, FALSE, FALSE);
5532 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5538 /* if the result is used in the next
5539 ifx conditional branch then generate
5540 code a little differently */
5543 genIfxJump (ifx, "c");
5549 /* leave the result in acc */
5551 freeAsmop (result, NULL, ic, TRUE);
5554 /*-----------------------------------------------------------------*/
5555 /* genCmpGt :- greater than comparison */
5556 /*-----------------------------------------------------------------*/
5558 genCmpGt (iCode * ic, iCode * ifx)
5560 operand *left, *right;
5561 sym_link *letype, *retype;
5564 D (emitcode (";", "genCmpGt ");
5567 left = IC_LEFT (ic);
5568 right = IC_RIGHT (ic);
5570 letype = getSpec (operandType (left));
5571 retype = getSpec (operandType (right));
5572 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5574 /* assign the left & right amsops */
5577 genCmp (right, left, ic, ifx, sign);
5580 /*-----------------------------------------------------------------*/
5581 /* genCmpLt - less than comparisons */
5582 /*-----------------------------------------------------------------*/
5584 genCmpLt (iCode * ic, iCode * ifx)
5586 operand *left, *right;
5587 sym_link *letype, *retype;
5590 D (emitcode (";", "genCmpLt "););
5592 left = IC_LEFT (ic);
5593 right = IC_RIGHT (ic);
5595 letype = getSpec (operandType (left));
5596 retype = getSpec (operandType (right));
5597 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5599 /* assign the left & right amsops */
5602 genCmp (left, right, ic, ifx, sign);
5605 /*-----------------------------------------------------------------*/
5606 /* gencjneshort - compare and jump if not equal */
5607 /*-----------------------------------------------------------------*/
5609 gencjneshort (operand * left, operand * right, symbol * lbl)
5611 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5613 unsigned long lit = 0L;
5615 D (emitcode (";", "gencjneshort");
5618 /* if the left side is a literal or
5619 if the right is in a pointer register and left
5621 if ((AOP_TYPE (left) == AOP_LIT) ||
5622 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5629 if (AOP_TYPE (right) == AOP_LIT)
5630 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5632 if (opIsGptr (left) || opIsGptr (right))
5634 /* We are comparing a generic pointer to something.
5635 * Exclude the generic type byte from the comparison.
5638 D (emitcode (";", "cjneshort: generic ptr special case."););
5642 /* if the right side is a literal then anything goes */
5643 if (AOP_TYPE (right) == AOP_LIT &&
5644 AOP_TYPE (left) != AOP_DIR)
5648 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5649 emitcode ("cjne", "a,%s,!tlabel",
5650 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5656 /* if the right side is in a register or in direct space or
5657 if the left is a pointer register & right is not */
5658 else if (AOP_TYPE (right) == AOP_REG ||
5659 AOP_TYPE (right) == AOP_DIR ||
5660 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5661 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5665 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5666 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5667 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5668 emitcode ("jnz", "!tlabel", lbl->key + 100);
5670 emitcode ("cjne", "a,%s,!tlabel",
5671 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
5678 /* right is a pointer reg need both a & b */
5681 MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5682 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
5683 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5689 /*-----------------------------------------------------------------*/
5690 /* gencjne - compare and jump if not equal */
5691 /*-----------------------------------------------------------------*/
5693 gencjne (operand * left, operand * right, symbol * lbl)
5695 symbol *tlbl = newiTempLabel (NULL);
5697 D (emitcode (";", "gencjne");
5700 gencjneshort (left, right, lbl);
5702 emitcode ("mov", "a,%s", one);
5703 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5704 emitcode ("", "!tlabeldef", lbl->key + 100);
5705 emitcode ("clr", "a");
5706 emitcode ("", "!tlabeldef", tlbl->key + 100);
5709 /*-----------------------------------------------------------------*/
5710 /* genCmpEq - generates code for equal to */
5711 /*-----------------------------------------------------------------*/
5713 genCmpEq (iCode * ic, iCode * ifx)
5715 operand *left, *right, *result;
5717 D (emitcode (";", "genCmpEq ");
5721 AOP_SET_LOCALS (ic);
5723 /* if literal, literal on the right or
5724 if the right is in a pointer register and left
5726 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5727 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5729 operand *t = IC_RIGHT (ic);
5730 IC_RIGHT (ic) = IC_LEFT (ic);
5734 if (ifx && /* !AOP_SIZE(result) */
5735 OP_SYMBOL (result) &&
5736 OP_SYMBOL (result)->regType == REG_CND)
5739 /* if they are both bit variables */
5740 if (AOP_TYPE (left) == AOP_CRY &&
5741 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5743 if (AOP_TYPE (right) == AOP_LIT)
5745 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5748 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5749 emitcode ("cpl", "c");
5753 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5757 emitcode ("clr", "c");
5759 /* AOP_TYPE(right) == AOP_CRY */
5763 symbol *lbl = newiTempLabel (NULL);
5764 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5765 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5766 emitcode ("cpl", "c");
5767 emitcode ("", "!tlabeldef", (lbl->key + 100));
5769 /* if true label then we jump if condition
5771 tlbl = newiTempLabel (NULL);
5774 emitcode ("jnc", "!tlabel", tlbl->key + 100);
5775 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5779 emitcode ("jc", "!tlabel", tlbl->key + 100);
5780 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5782 emitcode ("", "!tlabeldef", tlbl->key + 100);
5786 tlbl = newiTempLabel (NULL);
5787 gencjneshort (left, right, tlbl);
5790 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5791 emitcode ("", "!tlabeldef", tlbl->key + 100);
5795 symbol *lbl = newiTempLabel (NULL);
5796 emitcode ("sjmp", "!tlabel", lbl->key + 100);
5797 emitcode ("", "!tlabeldef", tlbl->key + 100);
5798 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5799 emitcode ("", "!tlabeldef", lbl->key + 100);
5802 /* mark the icode as generated */
5805 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5806 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5810 /* if they are both bit variables */
5811 if (AOP_TYPE (left) == AOP_CRY &&
5812 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5814 if (AOP_TYPE (right) == AOP_LIT)
5816 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5819 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5820 emitcode ("cpl", "c");
5824 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5828 emitcode ("clr", "c");
5830 /* AOP_TYPE(right) == AOP_CRY */
5834 symbol *lbl = newiTempLabel (NULL);
5835 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5836 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5837 emitcode ("cpl", "c");
5838 emitcode ("", "!tlabeldef", (lbl->key + 100));
5841 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5842 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5844 aopOp (result, ic, TRUE, FALSE);
5847 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5854 genIfxJump (ifx, "c");
5857 /* if the result is used in an arithmetic operation
5858 then put the result in place */
5863 gencjne (left, right, newiTempLabel (NULL));
5865 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5866 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5868 aopOp (result, ic, TRUE, FALSE);
5870 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5872 aopPut (AOP (result), "a", 0);
5877 genIfxJump (ifx, "a");
5880 /* if the result is used in an arithmetic operation
5881 then put the result in place */
5882 if (AOP_TYPE (result) != AOP_CRY)
5884 /* leave the result in acc */
5888 freeAsmop (result, NULL, ic, TRUE);
5891 /*-----------------------------------------------------------------*/
5892 /* ifxForOp - returns the icode containing the ifx for operand */
5893 /*-----------------------------------------------------------------*/
5895 ifxForOp (operand * op, iCode * ic)
5897 /* if true symbol then needs to be assigned */
5898 if (IS_TRUE_SYMOP (op))
5901 /* if this has register type condition and
5902 the next instruction is ifx with the same operand
5903 and live to of the operand is upto the ifx only then */
5905 ic->next->op == IFX &&
5906 IC_COND (ic->next)->key == op->key &&
5907 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5912 /*-----------------------------------------------------------------*/
5913 /* hasInc - operand is incremented before any other use */
5914 /*-----------------------------------------------------------------*/
5916 hasInc (operand *op, iCode *ic, int osize)
5918 sym_link *type = operandType(op);
5919 sym_link *retype = getSpec (type);
5920 iCode *lic = ic->next;
5923 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5924 if (!IS_SYMOP(op)) return NULL;
5926 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5927 if (IS_AGGREGATE(type->next)) return NULL;
5928 if (osize != (isize = getSize(type->next))) return NULL;
5931 /* if operand of the form op = op + <sizeof *op> */
5932 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5933 isOperandEqual(IC_RESULT(lic),op) &&
5934 isOperandLiteral(IC_RIGHT(lic)) &&
5935 operandLitValue(IC_RIGHT(lic)) == isize) {
5938 /* if the operand used or deffed */
5939 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5942 /* if GOTO or IFX */
5943 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5949 /*-----------------------------------------------------------------*/
5950 /* genAndOp - for && operation */
5951 /*-----------------------------------------------------------------*/
5953 genAndOp (iCode * ic)
5955 operand *left, *right, *result;
5958 D (emitcode (";", "genAndOp "););
5960 /* note here that && operations that are in an
5961 if statement are taken away by backPatchLabels
5962 only those used in arthmetic operations remain */
5964 AOP_SET_LOCALS (ic);
5966 /* if both are bit variables */
5967 if (AOP_TYPE (left) == AOP_CRY &&
5968 AOP_TYPE (right) == AOP_CRY)
5970 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5971 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5972 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5973 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5975 aopOp (result,ic,FALSE, FALSE);
5980 tlbl = newiTempLabel (NULL);
5982 emitcode ("jz", "!tlabel", tlbl->key + 100);
5984 emitcode ("", "!tlabeldef", tlbl->key + 100);
5985 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5986 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5988 aopOp (result,ic,FALSE, FALSE);
5991 freeAsmop (result, NULL, ic, TRUE);
5995 /*-----------------------------------------------------------------*/
5996 /* genOrOp - for || operation */
5997 /*-----------------------------------------------------------------*/
5999 genOrOp (iCode * ic)
6001 operand *left, *right, *result;
6004 D (emitcode (";", "genOrOp "););
6006 /* note here that || operations that are in an
6007 if statement are taken away by backPatchLabels
6008 only those used in arthmetic operations remain */
6010 AOP_SET_LOCALS (ic);
6012 /* if both are bit variables */
6013 if (AOP_TYPE (left) == AOP_CRY &&
6014 AOP_TYPE (right) == AOP_CRY)
6016 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6017 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6018 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6019 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6021 aopOp (result,ic,FALSE, FALSE);
6027 tlbl = newiTempLabel (NULL);
6029 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6031 emitcode ("", "!tlabeldef", tlbl->key + 100);
6032 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6033 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6035 aopOp (result,ic,FALSE, FALSE);
6040 freeAsmop (result, NULL, ic, TRUE);
6043 /*-----------------------------------------------------------------*/
6044 /* isLiteralBit - test if lit == 2^n */
6045 /*-----------------------------------------------------------------*/
6047 isLiteralBit (unsigned long lit)
6049 unsigned long pw[32] =
6050 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6051 0x100L, 0x200L, 0x400L, 0x800L,
6052 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6053 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6054 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6055 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6056 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6059 for (idx = 0; idx < 32; idx++)
6065 /*-----------------------------------------------------------------*/
6066 /* continueIfTrue - */
6067 /*-----------------------------------------------------------------*/
6069 continueIfTrue (iCode * ic)
6072 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6076 /*-----------------------------------------------------------------*/
6078 /*-----------------------------------------------------------------*/
6080 jumpIfTrue (iCode * ic)
6083 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6087 /*-----------------------------------------------------------------*/
6088 /* jmpTrueOrFalse - */
6089 /*-----------------------------------------------------------------*/
6091 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6093 // ugly but optimized by peephole
6096 symbol *nlbl = newiTempLabel (NULL);
6097 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6098 emitcode ("", "!tlabeldef", tlbl->key + 100);
6099 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6100 emitcode ("", "!tlabeldef", nlbl->key + 100);
6104 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6105 emitcode ("", "!tlabeldef", tlbl->key + 100);
6110 // Generate code to perform a bit-wise logic operation
6111 // on two operands in far space (assumed to already have been
6112 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6113 // in far space. This requires pushing the result on the stack
6114 // then popping it into the result.
6116 genFarFarLogicOp(iCode *ic, char *logicOp)
6118 int size, resultSize, compSize;
6122 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6123 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
6124 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6126 _startLazyDPSEvaluation();
6127 for (size = compSize; (size--); offset++)
6129 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6130 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6131 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6133 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6134 emitcode ("push", "acc");
6136 _endLazyDPSEvaluation();
6138 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6139 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6140 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6142 resultSize = AOP_SIZE(IC_RESULT(ic));
6144 ADJUST_PUSHED_RESULT(compSize, resultSize);
6146 _startLazyDPSEvaluation();
6149 emitcode ("pop", "acc");
6150 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6152 _endLazyDPSEvaluation();
6153 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6157 /*-----------------------------------------------------------------*/
6158 /* genAnd - code for and */
6159 /*-----------------------------------------------------------------*/
6161 genAnd (iCode * ic, iCode * ifx)
6163 operand *left, *right, *result;
6164 int size, offset = 0;
6165 unsigned long lit = 0L;
6170 D (emitcode (";", "genAnd "););
6172 AOP_OP_3_NOFATAL (ic, pushResult);
6173 AOP_SET_LOCALS (ic);
6177 genFarFarLogicOp(ic, "anl");
6182 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6184 AOP_TYPE (left), AOP_TYPE (right));
6185 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6187 AOP_SIZE (left), AOP_SIZE (right));
6190 /* if left is a literal & right is not then exchange them */
6191 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6192 #ifdef LOGIC_OPS_BROKEN
6193 || AOP_NEEDSACC (left)
6197 operand *tmp = right;
6202 /* if result = right then exchange them */
6203 if (sameRegs (AOP (result), AOP (right)))
6205 operand *tmp = right;
6210 /* if right is bit then exchange them */
6211 if (AOP_TYPE (right) == AOP_CRY &&
6212 AOP_TYPE (left) != AOP_CRY)
6214 operand *tmp = right;
6218 if (AOP_TYPE (right) == AOP_LIT)
6219 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6221 size = AOP_SIZE (result);
6224 // result = bit & yy;
6225 if (AOP_TYPE (left) == AOP_CRY)
6227 // c = bit & literal;
6228 if (AOP_TYPE (right) == AOP_LIT)
6232 if (size && sameRegs (AOP (result), AOP (left)))
6235 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6240 if (size && (AOP_TYPE (result) == AOP_CRY))
6242 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6245 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6250 emitcode ("clr", "c");
6255 if (AOP_TYPE (right) == AOP_CRY)
6258 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6259 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6264 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6266 emitcode ("rrc", "a");
6267 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6275 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6276 genIfxJump (ifx, "c");
6280 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6281 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6282 if ((AOP_TYPE (right) == AOP_LIT) &&
6283 (AOP_TYPE (result) == AOP_CRY) &&
6284 (AOP_TYPE (left) != AOP_CRY))
6286 int posbit = isLiteralBit (lit);
6291 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6294 emitcode ("mov", "c,acc.%d", posbit & 0x07);
6300 SNPRINTF (buff, sizeof(buff),
6301 "acc.%d", posbit & 0x07);
6302 genIfxJump (ifx, buff);
6306 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6313 symbol *tlbl = newiTempLabel (NULL);
6314 int sizel = AOP_SIZE (left);
6316 emitcode ("setb", "c");
6319 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6321 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6323 if ((posbit = isLiteralBit (bytelit)) != 0)
6324 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6327 if (bytelit != 0x0FFL)
6328 emitcode ("anl", "a,%s",
6329 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6330 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6335 // bit = left & literal
6338 emitcode ("clr", "c");
6339 emitcode ("", "!tlabeldef", tlbl->key + 100);
6341 // if(left & literal)
6345 jmpTrueOrFalse (ifx, tlbl);
6353 /* if left is same as result */
6354 if (sameRegs (AOP (result), AOP (left)))
6356 for (; size--; offset++)
6358 if (AOP_TYPE (right) == AOP_LIT)
6360 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6362 else if (bytelit == 0)
6363 aopPut (AOP (result), zero, offset);
6364 else if (IS_AOP_PREG (result))
6366 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6367 emitcode ("anl", "a,%s",
6368 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6369 aopPut (AOP (result), "a", offset);
6372 emitcode ("anl", "%s,%s",
6373 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6374 aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6378 if (AOP_TYPE (left) == AOP_ACC)
6379 emitcode ("anl", "a,%s",
6380 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6383 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6384 if (IS_AOP_PREG (result))
6386 emitcode ("anl", "a,%s",
6387 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6388 aopPut (AOP (result), "a", offset);
6391 emitcode ("anl", "%s,a",
6392 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6399 // left & result in different registers
6400 if (AOP_TYPE (result) == AOP_CRY)
6403 // if(size), result in bit
6404 // if(!size && ifx), conditional oper: if(left & right)
6405 symbol *tlbl = newiTempLabel (NULL);
6406 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6408 emitcode ("setb", "c");
6411 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6412 emitcode ("anl", "a,%s",
6413 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6415 if (AOP_TYPE(left)==AOP_ACC) {
6416 emitcode("mov", "b,a");
6417 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6418 emitcode("anl", "a,b");
6420 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6421 emitcode ("anl", "a,%s",
6422 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6425 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6431 emitcode ("", "!tlabeldef", tlbl->key + 100);
6435 jmpTrueOrFalse (ifx, tlbl);
6439 for (; (size--); offset++)
6442 // result = left & right
6443 if (AOP_TYPE (right) == AOP_LIT)
6445 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6447 aopPut (AOP (result),
6448 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6452 else if (bytelit == 0)
6454 aopPut (AOP (result), zero, offset);
6457 D (emitcode (";", "better literal AND."););
6458 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6459 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6460 FALSE, FALSE, DP2_RESULT_REG));
6465 // faster than result <- left, anl result,right
6466 // and better if result is SFR
6467 if (AOP_TYPE (left) == AOP_ACC)
6469 emitcode ("anl", "a,%s",
6470 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6474 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6475 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6477 emitcode("mov", "b,a");
6481 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6482 emitcode ("anl", "a,%s", rOp);
6485 aopPut (AOP (result), "a", offset);
6491 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6492 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6493 freeAsmop (result, NULL, ic, TRUE);
6497 /*-----------------------------------------------------------------*/
6498 /* genOr - code for or */
6499 /*-----------------------------------------------------------------*/
6501 genOr (iCode * ic, iCode * ifx)
6503 operand *left, *right, *result;
6504 int size, offset = 0;
6505 unsigned long lit = 0L;
6508 D (emitcode (";", "genOr "););
6510 AOP_OP_3_NOFATAL (ic, pushResult);
6511 AOP_SET_LOCALS (ic);
6515 genFarFarLogicOp(ic, "orl");
6521 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6523 AOP_TYPE (left), AOP_TYPE (right));
6524 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6526 AOP_SIZE (left), AOP_SIZE (right));
6529 /* if left is a literal & right is not then exchange them */
6530 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6531 #ifdef LOGIC_OPS_BROKEN
6532 || AOP_NEEDSACC (left) // I think this is a net loss now.
6536 operand *tmp = right;
6541 /* if result = right then exchange them */
6542 if (sameRegs (AOP (result), AOP (right)))
6544 operand *tmp = right;
6549 /* if right is bit then exchange them */
6550 if (AOP_TYPE (right) == AOP_CRY &&
6551 AOP_TYPE (left) != AOP_CRY)
6553 operand *tmp = right;
6557 if (AOP_TYPE (right) == AOP_LIT)
6558 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6560 size = AOP_SIZE (result);
6564 if (AOP_TYPE (left) == AOP_CRY)
6566 if (AOP_TYPE (right) == AOP_LIT)
6568 // c = bit & literal;
6571 // lit != 0 => result = 1
6572 if (AOP_TYPE (result) == AOP_CRY)
6575 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6577 continueIfTrue (ifx);
6580 emitcode ("setb", "c");
6584 // lit == 0 => result = left
6585 if (size && sameRegs (AOP (result), AOP (left)))
6587 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6592 if (AOP_TYPE (right) == AOP_CRY)
6595 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6596 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6601 symbol *tlbl = newiTempLabel (NULL);
6602 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6603 emitcode ("setb", "c");
6604 emitcode ("jb", "%s,!tlabel",
6605 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6607 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6608 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6610 jmpTrueOrFalse (ifx, tlbl);
6616 emitcode ("", "!tlabeldef", tlbl->key + 100);
6625 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6626 genIfxJump (ifx, "c");
6630 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6631 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6632 if ((AOP_TYPE (right) == AOP_LIT) &&
6633 (AOP_TYPE (result) == AOP_CRY) &&
6634 (AOP_TYPE (left) != AOP_CRY))
6640 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6642 continueIfTrue (ifx);
6647 // lit = 0, result = boolean(left)
6649 emitcode ("setb", "c");
6653 symbol *tlbl = newiTempLabel (NULL);
6654 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6656 emitcode ("", "!tlabeldef", tlbl->key + 100);
6660 genIfxJump (ifx, "a");
6668 /* if left is same as result */
6669 if (sameRegs (AOP (result), AOP (left)))
6671 for (; size--; offset++)
6673 if (AOP_TYPE (right) == AOP_LIT)
6675 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6681 if (IS_AOP_PREG (left))
6683 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6684 emitcode ("orl", "a,%s",
6685 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6686 aopPut (AOP (result), "a", offset);
6690 emitcode ("orl", "%s,%s",
6691 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6692 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6698 if (AOP_TYPE (left) == AOP_ACC)
6700 emitcode ("orl", "a,%s",
6701 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6705 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6706 if (IS_AOP_PREG (left))
6708 emitcode ("orl", "a,%s",
6709 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6710 aopPut (AOP (result), "a", offset);
6714 emitcode ("orl", "%s,a",
6715 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6723 // left & result in different registers
6724 if (AOP_TYPE (result) == AOP_CRY)
6727 // if(size), result in bit
6728 // if(!size && ifx), conditional oper: if(left | right)
6729 symbol *tlbl = newiTempLabel (NULL);
6730 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6732 emitcode ("setb", "c");
6735 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6736 emitcode ("orl", "a,%s",
6737 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6739 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6740 emitcode ("orl", "a,%s",
6741 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6743 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6749 emitcode ("", "!tlabeldef", tlbl->key + 100);
6753 jmpTrueOrFalse (ifx, tlbl);
6757 _startLazyDPSEvaluation();
6758 for (; (size--); offset++)
6761 // result = left & right
6762 if (AOP_TYPE (right) == AOP_LIT)
6764 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6766 aopPut (AOP (result),
6767 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6771 D (emitcode (";", "better literal OR."););
6772 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6773 emitcode ("orl", "a, %s",
6774 aopGet (AOP (right), offset,
6775 FALSE, FALSE, DP2_RESULT_REG));
6780 // faster than result <- left, anl result,right
6781 // and better if result is SFR
6782 if (AOP_TYPE (left) == AOP_ACC)
6784 emitcode ("orl", "a,%s",
6785 aopGet (AOP (right), offset,
6786 FALSE, FALSE, DP2_RESULT_REG));
6790 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6792 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6794 emitcode("mov", "b,a");
6798 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6799 emitcode ("orl", "a,%s", rOp);
6802 aopPut (AOP (result), "a", offset);
6804 _endLazyDPSEvaluation();
6809 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6810 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6811 freeAsmop (result, NULL, ic, TRUE);
6814 /*-----------------------------------------------------------------*/
6815 /* genXor - code for xclusive or */
6816 /*-----------------------------------------------------------------*/
6818 genXor (iCode * ic, iCode * ifx)
6820 operand *left, *right, *result;
6821 int size, offset = 0;
6822 unsigned long lit = 0L;
6825 D (emitcode (";", "genXor "););
6827 AOP_OP_3_NOFATAL (ic, pushResult);
6828 AOP_SET_LOCALS (ic);
6832 genFarFarLogicOp(ic, "xrl");
6837 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6839 AOP_TYPE (left), AOP_TYPE (right));
6840 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6842 AOP_SIZE (left), AOP_SIZE (right));
6845 /* if left is a literal & right is not ||
6846 if left needs acc & right does not */
6847 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6848 #ifdef LOGIC_OPS_BROKEN
6849 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6853 operand *tmp = right;
6858 /* if result = right then exchange them */
6859 if (sameRegs (AOP (result), AOP (right)))
6861 operand *tmp = right;
6866 /* if right is bit then exchange them */
6867 if (AOP_TYPE (right) == AOP_CRY &&
6868 AOP_TYPE (left) != AOP_CRY)
6870 operand *tmp = right;
6874 if (AOP_TYPE (right) == AOP_LIT)
6875 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6877 size = AOP_SIZE (result);
6881 if (AOP_TYPE (left) == AOP_CRY)
6883 if (AOP_TYPE (right) == AOP_LIT)
6885 // c = bit & literal;
6888 // lit>>1 != 0 => result = 1
6889 if (AOP_TYPE (result) == AOP_CRY)
6892 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6894 continueIfTrue (ifx);
6897 emitcode ("setb", "c");
6904 // lit == 0, result = left
6905 if (size && sameRegs (AOP (result), AOP (left)))
6907 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6911 // lit == 1, result = not(left)
6912 if (size && sameRegs (AOP (result), AOP (left)))
6914 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6919 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6920 emitcode ("cpl", "c");
6929 symbol *tlbl = newiTempLabel (NULL);
6930 if (AOP_TYPE (right) == AOP_CRY)
6933 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6937 int sizer = AOP_SIZE (right);
6939 // if val>>1 != 0, result = 1
6940 emitcode ("setb", "c");
6943 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
6945 // test the msb of the lsb
6946 emitcode ("anl", "a,#!constbyte",0xfe);
6947 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6951 emitcode ("rrc", "a");
6953 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6954 emitcode ("cpl", "c");
6955 emitcode ("", "!tlabeldef", (tlbl->key + 100));
6962 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6963 genIfxJump (ifx, "c");
6967 if (sameRegs (AOP (result), AOP (left)))
6969 /* if left is same as result */
6970 for (; size--; offset++)
6972 if (AOP_TYPE (right) == AOP_LIT)
6974 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6976 else if (IS_AOP_PREG (left))
6978 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6979 emitcode ("xrl", "a,%s",
6980 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6981 aopPut (AOP (result), "a", offset);
6984 emitcode ("xrl", "%s,%s",
6985 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6986 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6990 if (AOP_TYPE (left) == AOP_ACC)
6991 emitcode ("xrl", "a,%s",
6992 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6995 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6996 if (IS_AOP_PREG (left))
6998 emitcode ("xrl", "a,%s",
6999 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7000 aopPut (AOP (result), "a", offset);
7003 emitcode ("xrl", "%s,a",
7004 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7011 // left & result in different registers
7012 if (AOP_TYPE (result) == AOP_CRY)
7015 // if(size), result in bit
7016 // if(!size && ifx), conditional oper: if(left ^ right)
7017 symbol *tlbl = newiTempLabel (NULL);
7018 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7021 emitcode ("setb", "c");
7024 if ((AOP_TYPE (right) == AOP_LIT) &&
7025 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7027 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7031 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7032 emitcode ("xrl", "a,%s",
7033 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7035 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7036 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7038 emitcode("mov", "b,a");
7042 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7043 emitcode ("xrl", "a,%s", rOp);
7046 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7052 emitcode ("", "!tlabeldef", tlbl->key + 100);
7056 jmpTrueOrFalse (ifx, tlbl);
7060 for (; (size--); offset++)
7063 // result = left & right
7064 if (AOP_TYPE (right) == AOP_LIT)
7066 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7068 aopPut (AOP (result),
7069 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7073 D (emitcode (";", "better literal XOR."););
7074 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7075 emitcode ("xrl", "a, %s",
7076 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7080 // faster than result <- left, anl result,right
7081 // and better if result is SFR
7082 if (AOP_TYPE (left) == AOP_ACC)
7084 emitcode ("xrl", "a,%s",
7085 aopGet (AOP (right), offset,
7086 FALSE, FALSE, DP2_RESULT_REG));
7090 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7091 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7093 emitcode("mov", "b,a");
7097 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7098 emitcode ("xrl", "a,%s", rOp);
7101 aopPut (AOP (result), "a", offset);
7108 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7109 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7110 freeAsmop (result, NULL, ic, TRUE);
7113 /*-----------------------------------------------------------------*/
7114 /* genInline - write the inline code out */
7115 /*-----------------------------------------------------------------*/
7117 genInline (iCode * ic)
7119 char *buffer, *bp, *bp1;
7121 D (emitcode (";", "genInline "); );
7123 _G.inLine += (!options.asmpeep);
7125 buffer = Safe_strdup(IC_INLINE(ic));
7129 /* emit each line as a code */
7154 /* emitcode("",buffer); */
7155 _G.inLine -= (!options.asmpeep);
7158 /*-----------------------------------------------------------------*/
7159 /* genRRC - rotate right with carry */
7160 /*-----------------------------------------------------------------*/
7164 operand *left, *result;
7167 D (emitcode (";", "genRRC "););
7169 /* rotate right with carry */
7170 left = IC_LEFT (ic);
7171 result = IC_RESULT (ic);
7172 aopOp (left, ic, FALSE, FALSE);
7173 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7175 /* move it to the result */
7176 size = AOP_SIZE (result);
7180 _startLazyDPSEvaluation ();
7183 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7184 emitcode ("rrc", "a");
7185 if (AOP_SIZE (result) > 1)
7186 aopPut (AOP (result), "a", offset--);
7188 _endLazyDPSEvaluation ();
7190 /* now we need to put the carry into the
7191 highest order byte of the result */
7192 if (AOP_SIZE (result) > 1)
7194 MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7196 emitcode ("mov", "acc.7,c");
7197 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7198 freeAsmop (left, NULL, ic, TRUE);
7199 freeAsmop (result, NULL, ic, TRUE);
7202 /*-----------------------------------------------------------------*/
7203 /* genRLC - generate code for rotate left with carry */
7204 /*-----------------------------------------------------------------*/
7208 operand *left, *result;
7212 D (emitcode (";", "genRLC "););
7214 /* rotate right with carry */
7215 left = IC_LEFT (ic);
7216 result = IC_RESULT (ic);
7217 aopOp (left, ic, FALSE, FALSE);
7218 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7220 /* move it to the result */
7221 size = AOP_SIZE (result);
7225 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7227 emitcode ("add", "a,acc");
7228 if (AOP_SIZE (result) > 1)
7230 aopPut (AOP (result), "a", offset++);
7233 _startLazyDPSEvaluation ();
7236 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7238 emitcode ("rlc", "a");
7239 if (AOP_SIZE (result) > 1)
7240 aopPut (AOP (result), "a", offset++);
7242 _endLazyDPSEvaluation ();
7244 /* now we need to put the carry into the
7245 highest order byte of the result */
7246 if (AOP_SIZE (result) > 1)
7248 l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7251 emitcode ("mov", "acc.0,c");
7252 aopPut (AOP (result), "a", 0);
7253 freeAsmop (left, NULL, ic, TRUE);
7254 freeAsmop (result, NULL, ic, TRUE);
7257 /*-----------------------------------------------------------------*/
7258 /* genGetHbit - generates code get highest order bit */
7259 /*-----------------------------------------------------------------*/
7261 genGetHbit (iCode * ic)
7263 operand *left, *result;
7264 left = IC_LEFT (ic);
7265 result = IC_RESULT (ic);
7266 aopOp (left, ic, FALSE, FALSE);
7267 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7269 D (emitcode (";", "genGetHbit "););
7271 /* get the highest order byte into a */
7272 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7273 if (AOP_TYPE (result) == AOP_CRY)
7275 emitcode ("rlc", "a");
7280 emitcode ("rl", "a");
7281 emitcode ("anl", "a,#1");
7286 freeAsmop (left, NULL, ic, TRUE);
7287 freeAsmop (result, NULL, ic, TRUE);
7290 /*-----------------------------------------------------------------*/
7291 /* AccRol - rotate left accumulator by known count */
7292 /*-----------------------------------------------------------------*/
7294 AccRol (int shCount)
7296 shCount &= 0x0007; // shCount : 0..7
7303 emitcode ("rl", "a");
7306 emitcode ("rl", "a");
7307 emitcode ("rl", "a");
7310 emitcode ("swap", "a");
7311 emitcode ("rr", "a");
7314 emitcode ("swap", "a");
7317 emitcode ("swap", "a");
7318 emitcode ("rl", "a");
7321 emitcode ("rr", "a");
7322 emitcode ("rr", "a");
7325 emitcode ("rr", "a");
7330 /*-----------------------------------------------------------------*/
7331 /* AccLsh - left shift accumulator by known count */
7332 /*-----------------------------------------------------------------*/
7334 AccLsh (int shCount)
7339 emitcode ("add", "a,acc");
7340 else if (shCount == 2)
7342 emitcode ("add", "a,acc");
7343 emitcode ("add", "a,acc");
7347 /* rotate left accumulator */
7349 /* and kill the lower order bits */
7350 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7355 /*-----------------------------------------------------------------*/
7356 /* AccRsh - right shift accumulator by known count */
7357 /*-----------------------------------------------------------------*/
7359 AccRsh (int shCount)
7366 emitcode ("rrc", "a");
7370 /* rotate right accumulator */
7371 AccRol (8 - shCount);
7372 /* and kill the higher order bits */
7373 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7378 #ifdef BETTER_LITERAL_SHIFT
7379 /*-----------------------------------------------------------------*/
7380 /* AccSRsh - signed right shift accumulator by known count */
7381 /*-----------------------------------------------------------------*/
7383 AccSRsh (int shCount)
7390 emitcode ("mov", "c,acc.7");
7391 emitcode ("rrc", "a");
7393 else if (shCount == 2)
7395 emitcode ("mov", "c,acc.7");
7396 emitcode ("rrc", "a");
7397 emitcode ("mov", "c,acc.7");
7398 emitcode ("rrc", "a");
7402 tlbl = newiTempLabel (NULL);
7403 /* rotate right accumulator */
7404 AccRol (8 - shCount);
7405 /* and kill the higher order bits */
7406 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7407 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7408 emitcode ("orl", "a,#!constbyte",
7409 (unsigned char) ~SRMask[shCount]);
7410 emitcode ("", "!tlabeldef", tlbl->key + 100);
7416 #ifdef BETTER_LITERAL_SHIFT
7417 /*-----------------------------------------------------------------*/
7418 /* shiftR1Left2Result - shift right one byte from left to result */
7419 /*-----------------------------------------------------------------*/
7421 shiftR1Left2Result (operand * left, int offl,
7422 operand * result, int offr,
7423 int shCount, int sign)
7425 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7426 /* shift right accumulator */
7431 aopPut (AOP (result), "a", offr);
7435 #ifdef BETTER_LITERAL_SHIFT
7436 /*-----------------------------------------------------------------*/
7437 /* shiftL1Left2Result - shift left one byte from left to result */
7438 /*-----------------------------------------------------------------*/
7440 shiftL1Left2Result (operand * left, int offl,
7441 operand * result, int offr, int shCount)
7443 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7444 /* shift left accumulator */
7446 aopPut (AOP (result), "a", offr);
7450 #ifdef BETTER_LITERAL_SHIFT
7451 /*-----------------------------------------------------------------*/
7452 /* movLeft2Result - move byte from left to result */
7453 /*-----------------------------------------------------------------*/
7455 movLeft2Result (operand * left, int offl,
7456 operand * result, int offr, int sign)
7459 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7461 l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
7463 if (*l == '@' && (IS_AOP_PREG (result)))
7465 emitcode ("mov", "a,%s", l);
7466 aopPut (AOP (result), "a", offr);
7472 aopPut (AOP (result), l, offr);
7476 /* MSB sign in acc.7 ! */
7477 if (getDataSize (left) == offl + 1)
7479 emitcode ("mov", "a,%s", l);
7480 aopPut (AOP (result), "a", offr);
7488 #ifdef BETTER_LITERAL_SHIFT
7489 /*-----------------------------------------------------------------*/
7490 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7491 /*-----------------------------------------------------------------*/
7495 emitcode ("rrc", "a");
7496 emitcode ("xch", "a,%s", x);
7497 emitcode ("rrc", "a");
7498 emitcode ("xch", "a,%s", x);
7502 #ifdef BETTER_LITERAL_SHIFT
7504 /*-----------------------------------------------------------------*/
7505 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7506 /*-----------------------------------------------------------------*/
7510 emitcode ("xch", "a,%s", x);
7511 emitcode ("rlc", "a");
7512 emitcode ("xch", "a,%s", x);
7513 emitcode ("rlc", "a");
7517 #ifdef BETTER_LITERAL_SHIFT
7518 /*-----------------------------------------------------------------*/
7519 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7520 /*-----------------------------------------------------------------*/
7524 emitcode ("xch", "a,%s", x);
7525 emitcode ("add", "a,acc");
7526 emitcode ("xch", "a,%s", x);
7527 emitcode ("rlc", "a");
7531 #ifdef BETTER_LITERAL_SHIFT
7532 /*-----------------------------------------------------------------*/
7533 /* AccAXLsh - left shift a:x by known count (0..7) */
7534 /*-----------------------------------------------------------------*/
7536 AccAXLsh (char *x, int shCount)
7551 case 5: // AAAAABBB:CCCCCDDD
7553 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7555 emitcode ("anl", "a,#!constbyte",
7556 SLMask[shCount]); // BBB00000:CCCCCDDD
7558 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7560 AccRol (shCount); // DDDCCCCC:BBB00000
7562 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7564 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7566 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7568 emitcode ("anl", "a,#!constbyte",
7569 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7571 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7573 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7576 case 6: // AAAAAABB:CCCCCCDD
7577 emitcode ("anl", "a,#!constbyte",
7578 SRMask[shCount]); // 000000BB:CCCCCCDD
7579 emitcode ("mov", "c,acc.0"); // c = B
7580 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7582 AccAXRrl1 (x); // BCCCCCCD:D000000B
7583 AccAXRrl1 (x); // BBCCCCCC:DD000000
7585 emitcode("rrc","a");
7586 emitcode("xch","a,%s", x);
7587 emitcode("rrc","a");
7588 emitcode("mov","c,acc.0"); //<< get correct bit
7589 emitcode("xch","a,%s", x);
7591 emitcode("rrc","a");
7592 emitcode("xch","a,%s", x);
7593 emitcode("rrc","a");
7594 emitcode("xch","a,%s", x);
7597 case 7: // a:x <<= 7
7599 emitcode ("anl", "a,#!constbyte",
7600 SRMask[shCount]); // 0000000B:CCCCCCCD
7602 emitcode ("mov", "c,acc.0"); // c = B
7604 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7606 AccAXRrl1 (x); // BCCCCCCC:D0000000
7615 #ifdef BETTER_LITERAL_SHIFT
7617 /*-----------------------------------------------------------------*/
7618 /* AccAXRsh - right shift a:x known count (0..7) */
7619 /*-----------------------------------------------------------------*/
7621 AccAXRsh (char *x, int shCount)
7629 AccAXRrl1 (x); // 0->a:x
7634 AccAXRrl1 (x); // 0->a:x
7637 AccAXRrl1 (x); // 0->a:x
7642 case 5: // AAAAABBB:CCCCCDDD = a:x
7644 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7646 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7648 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7650 emitcode ("anl", "a,#!constbyte",
7651 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7653 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7655 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7657 emitcode ("anl", "a,#!constbyte",
7658 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7660 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7662 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7664 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7667 case 6: // AABBBBBB:CCDDDDDD
7669 emitcode ("mov", "c,acc.7");
7670 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7672 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7674 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7676 emitcode ("anl", "a,#!constbyte",
7677 SRMask[shCount]); // 000000AA:BBBBBBCC
7680 case 7: // ABBBBBBB:CDDDDDDD
7682 emitcode ("mov", "c,acc.7"); // c = A
7684 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7686 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7688 emitcode ("anl", "a,#!constbyte",
7689 SRMask[shCount]); // 0000000A:BBBBBBBC
7698 #ifdef BETTER_LITERAL_SHIFT
7699 /*-----------------------------------------------------------------*/
7700 /* AccAXRshS - right shift signed a:x known count (0..7) */
7701 /*-----------------------------------------------------------------*/
7703 AccAXRshS (char *x, int shCount)
7711 emitcode ("mov", "c,acc.7");
7712 AccAXRrl1 (x); // s->a:x
7716 emitcode ("mov", "c,acc.7");
7717 AccAXRrl1 (x); // s->a:x
7719 emitcode ("mov", "c,acc.7");
7720 AccAXRrl1 (x); // s->a:x
7725 case 5: // AAAAABBB:CCCCCDDD = a:x
7727 tlbl = newiTempLabel (NULL);
7728 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7730 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7732 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7734 emitcode ("anl", "a,#!constbyte",
7735 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7737 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7739 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7741 emitcode ("anl", "a,#!constbyte",
7742 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7744 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7746 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7748 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7750 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7751 emitcode ("orl", "a,#!constbyte",
7752 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7754 emitcode ("", "!tlabeldef", tlbl->key + 100);
7755 break; // SSSSAAAA:BBBCCCCC
7757 case 6: // AABBBBBB:CCDDDDDD
7759 tlbl = newiTempLabel (NULL);
7760 emitcode ("mov", "c,acc.7");
7761 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7763 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7765 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7767 emitcode ("anl", "a,#!constbyte",
7768 SRMask[shCount]); // 000000AA:BBBBBBCC
7770 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7771 emitcode ("orl", "a,#!constbyte",
7772 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7774 emitcode ("", "!tlabeldef", tlbl->key + 100);
7776 case 7: // ABBBBBBB:CDDDDDDD
7778 tlbl = newiTempLabel (NULL);
7779 emitcode ("mov", "c,acc.7"); // c = A
7781 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7783 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7785 emitcode ("anl", "a,#!constbyte",
7786 SRMask[shCount]); // 0000000A:BBBBBBBC
7788 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7789 emitcode ("orl", "a,#!constbyte",
7790 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7792 emitcode ("", "!tlabeldef", tlbl->key + 100);
7800 #ifdef BETTER_LITERAL_SHIFT
7802 _loadLeftIntoAx(char **lsb,
7808 // Get the initial value from left into a pair of registers.
7809 // MSB must be in A, LSB can be any register.
7811 // If the result is held in registers, it is an optimization
7812 // if the LSB can be held in the register which will hold the,
7813 // result LSB since this saves us from having to copy it into
7814 // the result following AccAXLsh.
7816 // If the result is addressed indirectly, this is not a gain.
7817 if (AOP_NEEDSACC(result))
7821 _startLazyDPSEvaluation();
7822 if (AOP_TYPE(left) == AOP_DPTR2)
7825 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
7826 // get LSB in DP2_RESULT_REG.
7827 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
7828 assert(!strcmp(leftByte, DP2_RESULT_REG));
7832 // get LSB into DP2_RESULT_REG
7833 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
7834 if (strcmp(leftByte, DP2_RESULT_REG))
7837 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7840 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
7841 assert(strcmp(leftByte, DP2_RESULT_REG));
7844 _endLazyDPSEvaluation();
7845 *lsb = DP2_RESULT_REG;
7849 if (sameRegs (AOP (result), AOP (left)) &&
7850 ((offl + MSB16) == offr))
7852 /* don't crash result[offr] */
7853 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
7854 emitcode ("xch", "a,%s",
7855 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
7859 movLeft2Result (left, offl, result, offr, 0);
7860 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
7862 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
7863 assert(strcmp(*lsb,"a"));
7868 _storeAxResults(char *lsb,
7872 _startLazyDPSEvaluation();
7873 if (AOP_NEEDSACC(result))
7875 /* We have to explicitly update the result LSB.
7877 emitcode("xch","a,%s", lsb);
7878 aopPut(AOP(result), "a", offr);
7879 emitcode("mov","a,%s", lsb);
7881 if (getDataSize (result) > 1)
7883 aopPut (AOP (result), "a", offr + MSB16);
7885 _endLazyDPSEvaluation();
7888 /*-----------------------------------------------------------------*/
7889 /* shiftL2Left2Result - shift left two bytes from left to result */
7890 /*-----------------------------------------------------------------*/
7892 shiftL2Left2Result (operand * left, int offl,
7893 operand * result, int offr, int shCount)
7897 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7899 AccAXLsh (lsb, shCount);
7901 _storeAxResults(lsb, result, offr);
7905 #ifdef BETTER_LITERAL_SHIFT
7906 /*-----------------------------------------------------------------*/
7907 /* shiftR2Left2Result - shift right two bytes from left to result */
7908 /*-----------------------------------------------------------------*/
7910 shiftR2Left2Result (operand * left, int offl,
7911 operand * result, int offr,
7912 int shCount, int sign)
7916 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7918 /* a:x >> shCount (x = lsb(result)) */
7921 AccAXRshS(lsb, shCount);
7925 AccAXRsh(lsb, shCount);
7928 _storeAxResults(lsb, result, offr);
7932 /*-----------------------------------------------------------------*/
7933 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7934 /*-----------------------------------------------------------------*/
7936 shiftLLeftOrResult (operand * left, int offl,
7937 operand * result, int offr, int shCount)
7939 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7940 /* shift left accumulator */
7942 /* or with result */
7943 emitcode ("orl", "a,%s",
7944 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7945 /* back to result */
7946 aopPut (AOP (result), "a", offr);
7951 /*-----------------------------------------------------------------*/
7952 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7953 /*-----------------------------------------------------------------*/
7955 shiftRLeftOrResult (operand * left, int offl,
7956 operand * result, int offr, int shCount)
7958 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7959 /* shift right accumulator */
7961 /* or with result */
7962 emitcode ("orl", "a,%s",
7963 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7964 /* back to result */
7965 aopPut (AOP (result), "a", offr);
7969 #ifdef BETTER_LITERAL_SHIFT
7970 /*-----------------------------------------------------------------*/
7971 /* genlshOne - left shift a one byte quantity by known count */
7972 /*-----------------------------------------------------------------*/
7974 genlshOne (operand * result, operand * left, int shCount)
7976 D (emitcode (";", "genlshOne "););
7977 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7981 #ifdef BETTER_LITERAL_SHIFT
7982 /*-----------------------------------------------------------------*/
7983 /* genlshTwo - left shift two bytes by known amount != 0 */
7984 /*-----------------------------------------------------------------*/
7986 genlshTwo (operand * result, operand * left, int shCount)
7990 D (emitcode (";", "genlshTwo "););
7992 size = getDataSize (result);
7994 /* if shCount >= 8 */
7999 _startLazyDPSEvaluation();
8005 _endLazyDPSEvaluation();
8006 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8007 aopPut (AOP (result), zero, LSB);
8011 movLeft2Result (left, LSB, result, MSB16, 0);
8012 aopPut (AOP (result), zero, LSB);
8013 _endLazyDPSEvaluation();
8018 aopPut (AOP (result), zero, LSB);
8019 _endLazyDPSEvaluation();
8023 /* 1 <= shCount <= 7 */
8028 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8032 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8040 /*-----------------------------------------------------------------*/
8041 /* shiftLLong - shift left one long from left to result */
8042 /* offl = LSB or MSB16 */
8043 /*-----------------------------------------------------------------*/
8045 shiftLLong (operand * left, operand * result, int offr)
8048 int size = AOP_SIZE (result);
8050 if (size >= LSB + offr)
8052 l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8054 emitcode ("add", "a,acc");
8055 if (sameRegs (AOP (left), AOP (result)) &&
8056 size >= MSB16 + offr && offr != LSB)
8057 emitcode ("xch", "a,%s",
8058 aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8060 aopPut (AOP (result), "a", LSB + offr);
8063 if (size >= MSB16 + offr)
8065 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8067 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8069 emitcode ("rlc", "a");
8070 if (sameRegs (AOP (left), AOP (result)) &&
8071 size >= MSB24 + offr && offr != LSB)
8072 emitcode ("xch", "a,%s",
8073 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8075 aopPut (AOP (result), "a", MSB16 + offr);
8078 if (size >= MSB24 + offr)
8080 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8082 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8084 emitcode ("rlc", "a");
8085 if (sameRegs (AOP (left), AOP (result)) &&
8086 size >= MSB32 + offr && offr != LSB)
8087 emitcode ("xch", "a,%s",
8088 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8090 aopPut (AOP (result), "a", MSB24 + offr);
8093 if (size > MSB32 + offr)
8095 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8097 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8099 emitcode ("rlc", "a");
8100 aopPut (AOP (result), "a", MSB32 + offr);
8103 aopPut (AOP (result), zero, LSB);
8109 /*-----------------------------------------------------------------*/
8110 /* genlshFour - shift four byte by a known amount != 0 */
8111 /*-----------------------------------------------------------------*/
8113 genlshFour (operand * result, operand * left, int shCount)
8117 D (emitcode (";", "genlshFour ");
8120 size = AOP_SIZE (result);
8122 /* if shifting more that 3 bytes */
8127 /* lowest order of left goes to the highest
8128 order of the destination */
8129 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8131 movLeft2Result (left, LSB, result, MSB32, 0);
8132 aopPut (AOP (result), zero, LSB);
8133 aopPut (AOP (result), zero, MSB16);
8134 aopPut (AOP (result), zero, MSB24);
8138 /* more than two bytes */
8139 else if (shCount >= 16)
8141 /* lower order two bytes goes to higher order two bytes */
8143 /* if some more remaining */
8145 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8148 movLeft2Result (left, MSB16, result, MSB32, 0);
8149 movLeft2Result (left, LSB, result, MSB24, 0);
8151 aopPut (AOP (result), zero, MSB16);
8152 aopPut (AOP (result), zero, LSB);
8156 /* if more than 1 byte */
8157 else if (shCount >= 8)
8159 /* lower order three bytes goes to higher order three bytes */
8164 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8166 movLeft2Result (left, LSB, result, MSB16, 0);
8172 movLeft2Result (left, MSB24, result, MSB32, 0);
8173 movLeft2Result (left, MSB16, result, MSB24, 0);
8174 movLeft2Result (left, LSB, result, MSB16, 0);
8175 aopPut (AOP (result), zero, LSB);
8177 else if (shCount == 1)
8178 shiftLLong (left, result, MSB16);
8181 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8182 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8183 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8184 aopPut (AOP (result), zero, LSB);
8189 /* 1 <= shCount <= 7 */
8190 else if (shCount <= 2)
8192 shiftLLong (left, result, LSB);
8194 shiftLLong (result, result, LSB);
8196 /* 3 <= shCount <= 7, optimize */
8199 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8200 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8201 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8206 #ifdef BETTER_LITERAL_SHIFT
8207 /*-----------------------------------------------------------------*/
8208 /* genLeftShiftLiteral - left shifting by known count */
8209 /*-----------------------------------------------------------------*/
8211 genLeftShiftLiteral (operand * left,
8216 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8219 size = getSize (operandType (result));
8221 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8223 /* We only handle certain easy cases so far. */
8225 && (shCount < (size * 8))
8229 D(emitcode (";", "genLeftShiftLiteral wimping out"););
8233 freeAsmop (right, NULL, ic, TRUE);
8235 aopOp(left, ic, FALSE, FALSE);
8236 aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8239 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8241 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8242 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8244 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8247 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8249 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8250 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8252 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8258 emitcode ("; shift left ", "result %d, left %d", size,
8262 /* I suppose that the left size >= result size */
8265 _startLazyDPSEvaluation();
8268 movLeft2Result (left, size, result, size, 0);
8270 _endLazyDPSEvaluation();
8272 else if (shCount >= (size * 8))
8274 _startLazyDPSEvaluation();
8277 aopPut (AOP (result), zero, size);
8279 _endLazyDPSEvaluation();
8286 genlshOne (result, left, shCount);
8290 genlshTwo (result, left, shCount);
8294 genlshFour (result, left, shCount);
8298 fprintf(stderr, "*** ack! mystery literal shift!\n");
8302 freeAsmop (left, NULL, ic, TRUE);
8303 freeAsmop (result, NULL, ic, TRUE);
8308 /*-----------------------------------------------------------------*/
8309 /* genLeftShift - generates code for left shifting */
8310 /*-----------------------------------------------------------------*/
8312 genLeftShift (iCode * ic)
8314 operand *left, *right, *result;
8317 symbol *tlbl, *tlbl1;
8319 D (emitcode (";", "genLeftShift "););
8321 right = IC_RIGHT (ic);
8322 left = IC_LEFT (ic);
8323 result = IC_RESULT (ic);
8325 aopOp (right, ic, FALSE, FALSE);
8328 #ifdef BETTER_LITERAL_SHIFT
8329 /* if the shift count is known then do it
8330 as efficiently as possible */
8331 if (AOP_TYPE (right) == AOP_LIT)
8333 if (genLeftShiftLiteral (left, right, result, ic))
8340 /* shift count is unknown then we have to form
8341 a loop get the loop count in B : Note: we take
8342 only the lower order byte since shifting
8343 more that 32 bits make no sense anyway, ( the
8344 largest size of an object can be only 32 bits ) */
8346 if (AOP_TYPE (right) == AOP_LIT)
8348 /* Really should be handled by genLeftShiftLiteral,
8349 * but since I'm too lazy to fix that today, at least we can make
8350 * some small improvement.
8352 emitcode("mov", "b,#!constbyte",
8353 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8357 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8358 emitcode ("inc", "b");
8360 freeAsmop (right, NULL, ic, TRUE);
8361 aopOp (left, ic, FALSE, FALSE);
8362 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8364 /* now move the left to the result if they are not the
8366 if (!sameRegs (AOP (left), AOP (result)) &&
8367 AOP_SIZE (result) > 1)
8370 size = AOP_SIZE (result);
8372 _startLazyDPSEvaluation ();
8375 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8376 if (*l == '@' && (IS_AOP_PREG (result)))
8379 emitcode ("mov", "a,%s", l);
8380 aopPut (AOP (result), "a", offset);
8383 aopPut (AOP (result), l, offset);
8386 _endLazyDPSEvaluation ();
8389 tlbl = newiTempLabel (NULL);
8390 size = AOP_SIZE (result);
8392 tlbl1 = newiTempLabel (NULL);
8394 /* if it is only one byte then */
8397 symbol *tlbl1 = newiTempLabel (NULL);
8399 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8400 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8401 emitcode ("", "!tlabeldef", tlbl->key + 100);
8402 emitcode ("add", "a,acc");
8403 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8404 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8405 aopPut (AOP (result), "a", 0);
8409 reAdjustPreg (AOP (result));
8411 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8412 emitcode ("", "!tlabeldef", tlbl->key + 100);
8413 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8414 emitcode ("add", "a,acc");
8415 aopPut (AOP (result), "a", offset++);
8416 _startLazyDPSEvaluation ();
8419 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8420 emitcode ("rlc", "a");
8421 aopPut (AOP (result), "a", offset++);
8423 _endLazyDPSEvaluation ();
8424 reAdjustPreg (AOP (result));
8426 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8427 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8429 freeAsmop (left, NULL, ic, TRUE);
8430 freeAsmop (result, NULL, ic, TRUE);
8433 #ifdef BETTER_LITERAL_SHIFT
8434 /*-----------------------------------------------------------------*/
8435 /* genrshOne - right shift a one byte quantity by known count */
8436 /*-----------------------------------------------------------------*/
8438 genrshOne (operand * result, operand * left,
8439 int shCount, int sign)
8441 D (emitcode (";", "genrshOne"););
8442 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8446 #ifdef BETTER_LITERAL_SHIFT
8447 /*-----------------------------------------------------------------*/
8448 /* genrshTwo - right shift two bytes by known amount != 0 */
8449 /*-----------------------------------------------------------------*/
8451 genrshTwo (operand * result, operand * left,
8452 int shCount, int sign)
8454 D (emitcode (";", "genrshTwo"););
8456 /* if shCount >= 8 */
8460 _startLazyDPSEvaluation();
8463 shiftR1Left2Result (left, MSB16, result, LSB,
8468 movLeft2Result (left, MSB16, result, LSB, sign);
8470 addSign (result, MSB16, sign);
8471 _endLazyDPSEvaluation();
8474 /* 1 <= shCount <= 7 */
8477 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8482 /*-----------------------------------------------------------------*/
8483 /* shiftRLong - shift right one long from left to result */
8484 /* offl = LSB or MSB16 */
8485 /*-----------------------------------------------------------------*/
8487 shiftRLong (operand * left, int offl,
8488 operand * result, int sign)
8490 int isSameRegs=sameRegs(AOP(left),AOP(result));
8492 if (isSameRegs && offl>1) {
8493 // we are in big trouble, but this shouldn't happen
8494 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8497 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8502 emitcode ("rlc", "a");
8503 emitcode ("subb", "a,acc");
8504 emitcode ("xch", "a,%s",
8505 aopGet(AOP(left), MSB32, FALSE, FALSE, DP2_RESULT_REG));
8507 aopPut (AOP(result), zero, MSB32);
8512 emitcode ("clr", "c");
8514 emitcode ("mov", "c,acc.7");
8517 emitcode ("rrc", "a");
8519 if (isSameRegs && offl==MSB16) {
8521 "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE, DP2_RESULT_REG));
8523 aopPut (AOP (result), "a", MSB32);
8524 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8527 emitcode ("rrc", "a");
8528 if (isSameRegs && offl==1) {
8529 emitcode ("xch", "a,%s",
8530 aopGet (AOP (left), MSB16, FALSE, FALSE, DP2_RESULT_REG));
8532 aopPut (AOP (result), "a", MSB24);
8533 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, NULL));
8535 emitcode ("rrc", "a");
8536 aopPut (AOP (result), "a", MSB16 - offl);
8540 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, NULL));
8541 emitcode ("rrc", "a");
8542 aopPut (AOP (result), "a", LSB);
8546 /*-----------------------------------------------------------------*/
8547 /* genrshFour - shift four byte by a known amount != 0 */
8548 /*-----------------------------------------------------------------*/
8550 genrshFour (operand * result, operand * left,
8551 int shCount, int sign)
8553 D (emitcode (";", "genrshFour"););
8555 /* if shifting more that 3 bytes */
8559 _startLazyDPSEvaluation();
8561 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8563 movLeft2Result (left, MSB32, result, LSB, sign);
8564 addSign (result, MSB16, sign);
8565 _endLazyDPSEvaluation();
8567 else if (shCount >= 16)
8570 _startLazyDPSEvaluation();
8572 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8575 movLeft2Result (left, MSB24, result, LSB, 0);
8576 movLeft2Result (left, MSB32, result, MSB16, sign);
8578 addSign (result, MSB24, sign);
8579 _endLazyDPSEvaluation();
8581 else if (shCount >= 8)
8584 _startLazyDPSEvaluation();
8587 shiftRLong (left, MSB16, result, sign);
8589 else if (shCount == 0)
8591 movLeft2Result (left, MSB16, result, LSB, 0);
8592 movLeft2Result (left, MSB24, result, MSB16, 0);
8593 movLeft2Result (left, MSB32, result, MSB24, sign);
8594 addSign (result, MSB32, sign);
8598 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8599 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8600 /* the last shift is signed */
8601 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8602 addSign (result, MSB32, sign);
8604 _endLazyDPSEvaluation();
8608 /* 1 <= shCount <= 7 */
8611 shiftRLong (left, LSB, result, sign);
8613 shiftRLong (result, LSB, result, sign);
8617 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8618 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8619 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8624 #ifdef BETTER_LITERAL_SHIFT
8625 /*-----------------------------------------------------------------*/
8626 /* genRightShiftLiteral - right shifting by known count */
8627 /*-----------------------------------------------------------------*/
8629 genRightShiftLiteral (operand * left,
8635 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8638 size = getSize (operandType (result));
8640 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8642 /* We only handle certain easy cases so far. */
8644 && (shCount < (size * 8))
8649 D(emitcode (";", "genRightShiftLiteral wimping out"););
8653 freeAsmop (right, NULL, ic, TRUE);
8655 aopOp (left, ic, FALSE, FALSE);
8656 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8659 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8663 /* test the LEFT size !!! */
8665 /* I suppose that the left size >= result size */
8668 size = getDataSize (result);
8669 _startLazyDPSEvaluation();
8672 movLeft2Result (left, size, result, size, 0);
8674 _endLazyDPSEvaluation();
8676 else if (shCount >= (size * 8))
8680 /* get sign in acc.7 */
8681 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
8683 addSign (result, LSB, sign);
8690 genrshOne (result, left, shCount, sign);
8694 genrshTwo (result, left, shCount, sign);
8698 genrshFour (result, left, shCount, sign);
8705 freeAsmop (left, NULL, ic, TRUE);
8706 freeAsmop (result, NULL, ic, TRUE);
8712 /*-----------------------------------------------------------------*/
8713 /* genSignedRightShift - right shift of signed number */
8714 /*-----------------------------------------------------------------*/
8716 genSignedRightShift (iCode * ic)
8718 operand *right, *left, *result;
8721 symbol *tlbl, *tlbl1;
8723 D (emitcode (";", "genSignedRightShift "););
8725 /* we do it the hard way put the shift count in b
8726 and loop thru preserving the sign */
8728 right = IC_RIGHT (ic);
8729 left = IC_LEFT (ic);
8730 result = IC_RESULT (ic);
8732 aopOp (right, ic, FALSE, FALSE);
8734 #ifdef BETTER_LITERAL_SHIFT
8735 if (AOP_TYPE (right) == AOP_LIT)
8737 if (genRightShiftLiteral (left, right, result, ic, 1))
8743 /* shift count is unknown then we have to form
8744 a loop get the loop count in B : Note: we take
8745 only the lower order byte since shifting
8746 more that 32 bits make no sense anyway, ( the
8747 largest size of an object can be only 32 bits ) */
8749 if (AOP_TYPE (right) == AOP_LIT)
8751 /* Really should be handled by genRightShiftLiteral,
8752 * but since I'm too lazy to fix that today, at least we can make
8753 * some small improvement.
8755 emitcode("mov", "b,#!constbyte",
8756 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8760 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8761 emitcode ("inc", "b");
8763 freeAsmop (right, NULL, ic, TRUE);
8764 aopOp (left, ic, FALSE, FALSE);
8765 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8767 /* now move the left to the result if they are not the
8769 if (!sameRegs (AOP (left), AOP (result)) &&
8770 AOP_SIZE (result) > 1)
8773 size = AOP_SIZE (result);
8775 _startLazyDPSEvaluation ();
8778 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8779 if (*l == '@' && IS_AOP_PREG (result))
8782 emitcode ("mov", "a,%s", l);
8783 aopPut (AOP (result), "a", offset);
8786 aopPut (AOP (result), l, offset);
8789 _endLazyDPSEvaluation ();
8792 /* mov the highest order bit to OVR */
8793 tlbl = newiTempLabel (NULL);
8794 tlbl1 = newiTempLabel (NULL);
8796 size = AOP_SIZE (result);
8798 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
8799 emitcode ("rlc", "a");
8800 emitcode ("mov", "ov,c");
8801 /* if it is only one byte then */
8804 MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8805 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8806 emitcode ("", "!tlabeldef", tlbl->key + 100);
8807 emitcode ("mov", "c,ov");
8808 emitcode ("rrc", "a");
8809 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8810 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8811 aopPut (AOP (result), "a", 0);
8815 reAdjustPreg (AOP (result));
8816 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8817 emitcode ("", "!tlabeldef", tlbl->key + 100);
8818 emitcode ("mov", "c,ov");
8819 _startLazyDPSEvaluation ();
8822 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8823 emitcode ("rrc", "a");
8824 aopPut (AOP (result), "a", offset--);
8826 _endLazyDPSEvaluation ();
8827 reAdjustPreg (AOP (result));
8828 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8829 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8832 freeAsmop (left, NULL, ic, TRUE);
8833 freeAsmop (result, NULL, ic, TRUE);
8836 /*-----------------------------------------------------------------*/
8837 /* genRightShift - generate code for right shifting */
8838 /*-----------------------------------------------------------------*/
8840 genRightShift (iCode * ic)
8842 operand *right, *left, *result;
8846 symbol *tlbl, *tlbl1;
8848 D (emitcode (";", "genRightShift "););
8850 /* if signed then we do it the hard way preserve the
8851 sign bit moving it inwards */
8852 retype = getSpec (operandType (IC_RESULT (ic)));
8854 if (!SPEC_USIGN (retype))
8856 genSignedRightShift (ic);
8860 /* signed & unsigned types are treated the same : i.e. the
8861 signed is NOT propagated inwards : quoting from the
8862 ANSI - standard : "for E1 >> E2, is equivalent to division
8863 by 2**E2 if unsigned or if it has a non-negative value,
8864 otherwise the result is implementation defined ", MY definition
8865 is that the sign does not get propagated */
8867 right = IC_RIGHT (ic);
8868 left = IC_LEFT (ic);
8869 result = IC_RESULT (ic);
8871 aopOp (right, ic, FALSE, FALSE);
8873 #ifdef BETTER_LITERAL_SHIFT
8874 /* if the shift count is known then do it
8875 as efficiently as possible */
8876 if (AOP_TYPE (right) == AOP_LIT)
8878 if (genRightShiftLiteral (left, right, result, ic, 0))
8885 /* shift count is unknown then we have to form
8886 a loop get the loop count in B : Note: we take
8887 only the lower order byte since shifting
8888 more that 32 bits make no sense anyway, ( the
8889 largest size of an object can be only 32 bits ) */
8891 if (AOP_TYPE (right) == AOP_LIT)
8893 /* Really should be handled by genRightShiftLiteral,
8894 * but since I'm too lazy to fix that today, at least we can make
8895 * some small improvement.
8897 emitcode("mov", "b,#!constbyte",
8898 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8902 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8903 emitcode ("inc", "b");
8905 freeAsmop (right, NULL, ic, TRUE);
8906 aopOp (left, ic, FALSE, FALSE);
8907 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8909 /* now move the left to the result if they are not the
8911 if (!sameRegs (AOP (left), AOP (result)) &&
8912 AOP_SIZE (result) > 1)
8915 size = AOP_SIZE (result);
8917 _startLazyDPSEvaluation ();
8920 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8921 if (*l == '@' && IS_AOP_PREG (result))
8924 emitcode ("mov", "a,%s", l);
8925 aopPut (AOP (result), "a", offset);
8928 aopPut (AOP (result), l, offset);
8931 _endLazyDPSEvaluation ();
8934 tlbl = newiTempLabel (NULL);
8935 tlbl1 = newiTempLabel (NULL);
8936 size = AOP_SIZE (result);
8939 /* if it is only one byte then */
8942 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8943 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8944 emitcode ("", "!tlabeldef", tlbl->key + 100);
8946 emitcode ("rrc", "a");
8947 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8948 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8949 aopPut (AOP (result), "a", 0);
8953 reAdjustPreg (AOP (result));
8954 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8955 emitcode ("", "!tlabeldef", tlbl->key + 100);
8957 _startLazyDPSEvaluation ();
8960 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8961 emitcode ("rrc", "a");
8962 aopPut (AOP (result), "a", offset--);
8964 _endLazyDPSEvaluation ();
8965 reAdjustPreg (AOP (result));
8967 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8968 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8971 freeAsmop (left, NULL, ic, TRUE);
8972 freeAsmop (result, NULL, ic, TRUE);
8976 /*-----------------------------------------------------------------*/
8977 /* emitPtrByteGet - emits code to get a byte into A through a */
8978 /* pointer register (R0, R1, or DPTR). The */
8979 /* original value of A can be preserved in B. */
8980 /*-----------------------------------------------------------------*/
8982 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
8989 emitcode ("mov", "b,a");
8990 emitcode ("mov", "a,@%s", rname);
8995 emitcode ("mov", "b,a");
8996 emitcode ("movx", "a,@%s", rname);
9001 emitcode ("mov", "b,a");
9002 emitcode ("movx", "a,@dptr");
9007 emitcode ("mov", "b,a");
9008 emitcode ("clr", "a");
9009 emitcode ("movc", "a,@a+dptr");
9015 emitcode ("push", "b");
9016 emitcode ("push", "acc");
9018 emitcode ("lcall", "__gptrget");
9020 emitcode ("pop", "b");
9025 /*-----------------------------------------------------------------*/
9026 /* emitPtrByteSet - emits code to set a byte from src through a */
9027 /* pointer register (R0, R1, or DPTR). */
9028 /*-----------------------------------------------------------------*/
9030 emitPtrByteSet (char *rname, int p_type, char *src)
9039 emitcode ("mov", "@%s,a", rname);
9042 emitcode ("mov", "@%s,%s", rname, src);
9047 emitcode ("movx", "@%s,a", rname);
9052 emitcode ("movx", "@dptr,a");
9057 emitcode ("lcall", "__gptrput");
9062 /*-----------------------------------------------------------------*/
9063 /* genUnpackBits - generates code for unpacking bits */
9064 /*-----------------------------------------------------------------*/
9066 genUnpackBits (operand * result, char *rname, int ptype)
9068 int offset = 0; /* result byte offset */
9069 int rsize; /* result size */
9070 int rlen = 0; /* remaining bitfield length */
9071 sym_link *etype; /* bitfield type information */
9072 int blen; /* bitfield length */
9073 int bstr; /* bitfield starting bit within byte */
9075 D(emitcode ("; genUnpackBits",""));
9077 etype = getSpec (operandType (result));
9078 rsize = getSize (operandType (result));
9079 blen = SPEC_BLEN (etype);
9080 bstr = SPEC_BSTR (etype);
9082 /* If the bitfield length is less than a byte */
9085 emitPtrByteGet (rname, ptype, FALSE);
9087 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
9088 aopPut (AOP (result), "a", offset++);
9092 /* Bit field did not fit in a byte. Copy all
9093 but the partial byte at the end. */
9094 for (rlen=blen;rlen>=8;rlen-=8)
9096 emitPtrByteGet (rname, ptype, FALSE);
9097 aopPut (AOP (result), "a", offset++);
9099 emitcode ("inc", "%s", rname);
9102 /* Handle the partial byte at the end */
9105 emitPtrByteGet (rname, ptype, FALSE);
9106 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
9107 aopPut (AOP (result), "a", offset++);
9115 aopPut (AOP (result), zero, offset++);
9119 /*-----------------------------------------------------------------*/
9120 /* genUnpackBits - generates code for unpacking bits */
9121 /*-----------------------------------------------------------------*/
9123 genUnpackBits (operand * result, char *rname, int ptype)
9131 D (emitcode (";", "genUnpackBits "););
9133 etype = getSpec (operandType (result));
9134 rsize = getSize (operandType (result));
9136 /* read the first byte */
9142 emitcode ("mov", "a,@%s", rname);
9146 emitcode ("movx", "a,@%s", rname);
9150 emitcode ("movx", "a,@dptr");
9154 emitcode ("clr", "a");
9155 emitcode ("movc", "a,@a+dptr");
9159 emitcode ("lcall", "__gptrget");
9163 /* if we have bitdisplacement then it fits */
9164 /* into this byte completely or if length is */
9165 /* less than a byte */
9166 if (((shCnt = SPEC_BSTR (etype)) != 0) || (SPEC_BLEN (etype) <= 8))
9169 /* shift right acc */
9172 emitcode ("anl", "a,#!constbyte",
9173 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
9174 aopPut (AOP (result), "a", offset++);
9178 /* bit field did not fit in a byte */
9179 rlen = SPEC_BLEN (etype);
9180 aopPut (AOP (result), "a", offset++);
9189 emitcode ("inc", "%s", rname);
9190 emitcode ("mov", "a,@%s", rname);
9194 emitcode ("inc", "%s", rname);
9195 emitcode ("movx", "a,@%s", rname);
9199 emitcode ("inc", "dptr");
9200 emitcode ("movx", "a,@dptr");
9204 emitcode ("clr", "a");
9205 emitcode ("inc", "dptr");
9206 emitcode ("movc", "a,@a+dptr");
9210 emitcode ("inc", "dptr");
9211 emitcode ("lcall", "__gptrget");
9216 /* if we are done */
9220 aopPut (AOP (result), "a", offset++);
9226 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
9227 aopPut (AOP (result), "a", offset++);
9235 aopPut (AOP (result), zero, offset++);
9241 /*-----------------------------------------------------------------*/
9242 /* genDataPointerGet - generates code when ptr offset is known */
9243 /*-----------------------------------------------------------------*/
9245 genDataPointerGet (operand * left,
9251 int size, offset = 0;
9252 aopOp (result, ic, TRUE, FALSE);
9254 /* get the string representation of the name */
9255 l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9256 size = AOP_SIZE (result);
9257 _startLazyDPSEvaluation ();
9262 SNPRINTF (buff, sizeof(buff),
9263 "(%s + %d)", l + 1, offset);
9267 SNPRINTF (buff, sizeof(buff),
9270 aopPut (AOP (result), buff, offset++);
9272 _endLazyDPSEvaluation ();
9274 freeAsmop (left, NULL, ic, TRUE);
9275 freeAsmop (result, NULL, ic, TRUE);
9278 /*-----------------------------------------------------------------*/
9279 /* genNearPointerGet - emitcode for near pointer fetch */
9280 /*-----------------------------------------------------------------*/
9282 genNearPointerGet (operand * left,
9290 sym_link *rtype, *retype, *letype;
9291 sym_link *ltype = operandType (left);
9294 rtype = operandType (result);
9295 retype = getSpec (rtype);
9296 letype = getSpec (ltype);
9298 aopOp (left, ic, FALSE, FALSE);
9300 /* if left is rematerialisable and
9301 result is not bit variable type and
9302 the left is pointer to data space i.e
9303 lower 128 bytes of space */
9304 if (AOP_TYPE (left) == AOP_IMMD &&
9305 !IS_BITVAR (retype) &&
9306 !IS_BITVAR (letype) &&
9307 DCL_TYPE (ltype) == POINTER)
9309 genDataPointerGet (left, result, ic);
9313 /* if the value is already in a pointer register
9314 then don't need anything more */
9315 if (!AOP_INPREG (AOP (left)))
9317 /* otherwise get a free pointer register */
9319 preg = getFreePtr (ic, &aop, FALSE);
9320 emitcode ("mov", "%s,%s",
9322 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9326 rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9328 freeAsmop (left, NULL, ic, TRUE);
9329 aopOp (result, ic, FALSE, FALSE);
9331 /* if bitfield then unpack the bits */
9332 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9333 genUnpackBits (result, rname, POINTER);
9336 /* we have can just get the values */
9337 int size = AOP_SIZE (result);
9342 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9345 emitcode ("mov", "a,@%s", rname);
9346 aopPut (AOP (result), "a", offset);
9350 SNPRINTF (buff, sizeof(buff), "@%s", rname);
9351 aopPut (AOP (result), buff, offset);
9356 emitcode ("inc", "%s", rname);
9361 /* now some housekeeping stuff */
9364 /* we had to allocate for this iCode */
9365 if (pi) { /* post increment present */
9366 aopPut(AOP ( left ),rname,0);
9368 freeAsmop (NULL, aop, ic, TRUE);
9372 /* we did not allocate which means left
9373 already in a pointer register, then
9374 if size > 0 && this could be used again
9375 we have to point it back to where it
9377 if (AOP_SIZE (result) > 1 &&
9378 !OP_SYMBOL (left)->remat &&
9379 (OP_SYMBOL (left)->liveTo > ic->seq ||
9383 int size = AOP_SIZE (result) - 1;
9385 emitcode ("dec", "%s", rname);
9390 freeAsmop (result, NULL, ic, TRUE);
9391 if (pi) pi->generated = 1;
9394 /*-----------------------------------------------------------------*/
9395 /* genPagedPointerGet - emitcode for paged pointer fetch */
9396 /*-----------------------------------------------------------------*/
9398 genPagedPointerGet (operand * left,
9406 sym_link *rtype, *retype, *letype;
9408 rtype = operandType (result);
9409 retype = getSpec (rtype);
9410 letype = getSpec (operandType (left));
9411 aopOp (left, ic, FALSE, FALSE);
9413 /* if the value is already in a pointer register
9414 then don't need anything more */
9415 if (!AOP_INPREG (AOP (left)))
9417 /* otherwise get a free pointer register */
9419 preg = getFreePtr (ic, &aop, FALSE);
9420 emitcode ("mov", "%s,%s",
9422 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9426 rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9428 freeAsmop (left, NULL, ic, TRUE);
9429 aopOp (result, ic, FALSE, FALSE);
9431 /* if bitfield then unpack the bits */
9432 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9433 genUnpackBits (result, rname, PPOINTER);
9436 /* we have can just get the values */
9437 int size = AOP_SIZE (result);
9443 emitcode ("movx", "a,@%s", rname);
9444 aopPut (AOP (result), "a", offset);
9449 emitcode ("inc", "%s", rname);
9453 /* now some housekeeping stuff */
9456 /* we had to allocate for this iCode */
9457 if (pi) aopPut ( AOP (left), rname, 0);
9458 freeAsmop (NULL, aop, ic, TRUE);
9462 /* we did not allocate which means left
9463 already in a pointer register, then
9464 if size > 0 && this could be used again
9465 we have to point it back to where it
9467 if (AOP_SIZE (result) > 1 &&
9468 !OP_SYMBOL (left)->remat &&
9469 (OP_SYMBOL (left)->liveTo > ic->seq ||
9473 int size = AOP_SIZE (result) - 1;
9475 emitcode ("dec", "%s", rname);
9480 freeAsmop (result, NULL, ic, TRUE);
9481 if (pi) pi->generated = 1;
9484 /*-----------------------------------------------------------------*/
9485 /* genFarPointerGet - gget value from far space */
9486 /*-----------------------------------------------------------------*/
9488 genFarPointerGet (operand * left,
9489 operand * result, iCode * ic, iCode *pi)
9491 int size, offset, dopi=1;
9492 sym_link *retype = getSpec (operandType (result));
9493 sym_link *letype = getSpec (operandType (left));
9494 D (emitcode (";", "genFarPointerGet"););
9496 aopOp (left, ic, FALSE, FALSE);
9498 /* if the operand is already in dptr
9499 then we do nothing else we move the value to dptr */
9500 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9502 /* if this is remateriazable */
9503 if (AOP_TYPE (left) == AOP_IMMD)
9505 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9509 /* we need to get it byte by byte */
9510 _startLazyDPSEvaluation ();
9511 if (AOP_TYPE (left) != AOP_DPTR)
9513 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9514 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9515 if (options.model == MODEL_FLAT24)
9516 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9520 /* We need to generate a load to DPTR indirect through DPTR. */
9521 D (emitcode (";", "genFarPointerGet -- indirection special case."););
9522 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9523 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9524 if (options.model == MODEL_FLAT24)
9525 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9526 emitcode ("pop", "dph");
9527 emitcode ("pop", "dpl");
9530 _endLazyDPSEvaluation ();
9533 /* so dptr know contains the address */
9534 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9536 /* if bit then unpack */
9537 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9538 if (AOP_INDPTRn(left)) {
9539 genSetDPTR(AOP(left)->aopu.dptr);
9541 genUnpackBits (result, "dptr", FPOINTER);
9542 if (AOP_INDPTRn(left)) {
9547 size = AOP_SIZE (result);
9550 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9552 genSetDPTR(AOP(left)->aopu.dptr);
9553 emitcode ("movx", "a,@dptr");
9554 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9555 emitcode ("inc", "dptr");
9557 aopPut (AOP (result), "a", offset++);
9560 _startLazyDPSEvaluation ();
9562 if (AOP_INDPTRn(left)) {
9563 genSetDPTR(AOP(left)->aopu.dptr);
9569 emitcode ("movx", "a,@dptr");
9570 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9571 emitcode ("inc", "dptr");
9573 aopPut (AOP (result), "a", offset++);
9575 _endLazyDPSEvaluation ();
9578 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9579 if (!AOP_INDPTRn(left)) {
9580 _startLazyDPSEvaluation ();
9581 aopPut ( AOP (left), "dpl", 0);
9582 aopPut ( AOP (left), "dph", 1);
9583 if (options.model == MODEL_FLAT24)
9584 aopPut ( AOP (left), "dpx", 2);
9585 _endLazyDPSEvaluation ();
9588 } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) &&
9589 AOP_SIZE(result) > 1 &&
9591 (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
9593 size = AOP_SIZE (result) - 1;
9594 if (AOP_INDPTRn(left)) {
9595 genSetDPTR(AOP(left)->aopu.dptr);
9597 while (size--) emitcode ("lcall","__decdptr");
9598 if (AOP_INDPTRn(left)) {
9603 freeAsmop (left, NULL, ic, TRUE);
9604 freeAsmop (result, NULL, ic, TRUE);
9607 /*-----------------------------------------------------------------*/
9608 /* genCodePointerGet - get value from code space */
9609 /*-----------------------------------------------------------------*/
9611 genCodePointerGet (operand * left,
9612 operand * result, iCode * ic, iCode *pi)
9614 int size, offset, dopi=1;
9615 sym_link *retype = getSpec (operandType (result));
9617 aopOp (left, ic, FALSE, FALSE);
9619 /* if the operand is already in dptr
9620 then we do nothing else we move the value to dptr */
9621 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
9623 /* if this is remateriazable */
9624 if (AOP_TYPE (left) == AOP_IMMD)
9626 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9629 { /* we need to get it byte by byte */
9630 _startLazyDPSEvaluation ();
9631 if (AOP_TYPE (left) != AOP_DPTR)
9633 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9634 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9635 if (options.model == MODEL_FLAT24)
9636 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9640 /* We need to generate a load to DPTR indirect through DPTR. */
9641 D (emitcode (";", "gencodePointerGet -- indirection special case."););
9642 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9643 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9644 if (options.model == MODEL_FLAT24)
9645 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9646 emitcode ("pop", "dph");
9647 emitcode ("pop", "dpl");
9650 _endLazyDPSEvaluation ();
9653 /* so dptr know contains the address */
9654 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9656 /* if bit then unpack */
9657 if (IS_BITVAR (retype)) {
9658 if (AOP_INDPTRn(left)) {
9659 genSetDPTR(AOP(left)->aopu.dptr);
9661 genUnpackBits (result, "dptr", CPOINTER);
9662 if (AOP_INDPTRn(left)) {
9667 size = AOP_SIZE (result);
9669 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9671 genSetDPTR(AOP(left)->aopu.dptr);
9672 emitcode ("clr", "a");
9673 emitcode ("movc", "a,@a+dptr");
9674 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9675 emitcode ("inc", "dptr");
9677 aopPut (AOP (result), "a", offset++);
9680 _startLazyDPSEvaluation ();
9683 if (AOP_INDPTRn(left)) {
9684 genSetDPTR(AOP(left)->aopu.dptr);
9690 emitcode ("clr", "a");
9691 emitcode ("movc", "a,@a+dptr");
9692 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9693 emitcode ("inc", "dptr");
9694 aopPut (AOP (result), "a", offset++);
9696 _endLazyDPSEvaluation ();
9699 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9700 if (!AOP_INDPTRn(left)) {
9701 _startLazyDPSEvaluation ();
9703 aopPut ( AOP (left), "dpl", 0);
9704 aopPut ( AOP (left), "dph", 1);
9705 if (options.model == MODEL_FLAT24)
9706 aopPut ( AOP (left), "dpx", 2);
9708 _endLazyDPSEvaluation ();
9711 } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
9712 AOP_SIZE(result) > 1 &&
9713 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9715 size = AOP_SIZE (result) - 1;
9716 if (AOP_INDPTRn(left)) {
9717 genSetDPTR(AOP(left)->aopu.dptr);
9719 while (size--) emitcode ("lcall","__decdptr");
9720 if (AOP_INDPTRn(left)) {
9725 freeAsmop (left, NULL, ic, TRUE);
9726 freeAsmop (result, NULL, ic, TRUE);
9729 /*-----------------------------------------------------------------*/
9730 /* genGenPointerGet - gget value from generic pointer space */
9731 /*-----------------------------------------------------------------*/
9733 genGenPointerGet (operand * left,
9734 operand * result, iCode * ic, iCode * pi)
9737 sym_link *retype = getSpec (operandType (result));
9738 sym_link *letype = getSpec (operandType (left));
9740 D (emitcode (";", "genGenPointerGet "); );
9742 aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
9744 /* if the operand is already in dptr
9745 then we do nothing else we move the value to dptr */
9746 if (AOP_TYPE (left) != AOP_STR)
9748 /* if this is remateriazable */
9749 if (AOP_TYPE (left) == AOP_IMMD)
9751 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9752 if (AOP(left)->aopu.aop_immd.from_cast_remat)
9754 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
9758 emitcode ("mov", "b,#%d", pointerCode (retype));
9762 { /* we need to get it byte by byte */
9763 _startLazyDPSEvaluation ();
9764 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
9765 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
9766 if (options.model == MODEL_FLAT24) {
9767 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9768 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
9770 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9772 _endLazyDPSEvaluation ();
9776 /* so dptr-b now contains the address */
9778 aopOp (result, ic, FALSE, TRUE);
9781 /* if bit then unpack */
9782 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9784 genUnpackBits (result, "dptr", GPOINTER);
9788 size = AOP_SIZE (result);
9795 // Get two bytes at a time, results in _AP & A.
9796 // dptr will be incremented ONCE by __gptrgetWord.
9798 // Note: any change here must be coordinated
9799 // with the implementation of __gptrgetWord
9800 // in device/lib/_gptrget.c
9801 emitcode ("lcall", "__gptrgetWord");
9802 aopPut (AOP (result), DP2_RESULT_REG, offset++);
9803 aopPut (AOP (result), "a", offset++);
9808 // Only one byte to get.
9809 emitcode ("lcall", "__gptrget");
9810 aopPut (AOP (result), "a", offset++);
9813 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9815 emitcode ("inc", "dptr");
9820 if (pi && AOP_TYPE (left) != AOP_IMMD) {
9821 _startLazyDPSEvaluation ();
9823 aopPut ( AOP (left), "dpl", 0);
9824 aopPut ( AOP (left), "dph", 1);
9825 if (options.model == MODEL_FLAT24) {
9826 aopPut ( AOP (left), "dpx", 2);
9827 aopPut ( AOP (left), "b", 3);
9828 } else aopPut ( AOP (left), "b", 2);
9830 _endLazyDPSEvaluation ();
9833 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9834 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9836 size = AOP_SIZE (result) - 1;
9837 while (size--) emitcode ("lcall","__decdptr");
9840 freeAsmop (left, NULL, ic, TRUE);
9841 freeAsmop (result, NULL, ic, TRUE);
9844 /*-----------------------------------------------------------------*/
9845 /* genPointerGet - generate code for pointer get */
9846 /*-----------------------------------------------------------------*/
9848 genPointerGet (iCode * ic, iCode *pi)
9850 operand *left, *result;
9851 sym_link *type, *etype;
9854 D (emitcode (";", "genPointerGet ");
9857 left = IC_LEFT (ic);
9858 result = IC_RESULT (ic);
9860 /* depending on the type of pointer we need to
9861 move it to the correct pointer register */
9862 type = operandType (left);
9863 etype = getSpec (type);
9864 /* if left is of type of pointer then it is simple */
9865 if (IS_PTR (type) && !IS_FUNC (type->next))
9866 p_type = DCL_TYPE (type);
9869 /* we have to go by the storage class */
9870 p_type = PTR_TYPE (SPEC_OCLS (etype));
9872 /* special case when cast remat */
9873 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9874 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9875 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9876 type = operandType (left);
9877 p_type = DCL_TYPE (type);
9879 /* now that we have the pointer type we assign
9880 the pointer values */
9886 genNearPointerGet (left, result, ic, pi);
9890 genPagedPointerGet (left, result, ic, pi);
9894 genFarPointerGet (left, result, ic, pi);
9898 genCodePointerGet (left, result, ic, pi);
9902 genGenPointerGet (left, result, ic, pi);
9908 /*-----------------------------------------------------------------*/
9909 /* genPackBits - generates code for packed bit storage */
9910 /*-----------------------------------------------------------------*/
9912 genPackBits (sym_link * etype,
9914 char *rname, int p_type)
9916 int offset = 0; /* source byte offset */
9917 int rlen = 0; /* remaining bitfield length */
9918 int blen; /* bitfield length */
9919 int bstr; /* bitfield starting bit within byte */
9920 int litval; /* source literal value (if AOP_LIT) */
9921 unsigned char mask; /* bitmask within current byte */
9923 D(emitcode ("; genPackBits",""));
9925 blen = SPEC_BLEN (etype);
9926 bstr = SPEC_BSTR (etype);
9928 /* If the bitfield length is less than a byte */
9931 mask = ((unsigned char) (0xFF << (blen + bstr)) |
9932 (unsigned char) (0xFF >> (8 - bstr)));
9934 if (AOP_TYPE (right) == AOP_LIT)
9936 /* Case with a bitfield length <8 and literal source
9938 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9940 litval &= (~mask) & 0xff;
9941 emitPtrByteGet (rname, p_type, FALSE);
9942 if ((mask|litval)!=0xff)
9943 emitcode ("anl","a,#!constbyte", mask);
9945 emitcode ("orl","a,#!constbyte", litval);
9949 if ((blen==1) && (p_type!=GPOINTER))
9951 /* Case with a bitfield length == 1 and no generic pointer
9953 if (AOP_TYPE (right) == AOP_CRY)
9954 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9957 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
9958 emitcode ("rrc","a");
9960 emitPtrByteGet (rname, p_type, FALSE);
9961 emitcode ("mov","acc.%d,c",bstr);
9965 /* Case with a bitfield length < 8 and arbitrary source
9967 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
9968 /* shift and mask source value */
9970 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
9972 /* transfer A to B and get next byte */
9973 emitPtrByteGet (rname, p_type, TRUE);
9975 emitcode ("anl", "a,#!constbyte", mask);
9976 emitcode ("orl", "a,b");
9977 if (p_type == GPOINTER)
9978 emitcode ("pop", "b");
9982 emitPtrByteSet (rname, p_type, "a");
9986 /* Bit length is greater than 7 bits. In this case, copy */
9987 /* all except the partial byte at the end */
9988 for (rlen=blen;rlen>=8;rlen-=8)
9990 emitPtrByteSet (rname, p_type,
9991 aopGet (AOP (right), offset++, FALSE, FALSE, NULL) );
9993 emitcode ("inc", "%s", rname);
9996 /* If there was a partial byte at the end */
9999 mask = (((unsigned char) -1 << rlen) & 0xff);
10001 if (AOP_TYPE (right) == AOP_LIT)
10003 /* Case with partial byte and literal source
10005 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10006 litval >>= (blen-rlen);
10007 litval &= (~mask) & 0xff;
10008 emitPtrByteGet (rname, p_type, FALSE);
10009 if ((mask|litval)!=0xff)
10010 emitcode ("anl","a,#!constbyte", mask);
10012 emitcode ("orl","a,#!constbyte", litval);
10016 /* Case with partial byte and arbitrary source
10018 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10019 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10021 /* transfer A to B and get next byte */
10022 emitPtrByteGet (rname, p_type, TRUE);
10024 emitcode ("anl", "a,#!constbyte", mask);
10025 emitcode ("orl", "a,b");
10026 if (p_type == GPOINTER)
10027 emitcode ("pop", "b");
10029 emitPtrByteSet (rname, p_type, "a");
10035 /*-----------------------------------------------------------------*/
10036 /* genPackBits - generates code for packed bit storage */
10037 /*-----------------------------------------------------------------*/
10039 genPackBits (sym_link * etype,
10041 char *rname, int p_type)
10049 blen = SPEC_BLEN (etype);
10050 bstr = SPEC_BSTR (etype);
10052 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10054 /* if the bit lenth is less than or */
10055 /* it exactly fits a byte then */
10056 if (SPEC_BLEN (etype) <= 8)
10058 unsigned char mask = ((unsigned char) (0xFF << (blen + bstr)) |
10059 (unsigned char) (0xFF >> (8 - bstr)));
10060 shCount = SPEC_BSTR (etype);
10062 /* shift left acc */
10065 if (SPEC_BLEN (etype) < 8)
10066 { /* if smaller than a byte */
10068 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10073 emitcode ("mov", "b,a");
10074 emitcode ("mov", "a,@%s", rname);
10078 emitcode ("mov", "b,a");
10079 emitcode ("movx", "a,@dptr");
10083 emitcode ("push", "b");
10084 emitcode ("push", "acc");
10085 emitcode ("lcall", "__gptrget");
10086 emitcode ("pop", "b");
10090 emitcode ("anl", "a,#!constbyte", mask);
10091 emitcode ("orl", "a,b");
10092 if (p_type == GPOINTER)
10093 emitcode ("pop", "b");
10100 emitcode ("mov", "@%s,a", rname);
10104 emitcode ("movx", "@dptr,a");
10108 emitcode ("lcall", "__gptrput");
10113 if (SPEC_BLEN (etype) <= 8)
10116 emitcode ("inc", "%s", rname);
10117 rLen = SPEC_BLEN (etype);
10119 /* now generate for lengths greater than one byte */
10123 l = aopGet (AOP (right), offset++, FALSE, TRUE, NULL);
10135 emitcode ("mov", "@%s,a", rname);
10138 emitcode ("mov", "@%s,%s", rname, l);
10143 emitcode ("movx", "@dptr,a");
10148 emitcode ("lcall", "__gptrput");
10151 emitcode ("inc", "%s", rname);
10156 /* last last was not complete */
10159 emitcode ("anl", "a,#!constbyte",
10160 (~(((unsigned char) -1 << rLen) & 0xff)) & 0xff);
10162 /* save the byte & read byte */
10166 emitcode ("mov", "b,a");
10167 emitcode ("mov", "a,@%s", rname);
10171 emitcode ("mov", "b,a");
10172 emitcode ("movx", "a,@dptr");
10176 emitcode ("push", "b");
10177 emitcode ("push", "acc");
10178 emitcode ("lcall", "__gptrget");
10179 emitcode ("pop", "b");
10183 emitcode ("anl", "a,#!constbyte", (((unsigned char) -1 << rLen) & 0xff));
10184 emitcode ("orl", "a,b");
10187 if (p_type == GPOINTER)
10188 emitcode ("pop", "b");
10194 emitcode ("mov", "@%s,a", rname);
10198 emitcode ("movx", "@dptr,a");
10202 emitcode ("lcall", "__gptrput");
10208 /*-----------------------------------------------------------------*/
10209 /* genDataPointerSet - remat pointer to data space */
10210 /*-----------------------------------------------------------------*/
10212 genDataPointerSet (operand * right,
10216 int size, offset = 0;
10217 char *l, buff[256];
10219 aopOp (right, ic, FALSE, FALSE);
10221 l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
10222 size = AOP_SIZE (right);
10227 SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
10231 SNPRINTF (buff, sizeof(buff), "%s", l + 1);
10234 emitcode ("mov", "%s,%s", buff,
10235 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10238 freeAsmop (right, NULL, ic, TRUE);
10239 freeAsmop (result, NULL, ic, TRUE);
10242 /*-----------------------------------------------------------------*/
10243 /* genNearPointerSet - emitcode for near pointer put */
10244 /*-----------------------------------------------------------------*/
10246 genNearPointerSet (operand * right,
10253 sym_link *retype, *letype;
10254 sym_link *ptype = operandType (result);
10256 retype = getSpec (operandType (right));
10257 letype = getSpec (ptype);
10259 aopOp (result, ic, FALSE, FALSE);
10261 /* if the result is rematerializable &
10262 in data space & not a bit variable */
10263 if (AOP_TYPE (result) == AOP_IMMD &&
10264 DCL_TYPE (ptype) == POINTER &&
10265 !IS_BITVAR (retype) &&
10266 !IS_BITVAR (letype))
10268 genDataPointerSet (right, result, ic);
10272 /* if the value is already in a pointer register
10273 then don't need anything more */
10274 if (!AOP_INPREG (AOP (result)))
10276 /* otherwise get a free pointer register */
10279 aop = newAsmop (0);
10280 preg = getFreePtr (ic, &aop, FALSE);
10281 emitcode ("mov", "%s,%s",
10283 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10284 rname = preg->name;
10287 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10289 aopOp (right, ic, FALSE, FALSE);
10291 /* if bitfield then unpack the bits */
10292 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10293 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
10296 /* we have can just get the values */
10297 int size = AOP_SIZE (right);
10302 l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
10306 emitcode ("mov", "@%s,a", rname);
10309 emitcode ("mov", "@%s,%s", rname, l);
10311 emitcode ("inc", "%s", rname);
10316 /* now some housekeeping stuff */
10319 /* we had to allocate for this iCode */
10320 if (pi) aopPut (AOP (result),rname,0);
10321 freeAsmop (NULL, aop, ic, TRUE);
10325 /* we did not allocate which means left
10326 already in a pointer register, then
10327 if size > 0 && this could be used again
10328 we have to point it back to where it
10330 if (AOP_SIZE (right) > 1 &&
10331 !OP_SYMBOL (result)->remat &&
10332 (OP_SYMBOL (result)->liveTo > ic->seq ||
10336 int size = AOP_SIZE (right) - 1;
10338 emitcode ("dec", "%s", rname);
10343 if (pi) pi->generated = 1;
10344 freeAsmop (result, NULL, ic, TRUE);
10345 freeAsmop (right, NULL, ic, TRUE);
10350 /*-----------------------------------------------------------------*/
10351 /* genPagedPointerSet - emitcode for Paged pointer put */
10352 /*-----------------------------------------------------------------*/
10354 genPagedPointerSet (operand * right,
10361 sym_link *retype, *letype;
10363 retype = getSpec (operandType (right));
10364 letype = getSpec (operandType (result));
10366 aopOp (result, ic, FALSE, FALSE);
10368 /* if the value is already in a pointer register
10369 then don't need anything more */
10370 if (!AOP_INPREG (AOP (result)))
10372 /* otherwise get a free pointer register */
10375 aop = newAsmop (0);
10376 preg = getFreePtr (ic, &aop, FALSE);
10377 emitcode ("mov", "%s,%s",
10379 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10380 rname = preg->name;
10383 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10385 aopOp (right, ic, FALSE, FALSE);
10387 /* if bitfield then unpack the bits */
10388 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10389 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
10392 /* we have can just get the values */
10393 int size = AOP_SIZE (right);
10398 MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10400 emitcode ("movx", "@%s,a", rname);
10403 emitcode ("inc", "%s", rname);
10409 /* now some housekeeping stuff */
10412 if (pi) aopPut (AOP (result),rname,0);
10413 /* we had to allocate for this iCode */
10414 freeAsmop (NULL, aop, ic, TRUE);
10418 /* we did not allocate which means left
10419 already in a pointer register, then
10420 if size > 0 && this could be used again
10421 we have to point it back to where it
10423 if (AOP_SIZE (right) > 1 &&
10424 !OP_SYMBOL (result)->remat &&
10425 (OP_SYMBOL (result)->liveTo > ic->seq ||
10429 int size = AOP_SIZE (right) - 1;
10431 emitcode ("dec", "%s", rname);
10436 if (pi) pi->generated = 1;
10437 freeAsmop (result, NULL, ic, TRUE);
10438 freeAsmop (right, NULL, ic, TRUE);
10443 /*-----------------------------------------------------------------*/
10444 /* genFarPointerSet - set value from far space */
10445 /*-----------------------------------------------------------------*/
10447 genFarPointerSet (operand * right,
10448 operand * result, iCode * ic, iCode *pi)
10450 int size, offset, dopi=1;
10451 sym_link *retype = getSpec (operandType (right));
10452 sym_link *letype = getSpec (operandType (result));
10454 aopOp (result, ic, FALSE, FALSE);
10456 /* if the operand is already in dptr
10457 then we do nothing else we move the value to dptr */
10458 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10460 /* if this is remateriazable */
10461 if (AOP_TYPE (result) == AOP_IMMD)
10462 emitcode ("mov", "dptr,%s",
10463 aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10466 /* we need to get it byte by byte */
10467 _startLazyDPSEvaluation ();
10468 if (AOP_TYPE (result) != AOP_DPTR)
10470 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10471 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10472 if (options.model == MODEL_FLAT24)
10473 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10477 /* We need to generate a load to DPTR indirect through DPTR. */
10478 D (emitcode (";", "genFarPointerSet -- indirection special case."););
10480 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10481 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10482 if (options.model == MODEL_FLAT24)
10483 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10484 emitcode ("pop", "dph");
10485 emitcode ("pop", "dpl");
10488 _endLazyDPSEvaluation ();
10491 /* so dptr know contains the address */
10492 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10494 /* if bit then unpack */
10495 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
10496 if (AOP_INDPTRn(result)) {
10497 genSetDPTR(AOP(result)->aopu.dptr);
10499 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
10500 if (AOP_INDPTRn(result)) {
10504 size = AOP_SIZE (right);
10506 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10508 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10510 genSetDPTR(AOP(result)->aopu.dptr);
10511 emitcode ("movx", "@dptr,a");
10512 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10513 emitcode ("inc", "dptr");
10517 _startLazyDPSEvaluation ();
10519 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10521 if (AOP_INDPTRn(result)) {
10522 genSetDPTR(AOP(result)->aopu.dptr);
10528 emitcode ("movx", "@dptr,a");
10529 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10530 emitcode ("inc", "dptr");
10532 _endLazyDPSEvaluation ();
10536 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10537 if (!AOP_INDPTRn(result)) {
10538 _startLazyDPSEvaluation ();
10540 aopPut (AOP(result),"dpl",0);
10541 aopPut (AOP(result),"dph",1);
10542 if (options.model == MODEL_FLAT24)
10543 aopPut (AOP(result),"dpx",2);
10545 _endLazyDPSEvaluation ();
10548 } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
10549 AOP_SIZE(right) > 1 &&
10550 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10552 size = AOP_SIZE (right) - 1;
10553 if (AOP_INDPTRn(result)) {
10554 genSetDPTR(AOP(result)->aopu.dptr);
10556 while (size--) emitcode ("lcall","__decdptr");
10557 if (AOP_INDPTRn(result)) {
10561 freeAsmop (result, NULL, ic, TRUE);
10562 freeAsmop (right, NULL, ic, TRUE);
10565 /*-----------------------------------------------------------------*/
10566 /* genGenPointerSet - set value from generic pointer space */
10567 /*-----------------------------------------------------------------*/
10569 genGenPointerSet (operand * right,
10570 operand * result, iCode * ic, iCode *pi)
10573 sym_link *retype = getSpec (operandType (right));
10574 sym_link *letype = getSpec (operandType (result));
10576 aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10578 /* if the operand is already in dptr
10579 then we do nothing else we move the value to dptr */
10580 if (AOP_TYPE (result) != AOP_STR)
10582 _startLazyDPSEvaluation ();
10583 /* if this is remateriazable */
10584 if (AOP_TYPE (result) == AOP_IMMD)
10586 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10587 if (AOP(result)->aopu.aop_immd.from_cast_remat)
10589 MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10594 "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10598 { /* we need to get it byte by byte */
10599 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10600 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10601 if (options.model == MODEL_FLAT24) {
10602 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10603 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10605 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10608 _endLazyDPSEvaluation ();
10610 /* so dptr + b now contains the address */
10612 aopOp (right, ic, FALSE, TRUE);
10616 /* if bit then unpack */
10617 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10619 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
10623 size = AOP_SIZE (right);
10626 _startLazyDPSEvaluation ();
10631 // Set two bytes at a time, passed in _AP & A.
10632 // dptr will be incremented ONCE by __gptrputWord.
10634 // Note: any change here must be coordinated
10635 // with the implementation of __gptrputWord
10636 // in device/lib/_gptrput.c
10637 emitcode("mov", "_ap, %s",
10638 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10639 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10643 emitcode ("lcall", "__gptrputWord");
10648 // Only one byte to put.
10649 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10653 emitcode ("lcall", "__gptrput");
10656 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10658 emitcode ("inc", "dptr");
10661 _endLazyDPSEvaluation ();
10664 if (pi && AOP_TYPE (result) != AOP_IMMD) {
10665 _startLazyDPSEvaluation ();
10667 aopPut (AOP(result),"dpl",0);
10668 aopPut (AOP(result),"dph",1);
10669 if (options.model == MODEL_FLAT24) {
10670 aopPut (AOP(result),"dpx",2);
10671 aopPut (AOP(result),"b",3);
10673 aopPut (AOP(result),"b",2);
10675 _endLazyDPSEvaluation ();
10678 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10679 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10681 size = AOP_SIZE (right) - 1;
10682 while (size--) emitcode ("lcall","__decdptr");
10684 freeAsmop (result, NULL, ic, TRUE);
10685 freeAsmop (right, NULL, ic, TRUE);
10688 /*-----------------------------------------------------------------*/
10689 /* genPointerSet - stores the value into a pointer location */
10690 /*-----------------------------------------------------------------*/
10692 genPointerSet (iCode * ic, iCode *pi)
10694 operand *right, *result;
10695 sym_link *type, *etype;
10698 D (emitcode (";", "genPointerSet "););
10700 right = IC_RIGHT (ic);
10701 result = IC_RESULT (ic);
10703 /* depending on the type of pointer we need to
10704 move it to the correct pointer register */
10705 type = operandType (result);
10706 etype = getSpec (type);
10707 /* if left is of type of pointer then it is simple */
10708 if (IS_PTR (type) && !IS_FUNC (type->next))
10710 p_type = DCL_TYPE (type);
10714 /* we have to go by the storage class */
10715 p_type = PTR_TYPE (SPEC_OCLS (etype));
10717 /* special case when cast remat */
10718 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10719 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10720 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10721 type = operandType (result);
10722 p_type = DCL_TYPE (type);
10725 /* now that we have the pointer type we assign
10726 the pointer values */
10732 genNearPointerSet (right, result, ic, pi);
10736 genPagedPointerSet (right, result, ic, pi);
10740 genFarPointerSet (right, result, ic, pi);
10744 genGenPointerSet (right, result, ic, pi);
10748 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10749 "genPointerSet: illegal pointer type");
10754 /*-----------------------------------------------------------------*/
10755 /* genIfx - generate code for Ifx statement */
10756 /*-----------------------------------------------------------------*/
10758 genIfx (iCode * ic, iCode * popIc)
10760 operand *cond = IC_COND (ic);
10763 D (emitcode (";", "genIfx "););
10765 aopOp (cond, ic, FALSE, FALSE);
10767 /* get the value into acc */
10768 if (AOP_TYPE (cond) != AOP_CRY)
10777 /* the result is now in the accumulator */
10778 freeAsmop (cond, NULL, ic, TRUE);
10780 /* if there was something to be popped then do it */
10784 /* if the condition is a bit variable */
10785 if (isbit && IS_ITEMP (cond) &&
10788 genIfxJump (ic, SPIL_LOC (cond)->rname);
10790 else if (isbit && !IS_ITEMP (cond))
10792 genIfxJump (ic, OP_SYMBOL (cond)->rname);
10796 genIfxJump (ic, "a");
10802 /*-----------------------------------------------------------------*/
10803 /* genAddrOf - generates code for address of */
10804 /*-----------------------------------------------------------------*/
10806 genAddrOf (iCode * ic)
10808 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10811 D (emitcode (";", "genAddrOf ");
10814 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10816 /* if the operand is on the stack then we
10817 need to get the stack offset of this
10819 if (sym->onStack) {
10821 /* if 10 bit stack */
10822 if (options.stack10bit) {
10826 tsprintf(buff, sizeof(buff),
10827 "#!constbyte",(options.stack_loc >> 16) & 0xff);
10828 /* if it has an offset then we need to compute it */
10829 /* emitcode ("subb", "a,#!constbyte", */
10830 /* -((sym->stack < 0) ? */
10831 /* ((short) (sym->stack - _G.nRegsSaved)) : */
10832 /* ((short) sym->stack)) & 0xff); */
10833 /* emitcode ("mov","b,a"); */
10834 /* emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
10835 /* ((short) (sym->stack - _G.nRegsSaved)) : */
10836 /* ((short) sym->stack)) >> 8) & 0xff); */
10838 emitcode ("mov", "a,_bpx");
10839 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
10840 ((char) (sym->stack - _G.nRegsSaved)) :
10841 ((char) sym->stack )) & 0xff);
10842 emitcode ("mov", "b,a");
10843 emitcode ("mov", "a,_bpx+1");
10845 offset = (((sym->stack < 0) ?
10846 ((short) (sym->stack - _G.nRegsSaved)) :
10847 ((short) sym->stack )) >> 8) & 0xff;
10849 emitcode ("addc","a,#!constbyte", offset);
10851 aopPut (AOP (IC_RESULT (ic)), "b", 0);
10852 aopPut (AOP (IC_RESULT (ic)), "a", 1);
10853 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10855 /* we can just move _bp */
10856 aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10857 aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10858 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10861 /* if it has an offset then we need to compute it */
10863 emitcode ("mov", "a,_bp");
10864 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10865 aopPut (AOP (IC_RESULT (ic)), "a", 0);
10867 /* we can just move _bp */
10868 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10870 /* fill the result with zero */
10871 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10874 if (options.stack10bit && size < (FPTRSIZE - 1)) {
10876 "*** warning: pointer to stack var truncated.\n");
10881 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10887 /* object not on stack then we need the name */
10888 size = AOP_SIZE (IC_RESULT (ic));
10893 char s[SDCC_NAME_MAX];
10897 tsprintf(s, sizeof(s), "#!his",sym->rname);
10900 tsprintf(s, sizeof(s), "#!hihis",sym->rname);
10903 tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
10905 default: /* should not need this (just in case) */
10906 SNPRINTF (s, sizeof(s), "#(%s >> %d)",
10913 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10916 aopPut (AOP (IC_RESULT (ic)), s, offset++);
10920 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10924 #if 0 // obsolete, and buggy for != xdata
10925 /*-----------------------------------------------------------------*/
10926 /* genArrayInit - generates code for address of */
10927 /*-----------------------------------------------------------------*/
10929 genArrayInit (iCode * ic)
10931 literalList *iLoop;
10933 int elementSize = 0, eIndex;
10934 unsigned val, lastVal;
10936 operand *left=IC_LEFT(ic);
10938 D (emitcode (";", "genArrayInit "););
10940 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10942 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10944 // Load immediate value into DPTR.
10945 emitcode("mov", "dptr, %s",
10946 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
10948 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10951 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10952 "Unexpected operand to genArrayInit.\n");
10955 // a regression because of SDCCcse.c:1.52
10956 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10957 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10958 if (options.model == MODEL_FLAT24)
10959 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10963 type = operandType(IC_LEFT(ic));
10965 if (type && type->next)
10967 elementSize = getSize(type->next);
10971 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10972 "can't determine element size in genArrayInit.\n");
10976 iLoop = IC_ARRAYILIST(ic);
10981 bool firstpass = TRUE;
10983 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
10984 iLoop->count, (int)iLoop->literalValue, elementSize);
10990 symbol *tlbl = NULL;
10992 count = ix > 256 ? 256 : ix;
10996 tlbl = newiTempLabel (NULL);
10997 if (firstpass || (count & 0xff))
10999 emitcode("mov", "b, #!constbyte", count & 0xff);
11002 emitcode ("", "!tlabeldef", tlbl->key + 100);
11007 for (eIndex = 0; eIndex < elementSize; eIndex++)
11009 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
11010 if (val != lastVal)
11012 emitcode("mov", "a, #!constbyte", val);
11016 emitcode("movx", "@dptr, a");
11017 emitcode("inc", "dptr");
11022 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
11028 iLoop = iLoop->next;
11031 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
11035 /*-----------------------------------------------------------------*/
11036 /* genFarFarAssign - assignment when both are in far space */
11037 /*-----------------------------------------------------------------*/
11039 genFarFarAssign (operand * result, operand * right, iCode * ic)
11041 int size = AOP_SIZE (right);
11043 symbol *rSym = NULL;
11047 /* quick & easy case. */
11048 D(emitcode(";","genFarFarAssign (1 byte case)"););
11049 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
11050 freeAsmop (right, NULL, ic, FALSE);
11051 /* now assign DPTR to result */
11053 aopOp(result, ic, FALSE, FALSE);
11055 aopPut(AOP(result), "a", 0);
11056 freeAsmop(result, NULL, ic, FALSE);
11060 /* See if we've got an underlying symbol to abuse. */
11061 if (IS_SYMOP(result) && OP_SYMBOL(result))
11063 if (IS_TRUE_SYMOP(result))
11065 rSym = OP_SYMBOL(result);
11067 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
11069 rSym = OP_SYMBOL(result)->usl.spillLoc;
11073 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
11075 /* We can use the '390 auto-toggle feature to good effect here. */
11077 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
11078 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11079 emitcode ("mov", "dptr,#%s", rSym->rname);
11080 /* DP2 = result, DP1 = right, DP1 is current. */
11083 emitcode("movx", "a,@dptr");
11084 emitcode("movx", "@dptr,a");
11087 emitcode("inc", "dptr");
11088 emitcode("inc", "dptr");
11091 emitcode("mov", "dps,#0");
11092 freeAsmop (right, NULL, ic, FALSE);
11094 some alternative code for processors without auto-toggle
11095 no time to test now, so later well put in...kpb
11096 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
11097 emitcode("mov", "dps,#1"); /* Select DPTR2. */
11098 emitcode ("mov", "dptr,#%s", rSym->rname);
11099 /* DP2 = result, DP1 = right, DP1 is current. */
11103 emitcode("movx", "a,@dptr");
11105 emitcode("inc", "dptr");
11106 emitcode("inc", "dps");
11107 emitcode("movx", "@dptr,a");
11109 emitcode("inc", "dptr");
11110 emitcode("inc", "dps");
11112 emitcode("mov", "dps,#0");
11113 freeAsmop (right, NULL, ic, FALSE);
11118 D (emitcode (";", "genFarFarAssign"););
11119 aopOp (result, ic, TRUE, TRUE);
11121 _startLazyDPSEvaluation ();
11125 aopPut (AOP (result),
11126 aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
11129 _endLazyDPSEvaluation ();
11130 freeAsmop (result, NULL, ic, FALSE);
11131 freeAsmop (right, NULL, ic, FALSE);
11135 /*-----------------------------------------------------------------*/
11136 /* genAssign - generate code for assignment */
11137 /*-----------------------------------------------------------------*/
11139 genAssign (iCode * ic)
11141 operand *result, *right;
11143 unsigned long lit = 0L;
11145 D (emitcode (";", "genAssign ");
11148 result = IC_RESULT (ic);
11149 right = IC_RIGHT (ic);
11151 /* if they are the same */
11152 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11155 aopOp (right, ic, FALSE, FALSE);
11157 emitcode (";", "genAssign: resultIsFar = %s",
11158 isOperandInFarSpace (result) ?
11161 /* special case both in far space */
11162 if ((AOP_TYPE (right) == AOP_DPTR ||
11163 AOP_TYPE (right) == AOP_DPTR2) &&
11164 /* IS_TRUE_SYMOP(result) && */
11165 isOperandInFarSpace (result))
11167 genFarFarAssign (result, right, ic);
11171 aopOp (result, ic, TRUE, FALSE);
11173 /* if they are the same registers */
11174 if (sameRegs (AOP (right), AOP (result)))
11177 /* if the result is a bit */
11178 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
11180 /* if the right size is a literal then
11181 we know what the value is */
11182 if (AOP_TYPE (right) == AOP_LIT)
11184 if (((int) operandLitValue (right)))
11185 aopPut (AOP (result), one, 0);
11187 aopPut (AOP (result), zero, 0);
11191 /* the right is also a bit variable */
11192 if (AOP_TYPE (right) == AOP_CRY)
11194 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11195 aopPut (AOP (result), "c", 0);
11199 /* we need to or */
11201 aopPut (AOP (result), "a", 0);
11205 /* bit variables done */
11207 size = AOP_SIZE (result);
11209 if (AOP_TYPE (right) == AOP_LIT)
11210 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11213 (AOP_TYPE (result) != AOP_REG) &&
11214 (AOP_TYPE (right) == AOP_LIT) &&
11215 !IS_FLOAT (operandType (right)))
11217 _startLazyDPSEvaluation ();
11218 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
11220 aopPut (AOP (result),
11221 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11226 /* And now fill the rest with zeros. */
11229 emitcode ("clr", "a");
11233 aopPut (AOP (result), "a", offset++);
11235 _endLazyDPSEvaluation ();
11239 _startLazyDPSEvaluation ();
11242 aopPut (AOP (result),
11243 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11247 _endLazyDPSEvaluation ();
11251 freeAsmop (right, NULL, ic, FALSE);
11252 freeAsmop (result, NULL, ic, TRUE);
11255 /*-----------------------------------------------------------------*/
11256 /* genJumpTab - generates code for jump table */
11257 /*-----------------------------------------------------------------*/
11259 genJumpTab (iCode * ic)
11264 D (emitcode (";", "genJumpTab ");
11267 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
11268 /* get the condition into accumulator */
11269 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
11271 /* multiply by four! */
11272 emitcode ("add", "a,acc");
11273 emitcode ("add", "a,acc");
11274 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11276 jtab = newiTempLabel (NULL);
11277 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
11278 emitcode ("jmp", "@a+dptr");
11279 emitcode ("", "!tlabeldef", jtab->key + 100);
11280 /* now generate the jump labels */
11281 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11282 jtab = setNextItem (IC_JTLABELS (ic)))
11283 emitcode ("ljmp", "!tlabel", jtab->key + 100);
11287 /*-----------------------------------------------------------------*/
11288 /* genCast - gen code for casting */
11289 /*-----------------------------------------------------------------*/
11291 genCast (iCode * ic)
11293 operand *result = IC_RESULT (ic);
11294 sym_link *ctype = operandType (IC_LEFT (ic));
11295 sym_link *rtype = operandType (IC_RIGHT (ic));
11296 operand *right = IC_RIGHT (ic);
11299 D (emitcode (";", "genCast "););
11301 /* if they are equivalent then do nothing */
11302 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11305 aopOp (right, ic, FALSE, FALSE);
11306 aopOp (result, ic, FALSE, AOP_USESDPTR(right));
11308 /* if the result is a bit */
11309 // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
11310 if (IS_BITVAR(OP_SYMBOL(result)->type))
11312 /* if the right size is a literal then
11313 we know what the value is */
11314 if (AOP_TYPE (right) == AOP_LIT)
11316 if (((int) operandLitValue (right)))
11317 aopPut (AOP (result), one, 0);
11319 aopPut (AOP (result), zero, 0);
11324 /* the right is also a bit variable */
11325 if (AOP_TYPE (right) == AOP_CRY)
11327 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11328 aopPut (AOP (result), "c", 0);
11332 /* we need to or */
11334 aopPut (AOP (result), "a", 0);
11338 /* if they are the same size : or less */
11339 if (AOP_SIZE (result) <= AOP_SIZE (right))
11342 /* if they are in the same place */
11343 if (sameRegs (AOP (right), AOP (result)))
11346 /* if they in different places then copy */
11347 size = AOP_SIZE (result);
11349 _startLazyDPSEvaluation ();
11352 aopPut (AOP (result),
11353 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11357 _endLazyDPSEvaluation ();
11362 /* if the result is of type pointer */
11363 if (IS_PTR (ctype))
11367 sym_link *type = operandType (right);
11369 /* pointer to generic pointer */
11370 if (IS_GENPTR (ctype))
11374 p_type = DCL_TYPE (type);
11378 #if OLD_CAST_BEHAVIOR
11379 /* KV: we are converting a non-pointer type to
11380 * a generic pointer. This (ifdef'd out) code
11381 * says that the resulting generic pointer
11382 * should have the same class as the storage
11383 * location of the non-pointer variable.
11385 * For example, converting an int (which happens
11386 * to be stored in DATA space) to a pointer results
11387 * in a DATA generic pointer; if the original int
11388 * in XDATA space, so will be the resulting pointer.
11390 * I don't like that behavior, and thus this change:
11391 * all such conversions will be forced to XDATA and
11392 * throw a warning. If you want some non-XDATA
11393 * type, or you want to suppress the warning, you
11394 * must go through an intermediate cast, like so:
11396 * char _generic *gp = (char _xdata *)(intVar);
11398 sym_link *etype = getSpec (type);
11400 /* we have to go by the storage class */
11401 if (SPEC_OCLS (etype) != generic)
11403 p_type = PTR_TYPE (SPEC_OCLS (etype));
11408 /* Converting unknown class (i.e. register variable)
11409 * to generic pointer. This is not good, but
11410 * we'll make a guess (and throw a warning).
11413 werror (W_INT_TO_GEN_PTR_CAST);
11417 /* the first two bytes are known */
11418 size = GPTRSIZE - 1;
11420 _startLazyDPSEvaluation ();
11423 aopPut (AOP (result),
11424 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11428 _endLazyDPSEvaluation ();
11430 /* the last byte depending on type */
11432 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11437 // pointerTypeToGPByte will have bitched.
11441 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11442 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11447 /* just copy the pointers */
11448 size = AOP_SIZE (result);
11450 _startLazyDPSEvaluation ();
11453 aopPut (AOP (result),
11454 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11458 _endLazyDPSEvaluation ();
11462 /* so we now know that the size of destination is greater
11463 than the size of the source */
11464 /* we move to result for the size of source */
11465 size = AOP_SIZE (right);
11467 _startLazyDPSEvaluation ();
11470 aopPut (AOP (result),
11471 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11475 _endLazyDPSEvaluation ();
11477 /* now depending on the sign of the source && destination */
11478 size = AOP_SIZE (result) - AOP_SIZE (right);
11479 /* if unsigned or not an integral type */
11480 /* also, if the source is a bit, we don't need to sign extend, because
11481 * it can't possibly have set the sign bit.
11483 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
11487 aopPut (AOP (result), zero, offset++);
11492 /* we need to extend the sign :{ */
11493 MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11494 FALSE, FALSE, NULL));
11495 emitcode ("rlc", "a");
11496 emitcode ("subb", "a,acc");
11498 aopPut (AOP (result), "a", offset++);
11501 /* we are done hurray !!!! */
11504 freeAsmop (right, NULL, ic, TRUE);
11505 freeAsmop (result, NULL, ic, TRUE);
11509 /*-----------------------------------------------------------------*/
11510 /* genDjnz - generate decrement & jump if not zero instrucion */
11511 /*-----------------------------------------------------------------*/
11513 genDjnz (iCode * ic, iCode * ifx)
11515 symbol *lbl, *lbl1;
11519 /* if the if condition has a false label
11520 then we cannot save */
11521 if (IC_FALSE (ifx))
11524 /* if the minus is not of the form
11526 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11527 !IS_OP_LITERAL (IC_RIGHT (ic)))
11530 if (operandLitValue (IC_RIGHT (ic)) != 1)
11533 /* if the size of this greater than one then no
11535 if (getSize (operandType (IC_RESULT (ic))) > 1)
11538 /* otherwise we can save BIG */
11539 D(emitcode(";", "genDjnz"););
11541 lbl = newiTempLabel (NULL);
11542 lbl1 = newiTempLabel (NULL);
11544 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11546 if (AOP_NEEDSACC(IC_RESULT(ic)))
11548 /* If the result is accessed indirectly via
11549 * the accumulator, we must explicitly write
11550 * it back after the decrement.
11552 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11554 if (strcmp(rByte, "a"))
11556 /* Something is hopelessly wrong */
11557 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11558 __FILE__, __LINE__);
11559 /* We can just give up; the generated code will be inefficient,
11560 * but what the hey.
11562 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11565 emitcode ("dec", "%s", rByte);
11566 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11567 emitcode ("jnz", "!tlabel", lbl->key + 100);
11569 else if (IS_AOP_PREG (IC_RESULT (ic)))
11571 emitcode ("dec", "%s",
11572 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11573 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11574 emitcode ("jnz", "!tlabel", lbl->key + 100);
11578 emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11581 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11582 emitcode ("", "!tlabeldef", lbl->key + 100);
11583 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11584 emitcode ("", "!tlabeldef", lbl1->key + 100);
11586 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11587 ifx->generated = 1;
11591 /*-----------------------------------------------------------------*/
11592 /* genReceive - generate code for a receive iCode */
11593 /*-----------------------------------------------------------------*/
11595 genReceive (iCode * ic)
11597 int size = getSize (operandType (IC_RESULT (ic)));
11601 D (emitcode (";", "genReceive "););
11603 if (ic->argreg == 1)
11605 /* first parameter */
11606 if (AOP_IS_STR(IC_RESULT(ic)))
11608 /* Nothing to do: it's already in the proper place. */
11615 useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11616 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11617 IS_TRUE_SYMOP (IC_RESULT (ic)));
11620 aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11623 /* Sanity checking... */
11624 if (AOP_USESDPTR(IC_RESULT(ic)))
11626 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11627 "genReceive got unexpected DPTR.");
11629 assignResultValue (IC_RESULT (ic));
11634 /* second receive onwards */
11635 /* this gets a little tricky since unused recevies will be
11636 eliminated, we have saved the reg in the type field . and
11637 we use that to figure out which register to use */
11638 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11639 rb1off = ic->argreg;
11642 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11645 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11648 /*-----------------------------------------------------------------*/
11649 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
11650 /*-----------------------------------------------------------------*/
11651 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11653 operand *from , *to , *count;
11658 /* we know it has to be 3 parameters */
11659 assert (nparms == 3);
11661 rsave = newBitVect(16);
11662 /* save DPTR if it needs to be saved */
11663 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11664 if (bitVectBitValue(ic->rMask,i))
11665 rsave = bitVectSetBit(rsave,i);
11667 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11668 ds390_rUmaskForOp (IC_RESULT(ic))));
11675 aopOp (from, ic->next, FALSE, FALSE);
11677 /* get from into DPTR1 */
11678 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11679 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11680 if (options.model == MODEL_FLAT24) {
11681 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11684 freeAsmop (from, NULL, ic, FALSE);
11685 aopOp (to, ic, FALSE, FALSE);
11686 /* get "to" into DPTR */
11687 /* if the operand is already in dptr
11688 then we do nothing else we move the value to dptr */
11689 if (AOP_TYPE (to) != AOP_STR) {
11690 /* if already in DPTR then we need to push */
11691 if (AOP_TYPE(to) == AOP_DPTR) {
11692 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11693 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11694 if (options.model == MODEL_FLAT24)
11695 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11696 emitcode ("pop", "dph");
11697 emitcode ("pop", "dpl");
11699 _startLazyDPSEvaluation ();
11700 /* if this is remateriazable */
11701 if (AOP_TYPE (to) == AOP_IMMD) {
11702 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11703 } else { /* we need to get it byte by byte */
11704 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11705 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11706 if (options.model == MODEL_FLAT24) {
11707 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11710 _endLazyDPSEvaluation ();
11713 freeAsmop (to, NULL, ic, FALSE);
11714 _G.dptrInUse = _G.dptr1InUse = 1;
11715 aopOp (count, ic->next->next, FALSE,FALSE);
11716 lbl =newiTempLabel(NULL);
11718 /* now for the actual copy */
11719 if (AOP_TYPE(count) == AOP_LIT &&
11720 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11721 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11723 emitcode ("lcall","__bi_memcpyc2x_s");
11725 emitcode ("lcall","__bi_memcpyx2x_s");
11727 freeAsmop (count, NULL, ic, FALSE);
11729 symbol *lbl1 = newiTempLabel(NULL);
11731 emitcode (";"," Auto increment but no djnz");
11732 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11733 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11734 freeAsmop (count, NULL, ic, FALSE);
11735 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11736 emitcode ("","!tlabeldef",lbl->key+100);
11738 emitcode ("clr","a");
11739 emitcode ("movc", "a,@a+dptr");
11741 emitcode ("movx", "a,@dptr");
11742 emitcode ("movx", "@dptr,a");
11743 emitcode ("inc", "dptr");
11744 emitcode ("inc", "dptr");
11745 emitcode ("mov","a,b");
11746 emitcode ("orl","a,_ap");
11747 emitcode ("jz","!tlabel",lbl1->key+100);
11748 emitcode ("mov","a,_ap");
11749 emitcode ("add","a,#!constbyte",0xFF);
11750 emitcode ("mov","_ap,a");
11751 emitcode ("mov","a,b");
11752 emitcode ("addc","a,#!constbyte",0xFF);
11753 emitcode ("mov","b,a");
11754 emitcode ("sjmp","!tlabel",lbl->key+100);
11755 emitcode ("","!tlabeldef",lbl1->key+100);
11757 emitcode ("mov", "dps,#0");
11758 _G.dptrInUse = _G.dptr1InUse = 0;
11759 unsavermask(rsave);
11763 /*-----------------------------------------------------------------*/
11764 /* genMemcmpX2X - gen code for memcmp xdata to xdata */
11765 /*-----------------------------------------------------------------*/
11766 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11768 operand *from , *to , *count;
11773 /* we know it has to be 3 parameters */
11774 assert (nparms == 3);
11776 rsave = newBitVect(16);
11777 /* save DPTR if it needs to be saved */
11778 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11779 if (bitVectBitValue(ic->rMask,i))
11780 rsave = bitVectSetBit(rsave,i);
11782 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11783 ds390_rUmaskForOp (IC_RESULT(ic))));
11790 aopOp (from, ic->next, FALSE, FALSE);
11792 /* get from into DPTR1 */
11793 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11794 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11795 if (options.model == MODEL_FLAT24) {
11796 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11799 freeAsmop (from, NULL, ic, FALSE);
11800 aopOp (to, ic, FALSE, FALSE);
11801 /* get "to" into DPTR */
11802 /* if the operand is already in dptr
11803 then we do nothing else we move the value to dptr */
11804 if (AOP_TYPE (to) != AOP_STR) {
11805 /* if already in DPTR then we need to push */
11806 if (AOP_TYPE(to) == AOP_DPTR) {
11807 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11808 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11809 if (options.model == MODEL_FLAT24)
11810 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11811 emitcode ("pop", "dph");
11812 emitcode ("pop", "dpl");
11814 _startLazyDPSEvaluation ();
11815 /* if this is remateriazable */
11816 if (AOP_TYPE (to) == AOP_IMMD) {
11817 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11818 } else { /* we need to get it byte by byte */
11819 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11820 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11821 if (options.model == MODEL_FLAT24) {
11822 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11825 _endLazyDPSEvaluation ();
11828 freeAsmop (to, NULL, ic, FALSE);
11829 _G.dptrInUse = _G.dptr1InUse = 1;
11830 aopOp (count, ic->next->next, FALSE,FALSE);
11831 lbl =newiTempLabel(NULL);
11832 lbl2 =newiTempLabel(NULL);
11834 /* now for the actual compare */
11835 if (AOP_TYPE(count) == AOP_LIT &&
11836 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11837 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11839 emitcode("lcall","__bi_memcmpc2x_s");
11841 emitcode("lcall","__bi_memcmpx2x_s");
11842 freeAsmop (count, NULL, ic, FALSE);
11843 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11844 aopPut(AOP(IC_RESULT(ic)),"a",0);
11845 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11847 symbol *lbl1 = newiTempLabel(NULL);
11849 emitcode("push","ar0");
11850 emitcode (";"," Auto increment but no djnz");
11851 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11852 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11853 freeAsmop (count, NULL, ic, FALSE);
11854 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11855 emitcode ("","!tlabeldef",lbl->key+100);
11857 emitcode ("clr","a");
11858 emitcode ("movc", "a,@a+dptr");
11860 emitcode ("movx", "a,@dptr");
11861 emitcode ("mov","r0,a");
11862 emitcode ("movx", "a,@dptr");
11863 emitcode ("clr","c");
11864 emitcode ("subb","a,r0");
11865 emitcode ("jnz","!tlabel",lbl2->key+100);
11866 emitcode ("inc", "dptr");
11867 emitcode ("inc", "dptr");
11868 emitcode ("mov","a,b");
11869 emitcode ("orl","a,_ap");
11870 emitcode ("jz","!tlabel",lbl1->key+100);
11871 emitcode ("mov","a,_ap");
11872 emitcode ("add","a,#!constbyte",0xFF);
11873 emitcode ("mov","_ap,a");
11874 emitcode ("mov","a,b");
11875 emitcode ("addc","a,#!constbyte",0xFF);
11876 emitcode ("mov","b,a");
11877 emitcode ("sjmp","!tlabel",lbl->key+100);
11878 emitcode ("","!tlabeldef",lbl1->key+100);
11879 emitcode ("clr","a");
11880 emitcode ("","!tlabeldef",lbl2->key+100);
11881 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11882 aopPut(AOP(IC_RESULT(ic)),"a",0);
11883 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11884 emitcode("pop","ar0");
11885 emitcode ("mov", "dps,#0");
11887 _G.dptrInUse = _G.dptr1InUse = 0;
11888 unsavermask(rsave);
11892 /*-----------------------------------------------------------------*/
11893 /* genInp - gen code for __builtin_inp read data from a mem mapped */
11894 /* port, first parameter output area second parameter pointer to */
11895 /* port third parameter count */
11896 /*-----------------------------------------------------------------*/
11897 static void genInp( iCode *ic, int nparms, operand **parms)
11899 operand *from , *to , *count;
11904 /* we know it has to be 3 parameters */
11905 assert (nparms == 3);
11907 rsave = newBitVect(16);
11908 /* save DPTR if it needs to be saved */
11909 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11910 if (bitVectBitValue(ic->rMask,i))
11911 rsave = bitVectSetBit(rsave,i);
11913 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11914 ds390_rUmaskForOp (IC_RESULT(ic))));
11921 aopOp (from, ic->next, FALSE, FALSE);
11923 /* get from into DPTR1 */
11924 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11925 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11926 if (options.model == MODEL_FLAT24) {
11927 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11930 freeAsmop (from, NULL, ic, FALSE);
11931 aopOp (to, ic, FALSE, FALSE);
11932 /* get "to" into DPTR */
11933 /* if the operand is already in dptr
11934 then we do nothing else we move the value to dptr */
11935 if (AOP_TYPE (to) != AOP_STR) {
11936 /* if already in DPTR then we need to push */
11937 if (AOP_TYPE(to) == AOP_DPTR) {
11938 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11939 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11940 if (options.model == MODEL_FLAT24)
11941 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11942 emitcode ("pop", "dph");
11943 emitcode ("pop", "dpl");
11945 _startLazyDPSEvaluation ();
11946 /* if this is remateriazable */
11947 if (AOP_TYPE (to) == AOP_IMMD) {
11948 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11949 } else { /* we need to get it byte by byte */
11950 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11951 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11952 if (options.model == MODEL_FLAT24) {
11953 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11956 _endLazyDPSEvaluation ();
11959 freeAsmop (to, NULL, ic, FALSE);
11961 _G.dptrInUse = _G.dptr1InUse = 1;
11962 aopOp (count, ic->next->next, FALSE,FALSE);
11963 lbl =newiTempLabel(NULL);
11965 /* now for the actual copy */
11966 if (AOP_TYPE(count) == AOP_LIT &&
11967 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11968 emitcode (";","OH JOY auto increment with djnz (very fast)");
11969 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11970 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11971 freeAsmop (count, NULL, ic, FALSE);
11972 emitcode ("","!tlabeldef",lbl->key+100);
11973 emitcode ("movx", "a,@dptr"); /* read data from port */
11974 emitcode ("dec","dps"); /* switch to DPTR */
11975 emitcode ("movx", "@dptr,a"); /* save into location */
11976 emitcode ("inc", "dptr"); /* point to next area */
11977 emitcode ("inc","dps"); /* switch to DPTR2 */
11978 emitcode ("djnz","b,!tlabel",lbl->key+100);
11980 symbol *lbl1 = newiTempLabel(NULL);
11982 emitcode (";"," Auto increment but no djnz");
11983 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11984 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11985 freeAsmop (count, NULL, ic, FALSE);
11986 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11987 emitcode ("","!tlabeldef",lbl->key+100);
11988 emitcode ("movx", "a,@dptr");
11989 emitcode ("dec","dps"); /* switch to DPTR */
11990 emitcode ("movx", "@dptr,a");
11991 emitcode ("inc", "dptr");
11992 emitcode ("inc","dps"); /* switch to DPTR2 */
11993 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
11994 /* emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
11995 emitcode ("mov","a,b");
11996 emitcode ("orl","a,_ap");
11997 emitcode ("jz","!tlabel",lbl1->key+100);
11998 emitcode ("mov","a,_ap");
11999 emitcode ("add","a,#!constbyte",0xFF);
12000 emitcode ("mov","_ap,a");
12001 emitcode ("mov","a,b");
12002 emitcode ("addc","a,#!constbyte",0xFF);
12003 emitcode ("mov","b,a");
12004 emitcode ("sjmp","!tlabel",lbl->key+100);
12005 emitcode ("","!tlabeldef",lbl1->key+100);
12007 emitcode ("mov", "dps,#0");
12008 _G.dptrInUse = _G.dptr1InUse = 0;
12009 unsavermask(rsave);
12013 /*-----------------------------------------------------------------*/
12014 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
12015 /* port, first parameter output area second parameter pointer to */
12016 /* port third parameter count */
12017 /*-----------------------------------------------------------------*/
12018 static void genOutp( iCode *ic, int nparms, operand **parms)
12020 operand *from , *to , *count;
12025 /* we know it has to be 3 parameters */
12026 assert (nparms == 3);
12028 rsave = newBitVect(16);
12029 /* save DPTR if it needs to be saved */
12030 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12031 if (bitVectBitValue(ic->rMask,i))
12032 rsave = bitVectSetBit(rsave,i);
12034 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12035 ds390_rUmaskForOp (IC_RESULT(ic))));
12042 aopOp (from, ic->next, FALSE, FALSE);
12044 /* get from into DPTR1 */
12045 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12046 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12047 if (options.model == MODEL_FLAT24) {
12048 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12051 freeAsmop (from, NULL, ic, FALSE);
12052 aopOp (to, ic, FALSE, FALSE);
12053 /* get "to" into DPTR */
12054 /* if the operand is already in dptr
12055 then we do nothing else we move the value to dptr */
12056 if (AOP_TYPE (to) != AOP_STR) {
12057 /* if already in DPTR then we need to push */
12058 if (AOP_TYPE(to) == AOP_DPTR) {
12059 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12060 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12061 if (options.model == MODEL_FLAT24)
12062 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12063 emitcode ("pop", "dph");
12064 emitcode ("pop", "dpl");
12066 _startLazyDPSEvaluation ();
12067 /* if this is remateriazable */
12068 if (AOP_TYPE (to) == AOP_IMMD) {
12069 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12070 } else { /* we need to get it byte by byte */
12071 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12072 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12073 if (options.model == MODEL_FLAT24) {
12074 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12077 _endLazyDPSEvaluation ();
12080 freeAsmop (to, NULL, ic, FALSE);
12082 _G.dptrInUse = _G.dptr1InUse = 1;
12083 aopOp (count, ic->next->next, FALSE,FALSE);
12084 lbl =newiTempLabel(NULL);
12086 /* now for the actual copy */
12087 if (AOP_TYPE(count) == AOP_LIT &&
12088 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12089 emitcode (";","OH JOY auto increment with djnz (very fast)");
12090 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
12091 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12092 emitcode ("","!tlabeldef",lbl->key+100);
12093 emitcode ("movx", "a,@dptr"); /* read data from port */
12094 emitcode ("inc","dps"); /* switch to DPTR2 */
12095 emitcode ("movx", "@dptr,a"); /* save into location */
12096 emitcode ("inc", "dptr"); /* point to next area */
12097 emitcode ("dec","dps"); /* switch to DPTR */
12098 emitcode ("djnz","b,!tlabel",lbl->key+100);
12099 freeAsmop (count, NULL, ic, FALSE);
12101 symbol *lbl1 = newiTempLabel(NULL);
12103 emitcode (";"," Auto increment but no djnz");
12104 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12105 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12106 freeAsmop (count, NULL, ic, FALSE);
12107 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
12108 emitcode ("","!tlabeldef",lbl->key+100);
12109 emitcode ("movx", "a,@dptr");
12110 emitcode ("inc", "dptr");
12111 emitcode ("inc","dps"); /* switch to DPTR2 */
12112 emitcode ("movx", "@dptr,a");
12113 emitcode ("dec","dps"); /* switch to DPTR */
12114 emitcode ("mov","a,b");
12115 emitcode ("orl","a,_ap");
12116 emitcode ("jz","!tlabel",lbl1->key+100);
12117 emitcode ("mov","a,_ap");
12118 emitcode ("add","a,#!constbyte",0xFF);
12119 emitcode ("mov","_ap,a");
12120 emitcode ("mov","a,b");
12121 emitcode ("addc","a,#!constbyte",0xFF);
12122 emitcode ("mov","b,a");
12123 emitcode ("sjmp","!tlabel",lbl->key+100);
12124 emitcode ("","!tlabeldef",lbl1->key+100);
12126 emitcode ("mov", "dps,#0");
12127 _G.dptrInUse = _G.dptr1InUse = 0;
12128 unsavermask(rsave);
12132 /*-----------------------------------------------------------------*/
12133 /* genSwapW - swap lower & high order bytes */
12134 /*-----------------------------------------------------------------*/
12135 static void genSwapW(iCode *ic, int nparms, operand **parms)
12139 assert (nparms==1);
12142 dest=IC_RESULT(ic);
12144 assert(getSize(operandType(src))==2);
12146 aopOp (src, ic, FALSE, FALSE);
12147 emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
12149 MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
12151 freeAsmop (src, NULL, ic, FALSE);
12153 aopOp (dest,ic, FALSE, FALSE);
12154 aopPut(AOP(dest),"b",0);
12155 aopPut(AOP(dest),"a",1);
12156 freeAsmop (dest, NULL, ic, FALSE);
12159 /*-----------------------------------------------------------------*/
12160 /* genMemsetX - gencode for memSetX data */
12161 /*-----------------------------------------------------------------*/
12162 static void genMemsetX(iCode *ic, int nparms, operand **parms)
12164 operand *to , *val , *count;
12170 /* we know it has to be 3 parameters */
12171 assert (nparms == 3);
12177 /* save DPTR if it needs to be saved */
12178 rsave = newBitVect(16);
12179 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12180 if (bitVectBitValue(ic->rMask,i))
12181 rsave = bitVectSetBit(rsave,i);
12183 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12184 ds390_rUmaskForOp (IC_RESULT(ic))));
12187 aopOp (to, ic, FALSE, FALSE);
12188 /* get "to" into DPTR */
12189 /* if the operand is already in dptr
12190 then we do nothing else we move the value to dptr */
12191 if (AOP_TYPE (to) != AOP_STR) {
12192 /* if already in DPTR then we need to push */
12193 if (AOP_TYPE(to) == AOP_DPTR) {
12194 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12195 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12196 if (options.model == MODEL_FLAT24)
12197 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12198 emitcode ("pop", "dph");
12199 emitcode ("pop", "dpl");
12201 _startLazyDPSEvaluation ();
12202 /* if this is remateriazable */
12203 if (AOP_TYPE (to) == AOP_IMMD) {
12204 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12205 } else { /* we need to get it byte by byte */
12206 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12207 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12208 if (options.model == MODEL_FLAT24) {
12209 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12212 _endLazyDPSEvaluation ();
12215 freeAsmop (to, NULL, ic, FALSE);
12217 aopOp (val, ic->next->next, FALSE,FALSE);
12218 aopOp (count, ic->next->next, FALSE,FALSE);
12219 lbl =newiTempLabel(NULL);
12220 /* now for the actual copy */
12221 if (AOP_TYPE(count) == AOP_LIT &&
12222 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12223 l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
12224 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12226 emitcode ("","!tlabeldef",lbl->key+100);
12227 emitcode ("movx", "@dptr,a");
12228 emitcode ("inc", "dptr");
12229 emitcode ("djnz","b,!tlabel",lbl->key+100);
12231 symbol *lbl1 = newiTempLabel(NULL);
12233 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12234 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12235 emitcode ("","!tlabeldef",lbl->key+100);
12236 MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
12237 emitcode ("movx", "@dptr,a");
12238 emitcode ("inc", "dptr");
12239 emitcode ("mov","a,b");
12240 emitcode ("orl","a,_ap");
12241 emitcode ("jz","!tlabel",lbl1->key+100);
12242 emitcode ("mov","a,_ap");
12243 emitcode ("add","a,#!constbyte",0xFF);
12244 emitcode ("mov","_ap,a");
12245 emitcode ("mov","a,b");
12246 emitcode ("addc","a,#!constbyte",0xFF);
12247 emitcode ("mov","b,a");
12248 emitcode ("sjmp","!tlabel",lbl->key+100);
12249 emitcode ("","!tlabeldef",lbl1->key+100);
12251 freeAsmop (count, NULL, ic, FALSE);
12252 unsavermask(rsave);
12255 /*-----------------------------------------------------------------*/
12256 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
12257 /*-----------------------------------------------------------------*/
12258 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
12261 operand *pnum, *result;
12264 assert (nparms==1);
12265 /* save registers that need to be saved */
12266 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12267 ds390_rUmaskForOp (IC_RESULT(ic))));
12270 aopOp (pnum, ic, FALSE, FALSE);
12271 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12272 freeAsmop (pnum, NULL, ic, FALSE);
12273 emitcode ("lcall","NatLib_LoadPrimitive");
12274 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12275 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
12276 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
12277 for (i = (size-1) ; i >= 0 ; i-- ) {
12278 emitcode ("push","a%s",javaRet[i]);
12280 for (i=0; i < size ; i++ ) {
12281 emitcode ("pop","a%s",
12282 aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
12285 for (i = 0 ; i < size ; i++ ) {
12286 aopPut(AOP(result),javaRet[i],i);
12289 freeAsmop (result, NULL, ic, FALSE);
12290 unsavermask(rsave);
12293 /*-----------------------------------------------------------------*/
12294 /* genNatLibLoadPointer - calls TINI api function to load pointer */
12295 /*-----------------------------------------------------------------*/
12296 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
12299 operand *pnum, *result;
12303 assert (nparms==1);
12304 /* save registers that need to be saved */
12305 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12306 ds390_rUmaskForOp (IC_RESULT(ic))));
12309 aopOp (pnum, ic, FALSE, FALSE);
12310 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12311 freeAsmop (pnum, NULL, ic, FALSE);
12312 emitcode ("lcall","NatLib_LoadPointer");
12313 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12314 if (AOP_TYPE(result)!=AOP_STR) {
12315 for (i = 0 ; i < size ; i++ ) {
12316 aopPut(AOP(result),fReturn[i],i);
12319 freeAsmop (result, NULL, ic, FALSE);
12320 unsavermask(rsave);
12323 /*-----------------------------------------------------------------*/
12324 /* genNatLibInstallStateBlock - */
12325 /*-----------------------------------------------------------------*/
12326 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
12327 operand **parms, const char *name)
12330 operand *psb, *handle;
12331 assert (nparms==2);
12333 /* save registers that need to be saved */
12334 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12335 ds390_rUmaskForOp (IC_RESULT(ic))));
12339 /* put pointer to state block into DPTR1 */
12340 aopOp (psb, ic, FALSE, FALSE);
12341 if (AOP_TYPE (psb) == AOP_IMMD) {
12342 emitcode ("mov","dps,#1");
12343 emitcode ("mov", "dptr,%s",
12344 aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12345 emitcode ("mov","dps,#0");
12347 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12348 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12349 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12351 freeAsmop (psb, NULL, ic, FALSE);
12353 /* put libraryID into DPTR */
12354 emitcode ("mov","dptr,#LibraryID");
12356 /* put handle into r3:r2 */
12357 aopOp (handle, ic, FALSE, FALSE);
12358 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12359 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12360 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12361 emitcode ("pop","ar3");
12362 emitcode ("pop","ar2");
12364 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12365 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12367 freeAsmop (psb, NULL, ic, FALSE);
12369 /* make the call */
12370 emitcode ("lcall","NatLib_Install%sStateBlock",name);
12372 /* put return value into place*/
12374 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12376 aopPut(AOP(IC_RESULT(ic)),"a",0);
12377 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12378 unsavermask(rsave);
12381 /*-----------------------------------------------------------------*/
12382 /* genNatLibRemoveStateBlock - */
12383 /*-----------------------------------------------------------------*/
12384 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12390 /* save registers that need to be saved */
12391 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12392 ds390_rUmaskForOp (IC_RESULT(ic))));
12394 /* put libraryID into DPTR */
12395 emitcode ("mov","dptr,#LibraryID");
12396 /* make the call */
12397 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12398 unsavermask(rsave);
12401 /*-----------------------------------------------------------------*/
12402 /* genNatLibGetStateBlock - */
12403 /*-----------------------------------------------------------------*/
12404 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12405 operand **parms,const char *name)
12408 symbol *lbl = newiTempLabel(NULL);
12411 /* save registers that need to be saved */
12412 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12413 ds390_rUmaskForOp (IC_RESULT(ic))));
12415 /* put libraryID into DPTR */
12416 emitcode ("mov","dptr,#LibraryID");
12417 /* make the call */
12418 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12419 emitcode ("jnz","!tlabel",lbl->key+100);
12421 /* put return value into place */
12422 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12423 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12424 emitcode ("push","ar3");
12425 emitcode ("push","ar2");
12426 emitcode ("pop","%s",
12427 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12428 emitcode ("pop","%s",
12429 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12431 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12432 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12434 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12435 emitcode ("","!tlabeldef",lbl->key+100);
12436 unsavermask(rsave);
12439 /*-----------------------------------------------------------------*/
12440 /* genMMMalloc - */
12441 /*-----------------------------------------------------------------*/
12442 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12443 int size, const char *name)
12448 symbol *lbl = newiTempLabel(NULL);
12450 assert (nparms == 1);
12451 /* save registers that need to be saved */
12452 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12453 ds390_rUmaskForOp (IC_RESULT(ic))));
12456 aopOp (bsize,ic,FALSE,FALSE);
12458 /* put the size in R4-R2 */
12459 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12460 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12461 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12463 emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12464 emitcode("pop","ar4");
12466 emitcode("pop","ar3");
12467 emitcode("pop","ar2");
12469 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12470 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12472 emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12475 freeAsmop (bsize, NULL, ic, FALSE);
12477 /* make the call */
12478 emitcode ("lcall","MM_%s",name);
12479 emitcode ("jz","!tlabel",lbl->key+100);
12480 emitcode ("mov","r2,#!constbyte",0xff);
12481 emitcode ("mov","r3,#!constbyte",0xff);
12482 emitcode ("","!tlabeldef",lbl->key+100);
12483 /* we don't care about the pointer : we just save the handle */
12484 rsym = OP_SYMBOL(IC_RESULT(ic));
12485 if (rsym->liveFrom != rsym->liveTo) {
12486 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12487 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12488 emitcode ("push","ar3");
12489 emitcode ("push","ar2");
12490 emitcode ("pop","%s",
12491 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12492 emitcode ("pop","%s",
12493 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12495 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12496 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12498 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12500 unsavermask(rsave);
12503 /*-----------------------------------------------------------------*/
12505 /*-----------------------------------------------------------------*/
12506 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12511 assert (nparms == 1);
12512 /* save registers that need to be saved */
12513 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12514 ds390_rUmaskForOp (IC_RESULT(ic))));
12517 aopOp (handle,ic,FALSE,FALSE);
12519 /* put the size in R4-R2 */
12520 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12521 emitcode("push","%s",
12522 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12523 emitcode("push","%s",
12524 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12525 emitcode("pop","ar3");
12526 emitcode("pop","ar2");
12528 emitcode ("mov","r2,%s",
12529 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12530 emitcode ("mov","r3,%s",
12531 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12533 freeAsmop (handle, NULL, ic, FALSE);
12535 /* make the call */
12536 emitcode ("lcall","MM_Deref");
12539 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12540 if (rsym->liveFrom != rsym->liveTo) {
12541 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12542 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12543 _startLazyDPSEvaluation ();
12545 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12546 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12547 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12549 _endLazyDPSEvaluation ();
12554 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12555 unsavermask(rsave);
12558 /*-----------------------------------------------------------------*/
12559 /* genMMUnrestrictedPersist - */
12560 /*-----------------------------------------------------------------*/
12561 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12566 assert (nparms == 1);
12567 /* save registers that need to be saved */
12568 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12569 ds390_rUmaskForOp (IC_RESULT(ic))));
12572 aopOp (handle,ic,FALSE,FALSE);
12574 /* put the size in R3-R2 */
12575 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12576 emitcode("push","%s",
12577 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12578 emitcode("push","%s",
12579 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12580 emitcode("pop","ar3");
12581 emitcode("pop","ar2");
12583 emitcode ("mov","r2,%s",
12584 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12585 emitcode ("mov","r3,%s",
12586 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12588 freeAsmop (handle, NULL, ic, FALSE);
12590 /* make the call */
12591 emitcode ("lcall","MM_UnrestrictedPersist");
12594 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12595 if (rsym->liveFrom != rsym->liveTo) {
12596 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12597 aopPut(AOP(IC_RESULT(ic)),"a",0);
12598 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12601 unsavermask(rsave);
12604 /*-----------------------------------------------------------------*/
12605 /* genSystemExecJavaProcess - */
12606 /*-----------------------------------------------------------------*/
12607 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12610 operand *handle, *pp;
12612 assert (nparms==2);
12613 /* save registers that need to be saved */
12614 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12615 ds390_rUmaskForOp (IC_RESULT(ic))));
12620 /* put the handle in R3-R2 */
12621 aopOp (handle,ic,FALSE,FALSE);
12622 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12623 emitcode("push","%s",
12624 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12625 emitcode("push","%s",
12626 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12627 emitcode("pop","ar3");
12628 emitcode("pop","ar2");
12630 emitcode ("mov","r2,%s",
12631 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12632 emitcode ("mov","r3,%s",
12633 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12635 freeAsmop (handle, NULL, ic, FALSE);
12637 /* put pointer in DPTR */
12638 aopOp (pp,ic,FALSE,FALSE);
12639 if (AOP_TYPE(pp) == AOP_IMMD) {
12640 emitcode ("mov", "dptr,%s",
12641 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12642 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12643 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12644 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12645 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12647 freeAsmop (handle, NULL, ic, FALSE);
12649 /* make the call */
12650 emitcode ("lcall","System_ExecJavaProcess");
12652 /* put result in place */
12654 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12655 if (rsym->liveFrom != rsym->liveTo) {
12656 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12657 aopPut(AOP(IC_RESULT(ic)),"a",0);
12658 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12662 unsavermask(rsave);
12665 /*-----------------------------------------------------------------*/
12666 /* genSystemRTCRegisters - */
12667 /*-----------------------------------------------------------------*/
12668 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12674 assert (nparms==1);
12675 /* save registers that need to be saved */
12676 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12677 ds390_rUmaskForOp (IC_RESULT(ic))));
12680 /* put pointer in DPTR */
12681 aopOp (pp,ic,FALSE,FALSE);
12682 if (AOP_TYPE (pp) == AOP_IMMD) {
12683 emitcode ("mov","dps,#1");
12684 emitcode ("mov", "dptr,%s",
12685 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12686 emitcode ("mov","dps,#0");
12688 emitcode ("mov","dpl1,%s",
12689 aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12690 emitcode ("mov","dph1,%s",
12691 aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12692 emitcode ("mov","dpx1,%s",
12693 aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12695 freeAsmop (pp, NULL, ic, FALSE);
12697 /* make the call */
12698 emitcode ("lcall","System_%sRTCRegisters",name);
12700 unsavermask(rsave);
12703 /*-----------------------------------------------------------------*/
12704 /* genSystemThreadSleep - */
12705 /*-----------------------------------------------------------------*/
12706 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12711 assert (nparms==1);
12712 /* save registers that need to be saved */
12713 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12714 ds390_rUmaskForOp (IC_RESULT(ic))));
12717 aopOp(to,ic,FALSE,FALSE);
12718 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12719 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12720 emitcode ("push","%s",
12721 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12722 emitcode ("push","%s",
12723 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12724 emitcode ("push","%s",
12725 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12726 emitcode ("push","%s",
12727 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12728 emitcode ("pop","ar3");
12729 emitcode ("pop","ar2");
12730 emitcode ("pop","ar1");
12731 emitcode ("pop","ar0");
12733 emitcode ("mov","r0,%s",
12734 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12735 emitcode ("mov","r1,%s",
12736 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12737 emitcode ("mov","r2,%s",
12738 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12739 emitcode ("mov","r3,%s",
12740 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12742 freeAsmop (to, NULL, ic, FALSE);
12744 /* suspend in acc */
12746 aopOp(s,ic,FALSE,FALSE);
12747 emitcode ("mov","a,%s",
12748 aopGet(AOP(s),0,FALSE,TRUE,NULL));
12749 freeAsmop (s, NULL, ic, FALSE);
12751 /* make the call */
12752 emitcode ("lcall","System_%s",name);
12754 unsavermask(rsave);
12757 /*-----------------------------------------------------------------*/
12758 /* genSystemThreadResume - */
12759 /*-----------------------------------------------------------------*/
12760 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12765 assert (nparms==2);
12766 /* save registers that need to be saved */
12767 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12768 ds390_rUmaskForOp (IC_RESULT(ic))));
12774 aopOp(pid,ic,FALSE,FALSE);
12775 emitcode ("mov","r0,%s",
12776 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12777 freeAsmop (pid, NULL, ic, FALSE);
12780 aopOp(tid,ic,FALSE,FALSE);
12781 emitcode ("mov","a,%s",
12782 aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
12783 freeAsmop (tid, NULL, ic, FALSE);
12785 emitcode ("lcall","System_ThreadResume");
12787 /* put result into place */
12789 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12790 if (rsym->liveFrom != rsym->liveTo) {
12791 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12792 aopPut(AOP(IC_RESULT(ic)),"a",0);
12793 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12796 unsavermask(rsave);
12799 /*-----------------------------------------------------------------*/
12800 /* genSystemProcessResume - */
12801 /*-----------------------------------------------------------------*/
12802 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
12807 assert (nparms==1);
12808 /* save registers that need to be saved */
12809 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12810 ds390_rUmaskForOp (IC_RESULT(ic))));
12815 aopOp(pid,ic,FALSE,FALSE);
12816 emitcode ("mov","a,%s",
12817 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12818 freeAsmop (pid, NULL, ic, FALSE);
12820 emitcode ("lcall","System_ProcessResume");
12822 unsavermask(rsave);
12825 /*-----------------------------------------------------------------*/
12827 /*-----------------------------------------------------------------*/
12828 static void genSystem (iCode *ic,int nparms,char *name)
12830 assert(nparms == 0);
12832 emitcode ("lcall","System_%s",name);
12835 /*-----------------------------------------------------------------*/
12836 /* genSystemPoll - */
12837 /*-----------------------------------------------------------------*/
12838 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
12843 assert (nparms==1);
12844 /* save registers that need to be saved */
12845 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12846 ds390_rUmaskForOp (IC_RESULT(ic))));
12849 aopOp (fp,ic,FALSE,FALSE);
12850 if (AOP_TYPE (fp) == AOP_IMMD) {
12851 emitcode ("mov", "dptr,%s",
12852 aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
12853 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
12854 emitcode ("mov","dpl,%s",
12855 aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
12856 emitcode ("mov","dph,%s",
12857 aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
12858 emitcode ("mov","dpx,%s",
12859 aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
12861 freeAsmop (fp, NULL, ic, FALSE);
12863 emitcode ("lcall","System_%sPoll",name);
12865 /* put result into place */
12867 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12868 if (rsym->liveFrom != rsym->liveTo) {
12869 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12870 aopPut(AOP(IC_RESULT(ic)),"a",0);
12871 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12874 unsavermask(rsave);
12877 /*-----------------------------------------------------------------*/
12878 /* genSystemGetCurrentID - */
12879 /*-----------------------------------------------------------------*/
12880 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
12882 assert (nparms==0);
12884 emitcode ("lcall","System_GetCurrent%sId",name);
12885 /* put result into place */
12887 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12888 if (rsym->liveFrom != rsym->liveTo) {
12889 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12890 aopPut(AOP(IC_RESULT(ic)),"a",0);
12891 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12896 /*-----------------------------------------------------------------*/
12897 /* genDummyRead - generate code for dummy read of volatiles */
12898 /*-----------------------------------------------------------------*/
12900 genDummyRead (iCode * ic)
12905 D(emitcode("; genDummyRead",""));
12907 right = IC_RIGHT (ic);
12909 aopOp (right, ic, FALSE, FALSE);
12911 /* if the result is a bit */
12912 if (AOP_TYPE (right) == AOP_CRY)
12914 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
12918 /* bit variables done */
12920 size = AOP_SIZE (right);
12924 emitcode ("mov", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
12929 freeAsmop (right, NULL, ic, TRUE);
12932 /*-----------------------------------------------------------------*/
12933 /* genBuiltIn - calls the appropriate function to generating code */
12934 /* for a built in function */
12935 /*-----------------------------------------------------------------*/
12936 static void genBuiltIn (iCode *ic)
12938 operand *bi_parms[MAX_BUILTIN_ARGS];
12943 /* get all the arguments for a built in function */
12944 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
12946 /* which function is it */
12947 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
12948 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
12949 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
12950 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
12951 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
12952 } else if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
12953 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
12954 } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
12955 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
12956 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
12957 genMemsetX(bi_iCode,nbi_parms,bi_parms);
12958 } else if (strcmp(bif->name,"__builtin_inp")==0) {
12959 genInp(bi_iCode,nbi_parms,bi_parms);
12960 } else if (strcmp(bif->name,"__builtin_outp")==0) {
12961 genOutp(bi_iCode,nbi_parms,bi_parms);
12962 } else if (strcmp(bif->name,"__builtin_swapw")==0) {
12963 genSwapW(bi_iCode,nbi_parms,bi_parms);
12964 /* JavaNative builtIns */
12965 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
12966 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
12967 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
12968 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
12969 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
12970 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
12971 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
12972 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
12973 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
12974 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12975 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
12976 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12977 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
12978 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
12979 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
12980 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
12981 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
12982 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12983 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
12984 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12985 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
12986 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
12987 } else if (strcmp(bif->name,"MM_Malloc")==0) {
12988 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
12989 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
12990 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
12991 } else if (strcmp(bif->name,"MM_Free")==0) {
12992 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
12993 } else if (strcmp(bif->name,"MM_Deref")==0) {
12994 genMMDeref(bi_iCode,nbi_parms,bi_parms);
12995 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
12996 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
12997 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
12998 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
12999 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
13000 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
13001 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
13002 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
13003 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
13004 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
13005 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
13006 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
13007 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
13008 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
13009 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
13010 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
13011 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
13012 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13013 } else if (strcmp(bif->name,"System_SaveThread")==0) {
13014 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13015 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
13016 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13017 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
13018 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
13019 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
13020 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
13021 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
13022 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
13023 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
13024 genSystem(bi_iCode,nbi_parms,"ProcessYield");
13025 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
13026 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
13027 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
13028 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
13029 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
13030 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
13031 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
13032 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
13033 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
13034 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
13036 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
13042 /*-----------------------------------------------------------------*/
13043 /* gen390Code - generate code for Dallas 390 based controllers */
13044 /*-----------------------------------------------------------------*/
13046 gen390Code (iCode * lic)
13051 lineHead = lineCurr = NULL;
13052 dptrn[1][0] = "dpl1";
13053 dptrn[1][1] = "dph1";
13054 dptrn[1][2] = "dpx1";
13056 if (options.model == MODEL_FLAT24) {
13057 fReturnSizeDS390 = 5;
13058 fReturn = fReturn24;
13060 fReturnSizeDS390 = 4;
13061 fReturn = fReturn16;
13062 options.stack10bit=0;
13065 /* print the allocation information */
13066 if (allocInfo && currFunc)
13067 printAllocInfo (currFunc, codeOutFile);
13069 /* if debug information required */
13070 if (options.debug && currFunc)
13072 debugFile->writeFunction(currFunc);
13074 if (IS_STATIC (currFunc->etype))
13075 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
13077 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
13080 /* stack pointer name */
13081 if (options.useXstack)
13087 for (ic = lic; ic; ic = ic->next)
13090 if (ic->lineno && cln != ic->lineno)
13095 emitcode ("", "C$%s$%d$%d$%d ==.",
13096 FileBaseName (ic->filename), ic->lineno,
13097 ic->level, ic->block);
13100 if (!options.noCcodeInAsm) {
13101 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
13102 printCLine(ic->filename, ic->lineno));
13106 if (options.iCodeInAsm) {
13107 emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
13109 /* if the result is marked as
13110 spilt and rematerializable or code for
13111 this has already been generated then
13113 if (resultRemat (ic) || ic->generated)
13116 /* depending on the operation */
13136 /* IPOP happens only when trying to restore a
13137 spilt live range, if there is an ifx statement
13138 following this pop then the if statement might
13139 be using some of the registers being popped which
13140 would destory the contents of the register so
13141 we need to check for this condition and handle it */
13143 ic->next->op == IFX &&
13144 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
13145 genIfx (ic->next, ic);
13163 genEndFunction (ic);
13183 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
13200 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
13204 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
13211 /* note these two are xlated by algebraic equivalence
13212 during parsing SDCC.y */
13213 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
13214 "got '>=' or '<=' shouldn't have come here");
13218 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
13230 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
13234 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
13238 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
13262 genRightShift (ic);
13265 case GET_VALUE_AT_ADDRESS:
13266 genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
13270 if (POINTER_SET (ic))
13271 genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
13297 if (ic->builtinSEND) genBuiltIn(ic);
13298 else addSet (&_G.sendSet, ic);
13301 case DUMMY_READ_VOLATILE:
13305 #if 0 // obsolete, and buggy for != xdata
13317 /* now we are ready to call the
13318 peep hole optimizer */
13319 if (!options.nopeep)
13320 peepHole (&lineHead);
13322 /* now do the actual printing */
13323 printLine (lineHead, codeOutFile);