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 #ifdef HAVE_SYS_ISA_DEFS_H
40 #include <sys/isa_defs.h>
42 #ifdef HAVE_MACHINE_ENDIAN_H
43 #include <machine/endian.h>
48 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
49 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
50 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
56 #define BETTER_LITERAL_SHIFT
58 char *aopLiteral (value * val, int offset);
60 /* this is the down and dirty file with all kinds of
61 kludgy & hacky stuff. This is what it is all about
62 CODE GENERATION for a specific MCU . some of the
63 routines may be reusable, will have to see */
65 static char *zero = "#0x00";
66 static char *one = "#0x01";
71 #define TR_DPTR(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_DPTR1 %s ", s); }
72 #define TR_AP(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_AP %s ", s); }
74 unsigned fReturnSizeDS390 = 5; /* shared with ralloc.c */
75 static char *fReturn24[] =
76 {"dpl", "dph", "dpx", "b", "a"};
77 static char *fReturn16[] =
78 {"dpl", "dph", "b", "a"};
79 static char **fReturn = fReturn24;
80 static char *accUse[] =
82 static char *javaRet[] = { "r0","r1","r2","r3"};
83 static short rbank = -1;
98 static void saveRBank (int, iCode *, bool);
100 #define RESULTONSTACK(x) \
101 (IC_RESULT(x) && IC_RESULT(x)->aop && \
102 IC_RESULT(x)->aop->type == AOP_STK )
104 /* #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x); */
105 #define MOVA(x) { char *_mova_tmp = strdup(x); \
106 if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \
108 emitcode("mov","a,%s",_mova_tmp); \
112 #define CLRC emitcode("clr","c")
113 #define SETC emitcode("setb","c")
115 // A scratch register which will be used to hold
116 // result bytes from operands in far space via DPTR2.
117 #define DP2_RESULT_REG "_ap"
119 static lineNode *lineHead = NULL;
120 static lineNode *lineCurr = NULL;
122 static unsigned char SLMask[] =
123 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
124 0xE0, 0xC0, 0x80, 0x00};
125 static unsigned char SRMask[] =
126 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
127 0x07, 0x03, 0x01, 0x00};
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];
149 sprintf (lb, "%s\t", inst);
151 sprintf (lb, "%s", inst);
152 tvsprintf (lb + (strlen (lb)), fmt, ap);
155 tvsprintf (lb, fmt, ap);
157 while (isspace (*lbp))
161 lineCurr = (lineCurr ?
162 connectLine (lineCurr, newLineNode (lb)) :
163 (lineHead = newLineNode (lb)));
164 lineCurr->isInline = _G.inLine;
165 lineCurr->isDebug = _G.debugLine;
169 /*-----------------------------------------------------------------*/
170 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
171 /*-----------------------------------------------------------------*/
173 getFreePtr (iCode * ic, asmop ** aopp, bool result)
175 bool r0iu = FALSE, r1iu = FALSE;
176 bool r0ou = FALSE, r1ou = FALSE;
178 /* the logic: if r0 & r1 used in the instruction
179 then we are in trouble otherwise */
181 /* first check if r0 & r1 are used by this
182 instruction, in which case we are in trouble */
183 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
184 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
189 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
190 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
192 /* if no usage of r0 then return it */
195 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
196 (*aopp)->type = AOP_R0;
198 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
201 /* if no usage of r1 then return it */
204 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
205 (*aopp)->type = AOP_R1;
207 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
210 /* now we know they both have usage */
211 /* if r0 not used in this instruction */
214 /* push it if not already pushed */
217 emitcode ("push", "%s",
218 ds390_regWithIdx (R0_IDX)->dname);
222 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
223 (*aopp)->type = AOP_R0;
225 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
228 /* if r1 not used then */
232 /* push it if not already pushed */
235 emitcode ("push", "%s",
236 ds390_regWithIdx (R1_IDX)->dname);
240 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
241 (*aopp)->type = AOP_R1;
242 return ds390_regWithIdx (R1_IDX);
246 /* I said end of world but not quite end of world yet */
247 /* if this is a result then we can push it on the stack */
250 (*aopp)->type = AOP_STK;
254 /* other wise this is true end of the world */
255 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
256 "getFreePtr should never reach here");
260 /*-----------------------------------------------------------------*/
261 /* newAsmop - creates a new asmOp */
262 /*-----------------------------------------------------------------*/
264 newAsmop (short type)
268 aop = Safe_calloc (1, sizeof (asmop));
273 static int _currentDPS; /* Current processor DPS. */
274 static int _desiredDPS; /* DPS value compiler thinks we should be using. */
275 static int _lazyDPS = 0; /* if non-zero, we are doing lazy evaluation of DPS changes. */
277 /*-----------------------------------------------------------------*/
278 /* genSetDPTR: generate code to select which DPTR is in use (zero */
279 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390 */
280 /* alternate DPTR (DPL1/DPH1/DPX1). */
281 /*-----------------------------------------------------------------*/
286 /* If we are doing lazy evaluation, simply note the desired
287 * change, but don't emit any code yet.
297 emitcode ("mov", "dps,#0");
302 emitcode ("mov", "dps,#1");
306 /*-----------------------------------------------------------------*/
307 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
309 /* Any code that operates on DPTR (NB: not on the individual */
310 /* components, like DPH) *must* call _flushLazyDPS() before using */
311 /* DPTR within a lazy DPS evaluation block. */
313 /* Note that aopPut and aopGet already contain the proper calls to */
314 /* _flushLazyDPS, so it is safe to use these calls within a lazy */
315 /* DPS evaluation block. */
317 /* Also, _flushLazyDPS must be called before any flow control */
318 /* operations that could potentially branch out of the block. */
320 /* Lazy DPS evaluation is simply an optimization (though an */
321 /* important one), so if in doubt, leave it out. */
322 /*-----------------------------------------------------------------*/
324 _startLazyDPSEvaluation (void)
328 #ifdef BETTER_LITERAL_SHIFT
335 /*-----------------------------------------------------------------*/
336 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
337 /* desired one. Call before using DPTR within a lazy DPS evaluation */
339 /*-----------------------------------------------------------------*/
349 if (_desiredDPS != _currentDPS)
353 emitcode ("inc", "dps");
357 emitcode ("dec", "dps");
359 _currentDPS = _desiredDPS;
363 /*-----------------------------------------------------------------*/
364 /* _endLazyDPSEvaluation: end lazy DPS evaluation block. */
366 /* Forces us back to the safe state (standard DPTR selected). */
367 /*-----------------------------------------------------------------*/
369 _endLazyDPSEvaluation (void)
371 #ifdef BETTER_LITERAL_SHIFT
390 /*-----------------------------------------------------------------*/
391 /* pointerCode - returns the code for a pointer type */
392 /*-----------------------------------------------------------------*/
394 pointerCode (sym_link * etype)
397 return PTR_TYPE (SPEC_OCLS (etype));
401 /*-----------------------------------------------------------------*/
402 /* aopForSym - for a true symbol */
403 /*-----------------------------------------------------------------*/
405 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
408 memmap *space = SPEC_OCLS (sym->etype);
410 /* if already has one */
414 /* assign depending on the storage class */
415 /* if it is on the stack or indirectly addressable */
416 /* space we need to assign either r0 or r1 to it */
417 if ((sym->onStack && !options.stack10bit) || sym->iaccess)
419 sym->aop = aop = newAsmop (0);
420 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
421 aop->size = getSize (sym->type);
423 /* now assign the address of the variable to
424 the pointer register */
425 if (aop->type != AOP_STK)
431 emitcode ("push", "acc");
434 emitcode ("push", "b");
436 emitcode ("mov", "a,_bp");
437 emitcode ("add", "a,#!constbyte",
439 ((char) (sym->stack - _G.nRegsSaved)) :
440 ((char) sym->stack)) & 0xff);
441 emitcode ("mov", "%s,a",
442 aop->aopu.aop_ptr->name);
445 emitcode ("pop", "b");
448 emitcode ("pop", "acc");
451 emitcode ("mov", "%s,#%s",
452 aop->aopu.aop_ptr->name,
454 aop->paged = space->paged;
457 aop->aopu.aop_stk = sym->stack;
461 if (sym->onStack && options.stack10bit)
463 short stack_val = -((sym->stack < 0) ?
464 ((short) (sym->stack - _G.nRegsSaved)) :
465 ((short) sym->stack)) ;
466 /* It's on the 10 bit stack, which is located in
469 if (stack_val < 0 && stack_val > -3) { /* between -3 & -1 */
471 if (options.model == MODEL_FLAT24)
472 emitcode ("mov", "dpx1,#!constbyte", (options.stack_loc >> 16) & 0xff);
474 emitcode ("mov", "dph1,_bpx+1");
475 emitcode ("mov", "dpl1,_bpx");
476 emitcode ("mov","dps,#1");
478 if (options.model == MODEL_FLAT24)
479 emitcode ("mov", "dpx,#!constbyte", (options.stack_loc >> 16) & 0xff);
480 emitcode ("mov", "dph,_bpx+1");
481 emitcode ("mov", "dpl,_bpx");
483 stack_val = -stack_val;
484 while (stack_val--) {
485 emitcode ("inc","dptr");
488 emitcode("mov","dps,#0");
492 emitcode ("push", "acc");
495 emitcode ("push", "b");
497 emitcode ("mov", "a,_bpx");
498 emitcode ("clr","c");
499 emitcode ("subb", "a,#!constbyte", stack_val & 0xff);
500 emitcode ("mov","b,a");
501 emitcode ("mov","a,_bpx+1");
502 emitcode ("subb","a,#!constbyte",(stack_val >> 8) & 0xff);
504 if (options.model == MODEL_FLAT24)
505 emitcode ("mov", "dpx1,#!constbyte", (options.stack_loc >> 16) & 0xff);
507 emitcode ("mov", "dph1,a");
508 emitcode ("mov", "dpl1,b");
510 if (options.model == MODEL_FLAT24)
511 emitcode ("mov", "dpx,#!constbyte", (options.stack_loc >> 16) & 0xff);
512 emitcode ("mov", "dph,a");
513 emitcode ("mov", "dpl,b");
517 emitcode ("pop", "b");
520 emitcode ("pop", "acc");
522 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
523 aop->size = getSize (sym->type);
527 /* if in bit space */
528 if (IN_BITSPACE (space))
530 sym->aop = aop = newAsmop (AOP_CRY);
531 aop->aopu.aop_dir = sym->rname;
532 aop->size = getSize (sym->type);
535 /* if it is in direct space */
536 if (IN_DIRSPACE (space))
538 sym->aop = aop = newAsmop (AOP_DIR);
539 aop->aopu.aop_dir = sym->rname;
540 aop->size = getSize (sym->type);
544 /* special case for a function */
545 if (IS_FUNC (sym->type))
547 sym->aop = aop = newAsmop (AOP_IMMD);
548 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
549 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
550 aop->size = FPTRSIZE;
554 /* only remaining is far space */
555 /* in which case DPTR gets the address */
556 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
561 emitcode ("mov", "dptr,#%s", sym->rname);
566 emitcode ("mov", "dptr,#%s", sym->rname);
568 aop->size = getSize (sym->type);
570 /* if it is in code space */
571 if (IN_CODESPACE (space))
577 /*-----------------------------------------------------------------*/
578 /* aopForRemat - rematerialzes an object */
579 /*-----------------------------------------------------------------*/
581 aopForRemat (symbol * sym)
583 iCode *ic = sym->rematiCode;
584 asmop *aop = newAsmop (AOP_IMMD);
591 val += (int) operandLitValue (IC_RIGHT (ic));
592 else if (ic->op == '-')
593 val -= (int) operandLitValue (IC_RIGHT (ic));
594 else if (IS_CAST_ICODE(ic)) {
595 sym_link *from_type = operandType(IC_RIGHT(ic));
596 aop->aopu.aop_immd.from_cast_remat = 1;
597 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
598 ptr_type = DCL_TYPE(from_type);
599 if (ptr_type == IPOINTER) {
606 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
610 sprintf (buffer, "(%s %c 0x%04x)",
611 OP_SYMBOL (IC_LEFT (ic))->rname,
612 val >= 0 ? '+' : '-',
615 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
617 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
618 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
619 /* set immd2 field if required */
620 if (aop->aopu.aop_immd.from_cast_remat) {
621 tsprintf(buffer,"#!constbyte",ptr_type);
622 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
623 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
629 /*-----------------------------------------------------------------*/
630 /* aopHasRegs - returns true if aop has regs between from-to */
631 /*-----------------------------------------------------------------*/
632 static int aopHasRegs(asmop *aop, int from, int to)
636 if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
638 for (; size < aop->size ; size++) {
640 for (reg = from ; reg <= to ; reg++)
641 if (aop->aopu.aop_reg[size] == ds390_regWithIdx(reg)) return 1;
646 /*-----------------------------------------------------------------*/
647 /* regsInCommon - two operands have some registers in common */
648 /*-----------------------------------------------------------------*/
650 regsInCommon (operand * op1, operand * op2)
655 /* if they have registers in common */
656 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
659 sym1 = OP_SYMBOL (op1);
660 sym2 = OP_SYMBOL (op2);
662 if (sym1->nRegs == 0 || sym2->nRegs == 0)
665 for (i = 0; i < sym1->nRegs; i++)
671 for (j = 0; j < sym2->nRegs; j++)
676 if (sym2->regs[j] == sym1->regs[i])
684 /*-----------------------------------------------------------------*/
685 /* operandsEqu - equivalent */
686 /*-----------------------------------------------------------------*/
688 operandsEqu (operand * op1, operand * op2)
692 /* if they not symbols */
693 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
696 sym1 = OP_SYMBOL (op1);
697 sym2 = OP_SYMBOL (op2);
699 /* if both are itemps & one is spilt
700 and the other is not then false */
701 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
702 sym1->isspilt != sym2->isspilt)
705 /* if they are the same */
709 if (strcmp (sym1->rname, sym2->rname) == 0)
713 /* if left is a tmp & right is not */
714 if (IS_ITEMP (op1) &&
717 (sym1->usl.spillLoc == sym2))
720 if (IS_ITEMP (op2) &&
724 (sym2->usl.spillLoc == sym1))
730 /*-----------------------------------------------------------------*/
731 /* sameRegs - two asmops have the same registers */
732 /*-----------------------------------------------------------------*/
734 sameRegs (asmop * aop1, asmop * aop2)
740 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
747 if (aop1->type != AOP_REG ||
748 aop2->type != AOP_REG)
751 if (aop1->size != aop2->size)
754 for (i = 0; i < aop1->size; i++)
755 if (aop1->aopu.aop_reg[i] !=
756 aop2->aopu.aop_reg[i])
762 /*-----------------------------------------------------------------*/
763 /* aopOp - allocates an asmop for an operand : */
764 /*-----------------------------------------------------------------*/
766 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
775 /* if this a literal */
776 if (IS_OP_LITERAL (op))
778 op->aop = aop = newAsmop (AOP_LIT);
779 aop->aopu.aop_lit = op->operand.valOperand;
780 aop->size = getSize (operandType (op));
784 /* if already has a asmop then continue */
788 /* if the underlying symbol has a aop */
789 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
791 op->aop = OP_SYMBOL (op)->aop;
795 /* if this is a true symbol */
796 if (IS_TRUE_SYMOP (op))
798 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
802 /* this is a temporary : this has
808 e) can be a return use only */
810 sym = OP_SYMBOL (op);
813 /* if the type is a conditional */
814 if (sym->regType == REG_CND)
816 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
821 /* if it is spilt then two situations
823 b) has a spill location */
824 if (sym->isspilt || sym->nRegs == 0)
827 /* rematerialize it NOW */
830 sym->aop = op->aop = aop =
832 aop->size = getSize (sym->type);
839 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
840 aop->size = getSize (sym->type);
841 for (i = 0; i < 2; i++)
842 aop->aopu.aop_str[i] = accUse[i];
852 /* a AOP_STR uses DPTR, but DPTR is already in use;
855 fprintf (stderr, "*** Internal error: AOP_STR with DPTR in use! for operand %s\n",sym->name);
858 aop = op->aop = sym->aop = newAsmop (AOP_STR);
859 aop->size = getSize (sym->type);
860 for (i = 0; i < (int) fReturnSizeDS390; i++)
861 aop->aopu.aop_str[i] = fReturn[i];
865 /* else spill location */
866 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
867 /* force a new aop if sizes differ */
868 sym->usl.spillLoc->aop = NULL;
870 sym->aop = op->aop = aop =
871 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
872 aop->size = getSize (sym->type);
876 /* must be in a register */
877 sym->aop = op->aop = aop = newAsmop (AOP_REG);
878 aop->size = sym->nRegs;
879 for (i = 0; i < sym->nRegs; i++)
880 aop->aopu.aop_reg[i] = sym->regs[i];
883 /*-----------------------------------------------------------------*/
884 /* freeAsmop - free up the asmop given to an operand */
885 /*----------------------------------------------------------------*/
887 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
904 /* depending on the asmop type only three cases need work AOP_RO
905 , AOP_R1 && AOP_STK */
913 emitcode ("pop", "ar0");
917 bitVectUnSetBit (ic->rUsed, R0_IDX);
925 emitcode ("pop", "ar1");
929 bitVectUnSetBit (ic->rUsed, R1_IDX);
935 int stk = aop->aopu.aop_stk + aop->size;
936 bitVectUnSetBit (ic->rUsed, R0_IDX);
937 bitVectUnSetBit (ic->rUsed, R1_IDX);
939 getFreePtr (ic, &aop, FALSE);
941 if (options.stack10bit)
943 /* I'm not sure what to do here yet... */
946 "*** Warning: probably generating bad code for "
947 "10 bit stack mode.\n");
952 emitcode ("mov", "a,_bp");
953 emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
954 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
958 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
963 emitcode ("pop", "acc");
964 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
967 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
970 freeAsmop (op, NULL, ic, TRUE);
973 emitcode ("pop", "ar0");
979 emitcode ("pop", "ar1");
986 /* all other cases just dealloc */
992 OP_SYMBOL (op)->aop = NULL;
993 /* if the symbol has a spill */
995 SPIL_LOC (op)->aop = NULL;
1000 /*------------------------------------------------------------------*/
1001 /* aopGet - for fetching value of the aop */
1003 /* Set canClobberACC if you are sure it is OK to clobber the value */
1004 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe, */
1005 /* just less efficient. */
1006 /*------------------------------------------------------------------*/
1009 aopGet (asmop * aop,
1018 /* offset is greater than
1020 if (offset > (aop->size - 1) &&
1021 aop->type != AOP_LIT)
1024 /* depending on type */
1030 /* if we need to increment it */
1031 while (offset > aop->coff)
1033 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1037 while (offset < aop->coff)
1039 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1046 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1047 return (dname ? "acc" : "a");
1049 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1050 rs = Safe_calloc (1, strlen (s) + 1);
1057 if (aop->type == AOP_DPTR2)
1063 emitcode ("xch", "a, %s", DP2_RESULT_REG);
1069 while (offset > aop->coff)
1071 emitcode ("inc", "dptr");
1075 while (offset < aop->coff)
1077 emitcode ("lcall", "__decdptr");
1084 emitcode ("clr", "a");
1085 emitcode ("movc", "a,@a+dptr");
1089 emitcode ("movx", "a,@dptr");
1092 if (aop->type == AOP_DPTR2)
1098 emitcode ("xch", "a, %s", DP2_RESULT_REG);
1099 return DP2_RESULT_REG;
1102 return (dname ? "acc" : "a");
1105 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1106 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1108 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1112 tsprintf(s,"#!his",aop->aopu.aop_immd.aop_immd1);
1115 tsprintf(s,"#!hihis",aop->aopu.aop_immd.aop_immd1);
1118 tsprintf(s,"#!hihihis",aop->aopu.aop_immd.aop_immd1);
1120 default: /* should not need this (just in case) */
1121 sprintf (s, "#(%s >> %d)",
1122 aop->aopu.aop_immd.aop_immd1,
1128 aop->aopu.aop_immd.aop_immd1);
1129 rs = Safe_calloc (1, strlen (s) + 1);
1135 sprintf (s, "(%s + %d)",
1139 sprintf (s, "%s", aop->aopu.aop_dir);
1140 rs = Safe_calloc (1, strlen (s) + 1);
1146 return aop->aopu.aop_reg[offset]->dname;
1148 return aop->aopu.aop_reg[offset]->name;
1151 emitcode ("clr", "a");
1152 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1153 emitcode ("rlc", "a");
1154 return (dname ? "acc" : "a");
1157 if (!offset && dname)
1159 return aop->aopu.aop_str[offset];
1162 return aopLiteral (aop->aopu.aop_lit, offset);
1166 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1170 return aop->aopu.aop_str[offset];
1174 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1175 "aopget got unsupported aop->type");
1178 /*-----------------------------------------------------------------*/
1179 /* aopPut - puts a string for a aop */
1180 /*-----------------------------------------------------------------*/
1182 aopPut (asmop * aop, char *s, int offset)
1186 if (aop->size && offset > (aop->size - 1))
1188 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1189 "aopPut got offset > aop->size");
1193 /* will assign value to value */
1194 /* depending on where it is ofcourse */
1199 sprintf (d, "(%s + %d)",
1200 aop->aopu.aop_dir, offset);
1202 sprintf (d, "%s", aop->aopu.aop_dir);
1205 emitcode ("mov", "%s,%s", d, s);
1210 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1211 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1214 strcmp (s, "r0") == 0 ||
1215 strcmp (s, "r1") == 0 ||
1216 strcmp (s, "r2") == 0 ||
1217 strcmp (s, "r3") == 0 ||
1218 strcmp (s, "r4") == 0 ||
1219 strcmp (s, "r5") == 0 ||
1220 strcmp (s, "r6") == 0 ||
1221 strcmp (s, "r7") == 0)
1222 emitcode ("mov", "%s,%s",
1223 aop->aopu.aop_reg[offset]->dname, s);
1225 emitcode ("mov", "%s,%s",
1226 aop->aopu.aop_reg[offset]->name, s);
1233 if (aop->type == AOP_DPTR2)
1241 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1242 "aopPut writting to code space");
1246 while (offset > aop->coff)
1249 emitcode ("inc", "dptr");
1252 while (offset < aop->coff)
1255 emitcode ("lcall", "__decdptr");
1260 /* if not in accumulater */
1263 emitcode ("movx", "@dptr,a");
1265 if (aop->type == AOP_DPTR2)
1273 while (offset > aop->coff)
1276 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1278 while (offset < aop->coff)
1281 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1288 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1294 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1296 else if (strcmp (s, "r0") == 0 ||
1297 strcmp (s, "r1") == 0 ||
1298 strcmp (s, "r2") == 0 ||
1299 strcmp (s, "r3") == 0 ||
1300 strcmp (s, "r4") == 0 ||
1301 strcmp (s, "r5") == 0 ||
1302 strcmp (s, "r6") == 0 ||
1303 strcmp (s, "r7") == 0)
1306 sprintf (buffer, "a%s", s);
1307 emitcode ("mov", "@%s,%s",
1308 aop->aopu.aop_ptr->name, buffer);
1311 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1316 if (strcmp (s, "a") == 0)
1317 emitcode ("push", "acc");
1321 emitcode ("push", "acc");
1323 emitcode ("push", s);
1329 /* if bit variable */
1330 if (!aop->aopu.aop_dir)
1332 emitcode ("clr", "a");
1333 emitcode ("rlc", "a");
1338 emitcode ("clr", "%s", aop->aopu.aop_dir);
1340 emitcode ("setb", "%s", aop->aopu.aop_dir);
1341 else if (!strcmp (s, "c"))
1342 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1345 if (strcmp (s, "a"))
1350 symbol *lbl = newiTempLabel (NULL);
1351 emitcode ("clr", "c");
1352 emitcode ("jz", "!tlabel", lbl->key + 100);
1353 emitcode ("cpl", "c");
1354 emitcode ("", "!tlabeldef", lbl->key + 100);
1355 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1363 if (strcmp (aop->aopu.aop_str[offset], s))
1364 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1369 if (!offset && (strcmp (s, "acc") == 0))
1372 if (strcmp (aop->aopu.aop_str[offset], s))
1373 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1377 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1378 "aopPut got unsupported aop->type");
1385 /*--------------------------------------------------------------------*/
1386 /* reAdjustPreg - points a register back to where it should (coff==0) */
1387 /*--------------------------------------------------------------------*/
1389 reAdjustPreg (asmop * aop)
1391 if ((aop->coff==0) || (aop->size <= 1)) {
1400 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1404 if (aop->type == AOP_DPTR2)
1411 emitcode ("lcall", "__decdptr");
1414 if (aop->type == AOP_DPTR2)
1424 #define AOP(op) op->aop
1425 #define AOP_TYPE(op) AOP(op)->type
1426 #define AOP_SIZE(op) AOP(op)->size
1427 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1428 AOP_TYPE(x) == AOP_R0))
1430 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1431 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1434 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1435 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1436 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1438 /* Workaround for DS80C390 bug: div ab may return bogus results
1439 * if A is accessed in instruction immediately before the div.
1441 * Will be fixed in B4 rev of processor, Dallas claims.
1444 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1445 if (!AOP_NEEDSACC(RIGHT)) \
1447 /* We can load A first, then B, since \
1448 * B (the RIGHT operand) won't clobber A, \
1449 * thus avoiding touching A right before the div. \
1451 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1452 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1454 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1458 /* Just stuff in a nop after loading A. */ \
1459 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1460 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1462 emitcode("nop", "; workaround for DS80C390 div bug."); \
1465 /*-----------------------------------------------------------------*/
1466 /* genNotFloat - generates not for float operations */
1467 /*-----------------------------------------------------------------*/
1469 genNotFloat (operand * op, operand * res)
1475 D (emitcode (";", "genNotFloat ");
1478 /* we will put 127 in the first byte of
1480 aopPut (AOP (res), "#127", 0);
1481 size = AOP_SIZE (op) - 1;
1484 _startLazyDPSEvaluation ();
1485 l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE);
1490 emitcode ("orl", "a,%s",
1492 offset++, FALSE, FALSE, FALSE));
1494 _endLazyDPSEvaluation ();
1496 tlbl = newiTempLabel (NULL);
1497 aopPut (res->aop, one, 1);
1498 emitcode ("jz", "!tlabel", (tlbl->key + 100));
1499 aopPut (res->aop, zero, 1);
1500 emitcode ("", "!tlabeldef", (tlbl->key + 100));
1502 size = res->aop->size - 2;
1504 /* put zeros in the rest */
1506 aopPut (res->aop, zero, offset++);
1509 /*-----------------------------------------------------------------*/
1510 /* opIsGptr: returns non-zero if the passed operand is */
1511 /* a generic pointer type. */
1512 /*-----------------------------------------------------------------*/
1514 opIsGptr (operand * op)
1516 sym_link *type = operandType (op);
1518 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1525 /*-----------------------------------------------------------------*/
1526 /* getDataSize - get the operand data size */
1527 /*-----------------------------------------------------------------*/
1529 getDataSize (operand * op)
1532 size = AOP_SIZE (op);
1533 if (size == GPTRSIZE)
1535 sym_link *type = operandType (op);
1536 if (IS_GENPTR (type))
1538 /* generic pointer; arithmetic operations
1539 * should ignore the high byte (pointer type).
1547 /*-----------------------------------------------------------------*/
1548 /* outAcc - output Acc */
1549 /*-----------------------------------------------------------------*/
1551 outAcc (operand * result)
1554 size = getDataSize (result);
1557 aopPut (AOP (result), "a", 0);
1560 /* unsigned or positive */
1563 aopPut (AOP (result), zero, offset++);
1568 /*-----------------------------------------------------------------*/
1569 /* outBitC - output a bit C */
1570 /*-----------------------------------------------------------------*/
1572 outBitC (operand * result)
1574 /* if the result is bit */
1575 if (AOP_TYPE (result) == AOP_CRY)
1577 aopPut (AOP (result), "c", 0);
1581 emitcode ("clr", "a");
1582 emitcode ("rlc", "a");
1587 /*-----------------------------------------------------------------*/
1588 /* toBoolean - emit code for orl a,operator(sizeop) */
1589 /*-----------------------------------------------------------------*/
1591 toBoolean (operand * oper)
1593 int size = AOP_SIZE (oper) - 1;
1597 /* The generic part of a generic pointer should
1598 * not participate in it's truth value.
1600 * i.e. 0x10000000 is zero.
1602 if (opIsGptr (oper))
1604 D (emitcode (";", "toBoolean: generic ptr special case.");
1609 _startLazyDPSEvaluation ();
1610 if (AOP_NEEDSACC (oper) && size)
1613 emitcode ("push", "b");
1614 emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1618 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1624 emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1628 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1631 _endLazyDPSEvaluation ();
1635 emitcode ("mov", "a,b");
1636 emitcode ("pop", "b");
1641 /*-----------------------------------------------------------------*/
1642 /* genNot - generate code for ! operation */
1643 /*-----------------------------------------------------------------*/
1648 sym_link *optype = operandType (IC_LEFT (ic));
1650 D (emitcode (";", "genNot ");
1653 /* assign asmOps to operand & result */
1654 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1655 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1657 /* if in bit space then a special case */
1658 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1660 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1661 emitcode ("cpl", "c");
1662 outBitC (IC_RESULT (ic));
1666 /* if type float then do float */
1667 if (IS_FLOAT (optype))
1669 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1673 toBoolean (IC_LEFT (ic));
1675 tlbl = newiTempLabel (NULL);
1676 emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1677 emitcode ("", "!tlabeldef", tlbl->key + 100);
1678 outBitC (IC_RESULT (ic));
1681 /* release the aops */
1682 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1683 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1687 /*-----------------------------------------------------------------*/
1688 /* genCpl - generate code for complement */
1689 /*-----------------------------------------------------------------*/
1696 D (emitcode (";", "genCpl ");
1700 /* assign asmOps to operand & result */
1701 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1702 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1704 /* if both are in bit space then
1706 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1707 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1710 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1711 emitcode ("cpl", "c");
1712 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1716 size = AOP_SIZE (IC_RESULT (ic));
1717 _startLazyDPSEvaluation ();
1720 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1722 emitcode ("cpl", "a");
1723 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1725 _endLazyDPSEvaluation ();
1729 /* release the aops */
1730 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1731 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1734 /*-----------------------------------------------------------------*/
1735 /* genUminusFloat - unary minus for floating points */
1736 /*-----------------------------------------------------------------*/
1738 genUminusFloat (operand * op, operand * result)
1740 int size, offset = 0;
1742 /* for this we just need to flip the
1743 first it then copy the rest in place */
1744 D (emitcode (";", "genUminusFloat");
1747 _startLazyDPSEvaluation ();
1748 size = AOP_SIZE (op) - 1;
1749 l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1752 emitcode ("cpl", "acc.7");
1753 aopPut (AOP (result), "a", 3);
1757 aopPut (AOP (result),
1758 aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1762 _endLazyDPSEvaluation ();
1765 /*-----------------------------------------------------------------*/
1766 /* genUminus - unary minus code generation */
1767 /*-----------------------------------------------------------------*/
1769 genUminus (iCode * ic)
1772 sym_link *optype, *rtype;
1774 D (emitcode (";", "genUminus ");
1779 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1780 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1782 /* if both in bit space then special
1784 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1785 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1788 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1789 emitcode ("cpl", "c");
1790 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1794 optype = operandType (IC_LEFT (ic));
1795 rtype = operandType (IC_RESULT (ic));
1797 /* if float then do float stuff */
1798 if (IS_FLOAT (optype))
1800 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1804 /* otherwise subtract from zero */
1805 size = AOP_SIZE (IC_LEFT (ic));
1807 _startLazyDPSEvaluation ();
1810 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1811 if (!strcmp (l, "a"))
1815 emitcode ("cpl", "a");
1816 emitcode ("addc", "a,#0");
1822 emitcode ("clr", "a");
1823 emitcode ("subb", "a,%s", l);
1825 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1827 _endLazyDPSEvaluation ();
1829 /* if any remaining bytes in the result */
1830 /* we just need to propagate the sign */
1831 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1833 emitcode ("rlc", "a");
1834 emitcode ("subb", "a,acc");
1836 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1840 /* release the aops */
1841 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1842 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1845 /*-----------------------------------------------------------------*/
1846 /* savermask - saves registers in the mask */
1847 /*-----------------------------------------------------------------*/
1848 static void savermask(bitVect *rs_mask)
1851 if (options.useXstack) {
1852 if (bitVectBitValue (rs_mask, R0_IDX))
1853 emitcode ("mov", "b,r0");
1854 emitcode ("mov", "r0,%s", spname);
1855 for (i = 0; i < ds390_nRegs; i++) {
1856 if (bitVectBitValue (rs_mask, i)) {
1858 emitcode ("mov", "a,b");
1860 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1861 emitcode ("movx", "@r0,a");
1862 emitcode ("inc", "r0");
1865 emitcode ("mov", "%s,r0", spname);
1866 if (bitVectBitValue (rs_mask, R0_IDX))
1867 emitcode ("mov", "r0,b");
1869 for (i = 0; i < ds390_nRegs; i++) {
1870 if (bitVectBitValue (rs_mask, i))
1871 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
1876 /*-----------------------------------------------------------------*/
1877 /* saveRegisters - will look for a call and save the registers */
1878 /*-----------------------------------------------------------------*/
1880 saveRegisters (iCode * lic)
1886 for (ic = lic; ic; ic = ic->next)
1887 if (ic->op == CALL || ic->op == PCALL)
1892 fprintf (stderr, "found parameter push with no function call\n");
1896 /* if the registers have been saved already then
1898 if (ic->regsSaved || IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic)))) return ;
1900 /* special case if DPTR alive across a function call then must save it
1901 even though callee saves */
1902 if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
1904 rsave = newBitVect(ic->rMask->size);
1905 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
1906 if (bitVectBitValue(ic->rMask,i))
1907 rsave = bitVectSetBit(rsave,i);
1909 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
1911 /* safe the registers in use at this time but skip the
1912 ones for the result */
1913 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1914 ds390_rUmaskForOp (IC_RESULT(ic)));
1920 /*-----------------------------------------------------------------*/
1921 /* usavermask - restore registers with mask */
1922 /*-----------------------------------------------------------------*/
1923 static void unsavermask(bitVect *rs_mask)
1926 if (options.useXstack) {
1927 emitcode ("mov", "r0,%s", spname);
1928 for (i = ds390_nRegs; i >= 0; i--) {
1929 if (bitVectBitValue (rs_mask, i)) {
1930 emitcode ("dec", "r0");
1931 emitcode ("movx", "a,@r0");
1933 emitcode ("mov", "b,a");
1935 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1938 emitcode ("mov", "%s,r0", spname);
1939 if (bitVectBitValue (rs_mask, R0_IDX))
1940 emitcode ("mov", "r0,b");
1942 for (i = ds390_nRegs; i >= 0; i--) {
1943 if (bitVectBitValue (rs_mask, i))
1944 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
1949 /*-----------------------------------------------------------------*/
1950 /* unsaveRegisters - pop the pushed registers */
1951 /*-----------------------------------------------------------------*/
1953 unsaveRegisters (iCode * ic)
1957 if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
1959 rsave = newBitVect(ic->rMask->size);
1960 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
1961 if (bitVectBitValue(ic->rMask,i))
1962 rsave = bitVectSetBit(rsave,i);
1964 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
1966 /* restore the registers in use at this time but skip the
1967 ones for the result */
1968 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1969 ds390_rUmaskForOp (IC_RESULT(ic)));
1975 /*-----------------------------------------------------------------*/
1977 /*-----------------------------------------------------------------*/
1979 pushSide (operand * oper, int size)
1982 _startLazyDPSEvaluation ();
1985 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
1986 if (AOP_TYPE (oper) != AOP_REG &&
1987 AOP_TYPE (oper) != AOP_DIR &&
1990 emitcode ("mov", "a,%s", l);
1991 emitcode ("push", "acc");
1994 emitcode ("push", "%s", l);
1996 _endLazyDPSEvaluation ();
1999 /*-----------------------------------------------------------------*/
2000 /* assignResultValue - */
2001 /*-----------------------------------------------------------------*/
2003 assignResultValue (operand * oper)
2006 int size = AOP_SIZE (oper);
2008 _startLazyDPSEvaluation ();
2011 aopPut (AOP (oper), fReturn[offset], offset);
2014 _endLazyDPSEvaluation ();
2018 /*-----------------------------------------------------------------*/
2019 /* genXpush - pushes onto the external stack */
2020 /*-----------------------------------------------------------------*/
2022 genXpush (iCode * ic)
2024 asmop *aop = newAsmop (0);
2026 int size, offset = 0;
2028 D (emitcode (";", "genXpush ");
2031 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2032 r = getFreePtr (ic, &aop, FALSE);
2035 emitcode ("mov", "%s,_spx", r->name);
2037 size = AOP_SIZE (IC_LEFT (ic));
2038 _startLazyDPSEvaluation ();
2042 char *l = aopGet (AOP (IC_LEFT (ic)),
2043 offset++, FALSE, FALSE, TRUE);
2045 emitcode ("movx", "@%s,a", r->name);
2046 emitcode ("inc", "%s", r->name);
2049 _endLazyDPSEvaluation ();
2052 emitcode ("mov", "_spx,%s", r->name);
2054 freeAsmop (NULL, aop, ic, TRUE);
2055 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2058 /*-----------------------------------------------------------------*/
2059 /* genIpush - genrate code for pushing this gets a little complex */
2060 /*-----------------------------------------------------------------*/
2062 genIpush (iCode * ic)
2064 int size, offset = 0;
2067 D (emitcode (";", "genIpush ");
2070 /* if this is not a parm push : ie. it is spill push
2071 and spill push is always done on the local stack */
2075 /* and the item is spilt then do nothing */
2076 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2079 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2080 size = AOP_SIZE (IC_LEFT (ic));
2081 /* push it on the stack */
2082 _startLazyDPSEvaluation ();
2085 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
2091 emitcode ("push", "%s", l);
2093 _endLazyDPSEvaluation ();
2097 /* this is a paramter push: in this case we call
2098 the routine to find the call and save those
2099 registers that need to be saved */
2102 /* if use external stack then call the external
2103 stack pushing routine */
2104 if (options.useXstack)
2110 /* then do the push */
2111 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2113 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2114 size = AOP_SIZE (IC_LEFT (ic));
2116 _startLazyDPSEvaluation ();
2119 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
2120 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2121 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2124 emitcode ("mov", "a,%s", l);
2125 emitcode ("push", "acc");
2128 emitcode ("push", "%s", l);
2130 _endLazyDPSEvaluation ();
2132 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2135 /*-----------------------------------------------------------------*/
2136 /* genIpop - recover the registers: can happen only for spilling */
2137 /*-----------------------------------------------------------------*/
2139 genIpop (iCode * ic)
2143 D (emitcode (";", "genIpop ");
2147 /* if the temp was not pushed then */
2148 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2151 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2152 size = AOP_SIZE (IC_LEFT (ic));
2153 offset = (size - 1);
2154 _startLazyDPSEvaluation ();
2157 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2158 FALSE, TRUE, TRUE));
2160 _endLazyDPSEvaluation ();
2162 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2165 /*-----------------------------------------------------------------*/
2166 /* unsaveRBank - restores the resgister bank from stack */
2167 /*-----------------------------------------------------------------*/
2169 unsaveRBank (int bank, iCode * ic, bool popPsw)
2175 if (options.useXstack)
2179 /* Assume r0 is available for use. */
2180 r = ds390_regWithIdx (R0_IDX);;
2185 r = getFreePtr (ic, &aop, FALSE);
2187 emitcode ("mov", "%s,_spx", r->name);
2192 if (options.useXstack)
2194 emitcode ("movx", "a,@%s", r->name);
2195 emitcode ("mov", "psw,a");
2196 emitcode ("dec", "%s", r->name);
2200 emitcode ("pop", "psw");
2204 for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2206 if (options.useXstack)
2208 emitcode ("movx", "a,@%s", r->name);
2209 emitcode ("mov", "(%s+%d),a",
2210 regs390[i].base, 8 * bank + regs390[i].offset);
2211 emitcode ("dec", "%s", r->name);
2215 emitcode ("pop", "(%s+%d)",
2216 regs390[i].base, 8 * bank + regs390[i].offset);
2219 if (options.useXstack)
2221 emitcode ("mov", "_spx,%s", r->name);
2226 freeAsmop (NULL, aop, ic, TRUE);
2230 /*-----------------------------------------------------------------*/
2231 /* saveRBank - saves an entire register bank on the stack */
2232 /*-----------------------------------------------------------------*/
2234 saveRBank (int bank, iCode * ic, bool pushPsw)
2240 if (options.useXstack)
2244 /* Assume r0 is available for use. */
2245 r = ds390_regWithIdx (R0_IDX);;
2250 r = getFreePtr (ic, &aop, FALSE);
2252 emitcode ("mov", "%s,_spx", r->name);
2255 for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2257 if (options.useXstack)
2259 emitcode ("inc", "%s", r->name);
2260 emitcode ("mov", "a,(%s+%d)",
2261 regs390[i].base, 8 * bank + regs390[i].offset);
2262 emitcode ("movx", "@%s,a", r->name);
2265 emitcode ("push", "(%s+%d)",
2266 regs390[i].base, 8 * bank + regs390[i].offset);
2271 if (options.useXstack)
2273 emitcode ("mov", "a,psw");
2274 emitcode ("movx", "@%s,a", r->name);
2275 emitcode ("inc", "%s", r->name);
2276 emitcode ("mov", "_spx,%s", r->name);
2280 emitcode ("push", "psw");
2283 emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2288 freeAsmop (NULL, aop, ic, TRUE);
2297 /*-----------------------------------------------------------------*/
2298 /* genCall - generates a call statement */
2299 /*-----------------------------------------------------------------*/
2301 genCall (iCode * ic)
2304 bool restoreBank = FALSE;
2305 bool swapBanks = FALSE;
2307 D (emitcode (";", "genCall "););
2309 /* if we are calling a not _naked function that is not using
2310 the same register bank then we need to save the
2311 destination registers on the stack */
2312 dtype = operandType (IC_LEFT (ic));
2313 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2314 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2315 IFFUNC_ISISR (currFunc->type))
2319 /* This is unexpected; the bank should have been saved in
2322 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2328 /* if caller saves & we have not saved then */
2332 /* if send set is not empty the assign */
2333 /* We've saved all the registers we care about;
2334 * therefore, we may clobber any register not used
2335 * in the calling convention (i.e. anything not in
2342 for (sic = setFirstItem (_G.sendSet); sic;
2343 sic = setNextItem (_G.sendSet))
2345 int size, offset = 0;
2347 // we know that dpl(hxb) is the result, so
2348 _startLazyDPSEvaluation ();
2349 size=getSize(operandType(IC_LEFT(sic)));
2351 aopOp (IC_LEFT (sic), sic, FALSE,
2352 (IS_SYMOP(IC_LEFT(sic)) && OP_SYMBOL(IC_LEFT(sic))->ruonly ? FALSE : TRUE));
2354 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2358 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2359 FALSE, FALSE, TRUE);
2360 if (strcmp (l, fReturn[offset]))
2362 emitcode ("mov", "%s,%s",
2368 _endLazyDPSEvaluation ();
2369 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2376 emitcode ("mov", "psw,#!constbyte",
2377 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2381 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2382 OP_SYMBOL (IC_LEFT (ic))->rname :
2383 OP_SYMBOL (IC_LEFT (ic))->name));
2387 emitcode ("mov", "psw,#!constbyte",
2388 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2391 /* if we need assign a result value */
2392 if ((IS_ITEMP (IC_RESULT (ic)) &&
2393 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2394 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2395 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2396 IS_TRUE_SYMOP (IC_RESULT (ic)))
2398 if (isOperandInFarSpace (IC_RESULT (ic))
2399 && getSize (operandType (IC_RESULT (ic))) <= 2)
2401 int size = getSize (operandType (IC_RESULT (ic)));
2403 /* Special case for 1 or 2 byte return in far space. */
2407 emitcode ("mov", "b,%s", fReturn[1]);
2410 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2411 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2415 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2417 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2422 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2425 assignResultValue (IC_RESULT (ic));
2427 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2431 /* adjust the stack for parameters if
2433 if (ic->parmBytes) {
2435 if (options.stack10bit) {
2436 if (ic->parmBytes <= 4) {
2437 emitcode(";","stack adjustment for parms");
2438 for (i=0; i < ic->parmBytes ; i++) {
2439 emitcode("pop","acc");
2442 emitcode ("clr","c");
2443 emitcode ("mov","a,sp");
2444 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2445 emitcode ("mov","sp,a");
2446 emitcode ("mov","a,esp");
2447 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2448 emitcode ("mov","esp,a");
2451 if (ic->parmBytes > 3) {
2452 emitcode ("mov", "a,%s", spname);
2453 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2454 emitcode ("mov", "%s,a", spname);
2456 for (i = 0; i < ic->parmBytes; i++)
2457 emitcode ("dec", "%s", spname);
2461 /* if we hade saved some registers then unsave them */
2463 unsaveRegisters (ic);
2465 /* if register bank was saved then pop them */
2467 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2470 /*-----------------------------------------------------------------*/
2471 /* genPcall - generates a call by pointer statement */
2472 /*-----------------------------------------------------------------*/
2474 genPcall (iCode * ic)
2477 symbol *rlbl = newiTempLabel (NULL);
2478 bool restoreBank=FALSE;
2480 D (emitcode (";", "genPcall ");
2484 /* if caller saves & we have not saved then */
2488 /* if we are calling a function that is not using
2489 the same register bank then we need to save the
2490 destination registers on the stack */
2491 dtype = operandType (IC_LEFT (ic));
2492 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2493 IFFUNC_ISISR (currFunc->type) &&
2494 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2495 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2499 /* push the return address on to the stack */
2500 emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2501 emitcode ("push", "acc");
2502 emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2503 emitcode ("push", "acc");
2505 if (options.model == MODEL_FLAT24)
2507 emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2508 emitcode ("push", "acc");
2511 /* now push the calling address */
2512 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2514 pushSide (IC_LEFT (ic), FPTRSIZE);
2516 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2518 /* if send set is not empty the assign */
2523 for (sic = setFirstItem (_G.sendSet); sic;
2524 sic = setNextItem (_G.sendSet))
2526 int size, offset = 0;
2528 // we know that dpl(hxb) is the result, so
2529 _startLazyDPSEvaluation ();
2530 size=getSize(operandType(IC_LEFT(sic)));
2532 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2534 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2538 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2539 FALSE, FALSE, TRUE);
2540 if (strcmp (l, fReturn[offset]))
2542 emitcode ("mov", "%s,%s",
2548 _endLazyDPSEvaluation ();
2549 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2554 emitcode ("ret", "");
2555 emitcode ("", "!tlabeldef", (rlbl->key + 100));
2558 /* if we need assign a result value */
2559 if ((IS_ITEMP (IC_RESULT (ic)) &&
2560 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2561 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2562 IS_TRUE_SYMOP (IC_RESULT (ic)))
2566 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2569 assignResultValue (IC_RESULT (ic));
2571 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2574 /* adjust the stack for parameters if
2579 if (ic->parmBytes > 3)
2581 emitcode ("mov", "a,%s", spname);
2582 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2583 emitcode ("mov", "%s,a", spname);
2586 for (i = 0; i < ic->parmBytes; i++)
2587 emitcode ("dec", "%s", spname);
2591 /* if register bank was saved then unsave them */
2593 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2595 /* if we hade saved some registers then
2598 unsaveRegisters (ic);
2602 /*-----------------------------------------------------------------*/
2603 /* resultRemat - result is rematerializable */
2604 /*-----------------------------------------------------------------*/
2606 resultRemat (iCode * ic)
2608 if (SKIP_IC (ic) || ic->op == IFX)
2611 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2613 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2614 if (sym->remat && !POINTER_SET (ic))
2621 #if defined(__BORLANDC__) || defined(_MSC_VER)
2622 #define STRCASECMP stricmp
2624 #define STRCASECMP strcasecmp
2627 /*-----------------------------------------------------------------*/
2628 /* inExcludeList - return 1 if the string is in exclude Reg list */
2629 /*-----------------------------------------------------------------*/
2631 inExcludeList (char *s)
2635 if (options.excludeRegs[i] &&
2636 STRCASECMP (options.excludeRegs[i], "none") == 0)
2639 for (i = 0; options.excludeRegs[i]; i++)
2641 if (options.excludeRegs[i] &&
2642 STRCASECMP (s, options.excludeRegs[i]) == 0)
2648 /*-----------------------------------------------------------------*/
2649 /* genFunction - generated code for function entry */
2650 /*-----------------------------------------------------------------*/
2652 genFunction (iCode * ic)
2656 bool switchedPSW = FALSE;
2658 D (emitcode (";", "genFunction "););
2661 /* create the function header */
2662 emitcode (";", "-----------------------------------------");
2663 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2664 emitcode (";", "-----------------------------------------");
2666 emitcode ("", "%s:", sym->rname);
2667 ftype = operandType (IC_LEFT (ic));
2669 if (IFFUNC_ISNAKED(ftype))
2671 emitcode(";", "naked function: no prologue.");
2675 if (options.stack_probe)
2676 emitcode ("lcall","__stack_probe");
2677 /* if critical function then turn interrupts off */
2678 if (IFFUNC_ISCRITICAL (ftype))
2679 emitcode ("clr", "ea");
2681 /* here we need to generate the equates for the
2682 register bank if required */
2683 if (FUNC_REGBANK (ftype) != rbank)
2687 rbank = FUNC_REGBANK (ftype);
2688 for (i = 0; i < ds390_nRegs; i++)
2690 if (regs390[i].print) {
2691 if (strcmp (regs390[i].base, "0") == 0)
2692 emitcode ("", "%s !equ !constbyte",
2694 8 * rbank + regs390[i].offset);
2696 emitcode ("", "%s !equ %s + !constbyte",
2699 8 * rbank + regs390[i].offset);
2704 /* if this is an interrupt service routine then
2705 save acc, b, dpl, dph */
2706 if (IFFUNC_ISISR (sym->type))
2709 if (!inExcludeList ("acc"))
2710 emitcode ("push", "acc");
2711 if (!inExcludeList ("b"))
2712 emitcode ("push", "b");
2713 if (!inExcludeList ("dpl"))
2714 emitcode ("push", "dpl");
2715 if (!inExcludeList ("dph"))
2716 emitcode ("push", "dph");
2717 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2719 emitcode ("push", "dpx");
2720 /* Make sure we're using standard DPTR */
2721 emitcode ("push", "dps");
2722 emitcode ("mov", "dps,#0");
2723 if (options.stack10bit)
2725 /* This ISR could conceivably use DPTR2. Better save it. */
2726 emitcode ("push", "dpl1");
2727 emitcode ("push", "dph1");
2728 emitcode ("push", "dpx1");
2729 emitcode ("push", DP2_RESULT_REG);
2732 /* if this isr has no bank i.e. is going to
2733 run with bank 0 , then we need to save more
2735 if (!FUNC_REGBANK (sym->type))
2738 /* if this function does not call any other
2739 function then we can be economical and
2740 save only those registers that are used */
2741 if (!IFFUNC_HASFCALL(sym->type))
2745 /* if any registers used */
2748 /* save the registers used */
2749 for (i = 0; i < sym->regsUsed->size; i++)
2751 if (bitVectBitValue (sym->regsUsed, i) ||
2752 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2753 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2760 /* this function has a function call cannot
2761 determines register usage so we will have to push the
2763 saveRBank (0, ic, FALSE);
2768 /* This ISR uses a non-zero bank.
2770 * We assume that the bank is available for our
2773 * However, if this ISR calls a function which uses some
2774 * other bank, we must save that bank entirely.
2776 unsigned long banksToSave = 0;
2778 if (IFFUNC_HASFCALL(sym->type))
2781 #define MAX_REGISTER_BANKS 4
2786 for (i = ic; i; i = i->next)
2788 if (i->op == ENDFUNCTION)
2790 /* we got to the end OK. */
2798 dtype = operandType (IC_LEFT(i));
2800 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2802 /* Mark this bank for saving. */
2803 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2805 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2809 banksToSave |= (1 << FUNC_REGBANK(dtype));
2812 /* And note that we don't need to do it in
2820 /* This is a mess; we have no idea what
2821 * register bank the called function might
2824 * The only thing I can think of to do is
2825 * throw a warning and hope.
2827 werror(W_FUNCPTR_IN_USING_ISR);
2831 if (banksToSave && options.useXstack)
2833 /* Since we aren't passing it an ic,
2834 * saveRBank will assume r0 is available to abuse.
2836 * So switch to our (trashable) bank now, so
2837 * the caller's R0 isn't trashed.
2839 emitcode ("push", "psw");
2840 emitcode ("mov", "psw,#!constbyte",
2841 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2845 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2847 if (banksToSave & (1 << ix))
2849 saveRBank(ix, NULL, FALSE);
2853 // jwk: this needs a closer look
2854 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2859 /* if callee-save to be used for this function
2860 then save the registers being used in this function */
2861 if (IFFUNC_CALLEESAVES(sym->type))
2865 /* if any registers used */
2868 /* save the registers used */
2869 for (i = 0; i < sym->regsUsed->size; i++)
2871 if (bitVectBitValue (sym->regsUsed, i) ||
2872 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2874 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2882 /* set the register bank to the desired value */
2883 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
2886 emitcode ("push", "psw");
2887 emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2890 if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
2891 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
2892 if (options.stack10bit) {
2893 emitcode ("push","_bpx");
2894 emitcode ("push","_bpx+1");
2895 emitcode ("mov","_bpx,%s",spname);
2896 emitcode ("mov","_bpx+1,esp");
2897 emitcode ("anl","_bpx+1,#3");
2899 if (options.useXstack) {
2900 emitcode ("mov", "r0,%s", spname);
2901 emitcode ("mov", "a,_bp");
2902 emitcode ("movx", "@r0,a");
2903 emitcode ("inc", "%s", spname);
2905 /* set up the stack */
2906 emitcode ("push", "_bp"); /* save the callers stack */
2908 emitcode ("mov", "_bp,%s", spname);
2912 /* adjust the stack for the function */
2915 if (options.stack10bit) {
2916 if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
2917 assert (sym->recvSize <= 4);
2918 emitcode ("mov","a,sp");
2919 emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
2920 emitcode ("mov","sp,a");
2921 emitcode ("mov","a,esp");
2922 emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
2923 emitcode ("mov","esp,a");
2926 werror (W_STACK_OVERFLOW, sym->name);
2928 if (i > 3 && sym->recvSize < 4) {
2930 emitcode ("mov", "a,sp");
2931 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
2932 emitcode ("mov", "sp,a");
2936 emitcode ("inc", "sp");
2943 emitcode ("mov", "a,_spx");
2944 emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
2945 emitcode ("mov", "_spx,a");
2950 /*-----------------------------------------------------------------*/
2951 /* genEndFunction - generates epilogue for functions */
2952 /*-----------------------------------------------------------------*/
2954 genEndFunction (iCode * ic)
2956 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2958 D (emitcode (";", "genEndFunction "););
2960 if (IFFUNC_ISNAKED(sym->type))
2962 emitcode(";", "naked function: no epilogue.");
2966 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
2967 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
2969 if (options.stack10bit) {
2970 emitcode ("mov", "sp,_bpx", spname);
2971 emitcode ("mov", "esp,_bpx+1", spname);
2973 emitcode ("mov", "%s,_bp", spname);
2977 /* if use external stack but some variables were
2978 added to the local stack then decrement the
2980 if (options.useXstack && sym->stack) {
2981 emitcode ("mov", "a,sp");
2982 emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
2983 emitcode ("mov", "sp,a");
2987 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
2988 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
2990 if (options.useXstack) {
2991 emitcode ("mov", "r0,%s", spname);
2992 emitcode ("movx", "a,@r0");
2993 emitcode ("mov", "_bp,a");
2994 emitcode ("dec", "%s", spname);
2996 if (options.stack10bit) {
2997 emitcode ("pop", "_bpx+1");
2998 emitcode ("pop", "_bpx");
3000 emitcode ("pop", "_bp");
3005 /* restore the register bank */
3006 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3008 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3009 || !options.useXstack)
3011 /* Special case of ISR using non-zero bank with useXstack
3014 emitcode ("pop", "psw");
3018 if (IFFUNC_ISISR (sym->type))
3021 /* now we need to restore the registers */
3022 /* if this isr has no bank i.e. is going to
3023 run with bank 0 , then we need to save more
3025 if (!FUNC_REGBANK (sym->type))
3027 /* if this function does not call any other
3028 function then we can be economical and
3029 save only those registers that are used */
3030 if (!IFFUNC_HASFCALL(sym->type))
3034 /* if any registers used */
3037 /* save the registers used */
3038 for (i = sym->regsUsed->size; i >= 0; i--)
3040 if (bitVectBitValue (sym->regsUsed, i) ||
3041 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3042 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3049 /* this function has a function call cannot
3050 determines register usage so we will have to pop the
3052 unsaveRBank (0, ic, FALSE);
3057 /* This ISR uses a non-zero bank.
3059 * Restore any register banks saved by genFunction
3062 // jwk: this needs a closer look
3063 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3066 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3068 if (savedBanks & (1 << ix))
3070 unsaveRBank(ix, NULL, FALSE);
3074 if (options.useXstack)
3076 /* Restore bank AFTER calling unsaveRBank,
3077 * since it can trash r0.
3079 emitcode ("pop", "psw");
3083 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3085 if (options.stack10bit)
3087 emitcode ("pop", DP2_RESULT_REG);
3088 emitcode ("pop", "dpx1");
3089 emitcode ("pop", "dph1");
3090 emitcode ("pop", "dpl1");
3092 emitcode ("pop", "dps");
3093 emitcode ("pop", "dpx");
3095 if (!inExcludeList ("dph"))
3096 emitcode ("pop", "dph");
3097 if (!inExcludeList ("dpl"))
3098 emitcode ("pop", "dpl");
3099 if (!inExcludeList ("b"))
3100 emitcode ("pop", "b");
3101 if (!inExcludeList ("acc"))
3102 emitcode ("pop", "acc");
3104 if (IFFUNC_ISCRITICAL (sym->type))
3105 emitcode ("setb", "ea");
3107 /* if debug then send end of function */
3108 if (options.debug && currFunc) {
3110 emitcode ("", "C$%s$%d$%d$%d ==.",
3111 FileBaseName (ic->filename), currFunc->lastLine,
3112 ic->level, ic->block);
3113 if (IS_STATIC (currFunc->etype))
3114 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3116 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3120 emitcode ("reti", "");
3124 if (IFFUNC_ISCRITICAL (sym->type))
3125 emitcode ("setb", "ea");
3127 if (IFFUNC_CALLEESAVES(sym->type))
3131 /* if any registers used */
3134 /* save the registers used */
3135 for (i = sym->regsUsed->size; i >= 0; i--)
3137 if (bitVectBitValue (sym->regsUsed, i) ||
3138 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3139 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3145 /* if debug then send end of function */
3146 if (options.debug && currFunc)
3149 emitcode ("", "C$%s$%d$%d$%d ==.",
3150 FileBaseName (ic->filename), currFunc->lastLine,
3151 ic->level, ic->block);
3152 if (IS_STATIC (currFunc->etype))
3153 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3155 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3159 emitcode ("ret", "");
3164 /*-----------------------------------------------------------------*/
3165 /* genJavaNativeRet - generate code for return JavaNative */
3166 /*-----------------------------------------------------------------*/
3167 static void genJavaNativeRet(iCode *ic)
3171 aopOp (IC_LEFT (ic), ic, FALSE,
3172 (IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly ? FALSE :TRUE));
3173 size = AOP_SIZE (IC_LEFT (ic));
3177 /* it is assigned to GPR0-R3 then push them */
3178 if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3179 aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3180 for (i = 0 ; i < size ; i++ ) {
3181 emitcode ("push","%s",aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,FALSE));
3183 for (i = (size-1) ; i >= 0 ; i--) {
3184 emitcode ("pop","a%s",javaRet[i]);
3187 for (i = 0 ; i < size ; i++)
3188 emitcode ("mov","%s,%s",javaRet[i],aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,FALSE));
3190 for (i = size ; i < 4 ; i++ )
3191 emitcode ("mov","%s,#0",javaRet[i]);
3195 /*-----------------------------------------------------------------*/
3196 /* genRet - generate code for return statement */
3197 /*-----------------------------------------------------------------*/
3201 int size, offset = 0, pushed = 0;
3203 D (emitcode (";", "genRet ");
3206 /* if we have no return value then
3207 just generate the "ret" */
3211 /* if this is a JavaNative function then return
3212 value in different register */
3213 if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3214 genJavaNativeRet(ic);
3217 /* we have something to return then
3218 move the return value into place */
3219 aopOp (IC_LEFT (ic), ic, FALSE,
3220 (IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly ? FALSE :TRUE));
3221 size = AOP_SIZE (IC_LEFT (ic));
3223 _startLazyDPSEvaluation ();
3227 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3229 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3230 FALSE, TRUE, FALSE);
3231 emitcode ("push", "%s", l);
3236 /* Since A is the last element of fReturn,
3237 * is is OK to clobber it in the aopGet.
3239 l = aopGet (AOP (IC_LEFT (ic)), offset,
3240 FALSE, FALSE, TRUE);
3241 if (strcmp (fReturn[offset], l))
3242 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3245 _endLazyDPSEvaluation ();
3252 if (strcmp (fReturn[pushed], "a"))
3253 emitcode ("pop", fReturn[pushed]);
3255 emitcode ("pop", "acc");
3258 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3261 /* generate a jump to the return label
3262 if the next is not the return statement */
3263 if (!(ic->next && ic->next->op == LABEL &&
3264 IC_LABEL (ic->next) == returnLabel))
3266 emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3270 /*-----------------------------------------------------------------*/
3271 /* genLabel - generates a label */
3272 /*-----------------------------------------------------------------*/
3274 genLabel (iCode * ic)
3276 /* special case never generate */
3277 if (IC_LABEL (ic) == entryLabel)
3280 D (emitcode (";", "genLabel ");
3283 emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3286 /*-----------------------------------------------------------------*/
3287 /* genGoto - generates a ljmp */
3288 /*-----------------------------------------------------------------*/
3290 genGoto (iCode * ic)
3292 D (emitcode (";", "genGoto ");
3294 emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3297 /*-----------------------------------------------------------------*/
3298 /* findLabelBackwards: walks back through the iCode chain looking */
3299 /* for the given label. Returns number of iCode instructions */
3300 /* between that label and given ic. */
3301 /* Returns zero if label not found. */
3302 /*-----------------------------------------------------------------*/
3304 findLabelBackwards (iCode * ic, int key)
3313 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3315 /* printf("findLabelBackwards = %d\n", count); */
3323 /*-----------------------------------------------------------------*/
3324 /* genPlusIncr :- does addition with increment if possible */
3325 /*-----------------------------------------------------------------*/
3327 genPlusIncr (iCode * ic)
3329 unsigned int icount;
3330 unsigned int size = getDataSize (IC_RESULT (ic));
3332 /* will try to generate an increment */
3333 /* if the right side is not a literal
3335 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3338 /* if the literal value of the right hand side
3339 is greater than 4 then it is not worth it */
3340 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3343 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3344 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3346 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
3350 /* if increment 16 bits in register */
3352 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3353 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3354 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3362 /* If the next instruction is a goto and the goto target
3363 * is <= 5 instructions previous to this, we can generate
3364 * jumps straight to that target.
3366 if (ic->next && ic->next->op == GOTO
3367 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3370 emitcode (";", "tail increment optimized (range %d)", labelRange);
3371 tlbl = IC_LABEL (ic->next);
3376 tlbl = newiTempLabel (NULL);
3379 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3380 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3381 IS_AOP_PREG (IC_RESULT (ic)))
3382 emitcode ("cjne", "%s,#0,!tlabel"
3383 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3387 emitcode ("clr", "a");
3388 emitcode ("cjne", "a,%s,!tlabel"
3389 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3393 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3396 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3397 IS_AOP_PREG (IC_RESULT (ic)))
3398 emitcode ("cjne", "%s,#0,!tlabel"
3399 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3402 emitcode ("cjne", "a,%s,!tlabel"
3403 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3406 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3410 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3411 IS_AOP_PREG (IC_RESULT (ic)))
3412 emitcode ("cjne", "%s,#0,!tlabel"
3413 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3417 emitcode ("cjne", "a,%s,!tlabel"
3418 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3421 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3426 emitcode ("", "!tlabeldef", tlbl->key + 100);
3431 /* if the sizes are greater than 1 then we cannot */
3432 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3433 AOP_SIZE (IC_LEFT (ic)) > 1)
3436 /* we can if the aops of the left & result match or
3437 if they are in registers and the registers are the
3440 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3441 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3442 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3447 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3448 emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3449 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3454 _startLazyDPSEvaluation ();
3457 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3459 _endLazyDPSEvaluation ();
3468 /*-----------------------------------------------------------------*/
3469 /* outBitAcc - output a bit in acc */
3470 /*-----------------------------------------------------------------*/
3472 outBitAcc (operand * result)
3474 symbol *tlbl = newiTempLabel (NULL);
3475 /* if the result is a bit */
3476 if (AOP_TYPE (result) == AOP_CRY)
3478 aopPut (AOP (result), "a", 0);
3482 emitcode ("jz", "!tlabel", tlbl->key + 100);
3483 emitcode ("mov", "a,%s", one);
3484 emitcode ("", "!tlabeldef", tlbl->key + 100);
3489 /*-----------------------------------------------------------------*/
3490 /* genPlusBits - generates code for addition of two bits */
3491 /*-----------------------------------------------------------------*/
3493 genPlusBits (iCode * ic)
3495 D (emitcode (";", "genPlusBits ");
3497 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3499 symbol *lbl = newiTempLabel (NULL);
3500 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3501 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3502 emitcode ("cpl", "c");
3503 emitcode ("", "!tlabeldef", (lbl->key + 100));
3504 outBitC (IC_RESULT (ic));
3508 emitcode ("clr", "a");
3509 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3510 emitcode ("rlc", "a");
3511 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3512 emitcode ("addc", "a,#0");
3513 outAcc (IC_RESULT (ic));
3518 adjustArithmeticResult (iCode * ic)
3520 if (opIsGptr (IC_RESULT (ic)) &&
3521 opIsGptr (IC_LEFT (ic)) &&
3522 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3524 aopPut (AOP (IC_RESULT (ic)),
3525 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3529 if (opIsGptr (IC_RESULT (ic)) &&
3530 opIsGptr (IC_RIGHT (ic)) &&
3531 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3533 aopPut (AOP (IC_RESULT (ic)),
3534 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3538 if (opIsGptr (IC_RESULT (ic)) &&
3539 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3540 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3541 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3542 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3545 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3546 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3550 #if 0 // AOP_OP_3 is deprecated; nobody likes Ack errors.
3551 // Please don't bring it back without a really good reason.
3552 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3553 // (because all three operands are in far space).
3554 #define AOP_OP_3(ic) \
3555 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3556 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3557 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3558 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3559 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3560 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3562 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3564 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3568 // Macro to aopOp all three operands of an ic. If this cannot be done,
3569 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3570 // will be set TRUE. The caller must then handle the case specially, noting
3571 // that the IC_RESULT operand is not aopOp'd.
3572 #define AOP_OP_3_NOFATAL(ic, rc) \
3573 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3574 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR) || \
3575 ((OP_SYMBOL(IC_RESULT(ic))->ruonly) && !isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)))); \
3576 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3577 (isOperandInFarSpace(IC_RESULT(ic)) || (OP_SYMBOL(IC_RESULT(ic))->ruonly && !isOperandEqual(IC_LEFT(ic),IC_RESULT(ic))))) \
3579 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3584 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3585 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3587 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3588 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3590 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3592 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3596 // aopOp the left & right operands of an ic.
3597 #define AOP_OP_2(ic) \
3598 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3599 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3601 // convienience macro.
3602 #define AOP_SET_LOCALS(ic) \
3603 left = IC_LEFT(ic); \
3604 right = IC_RIGHT(ic); \
3605 result = IC_RESULT(ic);
3608 // Given an integer value of pushedSize bytes on the stack,
3609 // adjust it to be resultSize bytes, either by discarding
3610 // the most significant bytes or by zero-padding.
3612 // On exit from this macro, pushedSize will have been adjusted to
3613 // equal resultSize, and ACC may be trashed.
3614 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3615 /* If the pushed data is bigger than the result, \
3616 * simply discard unused bytes. Icky, but works. \
3618 while (pushedSize > resultSize) \
3620 D (emitcode (";", "discarding unused result byte."););\
3621 emitcode ("pop", "acc"); \
3624 if (pushedSize < resultSize) \
3626 emitcode ("clr", "a"); \
3627 /* Conversly, we haven't pushed enough here. \
3628 * just zero-pad, and all is well. \
3630 while (pushedSize < resultSize) \
3632 emitcode("push", "acc"); \
3636 assert(pushedSize == resultSize);
3638 /*-----------------------------------------------------------------*/
3639 /* genPlus - generates code for addition */
3640 /*-----------------------------------------------------------------*/
3642 genPlus (iCode * ic)
3644 int size, offset = 0;
3645 bool pushResult = FALSE;
3648 D (emitcode (";", "genPlus "););
3650 /* special cases :- */
3651 if ( IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly &&
3652 isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
3653 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
3654 size = floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
3656 while (size--) emitcode ("inc","dptr");
3658 emitcode ("mov","a,dpl");
3659 emitcode ("add","a,#!constbyte",size & 0xff);
3660 emitcode ("mov","dpl,a");
3661 emitcode ("mov","a,dph");
3662 emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
3663 emitcode ("mov","dph,a");
3664 emitcode ("mov","a,dpx");
3665 emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
3666 emitcode ("mov","dpx,a");
3668 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
3671 if ( IS_SYMOP(IC_LEFT(ic)) &&
3672 OP_SYMBOL(IC_LEFT(ic))->remat &&
3673 isOperandInFarSpace(IC_RIGHT(ic))) {
3674 operand *op = IC_RIGHT(ic);
3675 IC_RIGHT(ic) = IC_LEFT(ic);
3679 AOP_OP_3_NOFATAL (ic, pushResult);
3682 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3687 /* if literal, literal on the right or
3688 if left requires ACC or right is already
3690 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3691 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3692 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3694 operand *t = IC_RIGHT (ic);
3695 IC_RIGHT (ic) = IC_LEFT (ic);
3697 emitcode (";", "Swapped plus args.");
3700 /* if both left & right are in bit
3702 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3703 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3709 /* if left in bit space & right literal */
3710 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3711 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3713 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3714 /* if result in bit space */
3715 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3717 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3718 emitcode ("cpl", "c");
3719 outBitC (IC_RESULT (ic));
3723 size = getDataSize (IC_RESULT (ic));
3724 _startLazyDPSEvaluation ();
3727 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3728 emitcode ("addc", "a,#0");
3729 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3731 _endLazyDPSEvaluation ();
3736 /* if I can do an increment instead
3737 of add then GOOD for ME */
3738 if (genPlusIncr (ic) == TRUE)
3740 emitcode (";", "did genPlusIncr");
3745 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3747 _startLazyDPSEvaluation ();
3750 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3752 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3754 emitcode ("add", "a,%s",
3755 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3757 emitcode ("addc", "a,%s",
3758 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3762 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3764 /* right is going to use ACC or we would have taken the
3767 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3769 D(emitcode(";", "+ AOP_ACC special case."););
3770 emitcode("xch", "a, %s", DP2_RESULT_REG);
3772 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3775 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3778 emitcode("add", "a, %s", DP2_RESULT_REG);
3782 emitcode ("add", "a,%s",
3783 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
3788 emitcode ("addc", "a,%s",
3789 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3794 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3798 emitcode ("push", "acc");
3802 _endLazyDPSEvaluation ();
3806 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3808 size = getDataSize (IC_LEFT (ic));
3809 rSize = getDataSize (IC_RESULT (ic));
3811 ADJUST_PUSHED_RESULT(size, rSize);
3813 _startLazyDPSEvaluation ();
3816 emitcode ("pop", "acc");
3817 aopPut (AOP (IC_RESULT (ic)), "a", size);
3819 _endLazyDPSEvaluation ();
3822 adjustArithmeticResult (ic);
3825 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3826 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3827 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3830 /*-----------------------------------------------------------------*/
3831 /* genMinusDec :- does subtraction with deccrement if possible */
3832 /*-----------------------------------------------------------------*/
3834 genMinusDec (iCode * ic)
3836 unsigned int icount;
3837 unsigned int size = getDataSize (IC_RESULT (ic));
3839 /* will try to generate an increment */
3840 /* if the right side is not a literal
3842 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3845 /* if the literal value of the right hand side
3846 is greater than 4 then it is not worth it */
3847 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3850 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3851 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3853 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
3857 /* if decrement 16 bits in register */
3858 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3859 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3860 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3868 /* If the next instruction is a goto and the goto target
3869 * is <= 5 instructions previous to this, we can generate
3870 * jumps straight to that target.
3872 if (ic->next && ic->next->op == GOTO
3873 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3876 emitcode (";", "tail decrement optimized (range %d)", labelRange);
3877 tlbl = IC_LABEL (ic->next);
3882 tlbl = newiTempLabel (NULL);
3886 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3887 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3888 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3889 IS_AOP_PREG (IC_RESULT (ic)))
3890 emitcode ("cjne", "%s,#!constbyte,!tlabel"
3891 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE), 0xff
3895 emitcode ("mov", "a,#!constbyte",0xff);
3896 emitcode ("cjne", "a,%s,!tlabel"
3897 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3900 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3903 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3904 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3905 IS_AOP_PREG (IC_RESULT (ic)))
3906 emitcode ("cjne", "%s,#!constbyte,!tlabel"
3907 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE),0xff
3911 emitcode ("cjne", "a,%s,!tlabel"
3912 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3915 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3919 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3920 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3921 IS_AOP_PREG (IC_RESULT (ic)))
3922 emitcode ("cjne", "%s,#!constbyte,!tlabel"
3923 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE),0xff
3927 emitcode ("cjne", "a,%s,!tlabel"
3928 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3931 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3935 emitcode ("", "!tlabeldef", tlbl->key + 100);
3940 /* if the sizes are greater than 1 then we cannot */
3941 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3942 AOP_SIZE (IC_LEFT (ic)) > 1)
3945 /* we can if the aops of the left & result match or
3946 if they are in registers and the registers are the
3949 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3950 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3951 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3954 _startLazyDPSEvaluation ();
3957 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3959 _endLazyDPSEvaluation ();
3967 /*-----------------------------------------------------------------*/
3968 /* addSign - complete with sign */
3969 /*-----------------------------------------------------------------*/
3971 addSign (operand * result, int offset, int sign)
3973 int size = (getDataSize (result) - offset);
3976 _startLazyDPSEvaluation();
3979 emitcode ("rlc", "a");
3980 emitcode ("subb", "a,acc");
3983 aopPut (AOP (result), "a", offset++);
3990 aopPut (AOP (result), zero, offset++);
3993 _endLazyDPSEvaluation();
3997 /*-----------------------------------------------------------------*/
3998 /* genMinusBits - generates code for subtraction of two bits */
3999 /*-----------------------------------------------------------------*/
4001 genMinusBits (iCode * ic)
4003 symbol *lbl = newiTempLabel (NULL);
4005 D (emitcode (";", "genMinusBits "););
4007 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4009 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4010 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4011 emitcode ("cpl", "c");
4012 emitcode ("", "!tlabeldef", (lbl->key + 100));
4013 outBitC (IC_RESULT (ic));
4017 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4018 emitcode ("subb", "a,acc");
4019 emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4020 emitcode ("inc", "a");
4021 emitcode ("", "!tlabeldef", (lbl->key + 100));
4022 aopPut (AOP (IC_RESULT (ic)), "a", 0);
4023 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4027 /*-----------------------------------------------------------------*/
4028 /* genMinus - generates code for subtraction */
4029 /*-----------------------------------------------------------------*/
4031 genMinus (iCode * ic)
4033 int size, offset = 0;
4035 unsigned long lit = 0L;
4036 bool pushResult = FALSE;
4038 D (emitcode (";", "genMinus "););
4040 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
4041 aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
4042 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
4043 (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
4049 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
4051 /* special cases :- */
4052 /* if both left & right are in bit space */
4053 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4054 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4060 /* if I can do an decrement instead
4061 of subtract then GOOD for ME */
4062 if (genMinusDec (ic) == TRUE)
4067 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4069 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4075 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4080 /* if literal, add a,#-lit, else normal subb */
4081 _startLazyDPSEvaluation ();
4084 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
4085 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4086 emitcode ("subb", "a,%s",
4087 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
4090 /* first add without previous c */
4092 if (!size && lit==-1) {
4093 emitcode ("dec", "a");
4095 emitcode ("add", "a,#!constbyte",
4096 (unsigned int) (lit & 0x0FFL));
4099 emitcode ("addc", "a,#!constbyte",
4100 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4106 emitcode ("push", "acc");
4110 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4114 _endLazyDPSEvaluation ();
4118 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4120 size = getDataSize (IC_LEFT (ic));
4121 rSize = getDataSize (IC_RESULT (ic));
4123 ADJUST_PUSHED_RESULT(size, rSize);
4125 _startLazyDPSEvaluation ();
4128 emitcode ("pop", "acc");
4129 aopPut (AOP (IC_RESULT (ic)), "a", size);
4131 _endLazyDPSEvaluation ();
4134 adjustArithmeticResult (ic);
4137 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4138 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4139 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4143 /*-----------------------------------------------------------------*/
4144 /* genMultbits :- multiplication of bits */
4145 /*-----------------------------------------------------------------*/
4147 genMultbits (operand * left,
4152 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4153 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4154 aopOp(result, ic, TRUE, FALSE);
4159 /*-----------------------------------------------------------------*/
4160 /* genMultOneByte : 8*8=8/16 bit multiplication */
4161 /*-----------------------------------------------------------------*/
4163 genMultOneByte (operand * left,
4168 sym_link *opetype = operandType (result);
4172 /* (if two literals: the value is computed before) */
4173 /* if one literal, literal on the right */
4174 if (AOP_TYPE (left) == AOP_LIT)
4179 emitcode (";", "swapped left and right");
4182 if (SPEC_USIGN(opetype)
4183 // ignore the sign of left and right, what else can we do?
4184 || (SPEC_USIGN(operandType(left)) &&
4185 SPEC_USIGN(operandType(right)))) {
4186 // just an unsigned 8*8=8/16 multiply
4187 //emitcode (";","unsigned");
4188 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4189 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4190 emitcode ("mul", "ab");
4192 _G.accInUse++; _G.bInUse++;
4193 aopOp(result, ic, TRUE, FALSE);
4195 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4197 // this should never happen
4198 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4199 AOP_SIZE(result), __FILE__, lineno);
4203 aopPut (AOP (result), "a", 0);
4204 _G.accInUse--; _G.bInUse--;
4205 if (AOP_SIZE(result)==2)
4207 aopPut (AOP (result), "b", 1);
4212 // we have to do a signed multiply
4214 emitcode (";", "signed");
4215 emitcode ("clr", "F0"); // reset sign flag
4216 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4218 lbl=newiTempLabel(NULL);
4219 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4220 // left side is negative, 8-bit two's complement, this fails for -128
4221 emitcode ("setb", "F0"); // set sign flag
4222 emitcode ("cpl", "a");
4223 emitcode ("inc", "a");
4225 emitcode ("", "!tlabeldef", lbl->key+100);
4228 if (AOP_TYPE(right)==AOP_LIT) {
4229 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4230 /* AND literal negative */
4231 if ((int) val < 0) {
4232 emitcode ("cpl", "F0"); // complement sign flag
4233 emitcode ("mov", "b,#!constbyte", -val);
4235 emitcode ("mov", "b,#!constbyte", val);
4238 lbl=newiTempLabel(NULL);
4239 emitcode ("mov", "b,a");
4240 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4241 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4242 // right side is negative, 8-bit two's complement
4243 emitcode ("cpl", "F0"); // complement sign flag
4244 emitcode ("cpl", "a");
4245 emitcode ("inc", "a");
4246 emitcode ("", "!tlabeldef", lbl->key+100);
4248 emitcode ("mul", "ab");
4250 _G.accInUse++;_G.bInUse++;
4251 aopOp(result, ic, TRUE, FALSE);
4253 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4255 // this should never happen
4256 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4257 AOP_SIZE(result), __FILE__, lineno);
4261 lbl=newiTempLabel(NULL);
4262 emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4263 // only ONE op was negative, we have to do a 8/16-bit two's complement
4264 emitcode ("cpl", "a"); // lsb
4265 if (AOP_SIZE(result)==1) {
4266 emitcode ("inc", "a");
4268 emitcode ("add", "a,#1");
4269 emitcode ("xch", "a,b");
4270 emitcode ("cpl", "a"); // msb
4271 emitcode ("addc", "a,#0");
4272 emitcode ("xch", "a,b");
4275 emitcode ("", "!tlabeldef", lbl->key+100);
4276 aopPut (AOP (result), "a", 0);
4277 _G.accInUse--;_G.bInUse--;
4278 if (AOP_SIZE(result)==2) {
4279 aopPut (AOP (result), "b", 1);
4283 /*-----------------------------------------------------------------*/
4284 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
4285 /*-----------------------------------------------------------------*/
4286 static void genMultTwoByte (operand *left, operand *right,
4287 operand *result, iCode *ic)
4289 sym_link *retype = getSpec(operandType(right));
4290 sym_link *letype = getSpec(operandType(left));
4291 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4294 if (AOP_TYPE (left) == AOP_LIT) {
4299 /* save EA bit in F1 */
4300 lbl = newiTempLabel(NULL);
4301 emitcode ("setb","F1");
4302 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4303 emitcode ("clr","F1");
4304 emitcode("","!tlabeldef",lbl->key+100);
4306 /* load up MB with right */
4308 emitcode("clr","F0");
4309 if (AOP_TYPE(right) == AOP_LIT) {
4310 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4312 emitcode("setb","F0");
4315 emitcode ("mov","mb,#!constbyte",val & 0xff);
4316 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4318 lbl = newiTempLabel(NULL);
4319 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4320 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4321 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4322 emitcode ("xch", "a,b");
4323 emitcode ("cpl","a");
4324 emitcode ("add", "a,#1");
4325 emitcode ("xch", "a,b");
4326 emitcode ("cpl", "a"); // msb
4327 emitcode ("addc", "a,#0");
4328 emitcode ("setb","F0");
4329 emitcode ("","!tlabeldef",lbl->key+100);
4330 emitcode ("mov","mb,b");
4331 emitcode ("mov","mb,a");
4334 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4335 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4337 /* load up MA with left */
4339 lbl = newiTempLabel(NULL);
4340 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4341 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4342 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4343 emitcode ("xch", "a,b");
4344 emitcode ("cpl","a");
4345 emitcode ("add", "a,#1");
4346 emitcode ("xch", "a,b");
4347 emitcode ("cpl", "a"); // msb
4348 emitcode ("addc","a,#0");
4349 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4350 emitcode ("setb","F0");
4351 emitcode ("","!tlabeldef",lbl->key+100);
4352 emitcode ("mov","ma,b");
4353 emitcode ("mov","ma,a");
4355 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4356 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4358 /* wait for multiplication to finish */
4359 lbl = newiTempLabel(NULL);
4360 emitcode("","!tlabeldef", lbl->key+100);
4361 emitcode("mov","a,mcnt1");
4362 emitcode("anl","a,#!constbyte",0x80);
4363 emitcode("jnz","!tlabel",lbl->key+100);
4365 freeAsmop (left, NULL, ic, TRUE);
4366 freeAsmop (right, NULL, ic,TRUE);
4367 aopOp(result, ic, TRUE, FALSE);
4369 /* if unsigned then simple */
4371 emitcode ("mov","a,ma");
4372 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4373 emitcode ("mov","a,ma");
4374 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4375 aopPut(AOP(result),"ma",1);
4376 aopPut(AOP(result),"ma",0);
4378 emitcode("push","ma");
4379 emitcode("push","ma");
4380 emitcode("push","ma");
4382 /* negate result if needed */
4383 lbl = newiTempLabel(NULL);
4384 emitcode("jnb","F0,!tlabel",lbl->key+100);
4385 emitcode("cpl","a");
4386 emitcode("add","a,#1");
4387 emitcode("","!tlabeldef", lbl->key+100);
4388 if (AOP_TYPE(result) == AOP_ACC)
4390 D(emitcode(";", "ACC special case."););
4391 /* We know result is the only live aop, and
4392 * it's obviously not a DPTR2, so AP is available.
4394 emitcode("mov", "%s,acc", DP2_RESULT_REG);
4398 aopPut(AOP(result),"a",0);
4401 emitcode("pop","acc");
4402 lbl = newiTempLabel(NULL);
4403 emitcode("jnb","F0,!tlabel",lbl->key+100);
4404 emitcode("cpl","a");
4405 emitcode("addc","a,#0");
4406 emitcode("","!tlabeldef", lbl->key+100);
4407 aopPut(AOP(result),"a",1);
4408 emitcode("pop","acc");
4409 if (AOP_SIZE(result) >= 3) {
4410 lbl = newiTempLabel(NULL);
4411 emitcode("jnb","F0,!tlabel",lbl->key+100);
4412 emitcode("cpl","a");
4413 emitcode("addc","a,#0");
4414 emitcode("","!tlabeldef", lbl->key+100);
4415 aopPut(AOP(result),"a",2);
4417 emitcode("pop","acc");
4418 if (AOP_SIZE(result) >= 4) {
4419 lbl = newiTempLabel(NULL);
4420 emitcode("jnb","F0,!tlabel",lbl->key+100);
4421 emitcode("cpl","a");
4422 emitcode("addc","a,#0");
4423 emitcode("","!tlabeldef", lbl->key+100);
4424 aopPut(AOP(result),"a",3);
4426 if (AOP_TYPE(result) == AOP_ACC)
4428 /* We stashed the result away above. */
4429 emitcode("mov", "acc,%s", DP2_RESULT_REG);
4433 freeAsmop (result, NULL, ic, TRUE);
4435 /* restore EA bit in F1 */
4436 lbl = newiTempLabel(NULL);
4437 emitcode ("jnb","F1,!tlabel",lbl->key+100);
4438 emitcode ("setb","EA");
4439 emitcode("","!tlabeldef",lbl->key+100);
4443 /*-----------------------------------------------------------------*/
4444 /* genMult - generates code for multiplication */
4445 /*-----------------------------------------------------------------*/
4447 genMult (iCode * ic)
4449 operand *left = IC_LEFT (ic);
4450 operand *right = IC_RIGHT (ic);
4451 operand *result = IC_RESULT (ic);
4453 D (emitcode (";", "genMult "););
4455 /* assign the amsops */
4458 /* special cases first */
4460 if (AOP_TYPE (left) == AOP_CRY &&
4461 AOP_TYPE (right) == AOP_CRY)
4463 genMultbits (left, right, result, ic);
4467 /* if both are of size == 1 */
4468 if (AOP_SIZE (left) == 1 &&
4469 AOP_SIZE (right) == 1)
4471 genMultOneByte (left, right, result, ic);
4475 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4476 /* use the ds390 ARITHMETIC accel UNIT */
4477 genMultTwoByte (left, right, result, ic);
4480 /* should have been converted to function call */
4484 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4485 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4486 freeAsmop (result, NULL, ic, TRUE);
4489 /*-----------------------------------------------------------------*/
4490 /* genDivbits :- division of bits */
4491 /*-----------------------------------------------------------------*/
4493 genDivbits (operand * left,
4501 /* the result must be bit */
4502 LOAD_AB_FOR_DIV (left, right, l);
4503 emitcode ("div", "ab");
4504 emitcode ("rrc", "a");
4505 aopOp(result, ic, TRUE, FALSE);
4507 aopPut (AOP (result), "c", 0);
4510 /*-----------------------------------------------------------------*/
4511 /* genDivOneByte : 8 bit division */
4512 /*-----------------------------------------------------------------*/
4514 genDivOneByte (operand * left,
4519 sym_link *opetype = operandType (result);
4525 /* signed or unsigned */
4526 if (SPEC_USIGN (opetype))
4528 /* unsigned is easy */
4529 LOAD_AB_FOR_DIV (left, right, l);
4530 emitcode ("div", "ab");
4533 aopOp(result, ic, TRUE, FALSE);
4534 aopPut (AOP (result), "a", 0);
4537 size = AOP_SIZE (result) - 1;
4541 aopPut (AOP (result), zero, offset++);
4546 /* signed is a little bit more difficult */
4548 /* save the signs of the operands */
4549 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4551 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4552 emitcode ("push", "acc"); /* save it on the stack */
4554 /* now sign adjust for both left & right */
4555 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4557 lbl = newiTempLabel (NULL);
4558 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4559 emitcode ("cpl", "a");
4560 emitcode ("inc", "a");
4561 emitcode ("", "!tlabeldef", (lbl->key + 100));
4562 emitcode ("mov", "b,a");
4564 /* sign adjust left side */
4565 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4568 lbl = newiTempLabel (NULL);
4569 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4570 emitcode ("cpl", "a");
4571 emitcode ("inc", "a");
4572 emitcode ("", "!tlabeldef", (lbl->key + 100));
4574 /* now the division */
4575 emitcode ("nop", "; workaround for DS80C390 div bug.");
4576 emitcode ("div", "ab");
4577 /* we are interested in the lower order
4579 emitcode ("mov", "b,a");
4580 lbl = newiTempLabel (NULL);
4581 emitcode ("pop", "acc");
4582 /* if there was an over flow we don't
4583 adjust the sign of the result */
4584 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4585 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4587 emitcode ("clr", "a");
4588 emitcode ("subb", "a,b");
4589 emitcode ("mov", "b,a");
4590 emitcode ("", "!tlabeldef", (lbl->key + 100));
4592 /* now we are done */
4593 _G.accInUse++; _G.bInUse++;
4594 aopOp(result, ic, TRUE, FALSE);
4596 aopPut (AOP (result), "b", 0);
4598 size = AOP_SIZE (result) - 1;
4602 emitcode ("mov", "c,b.7");
4603 emitcode ("subb", "a,acc");
4607 aopPut (AOP (result), "a", offset++);
4609 _G.accInUse--; _G.bInUse--;
4613 /*-----------------------------------------------------------------*/
4614 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
4615 /*-----------------------------------------------------------------*/
4616 static void genDivTwoByte (operand *left, operand *right,
4617 operand *result, iCode *ic)
4619 sym_link *retype = getSpec(operandType(right));
4620 sym_link *letype = getSpec(operandType(left));
4621 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4624 /* save EA bit in F1 */
4625 lbl = newiTempLabel(NULL);
4626 emitcode ("setb","F1");
4627 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4628 emitcode ("clr","F1");
4629 emitcode("","!tlabeldef",lbl->key+100);
4631 /* load up MA with left */
4633 emitcode("clr","F0");
4634 lbl = newiTempLabel(NULL);
4635 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4636 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4637 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4638 emitcode ("xch", "a,b");
4639 emitcode ("cpl","a");
4640 emitcode ("add", "a,#1");
4641 emitcode ("xch", "a,b");
4642 emitcode ("cpl", "a"); // msb
4643 emitcode ("addc","a,#0");
4644 emitcode ("setb","F0");
4645 emitcode ("","!tlabeldef",lbl->key+100);
4646 emitcode ("mov","ma,b");
4647 emitcode ("mov","ma,a");
4649 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4650 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4653 /* load up MB with right */
4655 if (AOP_TYPE(right) == AOP_LIT) {
4656 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4658 lbl = newiTempLabel(NULL);
4659 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4660 emitcode("setb","F0");
4661 emitcode ("","!tlabeldef",lbl->key+100);
4664 emitcode ("mov","mb,#!constbyte",val & 0xff);
4665 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4667 lbl = newiTempLabel(NULL);
4668 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4669 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4670 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4671 emitcode ("xch", "a,b");
4672 emitcode ("cpl","a");
4673 emitcode ("add", "a,#1");
4674 emitcode ("xch", "a,b");
4675 emitcode ("cpl", "a"); // msb
4676 emitcode ("addc", "a,#0");
4677 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4678 emitcode ("setb","F0");
4679 emitcode ("","!tlabeldef",lbl->key+100);
4680 emitcode ("mov","mb,b");
4681 emitcode ("mov","mb,a");
4684 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4685 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4688 /* wait for multiplication to finish */
4689 lbl = newiTempLabel(NULL);
4690 emitcode("","!tlabeldef", lbl->key+100);
4691 emitcode("mov","a,mcnt1");
4692 emitcode("anl","a,#!constbyte",0x80);
4693 emitcode("jnz","!tlabel",lbl->key+100);
4695 freeAsmop (left, NULL, ic, TRUE);
4696 freeAsmop (right, NULL, ic,TRUE);
4697 aopOp(result, ic, TRUE, FALSE);
4699 /* if unsigned then simple */
4701 aopPut(AOP(result),"ma",1);
4702 aopPut(AOP(result),"ma",0);
4704 emitcode("push","ma");
4706 /* negate result if needed */
4707 lbl = newiTempLabel(NULL);
4708 emitcode("jnb","F0,!tlabel",lbl->key+100);
4709 emitcode("cpl","a");
4710 emitcode("add","a,#1");
4711 emitcode("","!tlabeldef", lbl->key+100);
4712 aopPut(AOP(result),"a",0);
4713 emitcode("pop","acc");
4714 lbl = newiTempLabel(NULL);
4715 emitcode("jnb","F0,!tlabel",lbl->key+100);
4716 emitcode("cpl","a");
4717 emitcode("addc","a,#0");
4718 emitcode("","!tlabeldef", lbl->key+100);
4719 aopPut(AOP(result),"a",1);
4721 freeAsmop (result, NULL, ic, TRUE);
4722 /* restore EA bit in F1 */
4723 lbl = newiTempLabel(NULL);
4724 emitcode ("jnb","F1,!tlabel",lbl->key+100);
4725 emitcode ("setb","EA");
4726 emitcode("","!tlabeldef",lbl->key+100);
4730 /*-----------------------------------------------------------------*/
4731 /* genDiv - generates code for division */
4732 /*-----------------------------------------------------------------*/
4736 operand *left = IC_LEFT (ic);
4737 operand *right = IC_RIGHT (ic);
4738 operand *result = IC_RESULT (ic);
4740 D (emitcode (";", "genDiv "););
4742 /* assign the amsops */
4745 /* special cases first */
4747 if (AOP_TYPE (left) == AOP_CRY &&
4748 AOP_TYPE (right) == AOP_CRY)
4750 genDivbits (left, right, result, ic);
4754 /* if both are of size == 1 */
4755 if (AOP_SIZE (left) == 1 &&
4756 AOP_SIZE (right) == 1)
4758 genDivOneByte (left, right, result, ic);
4762 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4763 /* use the ds390 ARITHMETIC accel UNIT */
4764 genDivTwoByte (left, right, result, ic);
4767 /* should have been converted to function call */
4770 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4771 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4772 freeAsmop (result, NULL, ic, TRUE);
4775 /*-----------------------------------------------------------------*/
4776 /* genModbits :- modulus of bits */
4777 /*-----------------------------------------------------------------*/
4779 genModbits (operand * left,
4787 /* the result must be bit */
4788 LOAD_AB_FOR_DIV (left, right, l);
4789 emitcode ("div", "ab");
4790 emitcode ("mov", "a,b");
4791 emitcode ("rrc", "a");
4792 aopOp(result, ic, TRUE, FALSE);
4793 aopPut (AOP (result), "c", 0);
4796 /*-----------------------------------------------------------------*/
4797 /* genModOneByte : 8 bit modulus */
4798 /*-----------------------------------------------------------------*/
4800 genModOneByte (operand * left,
4805 sym_link *opetype = operandType (result);
4809 /* signed or unsigned */
4810 if (SPEC_USIGN (opetype))
4812 /* unsigned is easy */
4813 LOAD_AB_FOR_DIV (left, right, l);
4814 emitcode ("div", "ab");
4815 aopOp(result, ic, TRUE, FALSE);
4816 aopPut (AOP (result), "b", 0);
4820 /* signed is a little bit more difficult */
4822 /* save the signs of the operands */
4823 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4826 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4827 emitcode ("push", "acc"); /* save it on the stack */
4829 /* now sign adjust for both left & right */
4830 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4833 lbl = newiTempLabel (NULL);
4834 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4835 emitcode ("cpl", "a");
4836 emitcode ("inc", "a");
4837 emitcode ("", "!tlabeldef", (lbl->key + 100));
4838 emitcode ("mov", "b,a");
4840 /* sign adjust left side */
4841 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4844 lbl = newiTempLabel (NULL);
4845 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4846 emitcode ("cpl", "a");
4847 emitcode ("inc", "a");
4848 emitcode ("", "!tlabeldef", (lbl->key + 100));
4850 /* now the multiplication */
4851 emitcode ("nop", "; workaround for DS80C390 div bug.");
4852 emitcode ("div", "ab");
4853 /* we are interested in the lower order
4855 lbl = newiTempLabel (NULL);
4856 emitcode ("pop", "acc");
4857 /* if there was an over flow we don't
4858 adjust the sign of the result */
4859 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4860 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4862 emitcode ("clr", "a");
4863 emitcode ("subb", "a,b");
4864 emitcode ("mov", "b,a");
4865 emitcode ("", "!tlabeldef", (lbl->key + 100));
4868 /* now we are done */
4869 aopOp(result, ic, TRUE, FALSE);
4870 aopPut (AOP (result), "b", 0);
4875 /*-----------------------------------------------------------------*/
4876 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
4877 /*-----------------------------------------------------------------*/
4878 static void genModTwoByte (operand *left, operand *right,
4879 operand *result, iCode *ic)
4881 sym_link *retype = getSpec(operandType(right));
4882 sym_link *letype = getSpec(operandType(left));
4883 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4886 /* load up MA with left */
4887 /* save EA bit in F1 */
4888 lbl = newiTempLabel(NULL);
4889 emitcode ("setb","F1");
4890 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4891 emitcode ("clr","F1");
4892 emitcode("","!tlabeldef",lbl->key+100);
4895 lbl = newiTempLabel(NULL);
4896 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4897 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4898 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4899 emitcode ("xch", "a,b");
4900 emitcode ("cpl","a");
4901 emitcode ("add", "a,#1");
4902 emitcode ("xch", "a,b");
4903 emitcode ("cpl", "a"); // msb
4904 emitcode ("addc","a,#0");
4905 emitcode ("","!tlabeldef",lbl->key+100);
4906 emitcode ("mov","ma,b");
4907 emitcode ("mov","ma,a");
4909 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4910 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4913 /* load up MB with right */
4915 if (AOP_TYPE(right) == AOP_LIT) {
4916 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4920 emitcode ("mov","mb,#!constbyte",val & 0xff);
4921 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4923 lbl = newiTempLabel(NULL);
4924 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4925 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4926 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4927 emitcode ("xch", "a,b");
4928 emitcode ("cpl","a");
4929 emitcode ("add", "a,#1");
4930 emitcode ("xch", "a,b");
4931 emitcode ("cpl", "a"); // msb
4932 emitcode ("addc", "a,#0");
4933 emitcode ("","!tlabeldef",lbl->key+100);
4934 emitcode ("mov","mb,b");
4935 emitcode ("mov","mb,a");
4938 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4939 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4942 /* wait for multiplication to finish */
4943 lbl = newiTempLabel(NULL);
4944 emitcode("","!tlabeldef", lbl->key+100);
4945 emitcode("mov","a,mcnt1");
4946 emitcode("anl","a,#!constbyte",0x80);
4947 emitcode("jnz","!tlabel",lbl->key+100);
4949 freeAsmop (left, NULL, ic, TRUE);
4950 freeAsmop (right, NULL, ic,TRUE);
4951 aopOp(result, ic, TRUE, FALSE);
4953 aopPut(AOP(result),"mb",1);
4954 aopPut(AOP(result),"mb",0);
4955 freeAsmop (result, NULL, ic, TRUE);
4957 /* restore EA bit in F1 */
4958 lbl = newiTempLabel(NULL);
4959 emitcode ("jnb","F1,!tlabel",lbl->key+100);
4960 emitcode ("setb","EA");
4961 emitcode("","!tlabeldef",lbl->key+100);
4965 /*-----------------------------------------------------------------*/
4966 /* genMod - generates code for division */
4967 /*-----------------------------------------------------------------*/
4971 operand *left = IC_LEFT (ic);
4972 operand *right = IC_RIGHT (ic);
4973 operand *result = IC_RESULT (ic);
4975 D (emitcode (";", "genMod "); );
4977 /* assign the amsops */
4980 /* special cases first */
4982 if (AOP_TYPE (left) == AOP_CRY &&
4983 AOP_TYPE (right) == AOP_CRY)
4985 genModbits (left, right, result, ic);
4989 /* if both are of size == 1 */
4990 if (AOP_SIZE (left) == 1 &&
4991 AOP_SIZE (right) == 1)
4993 genModOneByte (left, right, result, ic);
4997 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4998 /* use the ds390 ARITHMETIC accel UNIT */
4999 genModTwoByte (left, right, result, ic);
5003 /* should have been converted to function call */
5007 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5008 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5009 freeAsmop (result, NULL, ic, TRUE);
5012 /*-----------------------------------------------------------------*/
5013 /* genIfxJump :- will create a jump depending on the ifx */
5014 /*-----------------------------------------------------------------*/
5016 genIfxJump (iCode * ic, char *jval)
5019 symbol *tlbl = newiTempLabel (NULL);
5022 D (emitcode (";", "genIfxJump ");
5025 /* if true label then we jump if condition
5029 jlbl = IC_TRUE (ic);
5030 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5031 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5035 /* false label is present */
5036 jlbl = IC_FALSE (ic);
5037 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5038 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5040 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5041 emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5043 emitcode (inst, "!tlabel", tlbl->key + 100);
5044 emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5045 emitcode ("", "!tlabeldef", tlbl->key + 100);
5047 /* mark the icode as generated */
5051 /*-----------------------------------------------------------------*/
5052 /* genCmp :- greater or less than comparison */
5053 /*-----------------------------------------------------------------*/
5055 genCmp (operand * left, operand * right,
5056 iCode * ic, iCode * ifx, int sign)
5058 int size, offset = 0;
5059 unsigned long lit = 0L;
5062 D (emitcode (";", "genCmp");
5065 result = IC_RESULT (ic);
5067 /* if left & right are bit variables */
5068 if (AOP_TYPE (left) == AOP_CRY &&
5069 AOP_TYPE (right) == AOP_CRY)
5071 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5072 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
5076 /* subtract right from left if at the
5077 end the carry flag is set then we know that
5078 left is greater than right */
5079 size = max (AOP_SIZE (left), AOP_SIZE (right));
5081 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5082 if ((size == 1) && !sign &&
5083 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5085 symbol *lbl = newiTempLabel (NULL);
5086 emitcode ("cjne", "%s,%s,!tlabel",
5087 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5088 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5090 emitcode ("", "!tlabeldef", lbl->key + 100);
5094 if (AOP_TYPE (right) == AOP_LIT)
5096 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5097 /* optimize if(x < 0) or if(x >= 0) */
5106 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
5108 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5109 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5111 aopOp (result, ic, FALSE, FALSE);
5113 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5115 freeAsmop (result, NULL, ic, TRUE);
5116 genIfxJump (ifx, "acc.7");
5121 emitcode ("rlc", "a");
5123 goto release_freedLR;
5131 //emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5132 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5133 //emitcode (";", "genCmp #2");
5134 if (sign && (size == 0))
5136 //emitcode (";", "genCmp #3");
5137 emitcode ("xrl", "a,#!constbyte",0x80);
5138 if (AOP_TYPE (right) == AOP_LIT)
5140 unsigned long lit = (unsigned long)
5141 floatFromVal (AOP (right)->aopu.aop_lit);
5142 //emitcode (";", "genCmp #3.1");
5143 emitcode ("subb", "a,#!constbyte",
5144 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5148 //emitcode (";", "genCmp #3.2");
5149 if (AOP_NEEDSACC (right))
5151 emitcode ("push", "acc");
5153 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
5154 FALSE, FALSE, FALSE));
5155 emitcode ("xrl", "b,#!constbyte",0x80);
5156 if (AOP_NEEDSACC (right))
5158 emitcode ("pop", "acc");
5160 emitcode ("subb", "a,b");
5167 //emitcode (";", "genCmp #4");
5168 if (AOP_NEEDSACC (right))
5171 //emitcode (";", "genCmp #4.1");
5172 emitcode ("xch", "a, b");
5173 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
5174 emitcode ("xch", "a, b");
5179 //emitcode (";", "genCmp #4.2");
5180 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
5183 emitcode ("subb", "a,%s", s);
5190 /* Don't need the left & right operands any more; do need the result. */
5191 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5192 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5194 aopOp (result, ic, FALSE, FALSE);
5198 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5204 /* if the result is used in the next
5205 ifx conditional branch then generate
5206 code a little differently */
5209 genIfxJump (ifx, "c");
5215 /* leave the result in acc */
5217 freeAsmop (result, NULL, ic, TRUE);
5220 /*-----------------------------------------------------------------*/
5221 /* genCmpGt :- greater than comparison */
5222 /*-----------------------------------------------------------------*/
5224 genCmpGt (iCode * ic, iCode * ifx)
5226 operand *left, *right;
5227 sym_link *letype, *retype;
5230 D (emitcode (";", "genCmpGt ");
5233 left = IC_LEFT (ic);
5234 right = IC_RIGHT (ic);
5236 letype = getSpec (operandType (left));
5237 retype = getSpec (operandType (right));
5238 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5240 /* assign the left & right amsops */
5243 genCmp (right, left, ic, ifx, sign);
5246 /*-----------------------------------------------------------------*/
5247 /* genCmpLt - less than comparisons */
5248 /*-----------------------------------------------------------------*/
5250 genCmpLt (iCode * ic, iCode * ifx)
5252 operand *left, *right;
5253 sym_link *letype, *retype;
5256 D (emitcode (";", "genCmpLt "););
5258 left = IC_LEFT (ic);
5259 right = IC_RIGHT (ic);
5261 letype = getSpec (operandType (left));
5262 retype = getSpec (operandType (right));
5263 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5265 /* assign the left & right amsops */
5268 genCmp (left, right, ic, ifx, sign);
5271 /*-----------------------------------------------------------------*/
5272 /* gencjneshort - compare and jump if not equal */
5273 /*-----------------------------------------------------------------*/
5275 gencjneshort (operand * left, operand * right, symbol * lbl)
5277 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5279 unsigned long lit = 0L;
5281 D (emitcode (";", "gencjneshort");
5284 /* if the left side is a literal or
5285 if the right is in a pointer register and left
5287 if ((AOP_TYPE (left) == AOP_LIT) ||
5288 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5295 if (AOP_TYPE (right) == AOP_LIT)
5296 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5298 if (opIsGptr (left) || opIsGptr (right))
5300 /* We are comparing a generic pointer to something.
5301 * Exclude the generic type byte from the comparison.
5304 D (emitcode (";", "cjneshort: generic ptr special case.");
5309 /* if the right side is a literal then anything goes */
5310 if (AOP_TYPE (right) == AOP_LIT &&
5311 AOP_TYPE (left) != AOP_DIR)
5315 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5317 emitcode ("cjne", "a,%s,!tlabel",
5318 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5324 /* if the right side is in a register or in direct space or
5325 if the left is a pointer register & right is not */
5326 else if (AOP_TYPE (right) == AOP_REG ||
5327 AOP_TYPE (right) == AOP_DIR ||
5328 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5329 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5333 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5334 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5335 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5336 emitcode ("jnz", "!tlabel", lbl->key + 100);
5338 emitcode ("cjne", "a,%s,!tlabel",
5339 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
5346 /* right is a pointer reg need both a & b */
5349 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5350 if (strcmp (l, "b"))
5351 emitcode ("mov", "b,%s", l);
5352 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5353 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5359 /*-----------------------------------------------------------------*/
5360 /* gencjne - compare and jump if not equal */
5361 /*-----------------------------------------------------------------*/
5363 gencjne (operand * left, operand * right, symbol * lbl)
5365 symbol *tlbl = newiTempLabel (NULL);
5367 D (emitcode (";", "gencjne");
5370 gencjneshort (left, right, lbl);
5372 emitcode ("mov", "a,%s", one);
5373 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5374 emitcode ("", "!tlabeldef", lbl->key + 100);
5375 emitcode ("clr", "a");
5376 emitcode ("", "!tlabeldef", tlbl->key + 100);
5379 /*-----------------------------------------------------------------*/
5380 /* genCmpEq - generates code for equal to */
5381 /*-----------------------------------------------------------------*/
5383 genCmpEq (iCode * ic, iCode * ifx)
5385 operand *left, *right, *result;
5387 D (emitcode (";", "genCmpEq ");
5391 AOP_SET_LOCALS (ic);
5393 /* if literal, literal on the right or
5394 if the right is in a pointer register and left
5396 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5397 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5399 operand *t = IC_RIGHT (ic);
5400 IC_RIGHT (ic) = IC_LEFT (ic);
5404 if (ifx && /* !AOP_SIZE(result) */
5405 OP_SYMBOL (result) &&
5406 OP_SYMBOL (result)->regType == REG_CND)
5409 /* if they are both bit variables */
5410 if (AOP_TYPE (left) == AOP_CRY &&
5411 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5413 if (AOP_TYPE (right) == AOP_LIT)
5415 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5418 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5419 emitcode ("cpl", "c");
5423 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5427 emitcode ("clr", "c");
5429 /* AOP_TYPE(right) == AOP_CRY */
5433 symbol *lbl = newiTempLabel (NULL);
5434 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5435 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5436 emitcode ("cpl", "c");
5437 emitcode ("", "!tlabeldef", (lbl->key + 100));
5439 /* if true label then we jump if condition
5441 tlbl = newiTempLabel (NULL);
5444 emitcode ("jnc", "!tlabel", tlbl->key + 100);
5445 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5449 emitcode ("jc", "!tlabel", tlbl->key + 100);
5450 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5452 emitcode ("", "!tlabeldef", tlbl->key + 100);
5456 tlbl = newiTempLabel (NULL);
5457 gencjneshort (left, right, tlbl);
5460 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5461 emitcode ("", "!tlabeldef", tlbl->key + 100);
5465 symbol *lbl = newiTempLabel (NULL);
5466 emitcode ("sjmp", "!tlabel", lbl->key + 100);
5467 emitcode ("", "!tlabeldef", tlbl->key + 100);
5468 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5469 emitcode ("", "!tlabeldef", lbl->key + 100);
5472 /* mark the icode as generated */
5475 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5476 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5480 /* if they are both bit variables */
5481 if (AOP_TYPE (left) == AOP_CRY &&
5482 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5484 if (AOP_TYPE (right) == AOP_LIT)
5486 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5489 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5490 emitcode ("cpl", "c");
5494 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5498 emitcode ("clr", "c");
5500 /* AOP_TYPE(right) == AOP_CRY */
5504 symbol *lbl = newiTempLabel (NULL);
5505 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5506 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5507 emitcode ("cpl", "c");
5508 emitcode ("", "!tlabeldef", (lbl->key + 100));
5511 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5512 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5514 aopOp (result, ic, TRUE, FALSE);
5517 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5524 genIfxJump (ifx, "c");
5527 /* if the result is used in an arithmetic operation
5528 then put the result in place */
5533 gencjne (left, right, newiTempLabel (NULL));
5535 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5536 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5538 aopOp (result, ic, TRUE, FALSE);
5540 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5542 aopPut (AOP (result), "a", 0);
5547 genIfxJump (ifx, "a");
5550 /* if the result is used in an arithmetic operation
5551 then put the result in place */
5552 if (AOP_TYPE (result) != AOP_CRY)
5554 /* leave the result in acc */
5558 freeAsmop (result, NULL, ic, TRUE);
5561 /*-----------------------------------------------------------------*/
5562 /* ifxForOp - returns the icode containing the ifx for operand */
5563 /*-----------------------------------------------------------------*/
5565 ifxForOp (operand * op, iCode * ic)
5567 /* if true symbol then needs to be assigned */
5568 if (IS_TRUE_SYMOP (op))
5571 /* if this has register type condition and
5572 the next instruction is ifx with the same operand
5573 and live to of the operand is upto the ifx only then */
5575 ic->next->op == IFX &&
5576 IC_COND (ic->next)->key == op->key &&
5577 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5582 /*-----------------------------------------------------------------*/
5583 /* hasInc - operand is incremented before any other use */
5584 /*-----------------------------------------------------------------*/
5586 hasInc (operand *op, iCode *ic, int osize)
5588 sym_link *type = operandType(op);
5589 sym_link *retype = getSpec (type);
5590 iCode *lic = ic->next;
5593 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5594 if (!IS_SYMOP(op)) return NULL;
5596 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5597 if (osize != (isize = getSize(type->next))) return NULL;
5599 /* if operand of the form op = op + <sizeof *op> */
5600 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5601 isOperandEqual(IC_RESULT(lic),op) &&
5602 isOperandLiteral(IC_RIGHT(lic)) &&
5603 operandLitValue(IC_RIGHT(lic)) == isize) {
5606 /* if the operand used or deffed */
5607 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5610 /* if GOTO or IFX */
5611 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5617 /*-----------------------------------------------------------------*/
5618 /* genAndOp - for && operation */
5619 /*-----------------------------------------------------------------*/
5621 genAndOp (iCode * ic)
5623 operand *left, *right, *result;
5626 D (emitcode (";", "genAndOp "););
5628 /* note here that && operations that are in an
5629 if statement are taken away by backPatchLabels
5630 only those used in arthmetic operations remain */
5632 AOP_SET_LOCALS (ic);
5634 /* if both are bit variables */
5635 if (AOP_TYPE (left) == AOP_CRY &&
5636 AOP_TYPE (right) == AOP_CRY)
5638 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5639 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5640 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5641 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5643 aopOp (result,ic,FALSE, FALSE);
5648 tlbl = newiTempLabel (NULL);
5650 emitcode ("jz", "!tlabel", tlbl->key + 100);
5652 emitcode ("", "!tlabeldef", tlbl->key + 100);
5653 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5654 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5656 aopOp (result,ic,FALSE, FALSE);
5659 freeAsmop (result, NULL, ic, TRUE);
5663 /*-----------------------------------------------------------------*/
5664 /* genOrOp - for || operation */
5665 /*-----------------------------------------------------------------*/
5667 genOrOp (iCode * ic)
5669 operand *left, *right, *result;
5672 D (emitcode (";", "genOrOp "););
5674 /* note here that || operations that are in an
5675 if statement are taken away by backPatchLabels
5676 only those used in arthmetic operations remain */
5678 AOP_SET_LOCALS (ic);
5680 /* if both are bit variables */
5681 if (AOP_TYPE (left) == AOP_CRY &&
5682 AOP_TYPE (right) == AOP_CRY)
5684 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5685 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5686 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5687 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5689 aopOp (result,ic,FALSE, FALSE);
5695 tlbl = newiTempLabel (NULL);
5697 emitcode ("jnz", "!tlabel", tlbl->key + 100);
5699 emitcode ("", "!tlabeldef", tlbl->key + 100);
5700 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5701 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5703 aopOp (result,ic,FALSE, FALSE);
5708 freeAsmop (result, NULL, ic, TRUE);
5711 /*-----------------------------------------------------------------*/
5712 /* isLiteralBit - test if lit == 2^n */
5713 /*-----------------------------------------------------------------*/
5715 isLiteralBit (unsigned long lit)
5717 unsigned long pw[32] =
5718 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5719 0x100L, 0x200L, 0x400L, 0x800L,
5720 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5721 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5722 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5723 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5724 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5727 for (idx = 0; idx < 32; idx++)
5733 /*-----------------------------------------------------------------*/
5734 /* continueIfTrue - */
5735 /*-----------------------------------------------------------------*/
5737 continueIfTrue (iCode * ic)
5740 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
5744 /*-----------------------------------------------------------------*/
5746 /*-----------------------------------------------------------------*/
5748 jumpIfTrue (iCode * ic)
5751 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
5755 /*-----------------------------------------------------------------*/
5756 /* jmpTrueOrFalse - */
5757 /*-----------------------------------------------------------------*/
5759 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5761 // ugly but optimized by peephole
5764 symbol *nlbl = newiTempLabel (NULL);
5765 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
5766 emitcode ("", "!tlabeldef", tlbl->key + 100);
5767 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
5768 emitcode ("", "!tlabeldef", nlbl->key + 100);
5772 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
5773 emitcode ("", "!tlabeldef", tlbl->key + 100);
5778 // Generate code to perform a bit-wise logic operation
5779 // on two operands in far space (assumed to already have been
5780 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5781 // in far space. This requires pushing the result on the stack
5782 // then popping it into the result.
5784 genFarFarLogicOp(iCode *ic, char *logicOp)
5786 int size, resultSize, compSize;
5790 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5791 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
5792 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5794 _startLazyDPSEvaluation();
5795 for (size = compSize; (size--); offset++)
5797 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5798 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5799 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5801 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5802 emitcode ("push", "acc");
5804 _endLazyDPSEvaluation();
5806 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5807 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5808 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5810 resultSize = AOP_SIZE(IC_RESULT(ic));
5812 ADJUST_PUSHED_RESULT(compSize, resultSize);
5814 _startLazyDPSEvaluation();
5817 emitcode ("pop", "acc");
5818 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5820 _endLazyDPSEvaluation();
5821 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5825 /*-----------------------------------------------------------------*/
5826 /* genAnd - code for and */
5827 /*-----------------------------------------------------------------*/
5829 genAnd (iCode * ic, iCode * ifx)
5831 operand *left, *right, *result;
5832 int size, offset = 0;
5833 unsigned long lit = 0L;
5838 D (emitcode (";", "genAnd "););
5840 AOP_OP_3_NOFATAL (ic, pushResult);
5841 AOP_SET_LOCALS (ic);
5845 genFarFarLogicOp(ic, "anl");
5850 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5852 AOP_TYPE (left), AOP_TYPE (right));
5853 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5855 AOP_SIZE (left), AOP_SIZE (right));
5858 /* if left is a literal & right is not then exchange them */
5859 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5860 #ifdef LOGIC_OPS_BROKEN
5861 || AOP_NEEDSACC (left)
5865 operand *tmp = right;
5870 /* if result = right then exchange them */
5871 if (sameRegs (AOP (result), AOP (right)))
5873 operand *tmp = right;
5878 /* if right is bit then exchange them */
5879 if (AOP_TYPE (right) == AOP_CRY &&
5880 AOP_TYPE (left) != AOP_CRY)
5882 operand *tmp = right;
5886 if (AOP_TYPE (right) == AOP_LIT)
5887 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5889 size = AOP_SIZE (result);
5892 // result = bit & yy;
5893 if (AOP_TYPE (left) == AOP_CRY)
5895 // c = bit & literal;
5896 if (AOP_TYPE (right) == AOP_LIT)
5900 if (size && sameRegs (AOP (result), AOP (left)))
5903 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5908 if (size && (AOP_TYPE (result) == AOP_CRY))
5910 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5913 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5918 emitcode ("clr", "c");
5923 if (AOP_TYPE (right) == AOP_CRY)
5926 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5927 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5932 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5934 emitcode ("rrc", "a");
5935 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5943 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5944 genIfxJump (ifx, "c");
5948 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5949 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5950 if ((AOP_TYPE (right) == AOP_LIT) &&
5951 (AOP_TYPE (result) == AOP_CRY) &&
5952 (AOP_TYPE (left) != AOP_CRY))
5954 int posbit = isLiteralBit (lit);
5959 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5962 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5968 sprintf (buffer, "acc.%d", posbit & 0x07);
5969 genIfxJump (ifx, buffer);
5976 symbol *tlbl = newiTempLabel (NULL);
5977 int sizel = AOP_SIZE (left);
5979 emitcode ("setb", "c");
5982 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5984 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5986 if ((posbit = isLiteralBit (bytelit)) != 0)
5987 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
5990 if (bytelit != 0x0FFL)
5991 emitcode ("anl", "a,%s",
5992 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5993 emitcode ("jnz", "!tlabel", tlbl->key + 100);
5998 // bit = left & literal
6001 emitcode ("clr", "c");
6002 emitcode ("", "!tlabeldef", tlbl->key + 100);
6004 // if(left & literal)
6008 jmpTrueOrFalse (ifx, tlbl);
6016 /* if left is same as result */
6017 if (sameRegs (AOP (result), AOP (left)))
6019 for (; size--; offset++)
6021 if (AOP_TYPE (right) == AOP_LIT)
6023 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6025 else if (bytelit == 0)
6026 aopPut (AOP (result), zero, offset);
6027 else if (IS_AOP_PREG (result))
6029 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6030 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6031 aopPut (AOP (result), "a", offset);
6034 emitcode ("anl", "%s,%s",
6035 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6036 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6040 if (AOP_TYPE (left) == AOP_ACC)
6041 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6044 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6045 if (IS_AOP_PREG (result))
6047 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6048 aopPut (AOP (result), "a", offset);
6052 emitcode ("anl", "%s,a",
6053 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6060 // left & result in different registers
6061 if (AOP_TYPE (result) == AOP_CRY)
6064 // if(size), result in bit
6065 // if(!size && ifx), conditional oper: if(left & right)
6066 symbol *tlbl = newiTempLabel (NULL);
6067 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6069 emitcode ("setb", "c");
6072 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6073 emitcode ("anl", "a,%s",
6074 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6076 if (AOP_TYPE(left)==AOP_ACC) {
6077 emitcode("mov", "b,a");
6078 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6079 emitcode("anl", "a,b");
6081 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6082 emitcode ("anl", "a,%s",
6083 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6086 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6092 emitcode ("", "!tlabeldef", tlbl->key + 100);
6096 jmpTrueOrFalse (ifx, tlbl);
6100 for (; (size--); offset++)
6103 // result = left & right
6104 if (AOP_TYPE (right) == AOP_LIT)
6106 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6108 aopPut (AOP (result),
6109 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6113 else if (bytelit == 0)
6115 aopPut (AOP (result), zero, offset);
6118 D (emitcode (";", "better literal AND."););
6119 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6120 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6121 FALSE, FALSE, FALSE));
6126 // faster than result <- left, anl result,right
6127 // and better if result is SFR
6128 if (AOP_TYPE (left) == AOP_ACC)
6130 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
6131 FALSE, FALSE, FALSE));
6135 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6136 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6138 emitcode("mov", "b,a");
6142 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6143 emitcode ("anl", "a,%s", rOp);
6146 aopPut (AOP (result), "a", offset);
6152 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6153 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6154 freeAsmop (result, NULL, ic, TRUE);
6158 /*-----------------------------------------------------------------*/
6159 /* genOr - code for or */
6160 /*-----------------------------------------------------------------*/
6162 genOr (iCode * ic, iCode * ifx)
6164 operand *left, *right, *result;
6165 int size, offset = 0;
6166 unsigned long lit = 0L;
6169 D (emitcode (";", "genOr "););
6171 AOP_OP_3_NOFATAL (ic, pushResult);
6172 AOP_SET_LOCALS (ic);
6176 genFarFarLogicOp(ic, "orl");
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) // I think this is a net loss now.
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);
6225 if (AOP_TYPE (left) == AOP_CRY)
6227 if (AOP_TYPE (right) == AOP_LIT)
6229 // c = bit & literal;
6232 // lit != 0 => result = 1
6233 if (AOP_TYPE (result) == AOP_CRY)
6236 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6238 continueIfTrue (ifx);
6241 emitcode ("setb", "c");
6245 // lit == 0 => result = left
6246 if (size && sameRegs (AOP (result), AOP (left)))
6248 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6253 if (AOP_TYPE (right) == AOP_CRY)
6256 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6257 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6262 symbol *tlbl = newiTempLabel (NULL);
6263 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6264 emitcode ("setb", "c");
6265 emitcode ("jb", "%s,!tlabel",
6266 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6268 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6269 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6271 jmpTrueOrFalse (ifx, tlbl);
6277 emitcode ("", "!tlabeldef", tlbl->key + 100);
6286 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6287 genIfxJump (ifx, "c");
6291 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6292 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6293 if ((AOP_TYPE (right) == AOP_LIT) &&
6294 (AOP_TYPE (result) == AOP_CRY) &&
6295 (AOP_TYPE (left) != AOP_CRY))
6301 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6303 continueIfTrue (ifx);
6308 // lit = 0, result = boolean(left)
6310 emitcode ("setb", "c");
6314 symbol *tlbl = newiTempLabel (NULL);
6315 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6317 emitcode ("", "!tlabeldef", tlbl->key + 100);
6321 genIfxJump (ifx, "a");
6329 /* if left is same as result */
6330 if (sameRegs (AOP (result), AOP (left)))
6332 for (; size--; offset++)
6334 if (AOP_TYPE (right) == AOP_LIT)
6336 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6342 if (IS_AOP_PREG (left))
6344 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6345 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6346 aopPut (AOP (result), "a", offset);
6350 emitcode ("orl", "%s,%s",
6351 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6352 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6358 if (AOP_TYPE (left) == AOP_ACC)
6360 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6364 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6365 if (IS_AOP_PREG (left))
6367 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6368 aopPut (AOP (result), "a", offset);
6372 emitcode ("orl", "%s,a",
6373 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6381 // left & result in different registers
6382 if (AOP_TYPE (result) == AOP_CRY)
6385 // if(size), result in bit
6386 // if(!size && ifx), conditional oper: if(left | right)
6387 symbol *tlbl = newiTempLabel (NULL);
6388 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6390 emitcode ("setb", "c");
6393 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6394 emitcode ("orl", "a,%s",
6395 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6397 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6398 emitcode ("orl", "a,%s",
6399 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6401 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6407 emitcode ("", "!tlabeldef", tlbl->key + 100);
6411 jmpTrueOrFalse (ifx, tlbl);
6415 _startLazyDPSEvaluation();
6416 for (; (size--); offset++)
6419 // result = left & right
6420 if (AOP_TYPE (right) == AOP_LIT)
6422 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6424 aopPut (AOP (result),
6425 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6429 D (emitcode (";", "better literal OR."););
6430 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6431 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
6432 FALSE, FALSE, FALSE));
6437 // faster than result <- left, anl result,right
6438 // and better if result is SFR
6439 if (AOP_TYPE (left) == AOP_ACC)
6441 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
6442 FALSE, FALSE, FALSE));
6446 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6448 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6450 emitcode("mov", "b,a");
6454 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6455 emitcode ("orl", "a,%s", rOp);
6458 aopPut (AOP (result), "a", offset);
6460 _endLazyDPSEvaluation();
6465 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6466 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6467 freeAsmop (result, NULL, ic, TRUE);
6470 /*-----------------------------------------------------------------*/
6471 /* genXor - code for xclusive or */
6472 /*-----------------------------------------------------------------*/
6474 genXor (iCode * ic, iCode * ifx)
6476 operand *left, *right, *result;
6477 int size, offset = 0;
6478 unsigned long lit = 0L;
6481 D (emitcode (";", "genXor "););
6483 AOP_OP_3_NOFATAL (ic, pushResult);
6484 AOP_SET_LOCALS (ic);
6488 genFarFarLogicOp(ic, "xrl");
6493 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6495 AOP_TYPE (left), AOP_TYPE (right));
6496 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6498 AOP_SIZE (left), AOP_SIZE (right));
6501 /* if left is a literal & right is not ||
6502 if left needs acc & right does not */
6503 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6504 #ifdef LOGIC_OPS_BROKEN
6505 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6509 operand *tmp = right;
6514 /* if result = right then exchange them */
6515 if (sameRegs (AOP (result), AOP (right)))
6517 operand *tmp = right;
6522 /* if right is bit then exchange them */
6523 if (AOP_TYPE (right) == AOP_CRY &&
6524 AOP_TYPE (left) != AOP_CRY)
6526 operand *tmp = right;
6530 if (AOP_TYPE (right) == AOP_LIT)
6531 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6533 size = AOP_SIZE (result);
6537 if (AOP_TYPE (left) == AOP_CRY)
6539 if (AOP_TYPE (right) == AOP_LIT)
6541 // c = bit & literal;
6544 // lit>>1 != 0 => result = 1
6545 if (AOP_TYPE (result) == AOP_CRY)
6548 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6550 continueIfTrue (ifx);
6553 emitcode ("setb", "c");
6560 // lit == 0, result = left
6561 if (size && sameRegs (AOP (result), AOP (left)))
6563 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6567 // lit == 1, result = not(left)
6568 if (size && sameRegs (AOP (result), AOP (left)))
6570 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6575 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6576 emitcode ("cpl", "c");
6585 symbol *tlbl = newiTempLabel (NULL);
6586 if (AOP_TYPE (right) == AOP_CRY)
6589 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6593 int sizer = AOP_SIZE (right);
6595 // if val>>1 != 0, result = 1
6596 emitcode ("setb", "c");
6599 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
6601 // test the msb of the lsb
6602 emitcode ("anl", "a,#!constbyte",0xfe);
6603 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6607 emitcode ("rrc", "a");
6609 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6610 emitcode ("cpl", "c");
6611 emitcode ("", "!tlabeldef", (tlbl->key + 100));
6618 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6619 genIfxJump (ifx, "c");
6623 if (sameRegs (AOP (result), AOP (left)))
6625 /* if left is same as result */
6626 for (; size--; offset++)
6628 if (AOP_TYPE (right) == AOP_LIT)
6630 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6632 else if (IS_AOP_PREG (left))
6634 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6635 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6636 aopPut (AOP (result), "a", offset);
6639 emitcode ("xrl", "%s,%s",
6640 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6641 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6645 if (AOP_TYPE (left) == AOP_ACC)
6646 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6649 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6650 if (IS_AOP_PREG (left))
6652 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6653 aopPut (AOP (result), "a", offset);
6656 emitcode ("xrl", "%s,a",
6657 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6664 // left & result in different registers
6665 if (AOP_TYPE (result) == AOP_CRY)
6668 // if(size), result in bit
6669 // if(!size && ifx), conditional oper: if(left ^ right)
6670 symbol *tlbl = newiTempLabel (NULL);
6671 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6674 emitcode ("setb", "c");
6677 if ((AOP_TYPE (right) == AOP_LIT) &&
6678 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6680 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6684 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6685 emitcode ("xrl", "a,%s",
6686 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6688 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6689 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6691 emitcode("mov", "b,a");
6695 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6696 emitcode ("xrl", "a,%s", rOp);
6699 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6705 emitcode ("", "!tlabeldef", tlbl->key + 100);
6709 jmpTrueOrFalse (ifx, tlbl);
6713 for (; (size--); offset++)
6716 // result = left & right
6717 if (AOP_TYPE (right) == AOP_LIT)
6719 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6721 aopPut (AOP (result),
6722 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6726 D (emitcode (";", "better literal XOR."););
6727 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6728 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
6729 FALSE, FALSE, FALSE));
6733 // faster than result <- left, anl result,right
6734 // and better if result is SFR
6735 if (AOP_TYPE (left) == AOP_ACC)
6737 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
6738 FALSE, FALSE, FALSE));
6742 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6743 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6745 emitcode("mov", "b,a");
6749 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6750 emitcode ("xrl", "a,%s", rOp);
6753 aopPut (AOP (result), "a", offset);
6760 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6761 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6762 freeAsmop (result, NULL, ic, TRUE);
6765 /*-----------------------------------------------------------------*/
6766 /* genInline - write the inline code out */
6767 /*-----------------------------------------------------------------*/
6769 genInline (iCode * ic)
6771 char *buffer, *bp, *bp1;
6773 D (emitcode (";", "genInline ");
6776 _G.inLine += (!options.asmpeep);
6778 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6779 strcpy (buffer, IC_INLINE (ic));
6781 /* emit each line as a code */
6806 /* emitcode("",buffer); */
6807 _G.inLine -= (!options.asmpeep);
6810 /*-----------------------------------------------------------------*/
6811 /* genRRC - rotate right with carry */
6812 /*-----------------------------------------------------------------*/
6816 operand *left, *result;
6817 int size, offset = 0;
6820 D (emitcode (";", "genRRC ");
6823 /* rotate right with carry */
6824 left = IC_LEFT (ic);
6825 result = IC_RESULT (ic);
6826 aopOp (left, ic, FALSE, FALSE);
6827 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6829 /* move it to the result */
6830 size = AOP_SIZE (result);
6834 _startLazyDPSEvaluation ();
6837 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6839 emitcode ("rrc", "a");
6840 if (AOP_SIZE (result) > 1)
6841 aopPut (AOP (result), "a", offset--);
6843 _endLazyDPSEvaluation ();
6845 /* now we need to put the carry into the
6846 highest order byte of the result */
6847 if (AOP_SIZE (result) > 1)
6849 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6852 emitcode ("mov", "acc.7,c");
6853 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6854 freeAsmop (left, NULL, ic, TRUE);
6855 freeAsmop (result, NULL, ic, TRUE);
6858 /*-----------------------------------------------------------------*/
6859 /* genRLC - generate code for rotate left with carry */
6860 /*-----------------------------------------------------------------*/
6864 operand *left, *result;
6865 int size, offset = 0;
6868 D (emitcode (";", "genRLC ");
6871 /* rotate right with carry */
6872 left = IC_LEFT (ic);
6873 result = IC_RESULT (ic);
6874 aopOp (left, ic, FALSE, FALSE);
6875 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6877 /* move it to the result */
6878 size = AOP_SIZE (result);
6882 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6884 emitcode ("add", "a,acc");
6885 if (AOP_SIZE (result) > 1)
6887 aopPut (AOP (result), "a", offset++);
6890 _startLazyDPSEvaluation ();
6893 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6895 emitcode ("rlc", "a");
6896 if (AOP_SIZE (result) > 1)
6897 aopPut (AOP (result), "a", offset++);
6899 _endLazyDPSEvaluation ();
6901 /* now we need to put the carry into the
6902 highest order byte of the result */
6903 if (AOP_SIZE (result) > 1)
6905 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6908 emitcode ("mov", "acc.0,c");
6909 aopPut (AOP (result), "a", 0);
6910 freeAsmop (left, NULL, ic, TRUE);
6911 freeAsmop (result, NULL, ic, TRUE);
6914 /*-----------------------------------------------------------------*/
6915 /* genGetHbit - generates code get highest order bit */
6916 /*-----------------------------------------------------------------*/
6918 genGetHbit (iCode * ic)
6920 operand *left, *result;
6921 left = IC_LEFT (ic);
6922 result = IC_RESULT (ic);
6923 aopOp (left, ic, FALSE, FALSE);
6924 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6926 D (emitcode (";", "genGetHbit ");
6929 /* get the highest order byte into a */
6930 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6931 if (AOP_TYPE (result) == AOP_CRY)
6933 emitcode ("rlc", "a");
6938 emitcode ("rl", "a");
6939 emitcode ("anl", "a,#1");
6944 freeAsmop (left, NULL, ic, TRUE);
6945 freeAsmop (result, NULL, ic, TRUE);
6948 /*-----------------------------------------------------------------*/
6949 /* AccRol - rotate left accumulator by known count */
6950 /*-----------------------------------------------------------------*/
6952 AccRol (int shCount)
6954 shCount &= 0x0007; // shCount : 0..7
6961 emitcode ("rl", "a");
6964 emitcode ("rl", "a");
6965 emitcode ("rl", "a");
6968 emitcode ("swap", "a");
6969 emitcode ("rr", "a");
6972 emitcode ("swap", "a");
6975 emitcode ("swap", "a");
6976 emitcode ("rl", "a");
6979 emitcode ("rr", "a");
6980 emitcode ("rr", "a");
6983 emitcode ("rr", "a");
6988 /*-----------------------------------------------------------------*/
6989 /* AccLsh - left shift accumulator by known count */
6990 /*-----------------------------------------------------------------*/
6992 AccLsh (int shCount)
6997 emitcode ("add", "a,acc");
6998 else if (shCount == 2)
7000 emitcode ("add", "a,acc");
7001 emitcode ("add", "a,acc");
7005 /* rotate left accumulator */
7007 /* and kill the lower order bits */
7008 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7013 /*-----------------------------------------------------------------*/
7014 /* AccRsh - right shift accumulator by known count */
7015 /*-----------------------------------------------------------------*/
7017 AccRsh (int shCount)
7024 emitcode ("rrc", "a");
7028 /* rotate right accumulator */
7029 AccRol (8 - shCount);
7030 /* and kill the higher order bits */
7031 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7036 #ifdef BETTER_LITERAL_SHIFT
7037 /*-----------------------------------------------------------------*/
7038 /* AccSRsh - signed right shift accumulator by known count */
7039 /*-----------------------------------------------------------------*/
7041 AccSRsh (int shCount)
7048 emitcode ("mov", "c,acc.7");
7049 emitcode ("rrc", "a");
7051 else if (shCount == 2)
7053 emitcode ("mov", "c,acc.7");
7054 emitcode ("rrc", "a");
7055 emitcode ("mov", "c,acc.7");
7056 emitcode ("rrc", "a");
7060 tlbl = newiTempLabel (NULL);
7061 /* rotate right accumulator */
7062 AccRol (8 - shCount);
7063 /* and kill the higher order bits */
7064 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7065 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7066 emitcode ("orl", "a,#!constbyte",
7067 (unsigned char) ~SRMask[shCount]);
7068 emitcode ("", "!tlabeldef", tlbl->key + 100);
7074 #ifdef BETTER_LITERAL_SHIFT
7075 /*-----------------------------------------------------------------*/
7076 /* shiftR1Left2Result - shift right one byte from left to result */
7077 /*-----------------------------------------------------------------*/
7079 shiftR1Left2Result (operand * left, int offl,
7080 operand * result, int offr,
7081 int shCount, int sign)
7083 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7084 /* shift right accumulator */
7089 aopPut (AOP (result), "a", offr);
7093 #ifdef BETTER_LITERAL_SHIFT
7094 /*-----------------------------------------------------------------*/
7095 /* shiftL1Left2Result - shift left one byte from left to result */
7096 /*-----------------------------------------------------------------*/
7098 shiftL1Left2Result (operand * left, int offl,
7099 operand * result, int offr, int shCount)
7101 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7102 /* shift left accumulator */
7104 aopPut (AOP (result), "a", offr);
7108 #ifdef BETTER_LITERAL_SHIFT
7109 /*-----------------------------------------------------------------*/
7110 /* movLeft2Result - move byte from left to result */
7111 /*-----------------------------------------------------------------*/
7113 movLeft2Result (operand * left, int offl,
7114 operand * result, int offr, int sign)
7117 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7119 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
7121 if (*l == '@' && (IS_AOP_PREG (result)))
7123 emitcode ("mov", "a,%s", l);
7124 aopPut (AOP (result), "a", offr);
7130 aopPut (AOP (result), l, offr);
7134 /* MSB sign in acc.7 ! */
7135 if (getDataSize (left) == offl + 1)
7137 emitcode ("mov", "a,%s", l);
7138 aopPut (AOP (result), "a", offr);
7146 #ifdef BETTER_LITERAL_SHIFT
7147 /*-----------------------------------------------------------------*/
7148 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7149 /*-----------------------------------------------------------------*/
7153 emitcode ("rrc", "a");
7154 emitcode ("xch", "a,%s", x);
7155 emitcode ("rrc", "a");
7156 emitcode ("xch", "a,%s", x);
7160 #ifdef BETTER_LITERAL_SHIFT
7162 /*-----------------------------------------------------------------*/
7163 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7164 /*-----------------------------------------------------------------*/
7168 emitcode ("xch", "a,%s", x);
7169 emitcode ("rlc", "a");
7170 emitcode ("xch", "a,%s", x);
7171 emitcode ("rlc", "a");
7175 #ifdef BETTER_LITERAL_SHIFT
7176 /*-----------------------------------------------------------------*/
7177 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7178 /*-----------------------------------------------------------------*/
7182 emitcode ("xch", "a,%s", x);
7183 emitcode ("add", "a,acc");
7184 emitcode ("xch", "a,%s", x);
7185 emitcode ("rlc", "a");
7189 #ifdef BETTER_LITERAL_SHIFT
7190 /*-----------------------------------------------------------------*/
7191 /* AccAXLsh - left shift a:x by known count (0..7) */
7192 /*-----------------------------------------------------------------*/
7194 AccAXLsh (char *x, int shCount)
7209 case 5: // AAAAABBB:CCCCCDDD
7211 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7213 emitcode ("anl", "a,#!constbyte",
7214 SLMask[shCount]); // BBB00000:CCCCCDDD
7216 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7218 AccRol (shCount); // DDDCCCCC:BBB00000
7220 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7222 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7224 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7226 emitcode ("anl", "a,#!constbyte",
7227 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7229 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7231 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7234 case 6: // AAAAAABB:CCCCCCDD
7235 emitcode ("anl", "a,#!constbyte",
7236 SRMask[shCount]); // 000000BB:CCCCCCDD
7237 emitcode ("mov", "c,acc.0"); // c = B
7238 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7240 AccAXRrl1 (x); // BCCCCCCD:D000000B
7241 AccAXRrl1 (x); // BBCCCCCC:DD000000
7243 emitcode("rrc","a");
7244 emitcode("xch","a,%s", x);
7245 emitcode("rrc","a");
7246 emitcode("mov","c,acc.0"); //<< get correct bit
7247 emitcode("xch","a,%s", x);
7249 emitcode("rrc","a");
7250 emitcode("xch","a,%s", x);
7251 emitcode("rrc","a");
7252 emitcode("xch","a,%s", x);
7255 case 7: // a:x <<= 7
7257 emitcode ("anl", "a,#!constbyte",
7258 SRMask[shCount]); // 0000000B:CCCCCCCD
7260 emitcode ("mov", "c,acc.0"); // c = B
7262 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7264 AccAXRrl1 (x); // BCCCCCCC:D0000000
7273 #ifdef BETTER_LITERAL_SHIFT
7275 /*-----------------------------------------------------------------*/
7276 /* AccAXRsh - right shift a:x known count (0..7) */
7277 /*-----------------------------------------------------------------*/
7279 AccAXRsh (char *x, int shCount)
7287 AccAXRrl1 (x); // 0->a:x
7292 AccAXRrl1 (x); // 0->a:x
7295 AccAXRrl1 (x); // 0->a:x
7300 case 5: // AAAAABBB:CCCCCDDD = a:x
7302 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7304 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7306 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7308 emitcode ("anl", "a,#!constbyte",
7309 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7311 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7313 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7315 emitcode ("anl", "a,#!constbyte",
7316 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7318 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7320 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7322 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7325 case 6: // AABBBBBB:CCDDDDDD
7327 emitcode ("mov", "c,acc.7");
7328 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7330 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7332 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7334 emitcode ("anl", "a,#!constbyte",
7335 SRMask[shCount]); // 000000AA:BBBBBBCC
7338 case 7: // ABBBBBBB:CDDDDDDD
7340 emitcode ("mov", "c,acc.7"); // c = A
7342 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7344 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7346 emitcode ("anl", "a,#!constbyte",
7347 SRMask[shCount]); // 0000000A:BBBBBBBC
7356 #ifdef BETTER_LITERAL_SHIFT
7357 /*-----------------------------------------------------------------*/
7358 /* AccAXRshS - right shift signed a:x known count (0..7) */
7359 /*-----------------------------------------------------------------*/
7361 AccAXRshS (char *x, int shCount)
7369 emitcode ("mov", "c,acc.7");
7370 AccAXRrl1 (x); // s->a:x
7374 emitcode ("mov", "c,acc.7");
7375 AccAXRrl1 (x); // s->a:x
7377 emitcode ("mov", "c,acc.7");
7378 AccAXRrl1 (x); // s->a:x
7383 case 5: // AAAAABBB:CCCCCDDD = a:x
7385 tlbl = newiTempLabel (NULL);
7386 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7388 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7390 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7392 emitcode ("anl", "a,#!constbyte",
7393 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7395 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7397 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7399 emitcode ("anl", "a,#!constbyte",
7400 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7402 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7404 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7406 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7408 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7409 emitcode ("orl", "a,#!constbyte",
7410 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7412 emitcode ("", "!tlabeldef", tlbl->key + 100);
7413 break; // SSSSAAAA:BBBCCCCC
7415 case 6: // AABBBBBB:CCDDDDDD
7417 tlbl = newiTempLabel (NULL);
7418 emitcode ("mov", "c,acc.7");
7419 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7421 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7423 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7425 emitcode ("anl", "a,#!constbyte",
7426 SRMask[shCount]); // 000000AA:BBBBBBCC
7428 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7429 emitcode ("orl", "a,#!constbyte",
7430 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7432 emitcode ("", "!tlabeldef", tlbl->key + 100);
7434 case 7: // ABBBBBBB:CDDDDDDD
7436 tlbl = newiTempLabel (NULL);
7437 emitcode ("mov", "c,acc.7"); // c = A
7439 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7441 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7443 emitcode ("anl", "a,#!constbyte",
7444 SRMask[shCount]); // 0000000A:BBBBBBBC
7446 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7447 emitcode ("orl", "a,#!constbyte",
7448 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7450 emitcode ("", "!tlabeldef", tlbl->key + 100);
7458 #ifdef BETTER_LITERAL_SHIFT
7460 _loadLeftIntoAx(char **lsb,
7466 // Get the initial value from left into a pair of registers.
7467 // MSB must be in A, LSB can be any register.
7469 // If the result is held in registers, it is an optimization
7470 // if the LSB can be held in the register which will hold the,
7471 // result LSB since this saves us from having to copy it into
7472 // the result following AccAXLsh.
7474 // If the result is addressed indirectly, this is not a gain.
7475 if (AOP_NEEDSACC(result))
7479 _startLazyDPSEvaluation();
7480 if (AOP_TYPE(left) == AOP_DPTR2)
7483 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
7484 // get LSB in DP2_RESULT_REG.
7485 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
7486 assert(!strcmp(leftByte, DP2_RESULT_REG));
7490 // get LSB into DP2_RESULT_REG
7491 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
7492 if (strcmp(leftByte, DP2_RESULT_REG))
7495 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7498 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
7499 assert(strcmp(leftByte, DP2_RESULT_REG));
7502 _endLazyDPSEvaluation();
7503 *lsb = DP2_RESULT_REG;
7507 if (sameRegs (AOP (result), AOP (left)) &&
7508 ((offl + MSB16) == offr))
7510 /* don't crash result[offr] */
7511 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
7512 emitcode ("xch", "a,%s",
7513 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
7517 movLeft2Result (left, offl, result, offr, 0);
7518 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
7520 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
7521 assert(strcmp(*lsb,"a"));
7526 _storeAxResults(char *lsb,
7530 _startLazyDPSEvaluation();
7531 if (AOP_NEEDSACC(result))
7533 /* We have to explicitly update the result LSB.
7535 emitcode("xch","a,%s", lsb);
7536 aopPut(AOP(result), "a", offr);
7537 emitcode("mov","a,%s", lsb);
7539 if (getDataSize (result) > 1)
7541 aopPut (AOP (result), "a", offr + MSB16);
7543 _endLazyDPSEvaluation();
7546 /*-----------------------------------------------------------------*/
7547 /* shiftL2Left2Result - shift left two bytes from left to result */
7548 /*-----------------------------------------------------------------*/
7550 shiftL2Left2Result (operand * left, int offl,
7551 operand * result, int offr, int shCount)
7555 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7557 AccAXLsh (lsb, shCount);
7559 _storeAxResults(lsb, result, offr);
7563 #ifdef BETTER_LITERAL_SHIFT
7564 /*-----------------------------------------------------------------*/
7565 /* shiftR2Left2Result - shift right two bytes from left to result */
7566 /*-----------------------------------------------------------------*/
7568 shiftR2Left2Result (operand * left, int offl,
7569 operand * result, int offr,
7570 int shCount, int sign)
7574 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7576 /* a:x >> shCount (x = lsb(result)) */
7579 AccAXRshS(lsb, shCount);
7583 AccAXRsh(lsb, shCount);
7586 _storeAxResults(lsb, result, offr);
7592 /*-----------------------------------------------------------------*/
7593 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7594 /*-----------------------------------------------------------------*/
7596 shiftLLeftOrResult (operand * left, int offl,
7597 operand * result, int offr, int shCount)
7599 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7600 /* shift left accumulator */
7602 /* or with result */
7603 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7604 /* back to result */
7605 aopPut (AOP (result), "a", offr);
7611 /*-----------------------------------------------------------------*/
7612 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7613 /*-----------------------------------------------------------------*/
7615 shiftRLeftOrResult (operand * left, int offl,
7616 operand * result, int offr, int shCount)
7618 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7619 /* shift right accumulator */
7621 /* or with result */
7622 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7623 /* back to result */
7624 aopPut (AOP (result), "a", offr);
7628 #ifdef BETTER_LITERAL_SHIFT
7629 /*-----------------------------------------------------------------*/
7630 /* genlshOne - left shift a one byte quantity by known count */
7631 /*-----------------------------------------------------------------*/
7633 genlshOne (operand * result, operand * left, int shCount)
7635 D (emitcode (";", "genlshOne "););
7636 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7640 #ifdef BETTER_LITERAL_SHIFT
7641 /*-----------------------------------------------------------------*/
7642 /* genlshTwo - left shift two bytes by known amount != 0 */
7643 /*-----------------------------------------------------------------*/
7645 genlshTwo (operand * result, operand * left, int shCount)
7649 D (emitcode (";", "genlshTwo "););
7651 size = getDataSize (result);
7653 /* if shCount >= 8 */
7658 _startLazyDPSEvaluation();
7664 _endLazyDPSEvaluation();
7665 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7666 aopPut (AOP (result), zero, LSB);
7670 movLeft2Result (left, LSB, result, MSB16, 0);
7671 aopPut (AOP (result), zero, LSB);
7672 _endLazyDPSEvaluation();
7677 aopPut (AOP (result), zero, LSB);
7678 _endLazyDPSEvaluation();
7682 /* 1 <= shCount <= 7 */
7687 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7691 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7699 /*-----------------------------------------------------------------*/
7700 /* shiftLLong - shift left one long from left to result */
7701 /* offl = LSB or MSB16 */
7702 /*-----------------------------------------------------------------*/
7704 shiftLLong (operand * left, operand * result, int offr)
7707 int size = AOP_SIZE (result);
7709 if (size >= LSB + offr)
7711 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
7713 emitcode ("add", "a,acc");
7714 if (sameRegs (AOP (left), AOP (result)) &&
7715 size >= MSB16 + offr && offr != LSB)
7716 emitcode ("xch", "a,%s",
7717 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
7719 aopPut (AOP (result), "a", LSB + offr);
7722 if (size >= MSB16 + offr)
7724 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7726 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
7729 emitcode ("rlc", "a");
7730 if (sameRegs (AOP (left), AOP (result)) &&
7731 size >= MSB24 + offr && offr != LSB)
7732 emitcode ("xch", "a,%s",
7733 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
7735 aopPut (AOP (result), "a", MSB16 + offr);
7738 if (size >= MSB24 + offr)
7740 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7742 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
7745 emitcode ("rlc", "a");
7746 if (sameRegs (AOP (left), AOP (result)) &&
7747 size >= MSB32 + offr && offr != LSB)
7748 emitcode ("xch", "a,%s",
7749 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
7751 aopPut (AOP (result), "a", MSB24 + offr);
7754 if (size > MSB32 + offr)
7756 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7758 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7761 emitcode ("rlc", "a");
7762 aopPut (AOP (result), "a", MSB32 + offr);
7765 aopPut (AOP (result), zero, LSB);
7771 /*-----------------------------------------------------------------*/
7772 /* genlshFour - shift four byte by a known amount != 0 */
7773 /*-----------------------------------------------------------------*/
7775 genlshFour (operand * result, operand * left, int shCount)
7779 D (emitcode (";", "genlshFour ");
7782 size = AOP_SIZE (result);
7784 /* if shifting more that 3 bytes */
7789 /* lowest order of left goes to the highest
7790 order of the destination */
7791 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7793 movLeft2Result (left, LSB, result, MSB32, 0);
7794 aopPut (AOP (result), zero, LSB);
7795 aopPut (AOP (result), zero, MSB16);
7796 aopPut (AOP (result), zero, MSB24);
7800 /* more than two bytes */
7801 else if (shCount >= 16)
7803 /* lower order two bytes goes to higher order two bytes */
7805 /* if some more remaining */
7807 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7810 movLeft2Result (left, MSB16, result, MSB32, 0);
7811 movLeft2Result (left, LSB, result, MSB24, 0);
7813 aopPut (AOP (result), zero, MSB16);
7814 aopPut (AOP (result), zero, LSB);
7818 /* if more than 1 byte */
7819 else if (shCount >= 8)
7821 /* lower order three bytes goes to higher order three bytes */
7826 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7828 movLeft2Result (left, LSB, result, MSB16, 0);
7834 movLeft2Result (left, MSB24, result, MSB32, 0);
7835 movLeft2Result (left, MSB16, result, MSB24, 0);
7836 movLeft2Result (left, LSB, result, MSB16, 0);
7837 aopPut (AOP (result), zero, LSB);
7839 else if (shCount == 1)
7840 shiftLLong (left, result, MSB16);
7843 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7844 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7845 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7846 aopPut (AOP (result), zero, LSB);
7851 /* 1 <= shCount <= 7 */
7852 else if (shCount <= 2)
7854 shiftLLong (left, result, LSB);
7856 shiftLLong (result, result, LSB);
7858 /* 3 <= shCount <= 7, optimize */
7861 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7862 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7863 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7868 #ifdef BETTER_LITERAL_SHIFT
7869 /*-----------------------------------------------------------------*/
7870 /* genLeftShiftLiteral - left shifting by known count */
7871 /*-----------------------------------------------------------------*/
7873 genLeftShiftLiteral (operand * left,
7878 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7881 size = getSize (operandType (result));
7883 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7885 /* We only handle certain easy cases so far. */
7887 && (shCount < (size * 8))
7891 D(emitcode (";", "genLeftShiftLiteral wimping out"););
7895 freeAsmop (right, NULL, ic, TRUE);
7897 aopOp(left, ic, FALSE, FALSE);
7898 aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7901 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7903 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7904 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7906 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7909 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7911 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7912 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7914 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7920 emitcode ("; shift left ", "result %d, left %d", size,
7924 /* I suppose that the left size >= result size */
7927 _startLazyDPSEvaluation();
7930 movLeft2Result (left, size, result, size, 0);
7932 _endLazyDPSEvaluation();
7934 else if (shCount >= (size * 8))
7936 _startLazyDPSEvaluation();
7939 aopPut (AOP (result), zero, size);
7941 _endLazyDPSEvaluation();
7948 genlshOne (result, left, shCount);
7952 genlshTwo (result, left, shCount);
7956 genlshFour (result, left, shCount);
7960 fprintf(stderr, "*** ack! mystery literal shift!\n");
7964 freeAsmop (left, NULL, ic, TRUE);
7965 freeAsmop (result, NULL, ic, TRUE);
7970 /*-----------------------------------------------------------------*/
7971 /* genLeftShift - generates code for left shifting */
7972 /*-----------------------------------------------------------------*/
7974 genLeftShift (iCode * ic)
7976 operand *left, *right, *result;
7979 symbol *tlbl, *tlbl1;
7981 D (emitcode (";", "genLeftShift "););
7983 right = IC_RIGHT (ic);
7984 left = IC_LEFT (ic);
7985 result = IC_RESULT (ic);
7987 aopOp (right, ic, FALSE, FALSE);
7990 #ifdef BETTER_LITERAL_SHIFT
7991 /* if the shift count is known then do it
7992 as efficiently as possible */
7993 if (AOP_TYPE (right) == AOP_LIT)
7995 if (genLeftShiftLiteral (left, right, result, ic))
8002 /* shift count is unknown then we have to form
8003 a loop get the loop count in B : Note: we take
8004 only the lower order byte since shifting
8005 more that 32 bits make no sense anyway, ( the
8006 largest size of an object can be only 32 bits ) */
8008 if (AOP_TYPE (right) == AOP_LIT)
8010 /* Really should be handled by genLeftShiftLiteral,
8011 * but since I'm too lazy to fix that today, at least we can make
8012 * some small improvement.
8014 emitcode("mov", "b,#!constbyte",
8015 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8019 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8020 emitcode ("inc", "b");
8022 freeAsmop (right, NULL, ic, TRUE);
8023 aopOp (left, ic, FALSE, FALSE);
8024 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8026 /* now move the left to the result if they are not the
8028 if (!sameRegs (AOP (left), AOP (result)) &&
8029 AOP_SIZE (result) > 1)
8032 size = AOP_SIZE (result);
8034 _startLazyDPSEvaluation ();
8037 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8038 if (*l == '@' && (IS_AOP_PREG (result)))
8041 emitcode ("mov", "a,%s", l);
8042 aopPut (AOP (result), "a", offset);
8045 aopPut (AOP (result), l, offset);
8048 _endLazyDPSEvaluation ();
8051 tlbl = newiTempLabel (NULL);
8052 size = AOP_SIZE (result);
8054 tlbl1 = newiTempLabel (NULL);
8056 /* if it is only one byte then */
8059 symbol *tlbl1 = newiTempLabel (NULL);
8061 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8063 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8064 emitcode ("", "!tlabeldef", tlbl->key + 100);
8065 emitcode ("add", "a,acc");
8066 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8067 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8068 aopPut (AOP (result), "a", 0);
8072 reAdjustPreg (AOP (result));
8074 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8075 emitcode ("", "!tlabeldef", tlbl->key + 100);
8076 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8078 emitcode ("add", "a,acc");
8079 aopPut (AOP (result), "a", offset++);
8080 _startLazyDPSEvaluation ();
8083 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8085 emitcode ("rlc", "a");
8086 aopPut (AOP (result), "a", offset++);
8088 _endLazyDPSEvaluation ();
8089 reAdjustPreg (AOP (result));
8091 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8092 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8094 freeAsmop (left, NULL, ic, TRUE);
8095 freeAsmop (result, NULL, ic, TRUE);
8098 #ifdef BETTER_LITERAL_SHIFT
8099 /*-----------------------------------------------------------------*/
8100 /* genrshOne - right shift a one byte quantity by known count */
8101 /*-----------------------------------------------------------------*/
8103 genrshOne (operand * result, operand * left,
8104 int shCount, int sign)
8106 D (emitcode (";", "genrshOne"););
8107 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8111 #ifdef BETTER_LITERAL_SHIFT
8112 /*-----------------------------------------------------------------*/
8113 /* genrshTwo - right shift two bytes by known amount != 0 */
8114 /*-----------------------------------------------------------------*/
8116 genrshTwo (operand * result, operand * left,
8117 int shCount, int sign)
8119 D (emitcode (";", "genrshTwo"););
8121 /* if shCount >= 8 */
8125 _startLazyDPSEvaluation();
8128 shiftR1Left2Result (left, MSB16, result, LSB,
8133 movLeft2Result (left, MSB16, result, LSB, sign);
8135 addSign (result, MSB16, sign);
8136 _endLazyDPSEvaluation();
8139 /* 1 <= shCount <= 7 */
8142 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8149 /*-----------------------------------------------------------------*/
8150 /* shiftRLong - shift right one long from left to result */
8151 /* offl = LSB or MSB16 */
8152 /*-----------------------------------------------------------------*/
8154 shiftRLong (operand * left, int offl,
8155 operand * result, int sign)
8157 int isSameRegs=sameRegs(AOP(left),AOP(result));
8159 if (isSameRegs && offl>1) {
8160 // we are in big trouble, but this shouldn't happen
8161 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8164 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
8169 emitcode ("rlc", "a");
8170 emitcode ("subb", "a,acc");
8171 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
8173 aopPut (AOP(result), zero, MSB32);
8178 emitcode ("clr", "c");
8180 emitcode ("mov", "c,acc.7");
8183 emitcode ("rrc", "a");
8185 if (isSameRegs && offl==MSB16) {
8186 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
8188 aopPut (AOP (result), "a", MSB32);
8189 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
8192 emitcode ("rrc", "a");
8193 if (isSameRegs && offl==1) {
8194 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
8196 aopPut (AOP (result), "a", MSB24);
8197 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
8199 emitcode ("rrc", "a");
8200 aopPut (AOP (result), "a", MSB16 - offl);
8204 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
8205 emitcode ("rrc", "a");
8206 aopPut (AOP (result), "a", LSB);
8213 /*-----------------------------------------------------------------*/
8214 /* genrshFour - shift four byte by a known amount != 0 */
8215 /*-----------------------------------------------------------------*/
8217 genrshFour (operand * result, operand * left,
8218 int shCount, int sign)
8220 D (emitcode (";", "genrshFour");
8223 /* if shifting more that 3 bytes */
8228 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8230 movLeft2Result (left, MSB32, result, LSB, sign);
8231 addSign (result, MSB16, sign);
8233 else if (shCount >= 16)
8237 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8240 movLeft2Result (left, MSB24, result, LSB, 0);
8241 movLeft2Result (left, MSB32, result, MSB16, sign);
8243 addSign (result, MSB24, sign);
8245 else if (shCount >= 8)
8249 shiftRLong (left, MSB16, result, sign);
8250 else if (shCount == 0)
8252 movLeft2Result (left, MSB16, result, LSB, 0);
8253 movLeft2Result (left, MSB24, result, MSB16, 0);
8254 movLeft2Result (left, MSB32, result, MSB24, sign);
8255 addSign (result, MSB32, sign);
8259 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8260 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8261 /* the last shift is signed */
8262 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8263 addSign (result, MSB32, sign);
8267 { /* 1 <= shCount <= 7 */
8270 shiftRLong (left, LSB, result, sign);
8272 shiftRLong (result, LSB, result, sign);
8276 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8277 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8278 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8284 #ifdef BETTER_LITERAL_SHIFT
8285 /*-----------------------------------------------------------------*/
8286 /* genRightShiftLiteral - right shifting by known count */
8287 /*-----------------------------------------------------------------*/
8289 genRightShiftLiteral (operand * left,
8295 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8298 size = getSize (operandType (result));
8300 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8302 /* We only handle certain easy cases so far. */
8304 && (shCount < (size * 8))
8308 D(emitcode (";", "genRightShiftLiteral wimping out"););
8312 freeAsmop (right, NULL, ic, TRUE);
8314 aopOp (left, ic, FALSE, FALSE);
8315 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8318 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8322 /* test the LEFT size !!! */
8324 /* I suppose that the left size >= result size */
8327 size = getDataSize (result);
8328 _startLazyDPSEvaluation();
8331 movLeft2Result (left, size, result, size, 0);
8333 _endLazyDPSEvaluation();
8335 else if (shCount >= (size * 8))
8339 /* get sign in acc.7 */
8340 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
8342 addSign (result, LSB, sign);
8349 genrshOne (result, left, shCount, sign);
8353 genrshTwo (result, left, shCount, sign);
8357 genrshFour (result, left, shCount, sign);
8364 freeAsmop (left, NULL, ic, TRUE);
8365 freeAsmop (result, NULL, ic, TRUE);
8371 /*-----------------------------------------------------------------*/
8372 /* genSignedRightShift - right shift of signed number */
8373 /*-----------------------------------------------------------------*/
8375 genSignedRightShift (iCode * ic)
8377 operand *right, *left, *result;
8380 symbol *tlbl, *tlbl1;
8382 D (emitcode (";", "genSignedRightShift "););
8384 /* we do it the hard way put the shift count in b
8385 and loop thru preserving the sign */
8387 right = IC_RIGHT (ic);
8388 left = IC_LEFT (ic);
8389 result = IC_RESULT (ic);
8391 aopOp (right, ic, FALSE, FALSE);
8393 #ifdef BETTER_LITERAL_SHIFT
8394 if (AOP_TYPE (right) == AOP_LIT)
8396 if (genRightShiftLiteral (left, right, result, ic, 1))
8402 /* shift count is unknown then we have to form
8403 a loop get the loop count in B : Note: we take
8404 only the lower order byte since shifting
8405 more that 32 bits make no sense anyway, ( the
8406 largest size of an object can be only 32 bits ) */
8408 if (AOP_TYPE (right) == AOP_LIT)
8410 /* Really should be handled by genRightShiftLiteral,
8411 * but since I'm too lazy to fix that today, at least we can make
8412 * some small improvement.
8414 emitcode("mov", "b,#!constbyte",
8415 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8419 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8420 emitcode ("inc", "b");
8422 freeAsmop (right, NULL, ic, TRUE);
8423 aopOp (left, ic, FALSE, FALSE);
8424 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8426 /* now move the left to the result if they are not the
8428 if (!sameRegs (AOP (left), AOP (result)) &&
8429 AOP_SIZE (result) > 1)
8432 size = AOP_SIZE (result);
8434 _startLazyDPSEvaluation ();
8437 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8438 if (*l == '@' && IS_AOP_PREG (result))
8441 emitcode ("mov", "a,%s", l);
8442 aopPut (AOP (result), "a", offset);
8445 aopPut (AOP (result), l, offset);
8448 _endLazyDPSEvaluation ();
8451 /* mov the highest order bit to OVR */
8452 tlbl = newiTempLabel (NULL);
8453 tlbl1 = newiTempLabel (NULL);
8455 size = AOP_SIZE (result);
8457 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
8458 emitcode ("rlc", "a");
8459 emitcode ("mov", "ov,c");
8460 /* if it is only one byte then */
8463 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8465 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8466 emitcode ("", "!tlabeldef", tlbl->key + 100);
8467 emitcode ("mov", "c,ov");
8468 emitcode ("rrc", "a");
8469 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8470 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8471 aopPut (AOP (result), "a", 0);
8475 reAdjustPreg (AOP (result));
8476 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8477 emitcode ("", "!tlabeldef", tlbl->key + 100);
8478 emitcode ("mov", "c,ov");
8479 _startLazyDPSEvaluation ();
8482 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8484 emitcode ("rrc", "a");
8485 aopPut (AOP (result), "a", offset--);
8487 _endLazyDPSEvaluation ();
8488 reAdjustPreg (AOP (result));
8489 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8490 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8493 freeAsmop (left, NULL, ic, TRUE);
8494 freeAsmop (result, NULL, ic, TRUE);
8497 /*-----------------------------------------------------------------*/
8498 /* genRightShift - generate code for right shifting */
8499 /*-----------------------------------------------------------------*/
8501 genRightShift (iCode * ic)
8503 operand *right, *left, *result;
8507 symbol *tlbl, *tlbl1;
8509 D (emitcode (";", "genRightShift "););
8511 /* if signed then we do it the hard way preserve the
8512 sign bit moving it inwards */
8513 retype = getSpec (operandType (IC_RESULT (ic)));
8515 if (!SPEC_USIGN (retype))
8517 genSignedRightShift (ic);
8521 /* signed & unsigned types are treated the same : i.e. the
8522 signed is NOT propagated inwards : quoting from the
8523 ANSI - standard : "for E1 >> E2, is equivalent to division
8524 by 2**E2 if unsigned or if it has a non-negative value,
8525 otherwise the result is implementation defined ", MY definition
8526 is that the sign does not get propagated */
8528 right = IC_RIGHT (ic);
8529 left = IC_LEFT (ic);
8530 result = IC_RESULT (ic);
8532 aopOp (right, ic, FALSE, FALSE);
8534 #ifdef BETTER_LITERAL_SHIFT
8535 /* if the shift count is known then do it
8536 as efficiently as possible */
8537 if (AOP_TYPE (right) == AOP_LIT)
8539 if (genRightShiftLiteral (left, right, result, ic, 0))
8546 /* shift count is unknown then we have to form
8547 a loop get the loop count in B : Note: we take
8548 only the lower order byte since shifting
8549 more that 32 bits make no sense anyway, ( the
8550 largest size of an object can be only 32 bits ) */
8552 if (AOP_TYPE (right) == AOP_LIT)
8554 /* Really should be handled by genRightShiftLiteral,
8555 * but since I'm too lazy to fix that today, at least we can make
8556 * some small improvement.
8558 emitcode("mov", "b,#!constbyte",
8559 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8563 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8564 emitcode ("inc", "b");
8566 freeAsmop (right, NULL, ic, TRUE);
8567 aopOp (left, ic, FALSE, FALSE);
8568 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8570 /* now move the left to the result if they are not the
8572 if (!sameRegs (AOP (left), AOP (result)) &&
8573 AOP_SIZE (result) > 1)
8576 size = AOP_SIZE (result);
8578 _startLazyDPSEvaluation ();
8581 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8582 if (*l == '@' && IS_AOP_PREG (result))
8585 emitcode ("mov", "a,%s", l);
8586 aopPut (AOP (result), "a", offset);
8589 aopPut (AOP (result), l, offset);
8592 _endLazyDPSEvaluation ();
8595 tlbl = newiTempLabel (NULL);
8596 tlbl1 = newiTempLabel (NULL);
8597 size = AOP_SIZE (result);
8600 /* if it is only one byte then */
8603 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8605 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8606 emitcode ("", "!tlabeldef", tlbl->key + 100);
8608 emitcode ("rrc", "a");
8609 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8610 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8611 aopPut (AOP (result), "a", 0);
8615 reAdjustPreg (AOP (result));
8616 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8617 emitcode ("", "!tlabeldef", tlbl->key + 100);
8619 _startLazyDPSEvaluation ();
8622 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8624 emitcode ("rrc", "a");
8625 aopPut (AOP (result), "a", offset--);
8627 _endLazyDPSEvaluation ();
8628 reAdjustPreg (AOP (result));
8630 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8631 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8634 freeAsmop (left, NULL, ic, TRUE);
8635 freeAsmop (result, NULL, ic, TRUE);
8638 /*-----------------------------------------------------------------*/
8639 /* genUnpackBits - generates code for unpacking bits */
8640 /*-----------------------------------------------------------------*/
8642 genUnpackBits (operand * result, char *rname, int ptype)
8649 D (emitcode (";", "genUnpackBits ");
8652 etype = getSpec (operandType (result));
8654 /* read the first byte */
8660 emitcode ("mov", "a,@%s", rname);
8664 emitcode ("movx", "a,@%s", rname);
8668 emitcode ("movx", "a,@dptr");
8672 emitcode ("clr", "a");
8673 emitcode ("movc", "a,@a+dptr");
8677 emitcode ("lcall", "__gptrget");
8681 /* if we have bitdisplacement then it fits */
8682 /* into this byte completely or if length is */
8683 /* less than a byte */
8684 if ((shCnt = SPEC_BSTR (etype)) ||
8685 (SPEC_BLEN (etype) <= 8))
8688 /* shift right acc */
8691 emitcode ("anl", "a,#!constbyte",
8692 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8693 aopPut (AOP (result), "a", offset);
8697 /* bit field did not fit in a byte */
8698 rlen = SPEC_BLEN (etype) - 8;
8699 aopPut (AOP (result), "a", offset++);
8708 emitcode ("inc", "%s", rname);
8709 emitcode ("mov", "a,@%s", rname);
8713 emitcode ("inc", "%s", rname);
8714 emitcode ("movx", "a,@%s", rname);
8718 emitcode ("inc", "dptr");
8719 emitcode ("movx", "a,@dptr");
8723 emitcode ("clr", "a");
8724 emitcode ("inc", "dptr");
8725 emitcode ("movc", "a,@a+dptr");
8729 emitcode ("inc", "dptr");
8730 emitcode ("lcall", "__gptrget");
8735 /* if we are done */
8739 aopPut (AOP (result), "a", offset++);
8745 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (rlen));
8746 aopPut (AOP (result), "a", offset);
8753 /*-----------------------------------------------------------------*/
8754 /* genDataPointerGet - generates code when ptr offset is known */
8755 /*-----------------------------------------------------------------*/
8757 genDataPointerGet (operand * left,
8763 int size, offset = 0;
8764 aopOp (result, ic, TRUE, FALSE);
8766 /* get the string representation of the name */
8767 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8768 size = AOP_SIZE (result);
8769 _startLazyDPSEvaluation ();
8773 sprintf (buffer, "(%s + %d)", l + 1, offset);
8775 sprintf (buffer, "%s", l + 1);
8776 aopPut (AOP (result), buffer, offset++);
8778 _endLazyDPSEvaluation ();
8780 freeAsmop (left, NULL, ic, TRUE);
8781 freeAsmop (result, NULL, ic, TRUE);
8784 /*-----------------------------------------------------------------*/
8785 /* genNearPointerGet - emitcode for near pointer fetch */
8786 /*-----------------------------------------------------------------*/
8788 genNearPointerGet (operand * left,
8796 sym_link *rtype, *retype, *letype;
8797 sym_link *ltype = operandType (left);
8800 rtype = operandType (result);
8801 retype = getSpec (rtype);
8802 letype = getSpec (ltype);
8804 aopOp (left, ic, FALSE, FALSE);
8806 /* if left is rematerialisable and
8807 result is not bit variable type and
8808 the left is pointer to data space i.e
8809 lower 128 bytes of space */
8810 if (AOP_TYPE (left) == AOP_IMMD &&
8811 !IS_BITVAR (retype) &&
8812 !IS_BITVAR (letype) &&
8813 DCL_TYPE (ltype) == POINTER)
8815 genDataPointerGet (left, result, ic);
8819 /* if the value is already in a pointer register
8820 then don't need anything more */
8821 if (!AOP_INPREG (AOP (left)))
8823 /* otherwise get a free pointer register */
8825 preg = getFreePtr (ic, &aop, FALSE);
8826 emitcode ("mov", "%s,%s",
8828 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8832 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8834 freeAsmop (left, NULL, ic, TRUE);
8835 aopOp (result, ic, FALSE, FALSE);
8837 /* if bitfield then unpack the bits */
8838 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8839 genUnpackBits (result, rname, POINTER);
8842 /* we have can just get the values */
8843 int size = AOP_SIZE (result);
8848 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8851 emitcode ("mov", "a,@%s", rname);
8852 aopPut (AOP (result), "a", offset);
8856 sprintf (buffer, "@%s", rname);
8857 aopPut (AOP (result), buffer, offset);
8861 emitcode ("inc", "%s", rname);
8865 /* now some housekeeping stuff */
8868 /* we had to allocate for this iCode */
8869 if (pi) { /* post increment present */
8870 aopPut(AOP ( left ),rname,0);
8872 freeAsmop (NULL, aop, ic, TRUE);
8876 /* we did not allocate which means left
8877 already in a pointer register, then
8878 if size > 0 && this could be used again
8879 we have to point it back to where it
8881 if (AOP_SIZE (result) > 1 &&
8882 !OP_SYMBOL (left)->remat &&
8883 (OP_SYMBOL (left)->liveTo > ic->seq ||
8887 int size = AOP_SIZE (result) - 1;
8889 emitcode ("dec", "%s", rname);
8894 freeAsmop (result, NULL, ic, TRUE);
8895 if (pi) pi->generated = 1;
8898 /*-----------------------------------------------------------------*/
8899 /* genPagedPointerGet - emitcode for paged pointer fetch */
8900 /*-----------------------------------------------------------------*/
8902 genPagedPointerGet (operand * left,
8910 sym_link *rtype, *retype, *letype;
8912 rtype = operandType (result);
8913 retype = getSpec (rtype);
8914 letype = getSpec (operandType (left));
8915 aopOp (left, ic, FALSE, FALSE);
8917 /* if the value is already in a pointer register
8918 then don't need anything more */
8919 if (!AOP_INPREG (AOP (left)))
8921 /* otherwise get a free pointer register */
8923 preg = getFreePtr (ic, &aop, FALSE);
8924 emitcode ("mov", "%s,%s",
8926 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8930 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8932 freeAsmop (left, NULL, ic, TRUE);
8933 aopOp (result, ic, FALSE, FALSE);
8935 /* if bitfield then unpack the bits */
8936 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8937 genUnpackBits (result, rname, PPOINTER);
8940 /* we have can just get the values */
8941 int size = AOP_SIZE (result);
8947 emitcode ("movx", "a,@%s", rname);
8948 aopPut (AOP (result), "a", offset);
8953 emitcode ("inc", "%s", rname);
8957 /* now some housekeeping stuff */
8960 /* we had to allocate for this iCode */
8961 if (pi) aopPut ( AOP (left), rname, 0);
8962 freeAsmop (NULL, aop, ic, TRUE);
8966 /* we did not allocate which means left
8967 already in a pointer register, then
8968 if size > 0 && this could be used again
8969 we have to point it back to where it
8971 if (AOP_SIZE (result) > 1 &&
8972 !OP_SYMBOL (left)->remat &&
8973 (OP_SYMBOL (left)->liveTo > ic->seq ||
8977 int size = AOP_SIZE (result) - 1;
8979 emitcode ("dec", "%s", rname);
8984 freeAsmop (result, NULL, ic, TRUE);
8985 if (pi) pi->generated = 1;
8988 /*-----------------------------------------------------------------*/
8989 /* genFarPointerGet - gget value from far space */
8990 /*-----------------------------------------------------------------*/
8992 genFarPointerGet (operand * left,
8993 operand * result, iCode * ic, iCode *pi)
8995 int size, offset, dopi=1;
8996 sym_link *retype = getSpec (operandType (result));
8997 sym_link *letype = getSpec (operandType (left));
8998 D (emitcode (";", "genFarPointerGet");
9001 aopOp (left, ic, FALSE, FALSE);
9003 /* if the operand is already in dptr
9004 then we do nothing else we move the value to dptr */
9005 if (AOP_TYPE (left) != AOP_STR)
9007 /* if this is remateriazable */
9008 if (AOP_TYPE (left) == AOP_IMMD)
9010 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9014 /* we need to get it byte by byte */
9015 _startLazyDPSEvaluation ();
9016 if (AOP_TYPE (left) != AOP_DPTR)
9018 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9019 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9020 if (options.model == MODEL_FLAT24)
9021 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9025 /* We need to generate a load to DPTR indirect through DPTR. */
9026 D (emitcode (";", "genFarPointerGet -- indirection special case.");
9028 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
9029 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
9030 if (options.model == MODEL_FLAT24)
9031 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9032 emitcode ("pop", "dph");
9033 emitcode ("pop", "dpl");
9036 _endLazyDPSEvaluation ();
9039 /* so dptr know contains the address */
9040 aopOp (result, ic, FALSE, TRUE);
9042 /* if bit then unpack */
9043 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9044 genUnpackBits (result, "dptr", FPOINTER);
9047 size = AOP_SIZE (result);
9050 _startLazyDPSEvaluation ();
9057 emitcode ("movx", "a,@dptr");
9058 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9059 emitcode ("inc", "dptr");
9061 aopPut (AOP (result), "a", offset++);
9063 _endLazyDPSEvaluation ();
9065 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9066 aopPut ( AOP (left), "dpl", 0);
9067 aopPut ( AOP (left), "dph", 1);
9068 if (options.model == MODEL_FLAT24)
9069 aopPut ( AOP (left), "dpx", 2);
9071 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9072 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9074 size = AOP_SIZE (result) - 1;
9075 while (size--) emitcode ("lcall","__decdptr");
9078 freeAsmop (left, NULL, ic, TRUE);
9079 freeAsmop (result, NULL, ic, TRUE);
9082 /*-----------------------------------------------------------------*/
9083 /* emitcodePointerGet - gget value from code space */
9084 /*-----------------------------------------------------------------*/
9086 emitcodePointerGet (operand * left,
9087 operand * result, iCode * ic, iCode *pi)
9089 int size, offset, dopi=1;
9090 sym_link *retype = getSpec (operandType (result));
9092 aopOp (left, ic, FALSE, FALSE);
9094 /* if the operand is already in dptr
9095 then we do nothing else we move the value to dptr */
9096 if (AOP_TYPE (left) != AOP_STR)
9098 /* if this is remateriazable */
9099 if (AOP_TYPE (left) == AOP_IMMD)
9101 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9104 { /* we need to get it byte by byte */
9105 _startLazyDPSEvaluation ();
9106 if (AOP_TYPE (left) != AOP_DPTR)
9108 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9109 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9110 if (options.model == MODEL_FLAT24)
9111 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9115 /* We need to generate a load to DPTR indirect through DPTR. */
9116 D (emitcode (";", "gencodePointerGet -- indirection special case.");
9118 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
9119 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
9120 if (options.model == MODEL_FLAT24)
9121 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9122 emitcode ("pop", "dph");
9123 emitcode ("pop", "dpl");
9126 _endLazyDPSEvaluation ();
9129 /* so dptr know contains the address */
9130 aopOp (result, ic, FALSE, TRUE);
9132 /* if bit then unpack */
9133 if (IS_BITVAR (retype))
9134 genUnpackBits (result, "dptr", CPOINTER);
9137 size = AOP_SIZE (result);
9140 _startLazyDPSEvaluation ();
9146 emitcode ("clr", "a");
9147 emitcode ("movc", "a,@a+dptr");
9148 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9149 emitcode ("inc", "dptr");
9150 aopPut (AOP (result), "a", offset++);
9152 _endLazyDPSEvaluation ();
9154 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9155 aopPut ( AOP (left), "dpl", 0);
9156 aopPut ( AOP (left), "dph", 1);
9157 if (options.model == MODEL_FLAT24)
9158 aopPut ( AOP (left), "dpx", 2);
9160 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9161 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9163 size = AOP_SIZE (result) - 1;
9164 while (size--) emitcode ("lcall","__decdptr");
9167 freeAsmop (left, NULL, ic, TRUE);
9168 freeAsmop (result, NULL, ic, TRUE);
9171 /*-----------------------------------------------------------------*/
9172 /* genGenPointerGet - gget value from generic pointer space */
9173 /*-----------------------------------------------------------------*/
9175 genGenPointerGet (operand * left,
9176 operand * result, iCode * ic, iCode * pi)
9179 sym_link *retype = getSpec (operandType (result));
9180 sym_link *letype = getSpec (operandType (left));
9182 D (emitcode (";", "genGenPointerGet "); );
9184 aopOp (left, ic, FALSE, (OP_SYMBOL(left)->ruonly ? FALSE : TRUE));
9186 /* if the operand is already in dptr
9187 then we do nothing else we move the value to dptr */
9188 if (AOP_TYPE (left) != AOP_STR)
9190 /* if this is remateriazable */
9191 if (AOP_TYPE (left) == AOP_IMMD)
9193 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9194 if (AOP(left)->aopu.aop_immd.from_cast_remat)
9195 emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, FALSE));
9197 emitcode ("mov", "b,#%d", pointerCode (retype));
9200 { /* we need to get it byte by byte */
9201 _startLazyDPSEvaluation ();
9202 if (AOP(left)->type==AOP_DPTR2) {
9204 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
9207 emitcode ("mov", "dpl,%s", l);
9208 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
9211 emitcode ("mov", "dph,%s", l);
9212 if (options.model == MODEL_FLAT24) {
9213 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
9216 emitcode ("mov", "dpx,%s", l);
9217 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9219 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9222 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
9223 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
9224 if (options.model == MODEL_FLAT24) {
9225 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9226 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9228 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9231 _endLazyDPSEvaluation ();
9234 /* so dptr know contains the address */
9235 aopOp (result, ic, FALSE, TRUE);
9237 /* if bit then unpack */
9238 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9239 genUnpackBits (result, "dptr", GPOINTER);
9242 size = AOP_SIZE (result);
9247 emitcode ("lcall", "__gptrget");
9248 aopPut (AOP (result), "a", offset++);
9249 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9250 emitcode ("inc", "dptr");
9254 if (pi && AOP_TYPE (left) != AOP_IMMD) {
9255 aopPut ( AOP (left), "dpl", 0);
9256 aopPut ( AOP (left), "dph", 1);
9257 if (options.model == MODEL_FLAT24) {
9258 aopPut ( AOP (left), "dpx", 2);
9259 aopPut ( AOP (left), "b", 3);
9260 } else aopPut ( AOP (left), "b", 2);
9262 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9263 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9265 size = AOP_SIZE (result) - 1;
9266 while (size--) emitcode ("lcall","__decdptr");
9269 freeAsmop (left, NULL, ic, TRUE);
9270 freeAsmop (result, NULL, ic, TRUE);
9273 /*-----------------------------------------------------------------*/
9274 /* genPointerGet - generate code for pointer get */
9275 /*-----------------------------------------------------------------*/
9277 genPointerGet (iCode * ic, iCode *pi)
9279 operand *left, *result;
9280 sym_link *type, *etype;
9283 D (emitcode (";", "genPointerGet ");
9286 left = IC_LEFT (ic);
9287 result = IC_RESULT (ic);
9289 /* depending on the type of pointer we need to
9290 move it to the correct pointer register */
9291 type = operandType (left);
9292 etype = getSpec (type);
9293 /* if left is of type of pointer then it is simple */
9294 if (IS_PTR (type) && !IS_FUNC (type->next))
9295 p_type = DCL_TYPE (type);
9298 /* we have to go by the storage class */
9299 p_type = PTR_TYPE (SPEC_OCLS (etype));
9301 /* special case when cast remat */
9302 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9303 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9304 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9305 type = type = operandType (left);
9306 p_type = DCL_TYPE (type);
9308 /* now that we have the pointer type we assign
9309 the pointer values */
9315 genNearPointerGet (left, result, ic, pi);
9319 genPagedPointerGet (left, result, ic, pi);
9323 genFarPointerGet (left, result, ic, pi);
9327 emitcodePointerGet (left, result, ic, pi);
9331 genGenPointerGet (left, result, ic, pi);
9337 /*-----------------------------------------------------------------*/
9338 /* genPackBits - generates code for packed bit storage */
9339 /*-----------------------------------------------------------------*/
9341 genPackBits (sym_link * etype,
9343 char *rname, int p_type)
9351 blen = SPEC_BLEN (etype);
9352 bstr = SPEC_BSTR (etype);
9354 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9357 /* if the bit lenth is less than or */
9358 /* it exactly fits a byte then */
9359 if (SPEC_BLEN (etype) <= 8)
9361 shCount = SPEC_BSTR (etype);
9363 /* shift left acc */
9366 if (SPEC_BLEN (etype) < 8)
9367 { /* if smaller than a byte */
9373 emitcode ("mov", "b,a");
9374 emitcode ("mov", "a,@%s", rname);
9378 emitcode ("mov", "b,a");
9379 emitcode ("movx", "a,@dptr");
9383 emitcode ("push", "b");
9384 emitcode ("push", "acc");
9385 emitcode ("lcall", "__gptrget");
9386 emitcode ("pop", "b");
9390 emitcode ("anl", "a,#!constbyte", (unsigned char)
9391 ((unsigned char) (0xFF << (blen + bstr)) |
9392 (unsigned char) (0xFF >> (8 - bstr))));
9393 emitcode ("orl", "a,b");
9394 if (p_type == GPOINTER)
9395 emitcode ("pop", "b");
9402 emitcode ("mov", "@%s,a", rname);
9406 emitcode ("movx", "@dptr,a");
9410 emitcode ("lcall", "__gptrput");
9415 if (SPEC_BLEN (etype) <= 8)
9418 emitcode ("inc", "%s", rname);
9419 rLen = SPEC_BLEN (etype);
9421 /* now generate for lengths greater than one byte */
9425 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
9437 emitcode ("mov", "@%s,a", rname);
9440 emitcode ("mov", "@%s,%s", rname, l);
9445 emitcode ("movx", "@dptr,a");
9450 emitcode ("lcall", "__gptrput");
9453 emitcode ("inc", "%s", rname);
9458 /* last last was not complete */
9461 /* save the byte & read byte */
9465 emitcode ("mov", "b,a");
9466 emitcode ("mov", "a,@%s", rname);
9470 emitcode ("mov", "b,a");
9471 emitcode ("movx", "a,@dptr");
9475 emitcode ("push", "b");
9476 emitcode ("push", "acc");
9477 emitcode ("lcall", "__gptrget");
9478 emitcode ("pop", "b");
9482 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1 << rLen));
9483 emitcode ("orl", "a,b");
9486 if (p_type == GPOINTER)
9487 emitcode ("pop", "b");
9493 emitcode ("mov", "@%s,a", rname);
9497 emitcode ("movx", "@dptr,a");
9501 emitcode ("lcall", "__gptrput");
9505 /*-----------------------------------------------------------------*/
9506 /* genDataPointerSet - remat pointer to data space */
9507 /*-----------------------------------------------------------------*/
9509 genDataPointerSet (operand * right,
9513 int size, offset = 0;
9514 char *l, buffer[256];
9516 aopOp (right, ic, FALSE, FALSE);
9518 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
9519 size = AOP_SIZE (right);
9523 sprintf (buffer, "(%s + %d)", l + 1, offset);
9525 sprintf (buffer, "%s", l + 1);
9526 emitcode ("mov", "%s,%s", buffer,
9527 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
9530 freeAsmop (right, NULL, ic, TRUE);
9531 freeAsmop (result, NULL, ic, TRUE);
9534 /*-----------------------------------------------------------------*/
9535 /* genNearPointerSet - emitcode for near pointer put */
9536 /*-----------------------------------------------------------------*/
9538 genNearPointerSet (operand * right,
9546 sym_link *retype, *letype;
9547 sym_link *ptype = operandType (result);
9549 retype = getSpec (operandType (right));
9550 letype = getSpec (ptype);
9552 aopOp (result, ic, FALSE, FALSE);
9554 /* if the result is rematerializable &
9555 in data space & not a bit variable */
9556 if (AOP_TYPE (result) == AOP_IMMD &&
9557 DCL_TYPE (ptype) == POINTER &&
9558 !IS_BITVAR (retype) &&
9559 !IS_BITVAR (letype))
9561 genDataPointerSet (right, result, ic);
9565 /* if the value is already in a pointer register
9566 then don't need anything more */
9567 if (!AOP_INPREG (AOP (result)))
9569 /* otherwise get a free pointer register */
9571 preg = getFreePtr (ic, &aop, FALSE);
9572 emitcode ("mov", "%s,%s",
9574 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9578 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9580 aopOp (right, ic, FALSE, FALSE);
9582 /* if bitfield then unpack the bits */
9583 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9584 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9587 /* we have can just get the values */
9588 int size = AOP_SIZE (right);
9593 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
9597 emitcode ("mov", "@%s,a", rname);
9600 emitcode ("mov", "@%s,%s", rname, l);
9602 emitcode ("inc", "%s", rname);
9607 /* now some housekeeping stuff */
9610 /* we had to allocate for this iCode */
9611 if (pi) aopPut (AOP (result),rname,0);
9612 freeAsmop (NULL, aop, ic, TRUE);
9616 /* we did not allocate which means left
9617 already in a pointer register, then
9618 if size > 0 && this could be used again
9619 we have to point it back to where it
9621 if (AOP_SIZE (right) > 1 &&
9622 !OP_SYMBOL (result)->remat &&
9623 (OP_SYMBOL (result)->liveTo > ic->seq ||
9627 int size = AOP_SIZE (right) - 1;
9629 emitcode ("dec", "%s", rname);
9634 if (pi) pi->generated = 1;
9635 freeAsmop (result, NULL, ic, TRUE);
9636 freeAsmop (right, NULL, ic, TRUE);
9641 /*-----------------------------------------------------------------*/
9642 /* genPagedPointerSet - emitcode for Paged pointer put */
9643 /*-----------------------------------------------------------------*/
9645 genPagedPointerSet (operand * right,
9653 sym_link *retype, *letype;
9655 retype = getSpec (operandType (right));
9656 letype = getSpec (operandType (result));
9658 aopOp (result, ic, FALSE, FALSE);
9660 /* if the value is already in a pointer register
9661 then don't need anything more */
9662 if (!AOP_INPREG (AOP (result)))
9664 /* otherwise get a free pointer register */
9666 preg = getFreePtr (ic, &aop, FALSE);
9667 emitcode ("mov", "%s,%s",
9669 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9673 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9675 aopOp (right, ic, FALSE, FALSE);
9677 /* if bitfield then unpack the bits */
9678 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9679 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
9682 /* we have can just get the values */
9683 int size = AOP_SIZE (right);
9688 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
9691 emitcode ("movx", "@%s,a", rname);
9694 emitcode ("inc", "%s", rname);
9700 /* now some housekeeping stuff */
9703 if (pi) aopPut (AOP (result),rname,0);
9704 /* we had to allocate for this iCode */
9705 freeAsmop (NULL, aop, ic, TRUE);
9709 /* we did not allocate which means left
9710 already in a pointer register, then
9711 if size > 0 && this could be used again
9712 we have to point it back to where it
9714 if (AOP_SIZE (right) > 1 &&
9715 !OP_SYMBOL (result)->remat &&
9716 (OP_SYMBOL (result)->liveTo > ic->seq ||
9720 int size = AOP_SIZE (right) - 1;
9722 emitcode ("dec", "%s", rname);
9727 if (pi) pi->generated = 1;
9728 freeAsmop (result, NULL, ic, TRUE);
9729 freeAsmop (right, NULL, ic, TRUE);
9734 /*-----------------------------------------------------------------*/
9735 /* genFarPointerSet - set value from far space */
9736 /*-----------------------------------------------------------------*/
9738 genFarPointerSet (operand * right,
9739 operand * result, iCode * ic, iCode *pi)
9741 int size, offset, dopi=1;
9742 sym_link *retype = getSpec (operandType (right));
9743 sym_link *letype = getSpec (operandType (result));
9745 aopOp (result, ic, FALSE, FALSE);
9747 /* if the operand is already in dptr
9748 then we do nothing else we move the value to dptr */
9749 if (AOP_TYPE (result) != AOP_STR)
9751 /* if this is remateriazable */
9752 if (AOP_TYPE (result) == AOP_IMMD)
9753 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9756 /* we need to get it byte by byte */
9757 _startLazyDPSEvaluation ();
9758 if (AOP_TYPE (result) != AOP_DPTR)
9760 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9761 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9762 if (options.model == MODEL_FLAT24)
9763 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9767 /* We need to generate a load to DPTR indirect through DPTR. */
9768 D (emitcode (";", "genFarPointerSet -- indirection special case.");
9770 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
9771 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
9772 if (options.model == MODEL_FLAT24)
9773 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9774 emitcode ("pop", "dph");
9775 emitcode ("pop", "dpl");
9778 _endLazyDPSEvaluation ();
9781 /* so dptr know contains the address */
9782 aopOp (right, ic, FALSE, TRUE);
9784 /* if bit then unpack */
9785 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9786 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
9789 size = AOP_SIZE (right);
9792 _startLazyDPSEvaluation ();
9795 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9801 emitcode ("movx", "@dptr,a");
9802 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
9803 emitcode ("inc", "dptr");
9805 _endLazyDPSEvaluation ();
9808 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
9809 aopPut (AOP(result),"dpl",0);
9810 aopPut (AOP(result),"dph",1);
9811 if (options.model == MODEL_FLAT24)
9812 aopPut (AOP(result),"dpx",2);
9814 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
9815 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
9817 size = AOP_SIZE (right) - 1;
9818 while (size--) emitcode ("lcall","__decdptr");
9820 freeAsmop (result, NULL, ic, TRUE);
9821 freeAsmop (right, NULL, ic, TRUE);
9824 /*-----------------------------------------------------------------*/
9825 /* genGenPointerSet - set value from generic pointer space */
9826 /*-----------------------------------------------------------------*/
9828 genGenPointerSet (operand * right,
9829 operand * result, iCode * ic, iCode *pi)
9832 sym_link *retype = getSpec (operandType (right));
9833 sym_link *letype = getSpec (operandType (result));
9835 aopOp (result, ic, FALSE, OP_SYMBOL(result)->ruonly ? FALSE : TRUE);
9837 /* if the operand is already in dptr
9838 then we do nothing else we move the value to dptr */
9839 if (AOP_TYPE (result) != AOP_STR)
9841 _startLazyDPSEvaluation ();
9842 /* if this is remateriazable */
9843 if (AOP_TYPE (result) == AOP_IMMD)
9845 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9846 if (AOP(result)->aopu.aop_immd.from_cast_remat)
9847 emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, FALSE));
9849 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9852 { /* we need to get it byte by byte */
9853 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9854 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9855 if (options.model == MODEL_FLAT24) {
9856 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9857 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
9859 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9862 _endLazyDPSEvaluation ();
9864 /* so dptr know contains the address */
9865 aopOp (right, ic, FALSE, TRUE);
9867 /* if bit then unpack */
9868 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9869 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
9872 size = AOP_SIZE (right);
9875 _startLazyDPSEvaluation ();
9878 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9884 emitcode ("lcall", "__gptrput");
9885 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
9886 emitcode ("inc", "dptr");
9888 _endLazyDPSEvaluation ();
9891 if (pi && AOP_TYPE (result) != AOP_IMMD) {
9892 aopPut (AOP(result),"dpl",0);
9893 aopPut (AOP(result),"dph",1);
9894 if (options.model == MODEL_FLAT24) {
9895 aopPut (AOP(result),"dpx",2);
9896 aopPut (AOP(result),"b",3);
9898 aopPut (AOP(result),"b",2);
9901 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
9902 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
9904 size = AOP_SIZE (right) - 1;
9905 while (size--) emitcode ("lcall","__decdptr");
9907 freeAsmop (result, NULL, ic, TRUE);
9908 freeAsmop (right, NULL, ic, TRUE);
9911 /*-----------------------------------------------------------------*/
9912 /* genPointerSet - stores the value into a pointer location */
9913 /*-----------------------------------------------------------------*/
9915 genPointerSet (iCode * ic, iCode *pi)
9917 operand *right, *result;
9918 sym_link *type, *etype;
9921 D (emitcode (";", "genPointerSet ");
9924 right = IC_RIGHT (ic);
9925 result = IC_RESULT (ic);
9927 /* depending on the type of pointer we need to
9928 move it to the correct pointer register */
9929 type = operandType (result);
9930 etype = getSpec (type);
9931 /* if left is of type of pointer then it is simple */
9932 if (IS_PTR (type) && !IS_FUNC (type->next))
9934 p_type = DCL_TYPE (type);
9938 /* we have to go by the storage class */
9939 p_type = PTR_TYPE (SPEC_OCLS (etype));
9941 /* special case when cast remat */
9942 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
9943 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
9944 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
9945 type = type = operandType (result);
9946 p_type = DCL_TYPE (type);
9949 /* now that we have the pointer type we assign
9950 the pointer values */
9956 genNearPointerSet (right, result, ic, pi);
9960 genPagedPointerSet (right, result, ic, pi);
9964 genFarPointerSet (right, result, ic, pi);
9968 genGenPointerSet (right, result, ic, pi);
9974 /*-----------------------------------------------------------------*/
9975 /* genIfx - generate code for Ifx statement */
9976 /*-----------------------------------------------------------------*/
9978 genIfx (iCode * ic, iCode * popIc)
9980 operand *cond = IC_COND (ic);
9983 D (emitcode (";", "genIfx "););
9985 aopOp (cond, ic, FALSE, FALSE);
9987 /* get the value into acc */
9988 if (AOP_TYPE (cond) != AOP_CRY)
9992 /* the result is now in the accumulator */
9993 freeAsmop (cond, NULL, ic, TRUE);
9995 /* if there was something to be popped then do it */
9999 /* if the condition is a bit variable */
10000 if (isbit && IS_ITEMP (cond) &&
10002 genIfxJump (ic, SPIL_LOC (cond)->rname);
10003 else if (isbit && !IS_ITEMP (cond))
10004 genIfxJump (ic, OP_SYMBOL (cond)->rname);
10006 genIfxJump (ic, "a");
10011 /*-----------------------------------------------------------------*/
10012 /* genAddrOf - generates code for address of */
10013 /*-----------------------------------------------------------------*/
10015 genAddrOf (iCode * ic)
10017 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10020 D (emitcode (";", "genAddrOf ");
10023 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10025 /* if the operand is on the stack then we
10026 need to get the stack offset of this
10028 if (sym->onStack) {
10030 /* if 10 bit stack */
10031 if (options.stack10bit) {
10033 tsprintf(buff,"#!constbyte",(options.stack_loc >> 16) & 0xff);
10034 /* if it has an offset then we need to compute it */
10035 emitcode ("subb", "a,#!constbyte",
10036 -((sym->stack < 0) ?
10037 ((short) (sym->stack - _G.nRegsSaved)) :
10038 ((short) sym->stack)) & 0xff);
10039 emitcode ("mov","b,a");
10040 emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ?
10041 ((short) (sym->stack - _G.nRegsSaved)) :
10042 ((short) sym->stack)) >> 8) & 0xff);
10044 emitcode ("mov", "a,_bpx");
10045 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
10046 ((char) (sym->stack - _G.nRegsSaved)) :
10047 ((char) sym->stack )) & 0xff);
10048 emitcode ("mov", "b,a");
10049 emitcode ("mov", "a,_bpx+1");
10050 emitcode ("addc","a,#!constbyte", (((sym->stack < 0) ?
10051 ((short) (sym->stack - _G.nRegsSaved)) :
10052 ((short) sym->stack )) >> 8) & 0xff);
10053 aopPut (AOP (IC_RESULT (ic)), "b", 0);
10054 aopPut (AOP (IC_RESULT (ic)), "a", 1);
10055 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10057 /* we can just move _bp */
10058 aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10059 aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10060 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10063 /* if it has an offset then we need to compute it */
10065 emitcode ("mov", "a,_bp");
10066 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10067 aopPut (AOP (IC_RESULT (ic)), "a", 0);
10069 /* we can just move _bp */
10070 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10072 /* fill the result with zero */
10073 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10076 if (options.stack10bit && size < (FPTRSIZE - 1)) {
10078 "*** warning: pointer to stack var truncated.\n");
10083 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10089 /* object not on stack then we need the name */
10090 size = AOP_SIZE (IC_RESULT (ic));
10095 char s[SDCC_NAME_MAX];
10099 tsprintf(s,"!his",sym->rname);
10102 tsprintf(s,"!hihis",sym->rname);
10105 tsprintf(s,"!hihihis",sym->rname);
10107 default: /* should not need this (just in case) */
10108 sprintf (s, "#(%s >> %d)",
10113 sprintf (s, "#%s", sym->rname);
10114 aopPut (AOP (IC_RESULT (ic)), s, offset++);
10118 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10122 /*-----------------------------------------------------------------*/
10123 /* genArrayInit - generates code for address of */
10124 /*-----------------------------------------------------------------*/
10126 genArrayInit (iCode * ic)
10128 literalList *iLoop;
10130 int elementSize = 0, eIndex;
10131 unsigned val, lastVal;
10133 operand *left=IC_LEFT(ic);
10135 D (emitcode (";", "genArrayInit "););
10137 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10139 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10141 // Load immediate value into DPTR.
10142 emitcode("mov", "dptr, %s",
10143 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
10145 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10148 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10149 "Unexpected operand to genArrayInit.\n");
10152 // a regression because of SDCCcse.c:1.52
10153 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
10154 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
10155 if (options.model == MODEL_FLAT24)
10156 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
10160 type = operandType(IC_LEFT(ic));
10162 if (type && type->next)
10164 elementSize = getSize(type->next);
10168 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10169 "can't determine element size in genArrayInit.\n");
10173 iLoop = IC_ARRAYILIST(ic);
10178 bool firstpass = TRUE;
10180 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
10181 iLoop->count, (int)iLoop->literalValue, elementSize);
10187 symbol *tlbl = NULL;
10189 count = ix > 256 ? 256 : ix;
10193 tlbl = newiTempLabel (NULL);
10194 if (firstpass || (count & 0xff))
10196 emitcode("mov", "b, #!constbyte", count & 0xff);
10199 emitcode ("", "!tlabeldef", tlbl->key + 100);
10204 for (eIndex = 0; eIndex < elementSize; eIndex++)
10206 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10207 if (val != lastVal)
10209 emitcode("mov", "a, #!constbyte", val);
10213 emitcode("movx", "@dptr, a");
10214 emitcode("inc", "dptr");
10219 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10225 iLoop = iLoop->next;
10228 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10231 /*-----------------------------------------------------------------*/
10232 /* genFarFarAssign - assignment when both are in far space */
10233 /*-----------------------------------------------------------------*/
10235 genFarFarAssign (operand * result, operand * right, iCode * ic)
10237 int size = AOP_SIZE (right);
10239 symbol *rSym = NULL;
10243 /* quick & easy case. */
10244 D(emitcode(";","genFarFarAssign (1 byte case)"););
10245 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
10246 freeAsmop (right, NULL, ic, FALSE);
10247 /* now assign DPTR to result */
10249 aopOp(result, ic, FALSE, FALSE);
10251 aopPut(AOP(result), "a", 0);
10252 freeAsmop(result, NULL, ic, FALSE);
10256 /* See if we've got an underlying symbol to abuse. */
10257 if (IS_SYMOP(result) && OP_SYMBOL(result))
10259 if (IS_TRUE_SYMOP(result))
10261 rSym = OP_SYMBOL(result);
10263 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10265 rSym = OP_SYMBOL(result)->usl.spillLoc;
10269 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10271 /* We can use the '390 auto-toggle feature to good effect here. */
10273 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10274 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
10275 emitcode ("mov", "dptr,#%s", rSym->rname);
10276 /* DP2 = result, DP1 = right, DP1 is current. */
10279 emitcode("movx", "a,@dptr");
10280 emitcode("movx", "@dptr,a");
10283 emitcode("inc", "dptr");
10284 emitcode("inc", "dptr");
10287 emitcode("mov", "dps,#0");
10288 freeAsmop (right, NULL, ic, FALSE);
10290 some alternative code for processors without auto-toggle
10291 no time to test now, so later well put in...kpb
10292 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10293 emitcode("mov", "dps,#1"); /* Select DPTR2. */
10294 emitcode ("mov", "dptr,#%s", rSym->rname);
10295 /* DP2 = result, DP1 = right, DP1 is current. */
10299 emitcode("movx", "a,@dptr");
10301 emitcode("inc", "dptr");
10302 emitcode("inc", "dps");
10303 emitcode("movx", "@dptr,a");
10305 emitcode("inc", "dptr");
10306 emitcode("inc", "dps");
10308 emitcode("mov", "dps,#0");
10309 freeAsmop (right, NULL, ic, FALSE);
10314 D (emitcode (";", "genFarFarAssign"););
10315 aopOp (result, ic, TRUE, TRUE);
10317 _startLazyDPSEvaluation ();
10321 aopPut (AOP (result),
10322 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
10325 _endLazyDPSEvaluation ();
10326 freeAsmop (result, NULL, ic, FALSE);
10327 freeAsmop (right, NULL, ic, FALSE);
10331 /*-----------------------------------------------------------------*/
10332 /* genAssign - generate code for assignment */
10333 /*-----------------------------------------------------------------*/
10335 genAssign (iCode * ic)
10337 operand *result, *right;
10339 unsigned long lit = 0L;
10341 D (emitcode (";", "genAssign ");
10344 result = IC_RESULT (ic);
10345 right = IC_RIGHT (ic);
10347 /* if they are the same */
10348 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10351 aopOp (right, ic, FALSE, FALSE);
10353 emitcode (";", "genAssign: resultIsFar = %s",
10354 isOperandInFarSpace (result) ?
10357 /* special case both in far space */
10358 if ((AOP_TYPE (right) == AOP_DPTR ||
10359 AOP_TYPE (right) == AOP_DPTR2) &&
10360 /* IS_TRUE_SYMOP(result) && */
10361 isOperandInFarSpace (result))
10363 genFarFarAssign (result, right, ic);
10367 aopOp (result, ic, TRUE, FALSE);
10369 /* if they are the same registers */
10370 if (sameRegs (AOP (right), AOP (result)))
10373 /* if the result is a bit */
10374 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10376 /* if the right size is a literal then
10377 we know what the value is */
10378 if (AOP_TYPE (right) == AOP_LIT)
10380 if (((int) operandLitValue (right)))
10381 aopPut (AOP (result), one, 0);
10383 aopPut (AOP (result), zero, 0);
10387 /* the right is also a bit variable */
10388 if (AOP_TYPE (right) == AOP_CRY)
10390 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10391 aopPut (AOP (result), "c", 0);
10395 /* we need to or */
10397 aopPut (AOP (result), "a", 0);
10401 /* bit variables done */
10403 size = AOP_SIZE (result);
10405 if (AOP_TYPE (right) == AOP_LIT)
10406 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10409 (AOP_TYPE (result) != AOP_REG) &&
10410 (AOP_TYPE (right) == AOP_LIT) &&
10411 !IS_FLOAT (operandType (right)))
10413 _startLazyDPSEvaluation ();
10414 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10416 aopPut (AOP (result),
10417 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
10422 /* And now fill the rest with zeros. */
10425 emitcode ("clr", "a");
10429 aopPut (AOP (result), "a", offset++);
10431 _endLazyDPSEvaluation ();
10435 _startLazyDPSEvaluation ();
10438 aopPut (AOP (result),
10439 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10443 _endLazyDPSEvaluation ();
10447 freeAsmop (right, NULL, ic, FALSE);
10448 freeAsmop (result, NULL, ic, TRUE);
10451 /*-----------------------------------------------------------------*/
10452 /* genJumpTab - generates code for jump table */
10453 /*-----------------------------------------------------------------*/
10455 genJumpTab (iCode * ic)
10460 D (emitcode (";", "genJumpTab ");
10463 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10464 /* get the condition into accumulator */
10465 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
10467 /* multiply by four! */
10468 emitcode ("add", "a,acc");
10469 emitcode ("add", "a,acc");
10470 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10472 jtab = newiTempLabel (NULL);
10473 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
10474 emitcode ("jmp", "@a+dptr");
10475 emitcode ("", "!tlabeldef", jtab->key + 100);
10476 /* now generate the jump labels */
10477 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10478 jtab = setNextItem (IC_JTLABELS (ic)))
10479 emitcode ("ljmp", "!tlabel", jtab->key + 100);
10483 /*-----------------------------------------------------------------*/
10484 /* genCast - gen code for casting */
10485 /*-----------------------------------------------------------------*/
10487 genCast (iCode * ic)
10489 operand *result = IC_RESULT (ic);
10490 sym_link *ctype = operandType (IC_LEFT (ic));
10491 sym_link *rtype = operandType (IC_RIGHT (ic));
10492 operand *right = IC_RIGHT (ic);
10495 D (emitcode (";", "genCast ");
10498 /* if they are equivalent then do nothing */
10499 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10502 aopOp (right, ic, FALSE, FALSE);
10503 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
10505 /* if the result is a bit */
10506 // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10507 if (IS_BITVAR(OP_SYMBOL(result)->type))
10509 /* if the right size is a literal then
10510 we know what the value is */
10511 if (AOP_TYPE (right) == AOP_LIT)
10513 if (((int) operandLitValue (right)))
10514 aopPut (AOP (result), one, 0);
10516 aopPut (AOP (result), zero, 0);
10521 /* the right is also a bit variable */
10522 if (AOP_TYPE (right) == AOP_CRY)
10524 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10525 aopPut (AOP (result), "c", 0);
10529 /* we need to or */
10531 aopPut (AOP (result), "a", 0);
10535 /* if they are the same size : or less */
10536 if (AOP_SIZE (result) <= AOP_SIZE (right))
10539 /* if they are in the same place */
10540 if (sameRegs (AOP (right), AOP (result)))
10543 /* if they in different places then copy */
10544 size = AOP_SIZE (result);
10546 _startLazyDPSEvaluation ();
10549 aopPut (AOP (result),
10550 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10554 _endLazyDPSEvaluation ();
10559 /* if the result is of type pointer */
10560 if (IS_PTR (ctype))
10564 sym_link *type = operandType (right);
10566 /* pointer to generic pointer */
10567 if (IS_GENPTR (ctype))
10573 p_type = DCL_TYPE (type);
10577 #if OLD_CAST_BEHAVIOR
10578 /* KV: we are converting a non-pointer type to
10579 * a generic pointer. This (ifdef'd out) code
10580 * says that the resulting generic pointer
10581 * should have the same class as the storage
10582 * location of the non-pointer variable.
10584 * For example, converting an int (which happens
10585 * to be stored in DATA space) to a pointer results
10586 * in a DATA generic pointer; if the original int
10587 * in XDATA space, so will be the resulting pointer.
10589 * I don't like that behavior, and thus this change:
10590 * all such conversions will be forced to XDATA and
10591 * throw a warning. If you want some non-XDATA
10592 * type, or you want to suppress the warning, you
10593 * must go through an intermediate cast, like so:
10595 * char _generic *gp = (char _xdata *)(intVar);
10597 sym_link *etype = getSpec (type);
10599 /* we have to go by the storage class */
10600 if (SPEC_OCLS (etype) != generic)
10602 p_type = PTR_TYPE (SPEC_OCLS (etype));
10607 /* Converting unknown class (i.e. register variable)
10608 * to generic pointer. This is not good, but
10609 * we'll make a guess (and throw a warning).
10612 werror (W_INT_TO_GEN_PTR_CAST);
10616 /* the first two bytes are known */
10617 size = GPTRSIZE - 1;
10619 _startLazyDPSEvaluation ();
10622 aopPut (AOP (result),
10623 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10627 _endLazyDPSEvaluation ();
10629 /* the last byte depending on type */
10647 /* this should never happen */
10648 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10649 "got unknown pointer type");
10652 aopPut (AOP (result), l, GPTRSIZE - 1);
10656 /* just copy the pointers */
10657 size = AOP_SIZE (result);
10659 _startLazyDPSEvaluation ();
10662 aopPut (AOP (result),
10663 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10667 _endLazyDPSEvaluation ();
10671 /* so we now know that the size of destination is greater
10672 than the size of the source */
10673 /* we move to result for the size of source */
10674 size = AOP_SIZE (right);
10676 _startLazyDPSEvaluation ();
10679 aopPut (AOP (result),
10680 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10684 _endLazyDPSEvaluation ();
10686 /* now depending on the sign of the source && destination */
10687 size = AOP_SIZE (result) - AOP_SIZE (right);
10688 /* if unsigned or not an integral type */
10689 /* also, if the source is a bit, we don't need to sign extend, because
10690 * it can't possibly have set the sign bit.
10692 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
10696 aopPut (AOP (result), zero, offset++);
10701 /* we need to extend the sign :{ */
10702 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
10703 FALSE, FALSE, TRUE);
10705 emitcode ("rlc", "a");
10706 emitcode ("subb", "a,acc");
10708 aopPut (AOP (result), "a", offset++);
10711 /* we are done hurray !!!! */
10714 freeAsmop (right, NULL, ic, TRUE);
10715 freeAsmop (result, NULL, ic, TRUE);
10719 /*-----------------------------------------------------------------*/
10720 /* genDjnz - generate decrement & jump if not zero instrucion */
10721 /*-----------------------------------------------------------------*/
10723 genDjnz (iCode * ic, iCode * ifx)
10725 symbol *lbl, *lbl1;
10729 /* if the if condition has a false label
10730 then we cannot save */
10731 if (IC_FALSE (ifx))
10734 /* if the minus is not of the form
10736 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10737 !IS_OP_LITERAL (IC_RIGHT (ic)))
10740 if (operandLitValue (IC_RIGHT (ic)) != 1)
10743 /* if the size of this greater than one then no
10745 if (getSize (operandType (IC_RESULT (ic))) > 1)
10748 /* otherwise we can save BIG */
10749 D(emitcode(";", "genDjnz"););
10751 lbl = newiTempLabel (NULL);
10752 lbl1 = newiTempLabel (NULL);
10754 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10756 if (AOP_NEEDSACC(IC_RESULT(ic)))
10758 /* If the result is accessed indirectly via
10759 * the accumulator, we must explicitly write
10760 * it back after the decrement.
10762 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
10764 if (strcmp(rByte, "a"))
10766 /* Something is hopelessly wrong */
10767 fprintf(stderr, "*** warning: internal error at %s:%d\n",
10768 __FILE__, __LINE__);
10769 /* We can just give up; the generated code will be inefficient,
10770 * but what the hey.
10772 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10775 emitcode ("dec", "%s", rByte);
10776 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
10777 emitcode ("jnz", "!tlabel", lbl->key + 100);
10779 else if (IS_AOP_PREG (IC_RESULT (ic)))
10781 emitcode ("dec", "%s",
10782 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10783 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10784 emitcode ("jnz", "!tlabel", lbl->key + 100);
10788 emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
10791 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
10792 emitcode ("", "!tlabeldef", lbl->key + 100);
10793 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
10794 emitcode ("", "!tlabeldef", lbl1->key + 100);
10796 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10797 ifx->generated = 1;
10801 /*-----------------------------------------------------------------*/
10802 /* genReceive - generate code for a receive iCode */
10803 /*-----------------------------------------------------------------*/
10805 genReceive (iCode * ic)
10808 D (emitcode (";", "genReceive ");
10811 if (isOperandInFarSpace (IC_RESULT (ic)) &&
10812 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10813 IS_TRUE_SYMOP (IC_RESULT (ic))))
10815 int size = getSize (operandType (IC_RESULT (ic)));
10816 int offset = fReturnSizeDS390 - size;
10819 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
10820 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
10823 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10824 size = AOP_SIZE (IC_RESULT (ic));
10828 emitcode ("pop", "acc");
10829 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
10836 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10838 assignResultValue (IC_RESULT (ic));
10841 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10844 /*-----------------------------------------------------------------*/
10845 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
10846 /*-----------------------------------------------------------------*/
10847 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
10849 operand *from , *to , *count;
10854 /* we know it has to be 3 parameters */
10855 assert (nparms == 3);
10857 rsave = newBitVect(16);
10858 /* save DPTR if it needs to be saved */
10859 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
10860 if (bitVectBitValue(ic->rMask,i))
10861 rsave = bitVectSetBit(rsave,i);
10863 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
10864 ds390_rUmaskForOp (IC_RESULT(ic))));
10871 aopOp (from, ic->next, FALSE, FALSE);
10873 /* get from into DPTR1 */
10874 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
10875 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
10876 if (options.model == MODEL_FLAT24) {
10877 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
10880 freeAsmop (from, NULL, ic, FALSE);
10881 aopOp (to, ic, FALSE, FALSE);
10882 /* get "to" into DPTR */
10883 /* if the operand is already in dptr
10884 then we do nothing else we move the value to dptr */
10885 if (AOP_TYPE (to) != AOP_STR) {
10886 /* if already in DPTR then we need to push */
10887 if (AOP_TYPE(to) == AOP_DPTR) {
10888 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
10889 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
10890 if (options.model == MODEL_FLAT24)
10891 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
10892 emitcode ("pop", "dph");
10893 emitcode ("pop", "dpl");
10895 _startLazyDPSEvaluation ();
10896 /* if this is remateriazable */
10897 if (AOP_TYPE (to) == AOP_IMMD) {
10898 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
10899 } else { /* we need to get it byte by byte */
10900 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
10901 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
10902 if (options.model == MODEL_FLAT24) {
10903 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
10906 _endLazyDPSEvaluation ();
10909 freeAsmop (to, NULL, ic, FALSE);
10911 aopOp (count, ic->next->next, FALSE,FALSE);
10912 lbl =newiTempLabel(NULL);
10914 /* now for the actual copy */
10915 if (AOP_TYPE(count) == AOP_LIT &&
10916 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
10917 emitcode (";","OH JOY auto increment with djnz (very fast)");
10918 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
10919 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
10920 emitcode ("","!tlabeldef",lbl->key+100);
10922 emitcode ("clr","a");
10923 emitcode ("movc", "a,@a+dptr");
10925 emitcode ("movx", "a,@dptr");
10926 emitcode ("movx", "@dptr,a");
10927 emitcode ("inc", "dptr");
10928 emitcode ("inc", "dptr");
10929 emitcode ("djnz","b,!tlabel",lbl->key+100);
10931 symbol *lbl1 = newiTempLabel(NULL);
10933 emitcode (";"," Auto increment but no djnz");
10934 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
10935 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
10936 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
10937 emitcode ("","!tlabeldef",lbl->key+100);
10939 emitcode ("clr","a");
10940 emitcode ("movc", "a,@a+dptr");
10942 emitcode ("movx", "a,@dptr");
10943 emitcode ("movx", "@dptr,a");
10944 emitcode ("inc", "dptr");
10945 emitcode ("inc", "dptr");
10946 emitcode ("mov","a,b");
10947 emitcode ("orl","a,_ap");
10948 emitcode ("jz","!tlabel",lbl1->key+100);
10949 emitcode ("mov","a,_ap");
10950 emitcode ("add","a,#!constbyte",0xFF);
10951 emitcode ("mov","_ap,a");
10952 emitcode ("mov","a,b");
10953 emitcode ("addc","a,#!constbyte",0xFF);
10954 emitcode ("mov","b,a");
10955 emitcode ("sjmp","!tlabel",lbl->key+100);
10956 emitcode ("","!tlabeldef",lbl1->key+100);
10958 emitcode ("mov", "dps,#0");
10959 freeAsmop (count, NULL, ic, FALSE);
10960 unsavermask(rsave);
10964 /*-----------------------------------------------------------------*/
10965 /* genMemsetX - gencode for memSetX data */
10966 /*-----------------------------------------------------------------*/
10967 static void genMemsetX(iCode *ic, int nparms, operand **parms)
10969 operand *to , *val , *count;
10973 bitVect *rsave = NULL;
10975 /* we know it has to be 3 parameters */
10976 assert (nparms == 3);
10982 /* save DPTR if it needs to be saved */
10983 rsave = newBitVect(16);
10984 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
10985 if (bitVectBitValue(ic->rMask,i))
10986 rsave = bitVectSetBit(rsave,i);
10988 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
10989 ds390_rUmaskForOp (IC_RESULT(ic))));
10992 aopOp (to, ic, FALSE, FALSE);
10993 /* get "to" into DPTR */
10994 /* if the operand is already in dptr
10995 then we do nothing else we move the value to dptr */
10996 if (AOP_TYPE (to) != AOP_STR) {
10997 /* if already in DPTR then we need to push */
10998 if (AOP_TYPE(to) == AOP_DPTR) {
10999 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11000 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11001 if (options.model == MODEL_FLAT24)
11002 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11003 emitcode ("pop", "dph");
11004 emitcode ("pop", "dpl");
11006 _startLazyDPSEvaluation ();
11007 /* if this is remateriazable */
11008 if (AOP_TYPE (to) == AOP_IMMD) {
11009 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11010 } else { /* we need to get it byte by byte */
11011 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11012 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11013 if (options.model == MODEL_FLAT24) {
11014 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11017 _endLazyDPSEvaluation ();
11020 freeAsmop (to, NULL, ic, FALSE);
11022 aopOp (val, ic->next->next, FALSE,FALSE);
11023 aopOp (count, ic->next->next, FALSE,FALSE);
11024 lbl =newiTempLabel(NULL);
11025 /* now for the actual copy */
11026 if (AOP_TYPE(count) == AOP_LIT &&
11027 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11028 l = aopGet(AOP (val), 0, FALSE, FALSE, TRUE);
11029 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11031 emitcode ("","!tlabeldef",lbl->key+100);
11032 emitcode ("movx", "@dptr,a");
11033 emitcode ("inc", "dptr");
11034 emitcode ("djnz","b,!tlabel",lbl->key+100);
11036 symbol *lbl1 = newiTempLabel(NULL);
11038 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11039 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11040 emitcode ("","!tlabeldef",lbl->key+100);
11041 l = aopGet(AOP (val), 0, FALSE, FALSE, TRUE);
11043 emitcode ("movx", "a,@dptr");
11044 emitcode ("inc", "dptr");
11045 emitcode ("mov","a,b");
11046 emitcode ("orl","a,_ap");
11047 emitcode ("jz","!tlabel",lbl1->key+100);
11048 emitcode ("mov","a,_ap");
11049 emitcode ("add","a,#!constbyte",0xFF);
11050 emitcode ("mov","_ap,a");
11051 emitcode ("mov","a,b");
11052 emitcode ("addc","a,#!constbyte",0xFF);
11053 emitcode ("mov","b,a");
11054 emitcode ("sjmp","!tlabel",lbl->key+100);
11055 emitcode ("","!tlabeldef",lbl1->key+100);
11057 freeAsmop (count, NULL, ic, FALSE);
11058 unsavermask(rsave);
11061 /*-----------------------------------------------------------------*/
11062 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
11063 /*-----------------------------------------------------------------*/
11064 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
11067 operand *pnum, *result;
11070 assert (nparms==1);
11071 /* save registers that need to be saved */
11072 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11073 ds390_rUmaskForOp (IC_RESULT(ic))));
11076 aopOp (pnum, ic, FALSE, FALSE);
11077 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,FALSE));
11078 freeAsmop (pnum, NULL, ic, FALSE);
11079 emitcode ("lcall","NatLib_LoadPrimitive");
11080 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11081 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
11082 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
11083 for (i = (size-1) ; i >= 0 ; i-- ) {
11084 emitcode ("push","a%s",javaRet[i]);
11086 for (i=0; i < size ; i++ ) {
11087 emitcode ("pop","a%s",aopGet(AOP(result),i,FALSE,FALSE,FALSE));
11090 for (i = 0 ; i < size ; i++ ) {
11091 aopPut(AOP(result),javaRet[i],i);
11094 freeAsmop (result, NULL, ic, FALSE);
11095 unsavermask(rsave);
11098 /*-----------------------------------------------------------------*/
11099 /* genNatLibLoadPointer - calls TINI api function to load pointer */
11100 /*-----------------------------------------------------------------*/
11101 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
11104 operand *pnum, *result;
11108 assert (nparms==1);
11109 /* save registers that need to be saved */
11110 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11111 ds390_rUmaskForOp (IC_RESULT(ic))));
11114 aopOp (pnum, ic, FALSE, FALSE);
11115 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,FALSE));
11116 freeAsmop (pnum, NULL, ic, FALSE);
11117 emitcode ("lcall","NatLib_LoadPointer");
11118 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11119 if (AOP_TYPE(result)!=AOP_STR) {
11120 for (i = 0 ; i < size ; i++ ) {
11121 aopPut(AOP(result),fReturn[i],i);
11124 freeAsmop (result, NULL, ic, FALSE);
11125 unsavermask(rsave);
11128 /*-----------------------------------------------------------------*/
11129 /* genNatLibInstallStateBlock - */
11130 /*-----------------------------------------------------------------*/
11131 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
11132 operand **parms, const char *name)
11135 operand *psb, *handle;
11136 assert (nparms==2);
11138 /* save registers that need to be saved */
11139 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11140 ds390_rUmaskForOp (IC_RESULT(ic))));
11144 /* put pointer to state block into DPTR1 */
11145 aopOp (psb, ic, FALSE, FALSE);
11146 if (AOP_TYPE (psb) == AOP_IMMD) {
11147 emitcode ("mov","dps,#1");
11148 emitcode ("mov", "dptr,%s", aopGet (AOP (psb), 0, TRUE, FALSE, FALSE));
11149 emitcode ("mov","dps,#0");
11151 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,FALSE));
11152 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,FALSE));
11153 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,FALSE));
11155 freeAsmop (psb, NULL, ic, FALSE);
11157 /* put libraryID into DPTR */
11158 emitcode ("mov","dptr,#LibraryID");
11160 /* put handle into r3:r2 */
11161 aopOp (handle, ic, FALSE, FALSE);
11162 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11163 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11164 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11165 emitcode ("pop","ar3");
11166 emitcode ("pop","ar2");
11168 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11169 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11171 freeAsmop (psb, NULL, ic, FALSE);
11173 /* make the call */
11174 emitcode ("lcall","NatLib_Install%sStateBlock",name);
11176 /* put return value into place*/
11178 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
11180 aopPut(AOP(IC_RESULT(ic)),"a",0);
11181 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11182 unsavermask(rsave);
11185 /*-----------------------------------------------------------------*/
11186 /* genNatLibRemoveStateBlock - */
11187 /*-----------------------------------------------------------------*/
11188 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
11194 /* save registers that need to be saved */
11195 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11196 ds390_rUmaskForOp (IC_RESULT(ic))));
11198 /* put libraryID into DPTR */
11199 emitcode ("mov","dptr,#LibraryID");
11200 /* make the call */
11201 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
11202 unsavermask(rsave);
11205 /*-----------------------------------------------------------------*/
11206 /* genNatLibGetStateBlock - */
11207 /*-----------------------------------------------------------------*/
11208 static void genNatLibGetStateBlock(iCode *ic,int nparms,
11209 operand **parms,const char *name)
11212 symbol *lbl = newiTempLabel(NULL);
11215 /* save registers that need to be saved */
11216 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11217 ds390_rUmaskForOp (IC_RESULT(ic))));
11219 /* put libraryID into DPTR */
11220 emitcode ("mov","dptr,#LibraryID");
11221 /* make the call */
11222 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
11223 emitcode ("jnz","!tlabel",lbl->key+100);
11225 /* put return value into place */
11226 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
11227 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
11228 emitcode ("push","ar3");
11229 emitcode ("push","ar2");
11230 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,FALSE));
11231 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,FALSE));
11233 aopPut(AOP(IC_RESULT(ic)),"r2",0);
11234 aopPut(AOP(IC_RESULT(ic)),"r3",1);
11236 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11237 emitcode ("","!tlabeldef",lbl->key+100);
11238 unsavermask(rsave);
11241 /*-----------------------------------------------------------------*/
11242 /* genMMMalloc - */
11243 /*-----------------------------------------------------------------*/
11244 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
11245 int size, const char *name)
11250 symbol *lbl = newiTempLabel(NULL);
11252 assert (nparms == 1);
11253 /* save registers that need to be saved */
11254 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11255 ds390_rUmaskForOp (IC_RESULT(ic))));
11258 aopOp (bsize,ic,FALSE,FALSE);
11260 /* put the size in R4-R2 */
11261 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
11262 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,FALSE));
11263 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,FALSE));
11265 emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,FALSE));
11266 emitcode("pop","ar4");
11268 emitcode("pop","ar3");
11269 emitcode("pop","ar2");
11271 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,FALSE));
11272 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,FALSE));
11274 emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,FALSE));
11277 freeAsmop (bsize, NULL, ic, FALSE);
11279 /* make the call */
11280 emitcode ("lcall","MM_%s",name);
11281 emitcode ("jz","!tlabel",lbl->key+100);
11282 emitcode ("mov","r2,#!constbyte",0xff);
11283 emitcode ("mov","r3,#!constbyte",0xff);
11284 emitcode ("","!tlabeldef",lbl->key+100);
11285 /* we don't care about the pointer : we just save the handle */
11286 rsym = OP_SYMBOL(IC_RESULT(ic));
11287 if (rsym->liveFrom != rsym->liveTo) {
11288 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
11289 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
11290 emitcode ("push","ar3");
11291 emitcode ("push","ar2");
11292 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,FALSE));
11293 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,FALSE));
11295 aopPut(AOP(IC_RESULT(ic)),"r2",0);
11296 aopPut(AOP(IC_RESULT(ic)),"r3",1);
11298 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11300 unsavermask(rsave);
11303 /*-----------------------------------------------------------------*/
11305 /*-----------------------------------------------------------------*/
11306 static void genMMDeref (iCode *ic,int nparms, operand **parms)
11311 assert (nparms == 1);
11312 /* save registers that need to be saved */
11313 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11314 ds390_rUmaskForOp (IC_RESULT(ic))));
11317 aopOp (handle,ic,FALSE,FALSE);
11319 /* put the size in R4-R2 */
11320 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11321 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11322 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11323 emitcode("pop","ar3");
11324 emitcode("pop","ar2");
11326 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11327 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11329 freeAsmop (handle, NULL, ic, FALSE);
11331 /* make the call */
11332 emitcode ("lcall","MM_Deref");
11335 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11336 if (rsym->liveFrom != rsym->liveTo) {
11337 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11338 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
11339 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
11340 aopPut(AOP(IC_RESULT(ic)),"dph",1);
11341 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
11345 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11346 unsavermask(rsave);
11349 /*-----------------------------------------------------------------*/
11350 /* genMMUnrestrictedPersist - */
11351 /*-----------------------------------------------------------------*/
11352 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
11357 assert (nparms == 1);
11358 /* save registers that need to be saved */
11359 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11360 ds390_rUmaskForOp (IC_RESULT(ic))));
11363 aopOp (handle,ic,FALSE,FALSE);
11365 /* put the size in R3-R2 */
11366 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11367 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11368 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11369 emitcode("pop","ar3");
11370 emitcode("pop","ar2");
11372 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11373 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11375 freeAsmop (handle, NULL, ic, FALSE);
11377 /* make the call */
11378 emitcode ("lcall","MM_UnrestrictedPersist");
11381 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11382 if (rsym->liveFrom != rsym->liveTo) {
11383 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11384 aopPut(AOP(IC_RESULT(ic)),"a",0);
11385 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11388 unsavermask(rsave);
11391 /*-----------------------------------------------------------------*/
11392 /* genSystemExecJavaProcess - */
11393 /*-----------------------------------------------------------------*/
11394 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
11397 operand *handle, *pp;
11399 assert (nparms==2);
11400 /* save registers that need to be saved */
11401 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11402 ds390_rUmaskForOp (IC_RESULT(ic))));
11407 /* put the handle in R3-R2 */
11408 aopOp (handle,ic,FALSE,FALSE);
11409 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11410 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11411 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11412 emitcode("pop","ar3");
11413 emitcode("pop","ar2");
11415 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11416 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11418 freeAsmop (handle, NULL, ic, FALSE);
11420 /* put pointer in DPTR */
11421 aopOp (pp,ic,FALSE,FALSE);
11422 if (AOP_TYPE(pp) == AOP_IMMD) {
11423 emitcode ("mov", "dptr,%s", aopGet (AOP (pp), 0, TRUE, FALSE, FALSE));
11424 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
11425 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,FALSE));
11426 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,FALSE));
11427 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,FALSE));
11429 freeAsmop (handle, NULL, ic, FALSE);
11431 /* make the call */
11432 emitcode ("lcall","System_ExecJavaProcess");
11434 /* put result in place */
11436 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11437 if (rsym->liveFrom != rsym->liveTo) {
11438 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11439 aopPut(AOP(IC_RESULT(ic)),"a",0);
11440 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11444 unsavermask(rsave);
11447 /*-----------------------------------------------------------------*/
11448 /* genSystemRTCRegisters - */
11449 /*-----------------------------------------------------------------*/
11450 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
11456 assert (nparms==1);
11457 /* save registers that need to be saved */
11458 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11459 ds390_rUmaskForOp (IC_RESULT(ic))));
11462 /* put pointer in DPTR */
11463 aopOp (pp,ic,FALSE,FALSE);
11464 if (AOP_TYPE (pp) == AOP_IMMD) {
11465 emitcode ("mov","dps,#1");
11466 emitcode ("mov", "dptr,%s", aopGet (AOP (pp), 0, TRUE, FALSE, FALSE));
11467 emitcode ("mov","dps,#0");
11469 emitcode ("mov","dpl1,%s",aopGet(AOP(pp),0,FALSE,FALSE,FALSE));
11470 emitcode ("mov","dph1,%s",aopGet(AOP(pp),1,FALSE,FALSE,FALSE));
11471 emitcode ("mov","dpx1,%s",aopGet(AOP(pp),2,FALSE,FALSE,FALSE));
11473 freeAsmop (pp, NULL, ic, FALSE);
11475 /* make the call */
11476 emitcode ("lcall","System_%sRTCRegisters",name);
11478 unsavermask(rsave);
11481 /*-----------------------------------------------------------------*/
11482 /* genSystemThreadSleep - */
11483 /*-----------------------------------------------------------------*/
11484 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
11489 assert (nparms==1);
11490 /* save registers that need to be saved */
11491 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11492 ds390_rUmaskForOp (IC_RESULT(ic))));
11495 aopOp(to,ic,FALSE,FALSE);
11496 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
11497 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
11498 emitcode ("push","%s",aopGet(AOP(to),0,FALSE,TRUE,FALSE));
11499 emitcode ("push","%s",aopGet(AOP(to),1,FALSE,TRUE,FALSE));
11500 emitcode ("push","%s",aopGet(AOP(to),2,FALSE,TRUE,FALSE));
11501 emitcode ("push","%s",aopGet(AOP(to),3,FALSE,TRUE,FALSE));
11502 emitcode ("pop","ar3");
11503 emitcode ("pop","ar2");
11504 emitcode ("pop","ar1");
11505 emitcode ("pop","ar0");
11507 emitcode ("mov","r0,%s",aopGet(AOP(to),0,FALSE,TRUE,FALSE));
11508 emitcode ("mov","r1,%s",aopGet(AOP(to),1,FALSE,TRUE,FALSE));
11509 emitcode ("mov","r2,%s",aopGet(AOP(to),2,FALSE,TRUE,FALSE));
11510 emitcode ("mov","r3,%s",aopGet(AOP(to),3,FALSE,TRUE,FALSE));
11512 freeAsmop (to, NULL, ic, FALSE);
11514 /* suspend in acc */
11516 aopOp(s,ic,FALSE,FALSE);
11517 emitcode ("mov","a,%s",aopGet(AOP(s),0,FALSE,TRUE,FALSE));
11518 freeAsmop (s, NULL, ic, FALSE);
11520 /* make the call */
11521 emitcode ("lcall","System_%s",name);
11523 unsavermask(rsave);
11526 /*-----------------------------------------------------------------*/
11527 /* genSystemThreadResume - */
11528 /*-----------------------------------------------------------------*/
11529 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
11534 assert (nparms==2);
11535 /* save registers that need to be saved */
11536 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11537 ds390_rUmaskForOp (IC_RESULT(ic))));
11543 aopOp(pid,ic,FALSE,FALSE);
11544 emitcode ("mov","r0,%s",aopGet(AOP(pid),0,FALSE,TRUE,FALSE));
11545 freeAsmop (pid, NULL, ic, FALSE);
11548 aopOp(tid,ic,FALSE,FALSE);
11549 emitcode ("mov","a,%s",aopGet(AOP(tid),0,FALSE,TRUE,FALSE));
11550 freeAsmop (tid, NULL, ic, FALSE);
11552 emitcode ("lcall","System_ThreadResume");
11554 /* put result into place */
11556 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11557 if (rsym->liveFrom != rsym->liveTo) {
11558 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11559 aopPut(AOP(IC_RESULT(ic)),"a",0);
11560 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11563 unsavermask(rsave);
11566 /*-----------------------------------------------------------------*/
11567 /* genSystemProcessResume - */
11568 /*-----------------------------------------------------------------*/
11569 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
11574 assert (nparms==1);
11575 /* save registers that need to be saved */
11576 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11577 ds390_rUmaskForOp (IC_RESULT(ic))));
11582 aopOp(pid,ic,FALSE,FALSE);
11583 emitcode ("mov","a,%s",aopGet(AOP(pid),0,FALSE,TRUE,FALSE));
11584 freeAsmop (pid, NULL, ic, FALSE);
11586 emitcode ("lcall","System_ProcessResume");
11588 unsavermask(rsave);
11591 /*-----------------------------------------------------------------*/
11593 /*-----------------------------------------------------------------*/
11594 static void genSystem (iCode *ic,int nparms,char *name)
11596 assert(nparms == 0);
11598 emitcode ("lcall","System_%s",name);
11601 /*-----------------------------------------------------------------*/
11602 /* genSystemPoll - */
11603 /*-----------------------------------------------------------------*/
11604 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
11609 assert (nparms==1);
11610 /* save registers that need to be saved */
11611 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11612 ds390_rUmaskForOp (IC_RESULT(ic))));
11615 aopOp (fp,ic,FALSE,FALSE);
11616 if (AOP_TYPE (fp) == AOP_IMMD) {
11617 emitcode ("mov", "dptr,%s", aopGet (AOP (fp), 0, TRUE, FALSE, FALSE));
11618 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
11619 emitcode ("mov","dpl,%s",aopGet(AOP(fp),0,FALSE,FALSE,FALSE));
11620 emitcode ("mov","dph,%s",aopGet(AOP(fp),1,FALSE,FALSE,FALSE));
11621 emitcode ("mov","dpx,%s",aopGet(AOP(fp),2,FALSE,FALSE,FALSE));
11623 freeAsmop (fp, NULL, ic, FALSE);
11625 emitcode ("lcall","System_%sPoll",name);
11627 /* put result into place */
11629 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11630 if (rsym->liveFrom != rsym->liveTo) {
11631 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11632 aopPut(AOP(IC_RESULT(ic)),"a",0);
11633 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11636 unsavermask(rsave);
11639 /*-----------------------------------------------------------------*/
11640 /* genSystemGetCurrentID - */
11641 /*-----------------------------------------------------------------*/
11642 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
11644 assert (nparms==0);
11646 emitcode ("lcall","System_GetCurrent%sId",name);
11647 /* put result into place */
11649 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11650 if (rsym->liveFrom != rsym->liveTo) {
11651 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11652 aopPut(AOP(IC_RESULT(ic)),"a",0);
11653 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11658 /*-----------------------------------------------------------------*/
11659 /* genBuiltIn - calls the appropriate function to generating code */
11660 /* for a built in function */
11661 /*-----------------------------------------------------------------*/
11662 static void genBuiltIn (iCode *ic)
11664 operand *bi_parms[MAX_BUILTIN_ARGS];
11669 /* get all the arguments for a built in function */
11670 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
11672 /* which function is it */
11673 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
11674 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
11675 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
11676 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
11677 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
11678 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
11679 genMemsetX(bi_iCode,nbi_parms,bi_parms);
11680 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
11681 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
11682 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
11683 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
11684 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
11685 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
11686 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
11687 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
11688 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
11689 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
11690 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
11691 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
11692 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
11693 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
11694 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
11695 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
11696 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
11697 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
11698 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
11699 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
11700 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
11701 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
11702 } else if (strcmp(bif->name,"MM_Malloc")==0) {
11703 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
11704 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
11705 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
11706 } else if (strcmp(bif->name,"MM_Free")==0) {
11707 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
11708 } else if (strcmp(bif->name,"MM_Deref")==0) {
11709 genMMDeref(bi_iCode,nbi_parms,bi_parms);
11710 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
11711 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
11712 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
11713 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
11714 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
11715 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
11716 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
11717 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
11718 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
11719 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
11720 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
11721 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
11722 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
11723 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
11724 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
11725 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
11726 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
11727 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
11728 } else if (strcmp(bif->name,"System_SaveThread")==0) {
11729 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
11730 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
11731 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
11732 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
11733 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
11734 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
11735 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
11736 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
11737 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
11738 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
11739 genSystem(bi_iCode,nbi_parms,"ProcessYield");
11740 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
11741 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
11742 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
11743 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
11744 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
11745 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
11746 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
11747 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
11748 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
11749 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
11751 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
11757 /*-----------------------------------------------------------------*/
11758 /* gen390Code - generate code for Dallas 390 based controllers */
11759 /*-----------------------------------------------------------------*/
11761 gen390Code (iCode * lic)
11766 lineHead = lineCurr = NULL;
11768 if (options.model == MODEL_FLAT24) {
11769 fReturnSizeDS390 = 5;
11770 fReturn = fReturn24;
11772 fReturnSizeDS390 = 4;
11773 fReturn = fReturn16;
11774 options.stack10bit=0;
11778 /* print the allocation information */
11780 printAllocInfo (currFunc, codeOutFile);
11782 /* if debug information required */
11783 if (options.debug && currFunc)
11785 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
11787 if (IS_STATIC (currFunc->etype))
11788 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
11790 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
11793 /* stack pointer name */
11794 if (options.useXstack)
11800 for (ic = lic; ic; ic = ic->next)
11803 if (cln != ic->lineno)
11808 emitcode ("", "C$%s$%d$%d$%d ==.",
11809 FileBaseName (ic->filename), ic->lineno,
11810 ic->level, ic->block);
11813 emitcode (";", "%s %d", ic->filename, ic->lineno);
11816 /* if the result is marked as
11817 spilt and rematerializable or code for
11818 this has already been generated then
11820 if (resultRemat (ic) || ic->generated)
11823 /* depending on the operation */
11843 /* IPOP happens only when trying to restore a
11844 spilt live range, if there is an ifx statement
11845 following this pop then the if statement might
11846 be using some of the registers being popped which
11847 would destory the contents of the register so
11848 we need to check for this condition and handle it */
11850 ic->next->op == IFX &&
11851 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11852 genIfx (ic->next, ic);
11870 genEndFunction (ic);
11890 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11907 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11911 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11918 /* note these two are xlated by algebraic equivalence
11919 during parsing SDCC.y */
11920 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11921 "got '>=' or '<=' shouldn't have come here");
11925 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11937 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11941 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11945 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11969 genRightShift (ic);
11972 case GET_VALUE_AT_ADDRESS:
11973 genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_LEFT(ic)))));
11977 if (POINTER_SET (ic))
11978 genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
12004 if (ic->builtinSEND) genBuiltIn(ic);
12005 else addSet (&_G.sendSet, ic);
12018 /* now we are ready to call the
12019 peep hole optimizer */
12020 if (!options.nopeep)
12021 peepHole (&lineHead);
12023 /* now do the actual printing */
12024 printLine (lineHead, codeOutFile);